Skip to content

Commit 232ae4b

Browse files
committed
Move effective_value to Amount and rename
Effective value uses the amount parameter which can be eliminated if it's moved to a method on Amount. Furthermore, moving to Amount gives access to Amount error type OutOfRange which is added on the next commit.
1 parent 985057c commit 232ae4b

File tree

3 files changed

+44
-22
lines changed

3 files changed

+44
-22
lines changed

bitcoin/src/blockdata/transaction.rs

+2-22
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,8 @@ impl Decodable for Transaction {
773773
///
774774
/// * `fee_rate` - the fee rate of the transaction being created.
775775
/// * `input_weight_prediction` - the predicted input weight.
776+
#[deprecated(since = "TBD", note = "use `Amount.to_effective_value()` instead")]
777+
// removes SignedAmount import from transaction once this is deprecated function is removed.
776778
pub fn effective_value(
777779
fee_rate: FeeRate,
778780
weight: Weight,
@@ -1647,28 +1649,6 @@ mod tests {
16471649
assert!(result.is_err());
16481650
}
16491651

1650-
#[test]
1651-
fn effective_value_happy_path() {
1652-
let value = "1 cBTC".parse::<Amount>().unwrap();
1653-
let fee_rate = FeeRate::from_sat_per_kwu(10);
1654-
let effective_value =
1655-
effective_value(
1656-
fee_rate, InputWeightPrediction::P2WPKH_MAX.total_weight(), value
1657-
).unwrap();
1658-
1659-
// 10 sat/kwu * 272 wu = 4 sats (rounding up)
1660-
let expected_fee = "3 sats".parse::<SignedAmount>().unwrap();
1661-
let expected_effective_value = (value.to_signed() - expected_fee).unwrap();
1662-
assert_eq!(effective_value, expected_effective_value);
1663-
}
1664-
1665-
#[test]
1666-
fn effective_value_fee_rate_does_not_overflow() {
1667-
let eff_value =
1668-
effective_value(FeeRate::MAX, InputWeightPrediction::P2WPKH_MAX.total_weight(), Amount::ZERO);
1669-
assert!(eff_value.is_none());
1670-
}
1671-
16721652
#[test]
16731653
fn txin_txout_weight() {
16741654
// [(is_segwit, tx_hex, expected_weight)]

units/src/amount/tests.rs

+19
Original file line numberDiff line numberDiff line change
@@ -1461,3 +1461,22 @@ fn math_op_errors() {
14611461
panic!("Expected a division by zero error, but got a valid result");
14621462
}
14631463
}
1464+
1465+
#[test]
1466+
fn to_effective_value() {
1467+
let amt = "1 cBTC".parse::<Amount>().unwrap();
1468+
let fee_rate = FeeRate::from_sat_per_kwu(10);
1469+
let effective_value =
1470+
amt.to_effective_value(fee_rate, Weight::from_wu(272)).unwrap();
1471+
1472+
// 10 sat/kwu * 272 wu = 4 sats (rounding up)
1473+
let expected_fee = "3 sats".parse::<SignedAmount>().unwrap();
1474+
let expected_effective_value = (amt.to_signed() - expected_fee).unwrap();
1475+
assert_eq!(effective_value, expected_effective_value);
1476+
}
1477+
1478+
#[test]
1479+
fn effective_value_fee_rate_does_not_overflow() {
1480+
let eff_value =Amount::ZERO.to_effective_value(FeeRate::MAX, Weight::from_wu(272));
1481+
assert!(eff_value.is_none());
1482+
}

units/src/amount/unsigned.rs

+23
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use super::{
1515
parse_signed_to_satoshi, split_amount_and_denomination, Denomination, Display, DisplayStyle,
1616
OutOfRangeError, ParseAmountError, ParseError, SignedAmount,
1717
};
18+
use crate::{FeeRate, Weight};
1819

1920
mod encapsulate {
2021
use super::OutOfRangeError;
@@ -234,6 +235,28 @@ impl Amount {
234235
#[cfg(feature = "alloc")]
235236
pub fn to_btc(self) -> f64 { self.to_float_in(Denomination::Bitcoin) }
236237

238+
/// Computes the effective value of an [`Amount`].
239+
///
240+
/// The effective value is the value of an output value minus the amount to spend it. That is, the
241+
/// effective_value can be calculated as: value - (fee_rate * weight).
242+
///
243+
/// Note: the effective value of a [`Transaction`] may increase less than the effective value of
244+
/// a [`TxOut`] when adding another [`TxOut`] to the transaction. This happens when the new
245+
/// [`TxOut`] added causes the output length `VarInt` to increase its encoding length.
246+
///
247+
/// # Parameters
248+
///
249+
/// * `fee_rate` - the fee rate of the transaction being created.
250+
/// * `input_weight_prediction` - the predicted input weight.
251+
pub fn to_effective_value(
252+
&self,
253+
fee_rate: FeeRate,
254+
weight: Weight,
255+
) -> Option<SignedAmount> {
256+
let signed_input_fee = fee_rate.to_fee(weight)?.to_signed();
257+
self.to_signed().checked_sub(signed_input_fee)
258+
}
259+
237260
/// Converts this [`Amount`] in floating-point notation in the given [`Denomination`].
238261
///
239262
/// # Errors

0 commit comments

Comments
 (0)