Merge rust-bitcoin/rust-bitcoin#3587: Split checked_div_by_weight into floor and ceiling version
8b928a1515
Split checked_div_by_weight into floor and ceiling version (yancy) Pull request description: closes https://github.com/rust-bitcoin/rust-bitcoin/issues/3563 ACKs for top commit: tcharding: ACK8b928a1515
apoelstra: ACK 8b928a151515b00d44e0c13a866eda874c73dbf6; successfully ran local tests Tree-SHA512: 1f5a669b24dd5896cf5b13ecdb299fc1e4d449e379e5ae811a66a2efaf2565b7c7edc3e70275cde3b5e0aa5e29c1bbf180be6514a0de78ffd00ac929dbabbb87
This commit is contained in:
commit
7df5e7c1bc
|
@ -140,22 +140,43 @@ fn checked_arithmetic() {
|
|||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[test]
|
||||
fn amount_checked_div_by_weight() {
|
||||
fn amount_checked_div_by_weight_ceil() {
|
||||
let weight = Weight::from_kwu(1).unwrap();
|
||||
let fee_rate = Amount::from_sat(1).checked_div_by_weight(weight).unwrap();
|
||||
let fee_rate = Amount::from_sat(1).checked_div_by_weight_ceil(weight).unwrap();
|
||||
// 1 sats / 1,000 wu = 1 sats/kwu
|
||||
assert_eq!(fee_rate, FeeRate::from_sat_per_kwu(1));
|
||||
|
||||
let weight = Weight::from_wu(381);
|
||||
let fee_rate = Amount::from_sat(329).checked_div_by_weight(weight).unwrap();
|
||||
let fee_rate = Amount::from_sat(329).checked_div_by_weight_ceil(weight).unwrap();
|
||||
// 329 sats / 381 wu = 863.5 sats/kwu
|
||||
// round up to 864
|
||||
assert_eq!(fee_rate, FeeRate::from_sat_per_kwu(864));
|
||||
|
||||
let fee_rate = Amount::MAX.checked_div_by_weight(weight);
|
||||
let fee_rate = Amount::MAX.checked_div_by_weight_ceil(weight);
|
||||
assert!(fee_rate.is_none());
|
||||
|
||||
let fee_rate = Amount::ONE_SAT.checked_div_by_weight(Weight::ZERO);
|
||||
let fee_rate = Amount::ONE_SAT.checked_div_by_weight_ceil(Weight::ZERO);
|
||||
assert!(fee_rate.is_none());
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[test]
|
||||
fn amount_checked_div_by_weight_floor() {
|
||||
let weight = Weight::from_kwu(1).unwrap();
|
||||
let fee_rate = Amount::from_sat(1).checked_div_by_weight_floor(weight).unwrap();
|
||||
// 1 sats / 1,000 wu = 1 sats/kwu
|
||||
assert_eq!(fee_rate, FeeRate::from_sat_per_kwu(1));
|
||||
|
||||
let weight = Weight::from_wu(381);
|
||||
let fee_rate = Amount::from_sat(329).checked_div_by_weight_floor(weight).unwrap();
|
||||
// 329 sats / 381 wu = 863.5 sats/kwu
|
||||
// round down to 863
|
||||
assert_eq!(fee_rate, FeeRate::from_sat_per_kwu(863));
|
||||
|
||||
let fee_rate = Amount::MAX.checked_div_by_weight_floor(weight);
|
||||
assert!(fee_rate.is_none());
|
||||
|
||||
let fee_rate = Amount::ONE_SAT.checked_div_by_weight_floor(Weight::ZERO);
|
||||
assert!(fee_rate.is_none());
|
||||
}
|
||||
|
||||
|
|
|
@ -231,22 +231,34 @@ impl Amount {
|
|||
/// Returns [`None`] if overflow occurred.
|
||||
pub fn checked_div(self, rhs: u64) -> Option<Amount> { self.0.checked_div(rhs).map(Amount) }
|
||||
|
||||
/// Checked weight division.
|
||||
/// Checked weight ceiling division.
|
||||
///
|
||||
/// Be aware that integer division loses the remainder if no exact division
|
||||
/// can be made. This method rounds up ensuring the transaction fee-rate is
|
||||
/// sufficient. If you wish to round down use `amount / weight`.
|
||||
/// sufficient. See also [`Amount::checked_div_by_weight_floor`].
|
||||
///
|
||||
/// Returns [`None`] if overflow occurred.
|
||||
#[cfg(feature = "alloc")]
|
||||
pub fn checked_div_by_weight(self, rhs: Weight) -> Option<FeeRate> {
|
||||
let sats = self.0.checked_mul(1000)?;
|
||||
pub fn checked_div_by_weight_ceil(self, rhs: Weight) -> Option<FeeRate> {
|
||||
let sats = self.0.checked_mul(1_000)?;
|
||||
let wu = rhs.to_wu();
|
||||
|
||||
let fee_rate = sats.checked_add(wu.checked_sub(1)?)?.checked_div(wu)?;
|
||||
Some(FeeRate::from_sat_per_kwu(fee_rate))
|
||||
}
|
||||
|
||||
/// Checked weight floor division.
|
||||
///
|
||||
/// Be aware that integer division loses the remainder if no exact division
|
||||
/// can be made. See also [`Amount::checked_div_by_weight_ceil`].
|
||||
///
|
||||
/// Returns [`None`] if overflow occurred.
|
||||
#[cfg(feature = "alloc")]
|
||||
pub fn checked_div_by_weight_floor(self, rhs: Weight) -> Option<FeeRate> {
|
||||
let fee_rate = self.0.checked_mul(1_000)?.checked_div(rhs.to_wu())?;
|
||||
Some(FeeRate::from_sat_per_kwu(fee_rate))
|
||||
}
|
||||
|
||||
/// Checked remainder.
|
||||
///
|
||||
/// Returns [`None`] if overflow occurred.
|
||||
|
|
Loading…
Reference in New Issue