Merge rust-bitcoin/rust-bitcoin#4319: units: Implement privacy boundaries

6323867c65 Run the formatter (Tobin C. Harding)
d5c08aef32 units: Update column width (Tobin C. Harding)
f7f1a0be8c Add privacy boundary to BlockTime (Tobin C. Harding)
b3dfe0df3f Add privacy boundary to Weight (Tobin C. Harding)
e1a14b3c2d Add privacy boundary to FeeRate (Tobin C. Harding)
4b733d4dad Run the formatter (Tobin C. Harding)

Pull request description:

  Add privacy boundary for `FeeRate`, `BlockTime`, and `Weight`. The lock times are a bit curly so just doing these ones for now.

ACKs for top commit:
  apoelstra:
    ACK 6323867c65cdbf0f1b25d252fded6873acd35a3a; successfully ran local tests

Tree-SHA512: b6cf5eb032e055414f48f3469ec1748635b9f53ca64c158bd861d1ae6e2cfbe7b4d82de98f7dc90913d98429e6ae6991a4a61b6c438574fcbef9b3bc7ebafb4b
This commit is contained in:
merge-script 2025-04-17 22:07:20 +00:00
commit 6241b34afc
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
6 changed files with 217 additions and 195 deletions

View File

@ -604,9 +604,7 @@ impl<T> CheckedSum<Amount> for T
where
T: Iterator<Item = Amount>,
{
fn checked_sum(mut self) -> Option<Amount> {
self.try_fold(Amount::ZERO, Amount::checked_add)
}
fn checked_sum(mut self) -> Option<Amount> { self.try_fold(Amount::ZERO, Amount::checked_add) }
}
impl<T> CheckedSum<SignedAmount> for T

View File

