Merge rust-bitcoin/rust-bitcoin#1947: Add absolute fee rate convenience functions to `FeeRate`
9eff2f2f5e
fee_rate: Add public absolute weight convenience functions (Tobin C. Harding)f00e93bdcd
Fix typos in rustdoc (Tobin C. Harding)f3412325ea
weight: Make docs uniform and terse (Tobin C. Harding) Pull request description: - Patch 1 is docs cleanup - Patch 2 adds two functions to `FeeRate` From the commit log of patch 2: 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). This seems like an obvious thing so I'm inclined to think that Kixunil left it out for a reason. (Mentioning you here Kix so even if this merges you'll see it in notifications later on.) ACKs for top commit: sanket1729: utACK9eff2f2f5e
apoelstra: ACK9eff2f2f5e
Tree-SHA512: 5b3997b721b7d7225bcf0e8a4a3efb6f207393541dbbcef533135af06a4d9c95210d450bb2322fd65a727e4560b29f0b20fb96c154d019fd4e745506213abc1c
This commit is contained in:
commit
49fa879b19
|
@ -83,10 +83,36 @@ impl FeeRate {
|
||||||
/// Checked weight multiplication.
|
/// Checked weight multiplication.
|
||||||
///
|
///
|
||||||
/// Computes `self * rhs` where rhs is of type Weight. `None` is returned if an overflow
|
/// Computes `self * rhs` where rhs is of type Weight. `None` is returned if an overflow
|
||||||
/// occured.
|
/// occurred.
|
||||||
pub fn checked_mul_by_weight(self, rhs: Weight) -> Option<Amount> {
|
pub fn checked_mul_by_weight(self, rhs: Weight) -> Option<Amount> {
|
||||||
self.0.checked_mul(rhs.to_wu()).map(Amount::from_sat)
|
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
|
||||||
|
/// # use bitcoin::{absolute, FeeRate, Transaction};
|
||||||
|
/// # // Dummy transaction.
|
||||||
|
/// # let tx = Transaction { version: 1, lock_time: absolute::LockTime::ZERO, input: vec![], output: vec![] };
|
||||||
|
///
|
||||||
|
/// let rate = FeeRate::from_sat_per_vb(1).expect("1 sat/vbyte is valid");
|
||||||
|
/// 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.
|
/// Alternative will display the unit.
|
||||||
|
@ -199,4 +225,20 @@ mod tests {
|
||||||
let fee_rate = FeeRate(10).checked_div(0);
|
let fee_rate = FeeRate(10).checked_div(0);
|
||||||
assert!(fee_rate.is_none());
|
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()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,11 +43,7 @@ impl Weight {
|
||||||
/// Constructs `Weight` from kilo weight units returning `None` if overflow occurred.
|
/// Constructs `Weight` from kilo weight units returning `None` if overflow occurred.
|
||||||
pub fn from_kwu(wu: u64) -> Option<Self> { wu.checked_mul(1000).map(Weight) }
|
pub fn from_kwu(wu: u64) -> Option<Self> { wu.checked_mul(1000).map(Weight) }
|
||||||
|
|
||||||
/// Constructs `Weight` from virtual bytes.
|
/// Constructs `Weight` from virtual bytes, returning `None` on overflow.
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
///
|
|
||||||
/// Returns `None` on overflow.
|
|
||||||
pub fn from_vb(vb: u64) -> Option<Self> { vb.checked_mul(4).map(Weight::from_wu) }
|
pub fn from_vb(vb: u64) -> Option<Self> { vb.checked_mul(4).map(Weight::from_wu) }
|
||||||
|
|
||||||
/// Constructs `Weight` from virtual bytes without overflow check.
|
/// Constructs `Weight` from virtual bytes without overflow check.
|
||||||
|
|
Loading…
Reference in New Issue