Skip to content

Commit

Permalink
fee_rate: Add public absolute weight convenience functions
Browse files Browse the repository at this point in the history
Calculating the absolute fee from a fee rate can currently be achieved
by creating a `Weight` object and using
`FeeRate::checked_mul_by_weight`. This is kind of hard to discover, we
can add two public convenience functions that make discovery of the
functionality easier.

Add two functions for calculating the absolute fee by multiplying by
weight units (`Weight`) and virtual bytes (by first converting to weight
units).
  • Loading branch information
tcharding committed Aug 1, 2023
1 parent f00e93b commit 5a469be
Showing 1 changed file with 38 additions and 0 deletions.
38 changes: 38 additions & 0 deletions bitcoin/src/blockdata/fee_rate.rs
Expand Up @@ -87,6 +87,28 @@ impl FeeRate {
pub fn checked_mul_by_weight(self, rhs: Weight) -> Option<Amount> {
self.0.checked_mul(rhs.to_wu()).map(Amount::from_sat)
}

/// Calculates fee by multiplying this fee rate by weight, in weight units, returning `None`
/// if overflow occurred.
///
/// This is equivalent to `Self::checked_mul_by_weight()`.
///
/// # Examples
///
/// ```no_run
/// let rate = FeeRate::from_sat_per_vb(1);
/// let fee = rate.fee_wu(tx.weight());
/// ```
pub fn fee_wu(self, weight: Weight) -> Option<Amount> { self.checked_mul_by_weight(weight) }

/// Calculates fee by multiplying this fee rate by weight, in virtual bytes, returning `None`
/// if overflow occurred.
///
/// This is equivalent to converting `vb` to `weight` using `Weight::from_vb` and then calling
/// `Self::fee_wu(weight)`.
pub fn fee_vb(self, vb: u64) -> Option<Amount> {
Weight::from_vb(vb).and_then(|w| self.fee_wu(w))
}
}

/// Alternative will display the unit.
Expand Down Expand Up @@ -199,4 +221,20 @@ mod tests {
let fee_rate = FeeRate(10).checked_div(0);
assert!(fee_rate.is_none());
}

#[test]
fn fee_convenience_functions_agree() {
use crate::blockdata::transaction::Transaction;
use crate::consensus::Decodable;
use crate::internal_macros::hex;

const SOME_TX: &str = "0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000";

let raw_tx = hex!(SOME_TX);
let tx: Transaction = Decodable::consensus_decode(&mut raw_tx.as_slice()).unwrap();

let rate = FeeRate::from_sat_per_vb(1).expect("1 sat/byte is valid");

assert_eq!(rate.fee_vb(tx.vsize() as u64), rate.fee_wu(tx.weight()));
}
}

0 comments on commit 5a469be

Please sign in to comment.