@ -13,10 +13,10 @@
use core::ops;
use crate::{Amount, FeeRate, MathOp, NumOpResult, OptionExt, Weight};
use NumOpResult as R;
use crate::{Amount, FeeRate, MathOp, NumOpResult, OptionExt, Weight};
impl Amount {
/// Checked weight ceiling division.
///

View File

@ -10,18 +10,32 @@ use core::{fmt, ops};
#[cfg(feature = "arbitrary")]
use arbitrary::{Arbitrary, Unstructured};
mod encapsulate {
/// Fee rate.
///
/// This is an integer newtype representing fee rate in `sat/kwu`. It provides protection against
/// mixing up the types as well as basic formatting features.
/// This is an integer newtype representing fee rate in `sat/kwu`. It provides protection
/// against mixing up the types as well as basic formatting features.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct FeeRate(u64);
impl FeeRate {
/// Constructs a new [`FeeRate`] from satoshis per 1000 weight units.
pub const fn from_sat_per_kwu(sat_kwu: u64) -> Self { FeeRate(sat_kwu) }
/// Returns raw fee rate.
///
/// Can be used instead of `into()` to avoid inference issues.
pub const fn to_sat_per_kwu(self) -> u64 { self.0 }
}
}
#[doc(inline)]
pub use encapsulate::FeeRate;
impl FeeRate {
/// 0 sat/kwu.
///
/// Equivalent to [`MIN`](Self::MIN), may better express intent in some contexts.
pub const ZERO: FeeRate = FeeRate(0);
pub const ZERO: FeeRate = FeeRate::from_sat_per_kwu(0);
/// Minimum possible value (0 sat/kwu).
///
@ -29,7 +43,7 @@ impl FeeRate {
pub const MIN: FeeRate = FeeRate::ZERO;
/// Maximum possible value.
pub const MAX: FeeRate = FeeRate(u64::MAX);
pub const MAX: FeeRate = FeeRate::from_sat_per_kwu(u64::MAX);
/// Minimum fee rate required to broadcast a transaction.
///
@ -39,9 +53,6 @@ impl FeeRate {
/// Fee rate used to compute dust amount.
pub const DUST: FeeRate = FeeRate::from_sat_per_vb_unchecked(3);
/// Constructs a new [`FeeRate`] from satoshis per 1000 weight units.
pub const fn from_sat_per_kwu(sat_kwu: u64) -> Self { FeeRate(sat_kwu) }
/// Constructs a new [`FeeRate`] from satoshis per virtual bytes.
///
/// # Errors
@ -51,25 +62,24 @@ impl FeeRate {
// 1 vb == 4 wu
// 1 sat/vb == 1/4 sat/wu
// sat_vb sat/vb * 1000 / 4 == sat/kwu
Some(FeeRate(sat_vb.checked_mul(1000 / 4)?))
Some(FeeRate::from_sat_per_kwu(sat_vb.checked_mul(1000 / 4)?))
}
/// Constructs a new [`FeeRate`] from satoshis per virtual bytes without overflow check.
pub const fn from_sat_per_vb_unchecked(sat_vb: u64) -> Self { FeeRate(sat_vb * (1000 / 4)) }
pub const fn from_sat_per_vb_unchecked(sat_vb: u64) -> Self {
FeeRate::from_sat_per_kwu(sat_vb * (1000 / 4))
}
/// 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(sat_kvb / 4) }
/// Returns raw fee rate.
///
/// Can be used instead of `into()` to avoid inference issues.
pub const fn to_sat_per_kwu(self) -> u64 { self.0 }
pub const fn from_sat_per_kvb(sat_kvb: u64) -> Self { FeeRate::from_sat_per_kwu(sat_kvb / 4) }
/// Converts to sat/vB rounding down.
pub const fn to_sat_per_vb_floor(self) -> u64 { self.0 / (1000 / 4) }
pub const fn to_sat_per_vb_floor(self) -> u64 { self.to_sat_per_kwu() / (1000 / 4) }
/// Converts to sat/vB rounding up.
pub const fn to_sat_per_vb_ceil(self) -> u64 { (self.0 + (1000 / 4 - 1)) / (1000 / 4) }
pub const fn to_sat_per_vb_ceil(self) -> u64 {
(self.to_sat_per_kwu() + (1000 / 4 - 1)) / (1000 / 4)
}
/// Checked multiplication.
///
@ -77,8 +87,8 @@ impl FeeRate {
#[must_use]
pub const fn checked_mul(self, rhs: u64) -> Option<Self> {
// No `map()` in const context.
match self.0.checked_mul(rhs) {
Some(res) => Some(Self(res)),
match self.to_sat_per_kwu().checked_mul(rhs) {
Some(res) => Some(Self::from_sat_per_kwu(res)),
None => None,
}
}
@ -89,8 +99,8 @@ impl FeeRate {
#[must_use]
pub const fn checked_div(self, rhs: u64) -> Option<Self> {
// No `map()` in const context.
match self.0.checked_div(rhs) {
Some(res) => Some(Self(res)),
match self.to_sat_per_kwu().checked_div(rhs) {
Some(res) => Some(Self::from_sat_per_kwu(res)),
None => None,
}
}
@ -101,8 +111,8 @@ impl FeeRate {
#[must_use]
pub const fn checked_add(self, rhs: u64) -> Option<Self> {
// No `map()` in const context.
match self.0.checked_add(rhs) {
Some(res) => Some(Self(res)),
match self.to_sat_per_kwu().checked_add(rhs) {
Some(res) => Some(Self::from_sat_per_kwu(res)),
None => None,
}
}
@ -113,8 +123,8 @@ impl FeeRate {
#[must_use]
pub const fn checked_sub(self, rhs: u64) -> Option<Self> {
// No `map()` in const context.
match self.0.checked_sub(rhs) {
Some(res) => Some(Self(res)),
match self.to_sat_per_kwu().checked_sub(rhs) {
Some(res) => Some(Self::from_sat_per_kwu(res)),
None => None,
}
}
@ -126,7 +136,7 @@ impl fmt::Display for FeeRate {
if f.alternate() {
write!(f, "{}.00 sat/vbyte", self.to_sat_per_vb_ceil())
} else {
fmt::Display::fmt(&self.0, f)
fmt::Display::fmt(&self.to_sat_per_kwu(), f)
}
}
}
@ -139,13 +149,13 @@ crate::internal_macros::impl_op_for_references! {
impl ops::Add<FeeRate> for FeeRate {
type Output = FeeRate;
fn add(self, rhs: FeeRate) -> Self::Output { FeeRate(self.0 + rhs.0) }
fn add(self, rhs: FeeRate) -> Self::Output { FeeRate::from_sat_per_kwu(self.to_sat_per_kwu() + rhs.to_sat_per_kwu()) }
}
impl ops::Sub<FeeRate> for FeeRate {
type Output = FeeRate;
fn sub(self, rhs: FeeRate) -> Self::Output { FeeRate(self.0 - rhs.0) }
fn sub(self, rhs: FeeRate) -> Self::Output { FeeRate::from_sat_per_kwu(self.to_sat_per_kwu() - rhs.to_sat_per_kwu()) }
}
}
crate::internal_macros::impl_add_assign!(FeeRate);
@ -180,7 +190,7 @@ impl<'a> Arbitrary<'a> for FeeRate {
1 => Ok(FeeRate::BROADCAST_MIN),
2 => Ok(FeeRate::DUST),
3 => Ok(FeeRate::MAX),
_ => Ok(FeeRate(u64::arbitrary(u)?)),
_ => Ok(FeeRate::from_sat_per_kwu(u64::arbitrary(u)?)),
}
}
}
@ -191,16 +201,16 @@ mod tests {
#[test]
fn sanity_check() {
let fee_rate: u64 = u64::from(FeeRate(100));
let fee_rate: u64 = u64::from(FeeRate::from_sat_per_kwu(100));
assert_eq!(fee_rate, 100_u64);
}
#[test]
#[allow(clippy::op_ref)]
fn addition() {
let one = FeeRate(1);
let two = FeeRate(2);
let three = FeeRate(3);
let one = FeeRate::from_sat_per_kwu(1);
let two = FeeRate::from_sat_per_kwu(2);
let three = FeeRate::from_sat_per_kwu(3);
assert!(one + two == three);
assert!(&one + two == three);
@ -211,9 +221,9 @@ mod tests {
#[test]
#[allow(clippy::op_ref)]
fn subtract() {
let three = FeeRate(3);
let seven = FeeRate(7);
let ten = FeeRate(10);
let three = FeeRate::from_sat_per_kwu(3);
let seven = FeeRate::from_sat_per_kwu(7);
let ten = FeeRate::from_sat_per_kwu(10);
assert_eq!(ten - seven, three);
assert_eq!(&ten - seven, three);
@ -223,39 +233,39 @@ mod tests {
#[test]
fn add_assign() {
let mut f = FeeRate(1);
f += FeeRate(2);
assert_eq!(f, FeeRate(3));
let mut f = FeeRate::from_sat_per_kwu(1);
f += FeeRate::from_sat_per_kwu(2);
assert_eq!(f, FeeRate::from_sat_per_kwu(3));
let mut f = FeeRate(1);
f += &FeeRate(2);
assert_eq!(f, FeeRate(3));
let mut f = FeeRate::from_sat_per_kwu(1);
f += &FeeRate::from_sat_per_kwu(2);
assert_eq!(f, FeeRate::from_sat_per_kwu(3));
}
#[test]
fn sub_assign() {
let mut f = FeeRate(3);
f -= FeeRate(2);
assert_eq!(f, FeeRate(1));
let mut f = FeeRate::from_sat_per_kwu(3);
f -= FeeRate::from_sat_per_kwu(2);
assert_eq!(f, FeeRate::from_sat_per_kwu(1));
let mut f = FeeRate(3);
f -= &FeeRate(2);
assert_eq!(f, FeeRate(1));
let mut f = FeeRate::from_sat_per_kwu(3);
f -= &FeeRate::from_sat_per_kwu(2);
assert_eq!(f, FeeRate::from_sat_per_kwu(1));
}
#[test]
fn checked_add() {
let f = FeeRate(1).checked_add(2).unwrap();
assert_eq!(FeeRate(3), f);
let f = FeeRate::from_sat_per_kwu(1).checked_add(2).unwrap();
assert_eq!(FeeRate::from_sat_per_kwu(3), f);
let f = FeeRate(u64::MAX).checked_add(1);
let f = FeeRate::from_sat_per_kwu(u64::MAX).checked_add(1);
assert!(f.is_none());
}
#[test]
fn checked_sub() {
let f = FeeRate(2).checked_sub(1).unwrap();
assert_eq!(FeeRate(1), f);
let f = FeeRate::from_sat_per_kwu(2).checked_sub(1).unwrap();
assert_eq!(FeeRate::from_sat_per_kwu(1), f);
let f = FeeRate::ZERO.checked_sub(1);
assert!(f.is_none());
@ -273,13 +283,13 @@ mod tests {
#[test]
fn fee_rate_from_sat_per_vb() {
let fee_rate = FeeRate::from_sat_per_vb(10).expect("expected feerate in sat/kwu");
assert_eq!(FeeRate(2500), fee_rate);
assert_eq!(FeeRate::from_sat_per_kwu(2500), fee_rate);
}
#[test]
fn fee_rate_from_sat_per_kvb() {
let fee_rate = FeeRate::from_sat_per_kvb(11);
assert_eq!(FeeRate(2), fee_rate);
assert_eq!(FeeRate::from_sat_per_kwu(2), fee_rate);
}
#[test]
@ -291,7 +301,7 @@ mod tests {
#[test]
fn from_sat_per_vb_unchecked() {
let fee_rate = FeeRate::from_sat_per_vb_unchecked(10);
assert_eq!(FeeRate(2500), fee_rate);
assert_eq!(FeeRate::from_sat_per_kwu(2500), fee_rate);
}
#[test]
@ -301,7 +311,7 @@ mod tests {
#[test]
fn raw_feerate() {
let fee_rate = FeeRate(749);
let fee_rate = FeeRate::from_sat_per_kwu(749);
assert_eq!(749, fee_rate.to_sat_per_kwu());
assert_eq!(2, fee_rate.to_sat_per_vb_floor());
assert_eq!(3, fee_rate.to_sat_per_vb_ceil());
@ -309,19 +319,21 @@ mod tests {
#[test]
fn checked_mul() {
let fee_rate = FeeRate(10).checked_mul(10).expect("expected feerate in sat/kwu");
assert_eq!(FeeRate(100), fee_rate);
let fee_rate =
FeeRate::from_sat_per_kwu(10).checked_mul(10).expect("expected feerate in sat/kwu");
assert_eq!(FeeRate::from_sat_per_kwu(100), fee_rate);
let fee_rate = FeeRate(10).checked_mul(u64::MAX);
let fee_rate = FeeRate::from_sat_per_kwu(10).checked_mul(u64::MAX);
assert!(fee_rate.is_none());
}
#[test]
fn checked_div() {
let fee_rate = FeeRate(10).checked_div(10).expect("expected feerate in sat/kwu");
assert_eq!(FeeRate(1), fee_rate);
let fee_rate =
FeeRate::from_sat_per_kwu(10).checked_div(10).expect("expected feerate in sat/kwu");
assert_eq!(FeeRate::from_sat_per_kwu(1), fee_rate);
let fee_rate = FeeRate(10).checked_div(0);
let fee_rate = FeeRate::from_sat_per_kwu(10).checked_div(0);
assert!(fee_rate.is_none());
}
}

View File

@ -9,6 +9,8 @@
#[cfg(feature = "arbitrary")]
use arbitrary::{Arbitrary, Unstructured};
mod encapsulate {
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
@ -37,6 +39,9 @@ impl BlockTime {
#[inline]
pub const fn to_u32(self) -> u32 { self.0 }
}
}
#[doc(inline)]
pub use encapsulate::BlockTime;
impl From<u32> for BlockTime {
#[inline]

View File

@ -6,46 +6,58 @@ use core::{fmt, ops};
#[cfg(feature = "arbitrary")]
use arbitrary::{Arbitrary, Unstructured};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
/// The factor that non-witness serialization data is multiplied by during weight calculation.
pub const WITNESS_SCALE_FACTOR: usize = 4;
mod encapsulate {
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
/// The weight of a transaction or block.
///
/// This is an integer newtype representing [`Weight`] in `wu`. It provides protection against mixing
/// up types as well as basic formatting features.
/// This is an integer newtype representing [`Weight`] in `wu`. It provides protection
/// against mixing up types as well as basic formatting features.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
pub struct Weight(u64);
impl Weight {
/// Constructs a new [`Weight`] from weight units.
pub const fn from_wu(wu: u64) -> Self { Weight(wu) }
/// Returns raw weight units.
///
/// Can be used instead of `into()` to avoid inference issues.
pub const fn to_wu(self) -> u64 { self.0 }
}
}
#[doc(inline)]
pub use encapsulate::Weight;
impl Weight {
/// 0 wu.
///
/// Equivalent to [`MIN`](Self::MIN), may better express intent in some contexts.
pub const ZERO: Weight = Weight(0);
pub const ZERO: Weight = Weight::from_wu(0);
/// Minimum possible value (0 wu).
///
/// Equivalent to [`ZERO`](Self::ZERO), may better express intent in some contexts.
pub const MIN: Weight = Weight(u64::MIN);
pub const MIN: Weight = Weight::from_wu(u64::MIN);
/// Maximum possible value.
pub const MAX: Weight = Weight(u64::MAX);
pub const MAX: Weight = Weight::from_wu(u64::MAX);
/// The factor that non-witness serialization data is multiplied by during weight calculation.
pub const WITNESS_SCALE_FACTOR: u64 = WITNESS_SCALE_FACTOR as u64;
/// The maximum allowed weight for a block, see BIP 141 (network rule).
pub const MAX_BLOCK: Weight = Weight(4_000_000);
pub const MAX_BLOCK: Weight = Weight::from_wu(4_000_000);
/// The minimum transaction weight for a valid serialized transaction.
pub const MIN_TRANSACTION: Weight = Weight(Self::WITNESS_SCALE_FACTOR * 60);
/// Constructs a new [`Weight`] from weight units.
pub const fn from_wu(wu: u64) -> Self { Weight(wu) }
pub const MIN_TRANSACTION: Weight = Weight::from_wu(Self::WITNESS_SCALE_FACTOR * 60);
/// Constructs a new [`Weight`] from kilo weight units returning [`None`] if an overflow occurred.
pub const fn from_kwu(wu: u64) -> Option<Self> {
@ -73,7 +85,7 @@ impl Weight {
#[deprecated(since = "TBD", note = "use `from_vb_unchecked` instead")]
pub const fn from_vb_unwrap(vb: u64) -> Weight {
match vb.checked_mul(Self::WITNESS_SCALE_FACTOR) {
Some(weight) => Weight(weight),
Some(weight) => Weight::from_wu(weight),
None => panic!("checked_mul overflowed"),
}
}
@ -82,30 +94,25 @@ impl Weight {
pub const fn from_vb_unchecked(vb: u64) -> Self { Weight::from_wu(vb * 4) }
/// Constructs a new [`Weight`] from witness size.
pub const fn from_witness_data_size(witness_size: u64) -> Self { Weight(witness_size) }
pub const fn from_witness_data_size(witness_size: u64) -> Self { Weight::from_wu(witness_size) }
/// Constructs a new [`Weight`] from non-witness size.
pub const fn from_non_witness_data_size(non_witness_size: u64) -> Self {
Weight(non_witness_size * Self::WITNESS_SCALE_FACTOR)
Weight::from_wu(non_witness_size * Self::WITNESS_SCALE_FACTOR)
}
/// Returns raw weight units.
///
/// Can be used instead of `into()` to avoid inference issues.
pub const fn to_wu(self) -> u64 { self.0 }
/// Converts to kilo weight units rounding down.
pub const fn to_kwu_floor(self) -> u64 { self.0 / 1000 }
pub const fn to_kwu_floor(self) -> u64 { self.to_wu() / 1000 }
/// Converts to kilo weight units rounding up.
pub const fn to_kwu_ceil(self) -> u64 { (self.0 + 999) / 1000 }
pub const fn to_kwu_ceil(self) -> u64 { (self.to_wu() + 999) / 1000 }
/// Converts to vB rounding down.
pub const fn to_vbytes_floor(self) -> u64 { self.0 / Self::WITNESS_SCALE_FACTOR }
pub const fn to_vbytes_floor(self) -> u64 { self.to_wu() / Self::WITNESS_SCALE_FACTOR }
/// Converts to vB rounding up.
pub const fn to_vbytes_ceil(self) -> u64 {
(self.0 + Self::WITNESS_SCALE_FACTOR - 1) / Self::WITNESS_SCALE_FACTOR
(self.to_wu() + Self::WITNESS_SCALE_FACTOR - 1) / Self::WITNESS_SCALE_FACTOR
}
/// Checked addition.
@ -114,7 +121,7 @@ impl Weight {
#[must_use]
pub const fn checked_add(self, rhs: Self) -> Option<Self> {
// No `map()` in const context.
match self.0.checked_add(rhs.0) {
match self.to_wu().checked_add(rhs.to_wu()) {
Some(wu) => Some(Weight::from_wu(wu)),
None => None,
}
@ -126,7 +133,7 @@ impl Weight {
#[must_use]
pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
// No `map()` in const context.
match self.0.checked_sub(rhs.0) {
match self.to_wu().checked_sub(rhs.to_wu()) {
Some(wu) => Some(Weight::from_wu(wu)),
None => None,
}
@ -138,7 +145,7 @@ impl Weight {
#[must_use]
pub const fn checked_mul(self, rhs: u64) -> Option<Self> {
// No `map()` in const context.
match self.0.checked_mul(rhs) {
match self.to_wu().checked_mul(rhs) {
Some(wu) => Some(Weight::from_wu(wu)),
None => None,
}
@ -150,7 +157,7 @@ impl Weight {
#[must_use]
pub const fn checked_div(self, rhs: u64) -> Option<Self> {
// No `map()` in const context.
match self.0.checked_div(rhs) {
match self.to_wu().checked_div(rhs) {
Some(wu) => Some(Weight::from_wu(wu)),
None => None,
}
@ -161,9 +168,9 @@ impl Weight {
impl fmt::Display for Weight {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if f.alternate() {
write!(f, "{} wu", self.0)
write!(f, "{} wu", self.to_wu())
} else {
fmt::Display::fmt(&self.0, f)
fmt::Display::fmt(&self.to_wu(), f)
}
}
}
@ -176,28 +183,28 @@ crate::internal_macros::impl_op_for_references! {
impl ops::Add<Weight> for Weight {
type Output = Weight;
fn add(self, rhs: Weight) -> Self::Output { Weight(self.0 + rhs.0) }
fn add(self, rhs: Weight) -> Self::Output { Weight::from_wu(self.to_wu() + rhs.to_wu()) }
}
impl ops::Sub<Weight> for Weight {
type Output = Weight;
fn sub(self, rhs: Weight) -> Self::Output { Weight(self.0 - rhs.0) }
fn sub(self, rhs: Weight) -> Self::Output { Weight::from_wu(self.to_wu() - rhs.to_wu()) }
}
impl ops::Mul<u64> for Weight {
type Output = Weight;
fn mul(self, rhs: u64) -> Self::Output { Weight(self.0 * rhs) }
fn mul(self, rhs: u64) -> Self::Output { Weight::from_wu(self.to_wu() * rhs) }
}
impl ops::Mul<Weight> for u64 {
type Output = Weight;
fn mul(self, rhs: Weight) -> Self::Output { Weight(self * rhs.0) }
fn mul(self, rhs: Weight) -> Self::Output { Weight::from_wu(self * rhs.to_wu()) }
}
impl ops::Div<u64> for Weight {
type Output = Weight;
fn div(self, rhs: u64) -> Self::Output { Weight(self.0 / rhs) }
fn div(self, rhs: u64) -> Self::Output { Weight::from_wu(self.to_wu() / rhs) }
}
impl ops::Div<Weight> for Weight {
type Output = u64;
@ -207,27 +214,27 @@ crate::internal_macros::impl_op_for_references! {
impl ops::Rem<u64> for Weight {
type Output = Weight;
fn rem(self, rhs: u64) -> Self::Output { Weight(self.0 % rhs) }
fn rem(self, rhs: u64) -> Self::Output { Weight::from_wu(self.to_wu() % rhs) }
}
impl ops::Rem<Weight> for Weight {
type Output = u64;
fn rem(self, rhs: Weight) -> Self::Output { self.0 % rhs.0 }
fn rem(self, rhs: Weight) -> Self::Output { self.to_wu() % rhs.to_wu() }
}
}
crate::internal_macros::impl_add_assign!(Weight);
crate::internal_macros::impl_sub_assign!(Weight);
impl ops::MulAssign<u64> for Weight {
fn mul_assign(&mut self, rhs: u64) { self.0 *= rhs }
fn mul_assign(&mut self, rhs: u64) { *self = Weight::from_wu(self.to_wu() * rhs); }
}
impl ops::DivAssign<u64> for Weight {
fn div_assign(&mut self, rhs: u64) { self.0 /= rhs }
fn div_assign(&mut self, rhs: u64) { *self = Weight::from_wu(self.to_wu() / rhs); }
}
impl ops::RemAssign<u64> for Weight {
fn rem_assign(&mut self, rhs: u64) { self.0 %= rhs }
fn rem_assign(&mut self, rhs: u64) { *self = Weight::from_wu(self.to_wu() % rhs); }
}
impl core::iter::Sum for Weight {
@ -235,7 +242,7 @@ impl core::iter::Sum for Weight {
where
I: Iterator<Item = Self>,
{
Weight(iter.map(Weight::to_wu).sum())
Weight::from_wu(iter.map(Weight::to_wu).sum())
}
}
@ -254,7 +261,7 @@ crate::impl_parse_str_from_int_infallible!(Weight, u64, from_wu);
impl<'a> Arbitrary<'a> for Weight {
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
let w = u64::arbitrary(u)?;
Ok(Weight(w))
Ok(Weight::from_wu(w))
}
}
@ -262,19 +269,19 @@ impl<'a> Arbitrary<'a> for Weight {
mod tests {
use super::*;
const ONE: Weight = Weight(1);
const TWO: Weight = Weight(2);
const FOUR: Weight = Weight(4);
const ONE: Weight = Weight::from_wu(1);
const TWO: Weight = Weight::from_wu(2);
const FOUR: Weight = Weight::from_wu(4);
#[test]
fn sanity_check() {
assert_eq!(Weight::MIN_TRANSACTION, Weight(240));
assert_eq!(Weight::MIN_TRANSACTION, Weight::from_wu(240));
}
#[test]
fn from_kwu() {
let got = Weight::from_kwu(1).unwrap();
let want = Weight(1_000);
let want = Weight::from_wu(1_000);
assert_eq!(got, want);
}
@ -284,7 +291,7 @@ mod tests {
#[test]
fn from_vb() {
let got = Weight::from_vb(1).unwrap();
let want = Weight(4);
let want = Weight::from_wu(4);
assert_eq!(got, want);
}
@ -296,7 +303,7 @@ mod tests {
#[test]
fn from_vb_unchecked() {
let got = Weight::from_vb_unchecked(1);
let want = Weight(4);
let want = Weight::from_wu(4);
assert_eq!(got, want);
}
@ -309,7 +316,7 @@ mod tests {
fn from_witness_data_size() {
let witness_data_size = 1;
let got = Weight::from_witness_data_size(witness_data_size);
let want = Weight(witness_data_size);
let want = Weight::from_wu(witness_data_size);
assert_eq!(got, want);
}
@ -317,32 +324,32 @@ mod tests {
fn from_non_witness_data_size() {
let non_witness_data_size = 1;
let got = Weight::from_non_witness_data_size(non_witness_data_size);
let want = Weight(non_witness_data_size * 4);
let want = Weight::from_wu(non_witness_data_size * 4);
assert_eq!(got, want);
}
#[test]
fn to_kwu_floor() {
assert_eq!(Weight(5_000).to_kwu_floor(), 5);
assert_eq!(Weight(5_999).to_kwu_floor(), 5);
assert_eq!(Weight::from_wu(5_000).to_kwu_floor(), 5);
assert_eq!(Weight::from_wu(5_999).to_kwu_floor(), 5);
}
#[test]
fn to_kwu_ceil() {
assert_eq!(Weight(1_000).to_kwu_ceil(), 1);
assert_eq!(Weight(1_001).to_kwu_ceil(), 2);
assert_eq!(Weight::from_wu(1_000).to_kwu_ceil(), 1);
assert_eq!(Weight::from_wu(1_001).to_kwu_ceil(), 2);
}
#[test]
fn to_vb_floor() {
assert_eq!(Weight(8).to_vbytes_floor(), 2);
assert_eq!(Weight(9).to_vbytes_floor(), 2);
assert_eq!(Weight::from_wu(8).to_vbytes_floor(), 2);
assert_eq!(Weight::from_wu(9).to_vbytes_floor(), 2);
}
#[test]
fn to_vb_ceil() {
assert_eq!(Weight(4).to_vbytes_ceil(), 1);
assert_eq!(Weight(5).to_vbytes_ceil(), 2);
assert_eq!(Weight::from_wu(4).to_vbytes_ceil(), 1);
assert_eq!(Weight::from_wu(5).to_vbytes_ceil(), 2);
}
#[test]
@ -382,9 +389,9 @@ mod tests {
#[test]
#[allow(clippy::op_ref)]
fn addition() {
let one = Weight(1);
let two = Weight(2);
let three = Weight(3);
let one = Weight::from_wu(1);
let two = Weight::from_wu(2);
let three = Weight::from_wu(3);
assert!(one + two == three);
assert!(&one + two == three);
@ -395,9 +402,9 @@ mod tests {
#[test]
#[allow(clippy::op_ref)]
fn subtract() {
let ten = Weight(10);
let seven = Weight(7);
let three = Weight(3);
let ten = Weight::from_wu(10);
let seven = Weight::from_wu(7);
let three = Weight::from_wu(3);
assert_eq!(ten - seven, three);
assert_eq!(&ten - seven, three);
@ -408,8 +415,8 @@ mod tests {
#[test]
#[allow(clippy::op_ref)]
fn multiply() {
let two = Weight(2);
let six = Weight(6);
let two = Weight::from_wu(2);
let six = Weight::from_wu(6);
assert_eq!(3_u64 * two, six);
assert_eq!(two * 3_u64, six);
@ -417,65 +424,65 @@ mod tests {
#[test]
fn divide() {
let eight = Weight(8);
let four = Weight(4);
let eight = Weight::from_wu(8);
let four = Weight::from_wu(4);
assert_eq!(eight / four, 2_u64);
assert_eq!(eight / 4_u64, Weight(2));
assert_eq!(eight / 4_u64, Weight::from_wu(2));
}
#[test]
fn add_assign() {
let mut f = Weight(1);
f += Weight(2);
assert_eq!(f, Weight(3));
let mut f = Weight::from_wu(1);
f += Weight::from_wu(2);
assert_eq!(f, Weight::from_wu(3));
let mut f = Weight(1);
f += &Weight(2);
assert_eq!(f, Weight(3));
let mut f = Weight::from_wu(1);
f += &Weight::from_wu(2);
assert_eq!(f, Weight::from_wu(3));
}
#[test]
fn sub_assign() {
let mut f = Weight(3);
f -= Weight(2);
assert_eq!(f, Weight(1));
let mut f = Weight::from_wu(3);
f -= Weight::from_wu(2);
assert_eq!(f, Weight::from_wu(1));
let mut f = Weight(3);
f -= &Weight(2);
assert_eq!(f, Weight(1));
let mut f = Weight::from_wu(3);
f -= &Weight::from_wu(2);
assert_eq!(f, Weight::from_wu(1));
}
#[test]
fn mul_assign() {
let mut w = Weight(3);
let mut w = Weight::from_wu(3);
w *= 2_u64;
assert_eq!(w, Weight(6));
assert_eq!(w, Weight::from_wu(6));
}
#[test]
fn div_assign() {
let mut w = Weight(8);
w /= Weight(4).into();
assert_eq!(w, Weight(2));
let mut w = Weight::from_wu(8);
w /= Weight::from_wu(4).into();
assert_eq!(w, Weight::from_wu(2));
}
#[test]
fn remainder() {
let weight10 = Weight(10);
let weight3 = Weight(3);
let weight10 = Weight::from_wu(10);
let weight3 = Weight::from_wu(3);
let remainder = weight10 % weight3;
assert_eq!(remainder, 1);
let remainder = weight10 % 3;
assert_eq!(remainder, Weight(1));
assert_eq!(remainder, Weight::from_wu(1));
}
#[test]
fn remainder_assign() {
let mut weight = Weight(10);
let mut weight = Weight::from_wu(10);
weight %= 3;
assert_eq!(weight, Weight(1));
assert_eq!(weight, Weight::from_wu(1));
}
}