Skip to content

Commit

Permalink
Add fee calculation function
Browse files Browse the repository at this point in the history
Pull out fee calculation from effective_value and make it available
as a stand-alone function.
  • Loading branch information
yancyribbens committed Jan 30, 2024
1 parent c4f286b commit 346992b
Showing 1 changed file with 31 additions and 2 deletions.
33 changes: 31 additions & 2 deletions bitcoin/src/blockdata/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1280,6 +1280,19 @@ impl From<&Transaction> for Wtxid {
fn from(tx: &Transaction) -> Wtxid { tx.compute_wtxid() }
}

/// Computes the fee to spend an output.
///
/// The fee is calculated as: fee_rate * weight.
///
/// # Arguments
///
/// * `fee_rate` - the fee rate of the transaction being created.
/// * `weight` - weight of output.
fn calculate_fee(fee_rate: FeeRate, weight: Weight) -> Option<Amount> {
let weight = weight.checked_add(TxIn::BASE_WEIGHT)?;
fee_rate.checked_mul_by_weight(weight)
}

/// Computes the value of an output accounting for the cost of spending it.
///
/// The effective value is the value of an output value minus the amount to spend it. That is, the
Expand All @@ -1298,8 +1311,7 @@ pub fn effective_value(
satisfaction_weight: Weight,
value: Amount,
) -> Option<SignedAmount> {
let weight = satisfaction_weight.checked_add(TxIn::BASE_WEIGHT)?;
let signed_input_fee = fee_rate.checked_mul_by_weight(weight)?.to_signed().ok()?;
let signed_input_fee = calculate_fee(fee_rate, satisfaction_weight)?.to_signed().ok()?;
value.to_signed().ok()?.checked_sub(signed_input_fee)
}

Expand Down Expand Up @@ -2135,6 +2147,23 @@ mod tests {
assert!(result.is_err());
}

#[test]
fn calculate_fee_happy_path() {
let fee_rate = FeeRate::from_sat_per_kwu(10);
let weight = Weight::from_wu(220);

// 10 sat/kwu * (204wu + BASE_WEIGHT) = 4 sats
let fee = calculate_fee(fee_rate, weight).unwrap();
let expected_fee = Amount::from_str("4 sats").unwrap();
assert_eq!(fee, expected_fee);
}

#[test]
fn calculate_fee_does_not_overflow() {
let fee = calculate_fee(FeeRate::MAX, Weight::MAX);
assert!(fee.is_none());
}

#[test]
fn effective_value_happy_path() {
let value = Amount::from_str("1 cBTC").unwrap();
Expand Down

0 comments on commit 346992b

Please sign in to comment.