From a8610a937bb5a2db129c779deacf3ade5bde12ab Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 12 Jun 2025 10:20:05 +1000 Subject: [PATCH] Inline checked mul / to fee back into fee_rate module A while back we move all the 'fee' stuff into a separate module because I thought it would help with clarity - I was wrong. Move the checked mul and to fee functions back into the `fee_rate` module on the main `FeeRate` impl block. Internal change only - code move. --- units/src/fee.rs | 58 --------------------------------------- units/src/fee_rate/mod.rs | 58 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 57 insertions(+), 59 deletions(-) diff --git a/units/src/fee.rs b/units/src/fee.rs index 1354fc848..144ad0fd8 100644 --- a/units/src/fee.rs +++ b/units/src/fee.rs @@ -17,64 +17,6 @@ use NumOpResult as R; use crate::{Amount, FeeRate, MathOp, NumOpError as E, NumOpResult, OptionExt, Weight}; -impl FeeRate { - /// Calculates the fee by multiplying this fee rate by weight. - /// - /// Computes the absolute fee amount for a given [`Weight`] at this fee rate. When the resulting - /// fee is a non-integer amount, the amount is rounded up, ensuring that the transaction fee is - /// enough instead of falling short if rounded down. - /// - /// If the calculation would overflow we saturate to [`Amount::MAX`]. Since such a fee can never - /// be paid this is meaningful as an error case while still removing the possibility of silently - /// wrapping. - pub const fn to_fee(self, weight: Weight) -> Amount { - // No `unwrap_or()` in const context. - match self.checked_mul_by_weight(weight) { - Some(fee) => fee, - None => Amount::MAX, - } - } - - /// Calculates the fee by multiplying this fee rate by weight, in weight units, returning [`None`] - /// if an overflow occurred. - /// - /// This is equivalent to `Self::checked_mul_by_weight()`. - #[must_use] - #[deprecated(since = "TBD", note = "use `to_fee()` instead")] - pub fn fee_wu(self, weight: Weight) -> Option { self.checked_mul_by_weight(weight) } - - /// Calculates the fee by multiplying this fee rate by weight, in virtual bytes, returning [`None`] - /// if an overflow occurred. - /// - /// This is equivalent to converting `vb` to [`Weight`] using [`Weight::from_vb`] and then calling - /// `Self::fee_wu(weight)`. - #[must_use] - #[deprecated(since = "TBD", note = "use Weight::from_vb and then `to_fee()` instead")] - pub fn fee_vb(self, vb: u64) -> Option { Weight::from_vb(vb).map(|w| self.to_fee(w)) } - - /// Checked weight multiplication. - /// - /// Computes the absolute fee amount for a given [`Weight`] at this fee rate. When the resulting - /// fee is a non-integer amount, the amount is rounded up, ensuring that the transaction fee is - /// enough instead of falling short if rounded down. - /// - /// Returns [`None`] if overflow occurred. - #[must_use] - pub const fn checked_mul_by_weight(self, weight: Weight) -> Option { - let wu = weight.to_wu(); - if let Some(fee_kwu) = self.to_sat_per_kwu_floor().checked_mul(wu) { - // Bump by 999 to do ceil division using kwu. - if let Some(bump) = fee_kwu.checked_add(999) { - let fee = bump / 1_000; - if let Ok(fee_amount) = Amount::from_sat(fee) { - return Some(fee_amount); - } - } - } - None - } -} - crate::internal_macros::impl_op_for_references! { impl ops::Mul for Weight { type Output = NumOpResult; diff --git a/units/src/fee_rate/mod.rs b/units/src/fee_rate/mod.rs index 75c516ea5..aec144041 100644 --- a/units/src/fee_rate/mod.rs +++ b/units/src/fee_rate/mod.rs @@ -13,7 +13,7 @@ use arbitrary::{Arbitrary, Unstructured}; use NumOpResult as R; -use crate::{Amount,MathOp, NumOpError as E, NumOpResult}; +use crate::{Amount, MathOp, NumOpError as E, NumOpResult, Weight}; mod encapsulate { /// Fee rate. @@ -184,6 +184,62 @@ impl FeeRate { None => None, } } + + /// Calculates the fee by multiplying this fee rate by weight. + /// + /// Computes the absolute fee amount for a given [`Weight`] at this fee rate. When the resulting + /// fee is a non-integer amount, the amount is rounded up, ensuring that the transaction fee is + /// enough instead of falling short if rounded down. + /// + /// If the calculation would overflow we saturate to [`Amount::MAX`]. Since such a fee can never + /// be paid this is meaningful as an error case while still removing the possibility of silently + /// wrapping. + pub const fn to_fee(self, weight: Weight) -> Amount { + // No `unwrap_or()` in const context. + match self.checked_mul_by_weight(weight) { + Some(fee) => fee, + None => Amount::MAX, + } + } + + /// Calculates the fee by multiplying this fee rate by weight, in weight units, returning [`None`] + /// if an overflow occurred. + /// + /// This is equivalent to `Self::checked_mul_by_weight()`. + #[must_use] + #[deprecated(since = "TBD", note = "use `to_fee()` instead")] + pub fn fee_wu(self, weight: Weight) -> Option { self.checked_mul_by_weight(weight) } + + /// Calculates the fee by multiplying this fee rate by weight, in virtual bytes, returning [`None`] + /// if an overflow occurred. + /// + /// This is equivalent to converting `vb` to [`Weight`] using [`Weight::from_vb`] and then calling + /// `Self::fee_wu(weight)`. + #[must_use] + #[deprecated(since = "TBD", note = "use Weight::from_vb and then `to_fee()` instead")] + pub fn fee_vb(self, vb: u64) -> Option { Weight::from_vb(vb).map(|w| self.to_fee(w)) } + + /// Checked weight multiplication. + /// + /// Computes the absolute fee amount for a given [`Weight`] at this fee rate. When the resulting + /// fee is a non-integer amount, the amount is rounded up, ensuring that the transaction fee is + /// enough instead of falling short if rounded down. + /// + /// Returns [`None`] if overflow occurred. + #[must_use] + pub const fn checked_mul_by_weight(self, weight: Weight) -> Option { + let wu = weight.to_wu(); + if let Some(fee_kwu) = self.to_sat_per_kwu_floor().checked_mul(wu) { + // Bump by 999 to do ceil division using kwu. + if let Some(bump) = fee_kwu.checked_add(999) { + let fee = bump / 1_000; + if let Ok(fee_amount) = Amount::from_sat(fee) { + return Some(fee_amount); + } + } + } + None + } } crate::internal_macros::impl_op_for_references! {