Add floor/ceil versions of to_sat_per_kwu
In preparation for changing the inner representation of `FeeRate` add floor and ceil versions of the getter function `to_sat_per_kwu`. For now both functions return the same thing but still call the correct one so that when we change the representation we do not need to re-visit them.
This commit is contained in:
parent
64098e4578
commit
b929022d56
|
@ -290,7 +290,7 @@ crate::internal_macros::define_extension_trait! {
|
|||
///
|
||||
/// [`minimal_non_dust`]: Script::minimal_non_dust
|
||||
fn minimal_non_dust_custom(&self, dust_relay_fee: FeeRate) -> Option<Amount> {
|
||||
self.minimal_non_dust_internal(dust_relay_fee.to_sat_per_kwu() * 4)
|
||||
self.minimal_non_dust_internal(dust_relay_fee.to_sat_per_kwu_ceil() * 4)
|
||||
}
|
||||
|
||||
/// Counts the sigops for this Script using accurate counting.
|
||||
|
|
|
@ -1178,8 +1178,11 @@ impl fmt::Display for ExtractTxError {
|
|||
use ExtractTxError::*;
|
||||
|
||||
match *self {
|
||||
AbsurdFeeRate { fee_rate, .. } =>
|
||||
write!(f, "an absurdly high fee rate of {} sat/kwu", fee_rate.to_sat_per_kwu()),
|
||||
AbsurdFeeRate { fee_rate, .. } => write!(
|
||||
f,
|
||||
"an absurdly high fee rate of {} sat/kwu",
|
||||
fee_rate.to_sat_per_kwu_floor()
|
||||
),
|
||||
MissingInputValue { .. } => write!(
|
||||
f,
|
||||
"one of the inputs lacked value information (witness_utxo or non_witness_utxo)"
|
||||
|
|
|
@ -80,7 +80,7 @@ impl Amount {
|
|||
#[must_use]
|
||||
pub const fn checked_div_by_fee_rate_floor(self, fee_rate: FeeRate) -> Option<Weight> {
|
||||
match self.to_sat().checked_mul(1000) {
|
||||
Some(amount_msats) => match amount_msats.checked_div(fee_rate.to_sat_per_kwu()) {
|
||||
Some(amount_msats) => match amount_msats.checked_div(fee_rate.to_sat_per_kwu_ceil()) {
|
||||
Some(wu) => Some(Weight::from_wu(wu)),
|
||||
None => None,
|
||||
},
|
||||
|
@ -96,7 +96,8 @@ impl Amount {
|
|||
/// Returns [`None`] if overflow occurred or if `fee_rate` is zero.
|
||||
#[must_use]
|
||||
pub const fn checked_div_by_fee_rate_ceil(self, fee_rate: FeeRate) -> Option<Weight> {
|
||||
let rate = fee_rate.to_sat_per_kwu();
|
||||
// Use ceil because result is used as the divisor.
|
||||
let rate = fee_rate.to_sat_per_kwu_ceil();
|
||||
match self.to_sat().checked_mul(1000) {
|
||||
Some(amount_msats) => match rate.checked_sub(1) {
|
||||
Some(rate_minus_one) => match amount_msats.checked_add(rate_minus_one) {
|
||||
|
@ -151,7 +152,7 @@ impl FeeRate {
|
|||
///
|
||||
/// Returns [`NumOpResult::Error`] if overflow occurred.
|
||||
pub const fn checked_mul_by_weight(self, weight: Weight) -> NumOpResult<Amount> {
|
||||
if let Some(fee) = self.to_sat_per_kwu().checked_mul(weight.to_wu()) {
|
||||
if let Some(fee) = self.to_sat_per_kwu_floor().checked_mul(weight.to_wu()) {
|
||||
if let Some(round_up) = fee.checked_add(999) {
|
||||
if let Ok(ret) = Amount::from_sat(round_up / 1_000) {
|
||||
return NumOpResult::Valid(ret);
|
||||
|
|
|
@ -64,15 +64,18 @@ impl FeeRate {
|
|||
/// Constructs a new [`FeeRate`] from satoshis per kilo virtual bytes (1,000 vbytes).
|
||||
pub const fn from_sat_per_kvb(sat_kvb: u64) -> Self { FeeRate::from_sat_per_kwu(sat_kvb / 4) }
|
||||
|
||||
/// Returns raw fee rate.
|
||||
pub const fn to_sat_per_kwu(self) -> u64 { self.0 }
|
||||
/// Converts to sat/kwu rounding down.
|
||||
pub const fn to_sat_per_kwu_floor(self) -> u64 { self.0 }
|
||||
|
||||
/// Converts to sat/kwu rounding up.
|
||||
pub const fn to_sat_per_kwu_ceil(self) -> u64 { self.0 }
|
||||
|
||||
/// Converts to sat/vB rounding down.
|
||||
pub const fn to_sat_per_vb_floor(self) -> u64 { self.to_sat_per_kwu() / (1000 / 4) }
|
||||
pub const fn to_sat_per_vb_floor(self) -> u64 { self.to_sat_per_kwu_floor() / (1000 / 4) }
|
||||
|
||||
/// Converts to sat/vB rounding up.
|
||||
pub const fn to_sat_per_vb_ceil(self) -> u64 {
|
||||
(self.to_sat_per_kwu() + (1000 / 4 - 1)) / (1000 / 4)
|
||||
(self.to_sat_per_kwu_floor() + (1000 / 4 - 1)) / (1000 / 4)
|
||||
}
|
||||
|
||||
/// Checked multiplication.
|
||||
|
@ -81,7 +84,7 @@ impl FeeRate {
|
|||
#[must_use]
|
||||
pub const fn checked_mul(self, rhs: u64) -> Option<Self> {
|
||||
// No `map()` in const context.
|
||||
match self.to_sat_per_kwu().checked_mul(rhs) {
|
||||
match self.to_sat_per_kwu_floor().checked_mul(rhs) {
|
||||
Some(res) => Some(Self::from_sat_per_kwu(res)),
|
||||
None => None,
|
||||
}
|
||||
|
@ -93,7 +96,7 @@ impl FeeRate {
|
|||
#[must_use]
|
||||
pub const fn checked_div(self, rhs: u64) -> Option<Self> {
|
||||
// No `map()` in const context.
|
||||
match self.to_sat_per_kwu().checked_div(rhs) {
|
||||
match self.to_sat_per_kwu_floor().checked_div(rhs) {
|
||||
Some(res) => Some(Self::from_sat_per_kwu(res)),
|
||||
None => None,
|
||||
}
|
||||
|
@ -105,7 +108,7 @@ impl FeeRate {
|
|||
#[must_use]
|
||||
pub const fn checked_add(self, rhs: FeeRate) -> Option<Self> {
|
||||
// No `map()` in const context.
|
||||
match self.to_sat_per_kwu().checked_add(rhs.to_sat_per_kwu()) {
|
||||
match self.to_sat_per_kwu_floor().checked_add(rhs.to_sat_per_kwu_floor()) {
|
||||
Some(res) => Some(Self::from_sat_per_kwu(res)),
|
||||
None => None,
|
||||
}
|
||||
|
@ -117,7 +120,7 @@ impl FeeRate {
|
|||
#[must_use]
|
||||
pub const fn checked_sub(self, rhs: FeeRate) -> Option<Self> {
|
||||
// No `map()` in const context.
|
||||
match self.to_sat_per_kwu().checked_sub(rhs.to_sat_per_kwu()) {
|
||||
match self.to_sat_per_kwu_floor().checked_sub(rhs.to_sat_per_kwu_floor()) {
|
||||
Some(res) => Some(Self::from_sat_per_kwu(res)),
|
||||
None => None,
|
||||
}
|
||||
|
@ -128,19 +131,19 @@ crate::internal_macros::impl_op_for_references! {
|
|||
impl ops::Add<FeeRate> for FeeRate {
|
||||
type Output = FeeRate;
|
||||
|
||||
fn add(self, rhs: FeeRate) -> Self::Output { FeeRate::from_sat_per_kwu(self.to_sat_per_kwu() + rhs.to_sat_per_kwu()) }
|
||||
fn add(self, rhs: FeeRate) -> Self::Output { FeeRate::from_sat_per_kwu(self.to_sat_per_kwu_floor() + rhs.to_sat_per_kwu_floor()) }
|
||||
}
|
||||
|
||||
impl ops::Sub<FeeRate> for FeeRate {
|
||||
type Output = FeeRate;
|
||||
|
||||
fn sub(self, rhs: FeeRate) -> Self::Output { FeeRate::from_sat_per_kwu(self.to_sat_per_kwu() - rhs.to_sat_per_kwu()) }
|
||||
fn sub(self, rhs: FeeRate) -> Self::Output { FeeRate::from_sat_per_kwu(self.to_sat_per_kwu_floor() - rhs.to_sat_per_kwu_floor()) }
|
||||
}
|
||||
|
||||
impl ops::Div<NonZeroU64> for FeeRate {
|
||||
type Output = FeeRate;
|
||||
|
||||
fn div(self, rhs: NonZeroU64) -> Self::Output{ Self::from_sat_per_kwu(self.to_sat_per_kwu() / rhs.get()) }
|
||||
fn div(self, rhs: NonZeroU64) -> Self::Output{ Self::from_sat_per_kwu(self.to_sat_per_kwu_floor() / rhs.get()) }
|
||||
}
|
||||
}
|
||||
crate::internal_macros::impl_add_assign!(FeeRate);
|
||||
|
@ -151,7 +154,7 @@ impl core::iter::Sum for FeeRate {
|
|||
where
|
||||
I: Iterator<Item = Self>,
|
||||
{
|
||||
FeeRate::from_sat_per_kwu(iter.map(FeeRate::to_sat_per_kwu).sum())
|
||||
FeeRate::from_sat_per_kwu(iter.map(FeeRate::to_sat_per_kwu_floor).sum())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,7 +163,7 @@ impl<'a> core::iter::Sum<&'a FeeRate> for FeeRate {
|
|||
where
|
||||
I: Iterator<Item = &'a FeeRate>,
|
||||
{
|
||||
FeeRate::from_sat_per_kwu(iter.map(|f| FeeRate::to_sat_per_kwu(*f)).sum())
|
||||
FeeRate::from_sat_per_kwu(iter.map(|f| FeeRate::to_sat_per_kwu_floor(*f)).sum())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -266,11 +269,11 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn fee_rate_const() {
|
||||
assert_eq!(FeeRate::ZERO.to_sat_per_kwu(), 0);
|
||||
assert_eq!(FeeRate::MIN.to_sat_per_kwu(), u64::MIN);
|
||||
assert_eq!(FeeRate::MAX.to_sat_per_kwu(), u64::MAX);
|
||||
assert_eq!(FeeRate::BROADCAST_MIN.to_sat_per_kwu(), 250);
|
||||
assert_eq!(FeeRate::DUST.to_sat_per_kwu(), 750);
|
||||
assert_eq!(FeeRate::ZERO.to_sat_per_kwu_floor(), 0);
|
||||
assert_eq!(FeeRate::MIN.to_sat_per_kwu_floor(), u64::MIN);
|
||||
assert_eq!(FeeRate::MAX.to_sat_per_kwu_floor(), u64::MAX);
|
||||
assert_eq!(FeeRate::BROADCAST_MIN.to_sat_per_kwu_floor(), 250);
|
||||
assert_eq!(FeeRate::DUST.to_sat_per_kwu_floor(), 750);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -304,7 +307,7 @@ mod tests {
|
|||
#[test]
|
||||
fn raw_feerate() {
|
||||
let fee_rate = FeeRate::from_sat_per_kwu(749);
|
||||
assert_eq!(fee_rate.to_sat_per_kwu(), 749);
|
||||
assert_eq!(fee_rate.to_sat_per_kwu_floor(), 749);
|
||||
assert_eq!(fee_rate.to_sat_per_vb_floor(), 2);
|
||||
assert_eq!(fee_rate.to_sat_per_vb_ceil(), 3);
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ pub mod as_sat_per_kwu {
|
|||
use crate::FeeRate;
|
||||
|
||||
pub fn serialize<S: Serializer>(f: &FeeRate, s: S) -> Result<S::Ok, S::Error> {
|
||||
u64::serialize(&f.to_sat_per_kwu(), s)
|
||||
u64::serialize(&f.to_sat_per_kwu_floor(), s)
|
||||
}
|
||||
|
||||
pub fn deserialize<'d, D: Deserializer<'d>>(d: D) -> Result<FeeRate, D::Error> {
|
||||
|
@ -57,7 +57,7 @@ pub mod as_sat_per_kwu {
|
|||
#[allow(clippy::ref_option)] // API forced by serde.
|
||||
pub fn serialize<S: Serializer>(f: &Option<FeeRate>, s: S) -> Result<S::Ok, S::Error> {
|
||||
match *f {
|
||||
Some(f) => s.serialize_some(&f.to_sat_per_kwu()),
|
||||
Some(f) => s.serialize_some(&f.to_sat_per_kwu_floor()),
|
||||
None => s.serialize_none(),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue