Merge rust-bitcoin/rust-bitcoin#4462: Do lock time renames
dca4266205
units: Fix rustdoc column width (Tobin C. Harding)d557caf552
Run the formatter (Tobin C. Harding)7c2115b68f
Rename MtpInterval to NumberOf512Seconds (Tobin C. Harding)3a97ea2259
Rename HeightInterval to NumberOfBlocks (Tobin C. Harding)c3b7457f6c
Rename Mtp to MedianTimePast (Tobin C. Harding)b38d2256fd
Run the formatter (Tobin C. Harding) Pull request description: Naming things is hard, naming lock time things is _really_ hard. This is another attempt at improving the very low level types in the `units::locktime` modules. Formatting done separately so that the diffs are easier to tab through. ACKs for top commit: apoelstra: ACK dca4266205361eb0aee802a46164b163b797d0ee; successfully ran local tests Tree-SHA512: 24d1b0cae3d7f926622177f00aedc50c53164e04f9d400f9c2c009157f36fd1f55ac2d1b70ceb10b0a165130ffe7eef25d64dc6ea5e6f3caec812c39ab0bbd66
This commit is contained in:
commit
3a6a399f48
|
@ -30,9 +30,7 @@ use crate::transaction::{Transaction, TransactionExt as _, Wtxid};
|
|||
#[doc(inline)]
|
||||
pub use primitives::block::{Block, Checked, Unchecked, Validation, Version, BlockHash, Header, WitnessCommitment};
|
||||
#[doc(inline)]
|
||||
pub use units::block::{
|
||||
BlockHeight, BlockHeightInterval, TooBigForRelativeBlockHeightIntervalError,
|
||||
};
|
||||
pub use units::block::{BlockHeight, BlockHeightInterval, TooBigForRelativeHeightError};
|
||||
|
||||
#[deprecated(since = "TBD", note = "use `BlockHeightInterval` instead")]
|
||||
#[doc(hidden)]
|
||||
|
|
|
@ -41,11 +41,11 @@ pub mod locktime {
|
|||
|
||||
/// Re-export everything from the `primitives::locktime::absolute` module.
|
||||
#[rustfmt::skip] // Keep public re-exports separate.
|
||||
pub use primitives::locktime::absolute::{ConversionError, Height, LockTime, ParseHeightError, ParseTimeError, Mtp};
|
||||
pub use primitives::locktime::absolute::{ConversionError, Height, LockTime, ParseHeightError, ParseTimeError, MedianTimePast};
|
||||
|
||||
#[deprecated(since = "TBD", note = "use `Mtp` instead")]
|
||||
#[deprecated(since = "TBD", note = "use `MedianTimePast` instead")]
|
||||
#[doc(hidden)]
|
||||
pub type Time = Mtp;
|
||||
pub type Time = MedianTimePast;
|
||||
|
||||
impl Encodable for LockTime {
|
||||
#[inline]
|
||||
|
@ -71,17 +71,17 @@ pub mod locktime {
|
|||
|
||||
/// Re-export everything from the `primitives::locktime::relative` module.
|
||||
pub use primitives::locktime::relative::{
|
||||
DisabledLockTimeError, HeightInterval, IncompatibleHeightError, IncompatibleTimeError,
|
||||
LockTime, MtpInterval, TimeOverflowError,
|
||||
DisabledLockTimeError, IncompatibleHeightError, IncompatibleTimeError, LockTime,
|
||||
NumberOf512Seconds, NumberOfBlocks, TimeOverflowError,
|
||||
};
|
||||
|
||||
#[deprecated(since = "TBD", note = "use `Mtp` instead")]
|
||||
#[deprecated(since = "TBD", note = "use `NumberOfBlocks` instead")]
|
||||
#[doc(hidden)]
|
||||
pub type Height = HeightInterval;
|
||||
pub type Height = NumberOfBlocks;
|
||||
|
||||
#[deprecated(since = "TBD", note = "use `Mtp` instead")]
|
||||
#[deprecated(since = "TBD", note = "use `NumberOf512Seconds` instead")]
|
||||
#[doc(hidden)]
|
||||
pub type Time = MtpInterval;
|
||||
pub type Time = NumberOf512Seconds;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ use primitives::Sequence;
|
|||
use super::Weight;
|
||||
use crate::consensus::{self, encode, Decodable, Encodable};
|
||||
use crate::internal_macros::{impl_consensus_encoding, impl_hashencode};
|
||||
use crate::locktime::absolute::{self, Height, Mtp};
|
||||
use crate::locktime::absolute::{self, Height, MedianTimePast};
|
||||
use crate::prelude::{Borrow, Vec};
|
||||
use crate::script::{Script, ScriptBuf, ScriptExt as _, ScriptExtPriv as _};
|
||||
#[cfg(doc)]
|
||||
|
@ -295,7 +295,7 @@ pub trait TransactionExt: sealed::Sealed {
|
|||
/// By definition if the lock time is not enabled the transaction's absolute timelock is
|
||||
/// considered to be satisfied i.e., there are no timelock constraints restricting this
|
||||
/// transaction from being mined immediately.
|
||||
fn is_absolute_timelock_satisfied(&self, height: Height, time: Mtp) -> bool;
|
||||
fn is_absolute_timelock_satisfied(&self, height: Height, time: MedianTimePast) -> bool;
|
||||
|
||||
/// Returns `true` if this transactions nLockTime is enabled ([BIP-65]).
|
||||
///
|
||||
|
@ -393,7 +393,7 @@ impl TransactionExt for Transaction {
|
|||
|
||||
fn is_explicitly_rbf(&self) -> bool { self.input.iter().any(|input| input.sequence.is_rbf()) }
|
||||
|
||||
fn is_absolute_timelock_satisfied(&self, height: Height, time: Mtp) -> bool {
|
||||
fn is_absolute_timelock_satisfied(&self, height: Height, time: MedianTimePast) -> bool {
|
||||
if !self.is_lock_time_enabled() {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -16,11 +16,11 @@ use crate::{absolute, Transaction};
|
|||
|
||||
#[rustfmt::skip] // Keep public re-exports separate.
|
||||
#[doc(inline)]
|
||||
pub use units::locktime::absolute::{ConversionError, Height, ParseHeightError, ParseTimeError, Mtp, LOCK_TIME_THRESHOLD};
|
||||
pub use units::locktime::absolute::{ConversionError, Height, ParseHeightError, ParseTimeError, MedianTimePast, LOCK_TIME_THRESHOLD};
|
||||
|
||||
#[deprecated(since = "TBD", note = "use `Mtp` instead")]
|
||||
#[deprecated(since = "TBD", note = "use `MedianTimePast` instead")]
|
||||
#[doc(hidden)]
|
||||
pub type Time = Mtp;
|
||||
pub type Time = MedianTimePast;
|
||||
|
||||
/// An absolute lock time value, representing either a block height or a UNIX timestamp (seconds
|
||||
/// since epoch).
|
||||
|
@ -83,7 +83,7 @@ pub enum LockTime {
|
|||
/// assert!(n.is_block_time());
|
||||
/// assert_eq!(n.to_consensus_u32(), seconds);
|
||||
/// ```
|
||||
Seconds(Mtp),
|
||||
Seconds(MedianTimePast),
|
||||
}
|
||||
|
||||
impl LockTime {
|
||||
|
@ -147,7 +147,7 @@ impl LockTime {
|
|||
if units::locktime::absolute::is_block_height(n) {
|
||||
Self::Blocks(Height::from_u32(n).expect("n is valid"))
|
||||
} else {
|
||||
Self::Seconds(Mtp::from_u32(n).expect("n is valid"))
|
||||
Self::Seconds(MedianTimePast::from_u32(n).expect("n is valid"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,7 +202,7 @@ impl LockTime {
|
|||
/// ```
|
||||
#[inline]
|
||||
pub fn from_mtp(n: u32) -> Result<Self, ConversionError> {
|
||||
let time = Mtp::from_u32(n)?;
|
||||
let time = MedianTimePast::from_u32(n)?;
|
||||
Ok(LockTime::Seconds(time))
|
||||
}
|
||||
|
||||
|
@ -239,7 +239,7 @@ impl LockTime {
|
|||
/// # use bitcoin_primitives::absolute;
|
||||
/// // Can be implemented if block chain data is available.
|
||||
/// fn get_height() -> absolute::Height { todo!("return the current block height") }
|
||||
/// fn get_time() -> absolute::Mtp { todo!("return the current block time") }
|
||||
/// fn get_time() -> absolute::MedianTimePast { todo!("return the current block time") }
|
||||
///
|
||||
/// let n = absolute::LockTime::from_consensus(741521); // `n OP_CHEKCLOCKTIMEVERIFY`.
|
||||
/// if n.is_satisfied_by(get_height(), get_time()) {
|
||||
|
@ -247,7 +247,7 @@ impl LockTime {
|
|||
/// }
|
||||
/// ````
|
||||
#[inline]
|
||||
pub fn is_satisfied_by(self, height: Height, time: Mtp) -> bool {
|
||||
pub fn is_satisfied_by(self, height: Height, time: MedianTimePast) -> bool {
|
||||
use LockTime as L;
|
||||
|
||||
match self {
|
||||
|
@ -333,9 +333,9 @@ impl From<Height> for LockTime {
|
|||
fn from(h: Height) -> Self { LockTime::Blocks(h) }
|
||||
}
|
||||
|
||||
impl From<Mtp> for LockTime {
|
||||
impl From<MedianTimePast> for LockTime {
|
||||
#[inline]
|
||||
fn from(t: Mtp) -> Self { LockTime::Seconds(t) }
|
||||
fn from(t: MedianTimePast) -> Self { LockTime::Seconds(t) }
|
||||
}
|
||||
|
||||
impl fmt::Debug for LockTime {
|
||||
|
@ -512,7 +512,7 @@ mod tests {
|
|||
let lock_by_height = LockTime::from(height);
|
||||
|
||||
let t: u32 = 1_653_195_600; // May 22nd, 5am UTC.
|
||||
let time = Mtp::from_u32(t).unwrap();
|
||||
let time = MedianTimePast::from_u32(t).unwrap();
|
||||
|
||||
assert!(!lock_by_height.is_satisfied_by(height_below, time));
|
||||
assert!(lock_by_height.is_satisfied_by(height, time));
|
||||
|
@ -521,9 +521,9 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn satisfied_by_time() {
|
||||
let time_before = Mtp::from_u32(1_653_109_200).unwrap(); // "May 21th 2022, 5am UTC.
|
||||
let time = Mtp::from_u32(1_653_195_600).unwrap(); // "May 22nd 2022, 5am UTC.
|
||||
let time_after = Mtp::from_u32(1_653_282_000).unwrap(); // "May 23rd 2022, 5am UTC.
|
||||
let time_before = MedianTimePast::from_u32(1_653_109_200).unwrap(); // "May 21th 2022, 5am UTC.
|
||||
let time = MedianTimePast::from_u32(1_653_195_600).unwrap(); // "May 22nd 2022, 5am UTC.
|
||||
let time_after = MedianTimePast::from_u32(1_653_282_000).unwrap(); // "May 23rd 2022, 5am UTC.
|
||||
|
||||
let lock_by_time = LockTime::from(time);
|
||||
|
||||
|
|
|
@ -13,16 +13,16 @@ use crate::{relative, TxIn};
|
|||
|
||||
#[rustfmt::skip] // Keep public re-exports separate.
|
||||
#[doc(inline)]
|
||||
pub use units::locktime::relative::{HeightInterval, MtpInterval, TimeOverflowError};
|
||||
pub use units::locktime::relative::{NumberOfBlocks, NumberOf512Seconds, TimeOverflowError};
|
||||
use units::{BlockHeight, BlockMtp};
|
||||
|
||||
#[deprecated(since = "TBD", note = "use `Mtp` instead")]
|
||||
#[deprecated(since = "TBD", note = "use `NumberOfBlocks` instead")]
|
||||
#[doc(hidden)]
|
||||
pub type Height = HeightInterval;
|
||||
pub type Height = NumberOfBlocks;
|
||||
|
||||
#[deprecated(since = "TBD", note = "use `Mtp` instead")]
|
||||
#[deprecated(since = "TBD", note = "use `NumberOf512Seconds` instead")]
|
||||
#[doc(hidden)]
|
||||
pub type Time = MtpInterval;
|
||||
pub type Time = NumberOf512Seconds;
|
||||
|
||||
/// A relative lock time value, representing either a block height or time (512 second intervals).
|
||||
///
|
||||
|
@ -68,7 +68,7 @@ pub type Time = MtpInterval;
|
|||
/// let utxo_height = BlockHeight::from(80);
|
||||
/// let utxo_mtp = BlockMtp::new(utxo_timestamps);
|
||||
///
|
||||
/// let locktime = relative::LockTime::Time(relative::MtpInterval::from_512_second_intervals(10));
|
||||
/// let locktime = relative::LockTime::Time(relative::NumberOf512Seconds::from_512_second_intervals(10));
|
||||
///
|
||||
/// // Check if locktime is satisfied
|
||||
/// assert!(locktime.is_satisfied_by(current_height, current_mtp, utxo_height, utxo_mtp));
|
||||
|
@ -77,15 +77,15 @@ pub type Time = MtpInterval;
|
|||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub enum LockTime {
|
||||
/// A block height lock time value.
|
||||
Blocks(HeightInterval),
|
||||
Blocks(NumberOfBlocks),
|
||||
/// A 512 second time interval value.
|
||||
Time(MtpInterval),
|
||||
Time(NumberOf512Seconds),
|
||||
}
|
||||
|
||||
impl LockTime {
|
||||
/// A relative locktime of 0 is always valid, and is assumed valid for inputs that
|
||||
/// are not yet confirmed.
|
||||
pub const ZERO: LockTime = LockTime::Blocks(HeightInterval::ZERO);
|
||||
pub const ZERO: LockTime = LockTime::Blocks(NumberOfBlocks::ZERO);
|
||||
|
||||
/// The number of bytes that the locktime contributes to the size of a transaction.
|
||||
pub const SIZE: usize = 4; // Serialized length of a u32.
|
||||
|
@ -164,7 +164,7 @@ impl LockTime {
|
|||
|
||||
/// Constructs a new `LockTime` from `n`, expecting `n` to be a 16-bit count of blocks.
|
||||
#[inline]
|
||||
pub const fn from_height(n: u16) -> Self { LockTime::Blocks(HeightInterval::from_height(n)) }
|
||||
pub const fn from_height(n: u16) -> Self { LockTime::Blocks(NumberOfBlocks::from_height(n)) }
|
||||
|
||||
/// Constructs a new `LockTime` from `n`, expecting `n` to be a count of 512-second intervals.
|
||||
///
|
||||
|
@ -172,7 +172,7 @@ impl LockTime {
|
|||
/// [`Self::from_seconds_floor`] or [`Self::from_seconds_ceil`].
|
||||
#[inline]
|
||||
pub const fn from_512_second_intervals(intervals: u16) -> Self {
|
||||
LockTime::Time(MtpInterval::from_512_second_intervals(intervals))
|
||||
LockTime::Time(NumberOf512Seconds::from_512_second_intervals(intervals))
|
||||
}
|
||||
|
||||
/// Construct a new [`LockTime`] from seconds, converting the seconds into 512 second interval
|
||||
|
@ -183,7 +183,7 @@ impl LockTime {
|
|||
/// Will return an error if the input cannot be encoded in 16 bits.
|
||||
#[inline]
|
||||
pub const fn from_seconds_floor(seconds: u32) -> Result<Self, TimeOverflowError> {
|
||||
match MtpInterval::from_seconds_floor(seconds) {
|
||||
match NumberOf512Seconds::from_seconds_floor(seconds) {
|
||||
Ok(time) => Ok(LockTime::Time(time)),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
|
@ -197,7 +197,7 @@ impl LockTime {
|
|||
/// Will return an error if the input cannot be encoded in 16 bits.
|
||||
#[inline]
|
||||
pub const fn from_seconds_ceil(seconds: u32) -> Result<Self, TimeOverflowError> {
|
||||
match MtpInterval::from_seconds_ceil(seconds) {
|
||||
match NumberOf512Seconds::from_seconds_ceil(seconds) {
|
||||
Ok(time) => Ok(LockTime::Time(time)),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
|
@ -332,7 +332,7 @@ impl LockTime {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns true if this [`relative::LockTime`] is satisfied by [`HeightInterval`].
|
||||
/// Returns true if this [`relative::LockTime`] is satisfied by [`NumberOfBlocks`].
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
|
@ -346,12 +346,12 @@ impl LockTime {
|
|||
///
|
||||
/// let required_height: u16 = 100;
|
||||
/// let lock = Sequence::from_height(required_height).to_relative_lock_time().expect("valid height");
|
||||
/// assert!(lock.is_satisfied_by_height(relative::HeightInterval::from(required_height + 1)).expect("a height"));
|
||||
/// assert!(lock.is_satisfied_by_height(relative::NumberOfBlocks::from(required_height + 1)).expect("a height"));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn is_satisfied_by_height(
|
||||
self,
|
||||
height: HeightInterval,
|
||||
height: NumberOfBlocks,
|
||||
) -> Result<bool, IncompatibleHeightError> {
|
||||
use LockTime as L;
|
||||
|
||||
|
@ -378,7 +378,10 @@ impl LockTime {
|
|||
/// assert!(lock.is_satisfied_by_time(relative::Time::from_512_second_intervals(intervals + 10)).expect("a time"));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn is_satisfied_by_time(self, time: MtpInterval) -> Result<bool, IncompatibleTimeError> {
|
||||
pub fn is_satisfied_by_time(
|
||||
self,
|
||||
time: NumberOf512Seconds,
|
||||
) -> Result<bool, IncompatibleTimeError> {
|
||||
use LockTime as L;
|
||||
|
||||
match self {
|
||||
|
@ -388,14 +391,14 @@ impl LockTime {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<HeightInterval> for LockTime {
|
||||
impl From<NumberOfBlocks> for LockTime {
|
||||
#[inline]
|
||||
fn from(h: HeightInterval) -> Self { LockTime::Blocks(h) }
|
||||
fn from(h: NumberOfBlocks) -> Self { LockTime::Blocks(h) }
|
||||
}
|
||||
|
||||
impl From<MtpInterval> for LockTime {
|
||||
impl From<NumberOf512Seconds> for LockTime {
|
||||
#[inline]
|
||||
fn from(t: MtpInterval) -> Self { LockTime::Time(t) }
|
||||
fn from(t: NumberOf512Seconds) -> Self { LockTime::Time(t) }
|
||||
}
|
||||
|
||||
impl fmt::Display for LockTime {
|
||||
|
@ -455,17 +458,17 @@ impl std::error::Error for DisabledLockTimeError {}
|
|||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct IncompatibleHeightError {
|
||||
/// Attempted to satisfy a lock-by-blocktime lock with this height.
|
||||
height: HeightInterval,
|
||||
height: NumberOfBlocks,
|
||||
/// The inner time value of the lock-by-blocktime lock.
|
||||
time: MtpInterval,
|
||||
time: NumberOf512Seconds,
|
||||
}
|
||||
|
||||
impl IncompatibleHeightError {
|
||||
/// Returns the height that was erroneously used to try and satisfy a lock-by-blocktime lock.
|
||||
pub fn incompatible(&self) -> HeightInterval { self.height }
|
||||
pub fn incompatible(&self) -> NumberOfBlocks { self.height }
|
||||
|
||||
/// Returns the time value of the lock-by-blocktime lock.
|
||||
pub fn expected(&self) -> MtpInterval { self.time }
|
||||
pub fn expected(&self) -> NumberOf512Seconds { self.time }
|
||||
}
|
||||
|
||||
impl fmt::Display for IncompatibleHeightError {
|
||||
|
@ -486,17 +489,17 @@ impl std::error::Error for IncompatibleHeightError {}
|
|||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct IncompatibleTimeError {
|
||||
/// Attempted to satisfy a lock-by-blockheight lock with this time.
|
||||
time: MtpInterval,
|
||||
time: NumberOf512Seconds,
|
||||
/// The inner height value of the lock-by-blockheight lock.
|
||||
height: HeightInterval,
|
||||
height: NumberOfBlocks,
|
||||
}
|
||||
|
||||
impl IncompatibleTimeError {
|
||||
/// Returns the time that was erroneously used to try and satisfy a lock-by-blockheight lock.
|
||||
pub fn incompatible(&self) -> MtpInterval { self.time }
|
||||
pub fn incompatible(&self) -> NumberOf512Seconds { self.time }
|
||||
|
||||
/// Returns the height value of the lock-by-blockheight lock.
|
||||
pub fn expected(&self) -> HeightInterval { self.height }
|
||||
pub fn expected(&self) -> NumberOfBlocks { self.height }
|
||||
}
|
||||
|
||||
impl fmt::Display for IncompatibleTimeError {
|
||||
|
@ -551,10 +554,10 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn parses_correctly_to_height_or_time() {
|
||||
let height1 = HeightInterval::from(10);
|
||||
let height2 = HeightInterval::from(11);
|
||||
let time1 = MtpInterval::from_512_second_intervals(70);
|
||||
let time2 = MtpInterval::from_512_second_intervals(71);
|
||||
let height1 = NumberOfBlocks::from(10);
|
||||
let height2 = NumberOfBlocks::from(11);
|
||||
let time1 = NumberOf512Seconds::from_512_second_intervals(70);
|
||||
let time2 = NumberOf512Seconds::from_512_second_intervals(71);
|
||||
|
||||
let lock_by_height1 = LockTime::from(height1);
|
||||
let lock_by_height2 = LockTime::from(height2);
|
||||
|
@ -576,34 +579,31 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn height_correctly_implies() {
|
||||
let height = HeightInterval::from(10);
|
||||
let height = NumberOfBlocks::from(10);
|
||||
let lock_by_height = LockTime::from(height);
|
||||
|
||||
assert!(!lock_by_height.is_implied_by(LockTime::from(HeightInterval::from(9))));
|
||||
assert!(lock_by_height.is_implied_by(LockTime::from(HeightInterval::from(10))));
|
||||
assert!(lock_by_height.is_implied_by(LockTime::from(HeightInterval::from(11))));
|
||||
assert!(!lock_by_height.is_implied_by(LockTime::from(NumberOfBlocks::from(9))));
|
||||
assert!(lock_by_height.is_implied_by(LockTime::from(NumberOfBlocks::from(10))));
|
||||
assert!(lock_by_height.is_implied_by(LockTime::from(NumberOfBlocks::from(11))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn time_correctly_implies() {
|
||||
let time = MtpInterval::from_512_second_intervals(70);
|
||||
let time = NumberOf512Seconds::from_512_second_intervals(70);
|
||||
let lock_by_time = LockTime::from(time);
|
||||
|
||||
assert!(
|
||||
!lock_by_time.is_implied_by(LockTime::from(MtpInterval::from_512_second_intervals(69)))
|
||||
);
|
||||
assert!(
|
||||
lock_by_time.is_implied_by(LockTime::from(MtpInterval::from_512_second_intervals(70)))
|
||||
);
|
||||
assert!(
|
||||
lock_by_time.is_implied_by(LockTime::from(MtpInterval::from_512_second_intervals(71)))
|
||||
);
|
||||
assert!(!lock_by_time
|
||||
.is_implied_by(LockTime::from(NumberOf512Seconds::from_512_second_intervals(69))));
|
||||
assert!(lock_by_time
|
||||
.is_implied_by(LockTime::from(NumberOf512Seconds::from_512_second_intervals(70))));
|
||||
assert!(lock_by_time
|
||||
.is_implied_by(LockTime::from(NumberOf512Seconds::from_512_second_intervals(71))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sequence_correctly_implies() {
|
||||
let height = HeightInterval::from(10);
|
||||
let time = MtpInterval::from_512_second_intervals(70);
|
||||
let height = NumberOfBlocks::from(10);
|
||||
let time = NumberOf512Seconds::from_512_second_intervals(70);
|
||||
|
||||
let lock_by_height = LockTime::from(height);
|
||||
let lock_by_time = LockTime::from(time);
|
||||
|
@ -624,8 +624,8 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn incorrect_units_do_not_imply() {
|
||||
let time = MtpInterval::from_512_second_intervals(70);
|
||||
let height = HeightInterval::from(10);
|
||||
let time = NumberOf512Seconds::from_512_second_intervals(70);
|
||||
let height = NumberOfBlocks::from(10);
|
||||
|
||||
let lock_by_time = LockTime::from(time);
|
||||
assert!(!lock_by_time.is_implied_by(LockTime::from(height)));
|
||||
|
@ -664,8 +664,8 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn incompatible_height_error() {
|
||||
let height = HeightInterval::from(10);
|
||||
let time = MtpInterval::from_512_second_intervals(70);
|
||||
let height = NumberOfBlocks::from(10);
|
||||
let time = NumberOf512Seconds::from_512_second_intervals(70);
|
||||
let lock_by_time = LockTime::from(time);
|
||||
let err = lock_by_time.is_satisfied_by_height(height).unwrap_err();
|
||||
|
||||
|
@ -676,8 +676,8 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn incompatible_time_error() {
|
||||
let height = HeightInterval::from(10);
|
||||
let time = MtpInterval::from_512_second_intervals(70);
|
||||
let height = NumberOfBlocks::from(10);
|
||||
let time = NumberOf512Seconds::from_512_second_intervals(70);
|
||||
let lock_by_height = LockTime::from(height);
|
||||
let err = lock_by_height.is_satisfied_by_time(time).unwrap_err();
|
||||
|
||||
|
@ -704,16 +704,16 @@ mod tests {
|
|||
let utxo_height = BlockHeight::from_u32(80);
|
||||
let utxo_mtp = BlockMtp::new(utxo_timestamps);
|
||||
|
||||
let lock1 = LockTime::Blocks(HeightInterval::from(10));
|
||||
let lock1 = LockTime::Blocks(NumberOfBlocks::from(10));
|
||||
assert!(lock1.is_satisfied_by(chain_height, chain_mtp, utxo_height, utxo_mtp));
|
||||
|
||||
let lock2 = LockTime::Blocks(HeightInterval::from(21));
|
||||
let lock2 = LockTime::Blocks(NumberOfBlocks::from(21));
|
||||
assert!(!lock2.is_satisfied_by(chain_height, chain_mtp, utxo_height, utxo_mtp));
|
||||
|
||||
let lock3 = LockTime::Time(MtpInterval::from_512_second_intervals(10));
|
||||
let lock3 = LockTime::Time(NumberOf512Seconds::from_512_second_intervals(10));
|
||||
assert!(lock3.is_satisfied_by(chain_height, chain_mtp, utxo_height, utxo_mtp));
|
||||
|
||||
let lock4 = LockTime::Time(MtpInterval::from_512_second_intervals(20000));
|
||||
let lock4 = LockTime::Time(NumberOf512Seconds::from_512_second_intervals(20000));
|
||||
assert!(!lock4.is_satisfied_by(chain_height, chain_mtp, utxo_height, utxo_mtp));
|
||||
|
||||
assert!(LockTime::ZERO.is_satisfied_by(chain_height, chain_mtp, utxo_height, utxo_mtp));
|
||||
|
@ -727,10 +727,10 @@ mod tests {
|
|||
let lock6 = LockTime::from_seconds_floor(5000).unwrap();
|
||||
assert!(lock6.is_satisfied_by(chain_height, chain_mtp, utxo_height, utxo_mtp));
|
||||
|
||||
let max_height_lock = LockTime::Blocks(HeightInterval::MAX);
|
||||
let max_height_lock = LockTime::Blocks(NumberOfBlocks::MAX);
|
||||
assert!(!max_height_lock.is_satisfied_by(chain_height, chain_mtp, utxo_height, utxo_mtp));
|
||||
|
||||
let max_time_lock = LockTime::Time(MtpInterval::MAX);
|
||||
let max_time_lock = LockTime::Time(NumberOf512Seconds::MAX);
|
||||
assert!(!max_time_lock.is_satisfied_by(chain_height, chain_mtp, utxo_height, utxo_mtp));
|
||||
|
||||
let max_chain_height = BlockHeight::from_u32(u32::MAX);
|
||||
|
|
|
@ -187,7 +187,7 @@ impl Sequence {
|
|||
/// Constructs a new [`relative::LockTime`] from this [`Sequence`] number.
|
||||
#[inline]
|
||||
pub fn to_relative_lock_time(self) -> Option<relative::LockTime> {
|
||||
use crate::locktime::relative::{HeightInterval, LockTime, MtpInterval};
|
||||
use crate::locktime::relative::{LockTime, NumberOf512Seconds, NumberOfBlocks};
|
||||
|
||||
if !self.is_relative_lock_time() {
|
||||
return None;
|
||||
|
@ -196,9 +196,9 @@ impl Sequence {
|
|||
let lock_value = self.low_u16();
|
||||
|
||||
if self.is_time_locked() {
|
||||
Some(LockTime::from(MtpInterval::from_512_second_intervals(lock_value)))
|
||||
Some(LockTime::from(NumberOf512Seconds::from_512_second_intervals(lock_value)))
|
||||
} else {
|
||||
Some(LockTime::from(HeightInterval::from(lock_value)))
|
||||
Some(LockTime::from(NumberOfBlocks::from(lock_value)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -261,15 +261,15 @@ impl<'a> Arbitrary<'a> for Sequence {
|
|||
1 => Ok(Sequence::ZERO),
|
||||
2 => Ok(Sequence::MIN_NO_RBF),
|
||||
3 => Ok(Sequence::ENABLE_LOCKTIME_AND_RBF),
|
||||
4 => Ok(Sequence::from_consensus(u32::from(relative::HeightInterval::MIN.to_height()))),
|
||||
5 => Ok(Sequence::from_consensus(u32::from(relative::HeightInterval::MAX.to_height()))),
|
||||
4 => Ok(Sequence::from_consensus(u32::from(relative::NumberOfBlocks::MIN.to_height()))),
|
||||
5 => Ok(Sequence::from_consensus(u32::from(relative::NumberOfBlocks::MAX.to_height()))),
|
||||
6 => Ok(Sequence::from_consensus(
|
||||
Sequence::LOCK_TYPE_MASK
|
||||
| u32::from(relative::MtpInterval::MIN.to_512_second_intervals()),
|
||||
| u32::from(relative::NumberOf512Seconds::MIN.to_512_second_intervals()),
|
||||
)),
|
||||
7 => Ok(Sequence::from_consensus(
|
||||
Sequence::LOCK_TYPE_MASK
|
||||
| u32::from(relative::MtpInterval::MAX.to_512_second_intervals()),
|
||||
| u32::from(relative::NumberOf512Seconds::MAX.to_512_second_intervals()),
|
||||
)),
|
||||
_ => Ok(Sequence(u.arbitrary()?)),
|
||||
}
|
||||
|
|
|
@ -142,18 +142,18 @@ impl BlockHeightInterval {
|
|||
pub fn checked_add(self, other: Self) -> Option<Self> { self.0.checked_add(other.0).map(Self) }
|
||||
}
|
||||
|
||||
impl From<relative::HeightInterval> for BlockHeightInterval {
|
||||
/// Converts a [`locktime::relative::HeightInterval`] to a [`BlockHeightInterval`].
|
||||
impl From<relative::NumberOfBlocks> for BlockHeightInterval {
|
||||
/// Converts a [`locktime::relative::NumberOfBlocks`] to a [`BlockHeightInterval`].
|
||||
///
|
||||
/// A relative locktime block height has a maximum value of `u16::MAX` where as a
|
||||
/// [`BlockHeightInterval`] is a thin wrapper around a `u32`, the two types are not interchangeable.
|
||||
fn from(h: relative::HeightInterval) -> Self { Self::from_u32(h.to_height().into()) }
|
||||
fn from(h: relative::NumberOfBlocks) -> Self { Self::from_u32(h.to_height().into()) }
|
||||
}
|
||||
|
||||
impl TryFrom<BlockHeightInterval> for relative::HeightInterval {
|
||||
type Error = TooBigForRelativeBlockHeightIntervalError;
|
||||
impl TryFrom<BlockHeightInterval> for relative::NumberOfBlocks {
|
||||
type Error = TooBigForRelativeHeightError;
|
||||
|
||||
/// Converts a [`BlockHeightInterval`] to a [`locktime::relative::HeightInterval`].
|
||||
/// Converts a [`BlockHeightInterval`] to a [`locktime::relative::NumberOfBlocks`].
|
||||
///
|
||||
/// A relative locktime block height has a maximum value of `u16::MAX` where as a
|
||||
/// [`BlockHeightInterval`] is a thin wrapper around a `u32`, the two types are not interchangeable.
|
||||
|
@ -161,9 +161,9 @@ impl TryFrom<BlockHeightInterval> for relative::HeightInterval {
|
|||
let h = h.to_u32();
|
||||
|
||||
if h > u32::from(u16::MAX) {
|
||||
return Err(TooBigForRelativeBlockHeightIntervalError(h));
|
||||
return Err(TooBigForRelativeHeightError(h));
|
||||
}
|
||||
Ok(relative::HeightInterval::from(h as u16)) // Cast ok, value checked above.
|
||||
Ok(relative::NumberOfBlocks::from(h as u16)) // Cast ok, value checked above.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,7 +171,7 @@ impl_u32_wrapper! {
|
|||
/// The median timestamp of 11 consecutive blocks.
|
||||
///
|
||||
/// This type is not meant for constructing time-based timelocks. It is a general purpose
|
||||
/// MTP abstraction. For locktimes please see [`locktime::absolute::Mtp`].
|
||||
/// MTP abstraction. For locktimes please see [`locktime::absolute::MedianTimePast`].
|
||||
///
|
||||
/// This is a thin wrapper around a `u32` that may take on all values of a `u32`.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
|
@ -202,29 +202,31 @@ impl BlockMtp {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<absolute::Mtp> for BlockMtp {
|
||||
/// Converts a [`locktime::absolute::Mtp`] to a [`BlockMtp`].
|
||||
impl From<absolute::MedianTimePast> for BlockMtp {
|
||||
/// Converts a [`locktime::absolute::MedianTimePast`] to a [`BlockMtp`].
|
||||
///
|
||||
/// An absolute locktime MTP has a minimum value of [`absolute::LOCK_TIME_THRESHOLD`],
|
||||
/// while [`BlockMtp`] may take the full range of `u32`.
|
||||
fn from(h: absolute::Mtp) -> Self { Self::from_u32(h.to_u32()) }
|
||||
fn from(h: absolute::MedianTimePast) -> Self { Self::from_u32(h.to_u32()) }
|
||||
}
|
||||
|
||||
impl TryFrom<BlockMtp> for absolute::Mtp {
|
||||
impl TryFrom<BlockMtp> for absolute::MedianTimePast {
|
||||
type Error = absolute::ConversionError;
|
||||
|
||||
/// Converts a [`BlockHeight`] to a [`locktime::absolute::Height`].
|
||||
///
|
||||
/// An absolute locktime MTP has a minimum value of [`absolute::LOCK_TIME_THRESHOLD`],
|
||||
/// while [`BlockMtp`] may take the full range of `u32`.
|
||||
fn try_from(h: BlockMtp) -> Result<Self, Self::Error> { absolute::Mtp::from_u32(h.to_u32()) }
|
||||
fn try_from(h: BlockMtp) -> Result<Self, Self::Error> {
|
||||
absolute::MedianTimePast::from_u32(h.to_u32())
|
||||
}
|
||||
}
|
||||
|
||||
impl_u32_wrapper! {
|
||||
/// An unsigned difference between two [`BlockMtp`]s.
|
||||
///
|
||||
/// This type is not meant for constructing time-based timelocks. It is a general purpose
|
||||
/// MTP abstraction. For locktimes please see [`locktime::relative::MtpInterval`].
|
||||
/// MTP abstraction. For locktimes please see [`locktime::relative::NumberOf512Seconds`].
|
||||
///
|
||||
/// This is a thin wrapper around a `u32` that may take on all values of a `u32`.
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
|
@ -234,7 +236,7 @@ impl_u32_wrapper! {
|
|||
}
|
||||
|
||||
impl BlockMtpInterval {
|
||||
/// Converts a [`BlockMtpInterval`] to a [`locktime::relative::MtpInterval`], rounding down.
|
||||
/// Converts a [`BlockMtpInterval`] to a [`locktime::relative::NumberOf512Seconds`], rounding down.
|
||||
///
|
||||
/// Relative timelock MTP intervals have a resolution of 512 seconds, while
|
||||
/// [`BlockMtpInterval`], like all block timestamp types, has a one-second resolution.
|
||||
|
@ -246,11 +248,11 @@ impl BlockMtpInterval {
|
|||
#[inline]
|
||||
pub const fn to_relative_mtp_interval_floor(
|
||||
self,
|
||||
) -> Result<relative::MtpInterval, relative::TimeOverflowError> {
|
||||
relative::MtpInterval::from_seconds_floor(self.to_u32())
|
||||
) -> Result<relative::NumberOf512Seconds, relative::TimeOverflowError> {
|
||||
relative::NumberOf512Seconds::from_seconds_floor(self.to_u32())
|
||||
}
|
||||
|
||||
/// Converts a [`BlockMtpInterval`] to a [`locktime::relative::MtpInterval`], rounding up.
|
||||
/// Converts a [`BlockMtpInterval`] to a [`locktime::relative::NumberOf512Seconds`], rounding up.
|
||||
///
|
||||
/// Relative timelock MTP intervals have a resolution of 512 seconds, while
|
||||
/// [`BlockMtpInterval`], like all block timestamp types, has a one-second resolution.
|
||||
|
@ -262,8 +264,8 @@ impl BlockMtpInterval {
|
|||
#[inline]
|
||||
pub const fn to_relative_mtp_interval_ceil(
|
||||
self,
|
||||
) -> Result<relative::MtpInterval, relative::TimeOverflowError> {
|
||||
relative::MtpInterval::from_seconds_ceil(self.to_u32())
|
||||
) -> Result<relative::NumberOf512Seconds, relative::TimeOverflowError> {
|
||||
relative::NumberOf512Seconds::from_seconds_ceil(self.to_u32())
|
||||
}
|
||||
|
||||
/// Attempt to subtract two [`BlockMtpInterval`]s, returning `None` in case of overflow.
|
||||
|
@ -273,32 +275,32 @@ impl BlockMtpInterval {
|
|||
pub fn checked_add(self, other: Self) -> Option<Self> { self.0.checked_add(other.0).map(Self) }
|
||||
}
|
||||
|
||||
impl From<relative::MtpInterval> for BlockMtpInterval {
|
||||
/// Converts a [`locktime::relative::MtpInterval`] to a [`BlockMtpInterval `].
|
||||
impl From<relative::NumberOf512Seconds> for BlockMtpInterval {
|
||||
/// Converts a [`locktime::relative::NumberOf512Seconds`] to a [`BlockMtpInterval `].
|
||||
///
|
||||
/// A relative locktime MTP interval has a resolution of 512 seconds, and a maximum value
|
||||
/// of `u16::MAX` 512-second intervals. [`BlockMtpInterval`] may take the full range of
|
||||
/// `u32`.
|
||||
fn from(h: relative::MtpInterval) -> Self { Self::from_u32(h.to_seconds()) }
|
||||
fn from(h: relative::NumberOf512Seconds) -> Self { Self::from_u32(h.to_seconds()) }
|
||||
}
|
||||
|
||||
/// Error returned when the block interval is too big to be used as a relative lock time.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct TooBigForRelativeBlockHeightIntervalError(u32);
|
||||
pub struct TooBigForRelativeHeightError(u32);
|
||||
|
||||
impl fmt::Display for TooBigForRelativeBlockHeightIntervalError {
|
||||
impl fmt::Display for TooBigForRelativeHeightError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"block interval is too big to be used as a relative lock time: {} (max: {})",
|
||||
self.0,
|
||||
relative::HeightInterval::MAX
|
||||
relative::NumberOfBlocks::MAX
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for TooBigForRelativeBlockHeightIntervalError {}
|
||||
impl std::error::Error for TooBigForRelativeHeightError {}
|
||||
|
||||
crate::internal_macros::impl_op_for_references! {
|
||||
// height - height = interval
|
||||
|
@ -454,15 +456,15 @@ mod tests {
|
|||
assert_eq!(interval, 100);
|
||||
|
||||
let interval_from_height: BlockHeightInterval =
|
||||
relative::HeightInterval::from(10u16).into();
|
||||
relative::NumberOfBlocks::from(10u16).into();
|
||||
assert_eq!(interval_from_height.to_u32(), 10u32);
|
||||
|
||||
let invalid_height_greater =
|
||||
relative::HeightInterval::try_from(BlockHeightInterval(u32::from(u16::MAX) + 1));
|
||||
relative::NumberOfBlocks::try_from(BlockHeightInterval(u32::from(u16::MAX) + 1));
|
||||
assert!(invalid_height_greater.is_err());
|
||||
|
||||
let valid_height =
|
||||
relative::HeightInterval::try_from(BlockHeightInterval(u32::from(u16::MAX)));
|
||||
relative::NumberOfBlocks::try_from(BlockHeightInterval(u32::from(u16::MAX)));
|
||||
assert!(valid_height.is_ok());
|
||||
}
|
||||
|
||||
|
|
|
@ -14,9 +14,8 @@
|
|||
use core::ops;
|
||||
|
||||
use NumOpResult as R;
|
||||
use crate::NumOpError as E;
|
||||
|
||||
use crate::{Amount, FeeRate, MathOp, NumOpResult, OptionExt, Weight};
|
||||
use crate::{Amount, FeeRate, MathOp, NumOpError as E, NumOpResult, OptionExt, Weight};
|
||||
|
||||
impl Amount {
|
||||
/// Checked weight ceiling division.
|
||||
|
@ -119,7 +118,9 @@ impl FeeRate {
|
|||
/// [`NumOpResult::Error`] if an overflow occurred.
|
||||
///
|
||||
/// This is equivalent to `Self::checked_mul_by_weight()`.
|
||||
pub fn to_fee(self, weight: Weight) -> NumOpResult<Amount> { self.checked_mul_by_weight(weight) }
|
||||
pub fn to_fee(self, weight: Weight) -> NumOpResult<Amount> {
|
||||
self.checked_mul_by_weight(weight)
|
||||
}
|
||||
|
||||
/// Calculates the fee by multiplying this fee rate by weight, in weight units, returning [`None`]
|
||||
/// if an overflow occurred.
|
||||
|
@ -150,7 +151,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().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);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
//! Provides [`Height`] and [`Mtp`] types used by the `rust-bitcoin` `absolute::LockTime` type.
|
||||
//! Provides [`Height`] and [`MedianTimePast`] types used by the `rust-bitcoin` `absolute::LockTime` type.
|
||||
|
||||
use core::convert::Infallible;
|
||||
use core::fmt;
|
||||
|
@ -132,9 +132,9 @@ impl serde::Serialize for Height {
|
|||
}
|
||||
}
|
||||
|
||||
#[deprecated(since = "TBD", note = "use `Mtp` instead")]
|
||||
#[deprecated(since = "TBD", note = "use `MedianTimePast` instead")]
|
||||
#[doc(hidden)]
|
||||
pub type Time = Mtp;
|
||||
pub type Time = MedianTimePast;
|
||||
|
||||
/// The median timestamp of 11 consecutive blocks, representing "the timestamp" of the
|
||||
/// final block for locktime-checking purposes.
|
||||
|
@ -145,16 +145,16 @@ pub type Time = Mtp;
|
|||
/// a quantity which is required by consensus to be monotone and which is difficult
|
||||
/// for any individual miner to manipulate.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct Mtp(u32);
|
||||
pub struct MedianTimePast(u32);
|
||||
|
||||
impl Mtp {
|
||||
impl MedianTimePast {
|
||||
/// The minimum MTP allowable in a locktime (Tue Nov 05 1985 00:53:20 GMT+0000).
|
||||
pub const MIN: Self = Mtp(LOCK_TIME_THRESHOLD);
|
||||
pub const MIN: Self = MedianTimePast(LOCK_TIME_THRESHOLD);
|
||||
|
||||
/// The maximum MTP allowable in a locktime (Sun Feb 07 2106 06:28:15 GMT+0000).
|
||||
pub const MAX: Self = Mtp(u32::MAX);
|
||||
pub const MAX: Self = MedianTimePast(u32::MAX);
|
||||
|
||||
/// Constructs an [`Mtp`] by computing the median‐time‐past from the last 11 block timestamps
|
||||
/// Constructs an [`MedianTimePast`] by computing the median‐time‐past from the last 11 block timestamps
|
||||
///
|
||||
/// Because block timestamps are not monotonic, this function internally sorts them;
|
||||
/// it is therefore not important what order they appear in the array; use whatever
|
||||
|
@ -170,7 +170,7 @@ impl Mtp {
|
|||
crate::BlockMtp::new(timestamps).try_into()
|
||||
}
|
||||
|
||||
/// Constructs a new [`Mtp`] from a big-endian hex-encoded `u32`.
|
||||
/// Constructs a new [`MedianTimePast`] from a big-endian hex-encoded `u32`.
|
||||
///
|
||||
/// The input string may or may not contain a typical hex prefix e.g., `0x`.
|
||||
///
|
||||
|
@ -189,7 +189,7 @@ impl Mtp {
|
|||
|
||||
/// Constructs a new MTP directly from a `u32` value.
|
||||
///
|
||||
/// This function, with [`Mtp::to_u32`], is used to obtain a raw MTP value. It is
|
||||
/// This function, with [`MedianTimePast::to_u32`], is used to obtain a raw MTP value. It is
|
||||
/// **not** used to convert to or from a block timestamp, which is not a MTP.
|
||||
///
|
||||
/// # Errors
|
||||
|
@ -199,10 +199,10 @@ impl Mtp {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use bitcoin_units::locktime::absolute::Mtp;
|
||||
/// use bitcoin_units::locktime::absolute::MedianTimePast;
|
||||
///
|
||||
/// let t: u32 = 1653195600; // May 22nd, 5am UTC.
|
||||
/// let time = Mtp::from_u32(t).expect("invalid time value");
|
||||
/// let time = MedianTimePast::from_u32(t).expect("invalid time value");
|
||||
/// assert_eq!(time.to_consensus_u32(), t);
|
||||
/// ```
|
||||
#[inline]
|
||||
|
@ -214,30 +214,30 @@ impl Mtp {
|
|||
}
|
||||
}
|
||||
|
||||
/// Converts this [`Mtp`] to a raw `u32` value.
|
||||
/// Converts this [`MedianTimePast`] to a raw `u32` value.
|
||||
#[inline]
|
||||
pub const fn to_u32(self) -> u32 { self.0 }
|
||||
}
|
||||
|
||||
impl fmt::Display for Mtp {
|
||||
impl fmt::Display for MedianTimePast {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
|
||||
}
|
||||
|
||||
crate::impl_parse_str!(Mtp, ParseTimeError, parser(Mtp::from_u32));
|
||||
crate::impl_parse_str!(MedianTimePast, ParseTimeError, parser(MedianTimePast::from_u32));
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<'de> serde::Deserialize<'de> for Mtp {
|
||||
impl<'de> serde::Deserialize<'de> for MedianTimePast {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let u = u32::deserialize(deserializer)?;
|
||||
Mtp::from_u32(u).map_err(serde::de::Error::custom)
|
||||
MedianTimePast::from_u32(u).map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl serde::Serialize for Mtp {
|
||||
impl serde::Serialize for MedianTimePast {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
|
@ -383,11 +383,11 @@ impl ParseError {
|
|||
E::ParseInt(ParseIntError { input, bits: _, is_signed: _, source })
|
||||
if *source.kind() == IntErrorKind::PosOverflow =>
|
||||
{
|
||||
// Outputs "failed to parse <input_string> as absolute Height/Mtp (<subject> is above limit <upper_bound>)"
|
||||
// Outputs "failed to parse <input_string> as absolute Height/MedianTimePast (<subject> is above limit <upper_bound>)"
|
||||
write!(
|
||||
f,
|
||||
"{} ({} is above limit {})",
|
||||
input.display_cannot_parse("absolute Height/Mtp"),
|
||||
input.display_cannot_parse("absolute Height/MedianTimePast"),
|
||||
subject,
|
||||
upper_bound
|
||||
)
|
||||
|
@ -395,17 +395,22 @@ impl ParseError {
|
|||
E::ParseInt(ParseIntError { input, bits: _, is_signed: _, source })
|
||||
if *source.kind() == IntErrorKind::NegOverflow =>
|
||||
{
|
||||
// Outputs "failed to parse <input_string> as absolute Height/Mtp (<subject> is below limit <lower_bound>)"
|
||||
// Outputs "failed to parse <input_string> as absolute Height/MedianTimePast (<subject> is below limit <lower_bound>)"
|
||||
write!(
|
||||
f,
|
||||
"{} ({} is below limit {})",
|
||||
input.display_cannot_parse("absolute Height/Mtp"),
|
||||
input.display_cannot_parse("absolute Height/MedianTimePast"),
|
||||
subject,
|
||||
lower_bound
|
||||
)
|
||||
}
|
||||
E::ParseInt(ParseIntError { input, bits: _, is_signed: _, source: _ }) => {
|
||||
write!(f, "{} ({})", input.display_cannot_parse("absolute Height/Mtp"), subject)
|
||||
write!(
|
||||
f,
|
||||
"{} ({})",
|
||||
input.display_cannot_parse("absolute Height/MedianTimePast"),
|
||||
subject
|
||||
)
|
||||
}
|
||||
E::Conversion(value) if *value < i64::from(lower_bound) => {
|
||||
write!(f, "{} {} is below limit {}", subject, value, lower_bound)
|
||||
|
@ -458,17 +463,17 @@ impl<'a> Arbitrary<'a> for Height {
|
|||
}
|
||||
|
||||
#[cfg(feature = "arbitrary")]
|
||||
impl<'a> Arbitrary<'a> for Mtp {
|
||||
impl<'a> Arbitrary<'a> for MedianTimePast {
|
||||
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
|
||||
let choice = u.int_in_range(0..=2)?;
|
||||
match choice {
|
||||
0 => Ok(Mtp::MIN),
|
||||
1 => Ok(Mtp::MAX),
|
||||
0 => Ok(MedianTimePast::MIN),
|
||||
1 => Ok(MedianTimePast::MAX),
|
||||
_ => {
|
||||
let min = Mtp::MIN.to_u32();
|
||||
let max = Mtp::MAX.to_u32();
|
||||
let min = MedianTimePast::MIN.to_u32();
|
||||
let max = MedianTimePast::MAX.to_u32();
|
||||
let t = u.int_in_range(min..=max)?;
|
||||
Ok(Mtp::from_u32(t).unwrap())
|
||||
Ok(MedianTimePast::from_u32(t).unwrap())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -483,21 +488,21 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn time_from_str_hex_happy_path() {
|
||||
let actual = Mtp::from_hex("0x6289C350").unwrap();
|
||||
let expected = Mtp::from_u32(0x6289_C350).unwrap();
|
||||
let actual = MedianTimePast::from_hex("0x6289C350").unwrap();
|
||||
let expected = MedianTimePast::from_u32(0x6289_C350).unwrap();
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn time_from_str_hex_no_prefix_happy_path() {
|
||||
let time = Mtp::from_hex("6289C350").unwrap();
|
||||
assert_eq!(time, Mtp(0x6289_C350));
|
||||
let time = MedianTimePast::from_hex("6289C350").unwrap();
|
||||
assert_eq!(time, MedianTimePast(0x6289_C350));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn time_from_str_hex_invalid_hex_should_err() {
|
||||
let hex = "0xzb93";
|
||||
let result = Mtp::from_hex(hex);
|
||||
let result = MedianTimePast::from_hex(hex);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
|
@ -541,8 +546,8 @@ mod tests {
|
|||
#[test]
|
||||
#[cfg(feature = "serde")]
|
||||
pub fn encode_decode_time() {
|
||||
serde_round_trip!(Mtp::MIN);
|
||||
serde_round_trip!(Mtp::MAX);
|
||||
serde_round_trip!(MedianTimePast::MIN);
|
||||
serde_round_trip!(MedianTimePast::MAX);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -575,12 +580,12 @@ mod tests {
|
|||
];
|
||||
|
||||
// Try various reorderings
|
||||
assert_eq!(Mtp::new(timestamps).unwrap().to_u32(), 500_000_005);
|
||||
assert_eq!(MedianTimePast::new(timestamps).unwrap().to_u32(), 500_000_005);
|
||||
timestamps.reverse();
|
||||
assert_eq!(Mtp::new(timestamps).unwrap().to_u32(), 500_000_005);
|
||||
assert_eq!(MedianTimePast::new(timestamps).unwrap().to_u32(), 500_000_005);
|
||||
timestamps.sort();
|
||||
assert_eq!(Mtp::new(timestamps).unwrap().to_u32(), 500_000_005);
|
||||
assert_eq!(MedianTimePast::new(timestamps).unwrap().to_u32(), 500_000_005);
|
||||
timestamps.reverse();
|
||||
assert_eq!(Mtp::new(timestamps).unwrap().to_u32(), 500_000_005);
|
||||
assert_eq!(MedianTimePast::new(timestamps).unwrap().to_u32(), 500_000_005);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
//! Provides [`Height`] and [`MtpInterval`] types used by the `rust-bitcoin` `relative::LockTime` type.
|
||||
//! Provides [`NumberOfBlocks`] and [`NumberOf512Seconds`] types used by the
|
||||
//! `rust-bitcoin` `relative::LockTime` type.
|
||||
|
||||
use core::fmt;
|
||||
|
||||
|
@ -9,16 +10,16 @@ use arbitrary::{Arbitrary, Unstructured};
|
|||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[deprecated(since = "TBD", note = "use `HeightIterval` instead")]
|
||||
#[deprecated(since = "TBD", note = "use `NumberOfBlocks` instead")]
|
||||
#[doc(hidden)]
|
||||
pub type Height = HeightInterval;
|
||||
pub type Height = NumberOfBlocks;
|
||||
|
||||
/// A relative lock time lock-by-blockheight value.
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct HeightInterval(u16);
|
||||
pub struct NumberOfBlocks(u16);
|
||||
|
||||
impl HeightInterval {
|
||||
impl NumberOfBlocks {
|
||||
/// Relative block height 0, can be included in any block.
|
||||
pub const ZERO: Self = Self(0);
|
||||
|
||||
|
@ -28,7 +29,7 @@ impl HeightInterval {
|
|||
/// The maximum relative block height.
|
||||
pub const MAX: Self = Self(u16::MAX);
|
||||
|
||||
/// Constructs a new [`HeightInterval`] using a count of blocks.
|
||||
/// Constructs a new [`NumberOfBlocks`] using a count of blocks.
|
||||
#[inline]
|
||||
pub const fn from_height(blocks: u16) -> Self { Self(blocks) }
|
||||
|
||||
|
@ -80,51 +81,51 @@ impl HeightInterval {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<u16> for HeightInterval {
|
||||
impl From<u16> for NumberOfBlocks {
|
||||
#[inline]
|
||||
fn from(value: u16) -> Self { HeightInterval(value) }
|
||||
fn from(value: u16) -> Self { NumberOfBlocks(value) }
|
||||
}
|
||||
|
||||
crate::impl_parse_str_from_int_infallible!(HeightInterval, u16, from);
|
||||
crate::impl_parse_str_from_int_infallible!(NumberOfBlocks, u16, from);
|
||||
|
||||
impl fmt::Display for HeightInterval {
|
||||
impl fmt::Display for NumberOfBlocks {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
|
||||
}
|
||||
|
||||
#[deprecated(since = "TBD", note = "use `Mtp` instead")]
|
||||
#[deprecated(since = "TBD", note = "use `NumberOf512Seconds` instead")]
|
||||
#[doc(hidden)]
|
||||
pub type Time = MtpInterval;
|
||||
pub type Time = NumberOf512Seconds;
|
||||
|
||||
/// A relative lock time lock-by-blocktime value.
|
||||
///
|
||||
/// For BIP 68 relative lock-by-blocktime locks, time is measured in 512 second intervals.
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct MtpInterval(u16);
|
||||
pub struct NumberOf512Seconds(u16);
|
||||
|
||||
impl MtpInterval {
|
||||
impl NumberOf512Seconds {
|
||||
/// Relative block time 0, can be included in any block.
|
||||
pub const ZERO: Self = MtpInterval(0);
|
||||
pub const ZERO: Self = NumberOf512Seconds(0);
|
||||
|
||||
/// The minimum relative block time (0), can be included in any block.
|
||||
pub const MIN: Self = MtpInterval::ZERO;
|
||||
pub const MIN: Self = NumberOf512Seconds::ZERO;
|
||||
|
||||
/// The maximum relative block time (33,554,432 seconds or approx 388 days).
|
||||
pub const MAX: Self = MtpInterval(u16::MAX);
|
||||
pub const MAX: Self = NumberOf512Seconds(u16::MAX);
|
||||
|
||||
/// Constructs a new [`MtpInterval`] using time intervals where each interval is equivalent to 512 seconds.
|
||||
/// Constructs a new [`NumberOf512Seconds`] using time intervals where each interval is equivalent to 512 seconds.
|
||||
///
|
||||
/// Encoding finer granularity of time for relative lock-times is not supported in Bitcoin.
|
||||
#[inline]
|
||||
pub const fn from_512_second_intervals(intervals: u16) -> Self { MtpInterval(intervals) }
|
||||
pub const fn from_512_second_intervals(intervals: u16) -> Self { NumberOf512Seconds(intervals) }
|
||||
|
||||
/// Express the [`MtpInterval`] as an integer number of 512-second intervals.
|
||||
/// Express the [`NumberOf512Seconds`] as an integer number of 512-second intervals.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn to_512_second_intervals(self) -> u16 { self.0 }
|
||||
|
||||
/// Constructs a new [`MtpInterval`] from seconds, converting the seconds into 512 second interval with
|
||||
/// truncating division.
|
||||
/// Constructs a new [`NumberOf512Seconds`] from seconds, converting the seconds into 512 second
|
||||
/// interval with truncating division.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
|
@ -134,14 +135,14 @@ impl MtpInterval {
|
|||
pub const fn from_seconds_floor(seconds: u32) -> Result<Self, TimeOverflowError> {
|
||||
let interval = seconds / 512;
|
||||
if interval <= u16::MAX as u32 { // infallible cast, needed by const code
|
||||
Ok(MtpInterval::from_512_second_intervals(interval as u16)) // Cast checked above, needed by const code.
|
||||
Ok(NumberOf512Seconds::from_512_second_intervals(interval as u16)) // Cast checked above, needed by const code.
|
||||
} else {
|
||||
Err(TimeOverflowError { seconds })
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs a new [`MtpInterval`] from seconds, converting the seconds into 512 second intervals with
|
||||
/// ceiling division.
|
||||
/// Constructs a new [`NumberOf512Seconds`] from seconds, converting the seconds into 512 second
|
||||
/// intervals with ceiling division.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
|
@ -151,13 +152,13 @@ impl MtpInterval {
|
|||
pub const fn from_seconds_ceil(seconds: u32) -> Result<Self, TimeOverflowError> {
|
||||
if seconds <= u16::MAX as u32 * 512 {
|
||||
let interval = (seconds + 511) / 512;
|
||||
Ok(MtpInterval::from_512_second_intervals(interval as u16)) // Cast checked above, needed by const code.
|
||||
Ok(NumberOf512Seconds::from_512_second_intervals(interval as u16)) // Cast checked above, needed by const code.
|
||||
} else {
|
||||
Err(TimeOverflowError { seconds })
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the [`MtpInterval`] as an integer number of seconds.
|
||||
/// Represents the [`NumberOf512Seconds`] as an integer number of seconds.
|
||||
#[inline]
|
||||
pub const fn to_seconds(self) -> u32 {
|
||||
self.0 as u32 * 512 // u16->u32 cast ok, const context
|
||||
|
@ -206,9 +207,9 @@ impl MtpInterval {
|
|||
}
|
||||
}
|
||||
|
||||
crate::impl_parse_str_from_int_infallible!(MtpInterval, u16, from_512_second_intervals);
|
||||
crate::impl_parse_str_from_int_infallible!(NumberOf512Seconds, u16, from_512_second_intervals);
|
||||
|
||||
impl fmt::Display for MtpInterval {
|
||||
impl fmt::Display for NumberOf512Seconds {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
|
||||
}
|
||||
|
||||
|
@ -246,27 +247,27 @@ impl fmt::Display for TimeOverflowError {
|
|||
impl std::error::Error for TimeOverflowError {}
|
||||
|
||||
#[cfg(feature = "arbitrary")]
|
||||
impl<'a> Arbitrary<'a> for HeightInterval {
|
||||
impl<'a> Arbitrary<'a> for NumberOfBlocks {
|
||||
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
|
||||
let choice = u.int_in_range(0..=2)?;
|
||||
|
||||
match choice {
|
||||
0 => Ok(HeightInterval::MIN),
|
||||
1 => Ok(HeightInterval::MAX),
|
||||
_ => Ok(HeightInterval::from_height(u16::arbitrary(u)?)),
|
||||
0 => Ok(NumberOfBlocks::MIN),
|
||||
1 => Ok(NumberOfBlocks::MAX),
|
||||
_ => Ok(NumberOfBlocks::from_height(u16::arbitrary(u)?)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary")]
|
||||
impl<'a> Arbitrary<'a> for MtpInterval {
|
||||
impl<'a> Arbitrary<'a> for NumberOf512Seconds {
|
||||
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
|
||||
let choice = u.int_in_range(0..=2)?;
|
||||
|
||||
match choice {
|
||||
0 => Ok(MtpInterval::MIN),
|
||||
1 => Ok(MtpInterval::MAX),
|
||||
_ => Ok(MtpInterval::from_512_second_intervals(u16::arbitrary(u)?)),
|
||||
0 => Ok(NumberOf512Seconds::MIN),
|
||||
1 => Ok(NumberOf512Seconds::MAX),
|
||||
_ => Ok(NumberOf512Seconds::from_512_second_intervals(u16::arbitrary(u)?)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -284,72 +285,76 @@ mod tests {
|
|||
#[test]
|
||||
#[allow(deprecated_in_future)]
|
||||
fn sanity_check() {
|
||||
assert_eq!(HeightInterval::MAX.to_consensus_u32(), u32::from(u16::MAX));
|
||||
assert_eq!(MtpInterval::from_512_second_intervals(100).value(), 100u16);
|
||||
assert_eq!(MtpInterval::from_512_second_intervals(100).to_consensus_u32(), 4_194_404u32); // 0x400064
|
||||
assert_eq!(NumberOfBlocks::MAX.to_consensus_u32(), u32::from(u16::MAX));
|
||||
assert_eq!(NumberOf512Seconds::from_512_second_intervals(100).value(), 100u16);
|
||||
assert_eq!(
|
||||
NumberOf512Seconds::from_512_second_intervals(100).to_consensus_u32(),
|
||||
4_194_404u32
|
||||
); // 0x400064
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_seconds_ceil_success() {
|
||||
let actual = MtpInterval::from_seconds_ceil(100).unwrap();
|
||||
let expected = MtpInterval(1_u16);
|
||||
let actual = NumberOf512Seconds::from_seconds_ceil(100).unwrap();
|
||||
let expected = NumberOf512Seconds(1_u16);
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_seconds_ceil_with_maximum_encodable_seconds_success() {
|
||||
let actual = MtpInterval::from_seconds_ceil(MAXIMUM_ENCODABLE_SECONDS).unwrap();
|
||||
let expected = MtpInterval(u16::MAX);
|
||||
let actual = NumberOf512Seconds::from_seconds_ceil(MAXIMUM_ENCODABLE_SECONDS).unwrap();
|
||||
let expected = NumberOf512Seconds(u16::MAX);
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_seconds_ceil_causes_time_overflow_error() {
|
||||
let result = MtpInterval::from_seconds_ceil(MAXIMUM_ENCODABLE_SECONDS + 1);
|
||||
let result = NumberOf512Seconds::from_seconds_ceil(MAXIMUM_ENCODABLE_SECONDS + 1);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_seconds_floor_success() {
|
||||
let actual = MtpInterval::from_seconds_floor(100).unwrap();
|
||||
let expected = MtpInterval(0_u16);
|
||||
let actual = NumberOf512Seconds::from_seconds_floor(100).unwrap();
|
||||
let expected = NumberOf512Seconds(0_u16);
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_seconds_floor_with_exact_interval() {
|
||||
let actual = MtpInterval::from_seconds_floor(512).unwrap();
|
||||
let expected = MtpInterval(1_u16);
|
||||
let actual = NumberOf512Seconds::from_seconds_floor(512).unwrap();
|
||||
let expected = NumberOf512Seconds(1_u16);
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_seconds_floor_with_maximum_encodable_seconds_success() {
|
||||
let actual = MtpInterval::from_seconds_floor(MAXIMUM_ENCODABLE_SECONDS + 511).unwrap();
|
||||
let expected = MtpInterval(u16::MAX);
|
||||
let actual =
|
||||
NumberOf512Seconds::from_seconds_floor(MAXIMUM_ENCODABLE_SECONDS + 511).unwrap();
|
||||
let expected = NumberOf512Seconds(u16::MAX);
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_seconds_floor_causes_time_overflow_error() {
|
||||
let result = MtpInterval::from_seconds_floor(MAXIMUM_ENCODABLE_SECONDS + 512);
|
||||
let result = NumberOf512Seconds::from_seconds_floor(MAXIMUM_ENCODABLE_SECONDS + 512);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "serde")]
|
||||
pub fn encode_decode_height() {
|
||||
serde_round_trip!(HeightInterval::ZERO);
|
||||
serde_round_trip!(HeightInterval::MIN);
|
||||
serde_round_trip!(HeightInterval::MAX);
|
||||
serde_round_trip!(NumberOfBlocks::ZERO);
|
||||
serde_round_trip!(NumberOfBlocks::MIN);
|
||||
serde_round_trip!(NumberOfBlocks::MAX);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "serde")]
|
||||
pub fn encode_decode_time() {
|
||||
serde_round_trip!(MtpInterval::ZERO);
|
||||
serde_round_trip!(MtpInterval::MIN);
|
||||
serde_round_trip!(MtpInterval::MAX);
|
||||
serde_round_trip!(NumberOf512Seconds::ZERO);
|
||||
serde_round_trip!(NumberOf512Seconds::MIN);
|
||||
serde_round_trip!(NumberOf512Seconds::MAX);
|
||||
}
|
||||
|
||||
fn generate_timestamps(start: u32, step: u16) -> [BlockTime; 11] {
|
||||
|
@ -375,7 +380,7 @@ mod tests {
|
|||
|
||||
// Test case 1: Satisfaction (current_mtp >= utxo_mtp + required_seconds)
|
||||
// 10 intervals × 512 seconds = 5120 seconds
|
||||
let time_lock = MtpInterval::from_512_second_intervals(10);
|
||||
let time_lock = NumberOf512Seconds::from_512_second_intervals(10);
|
||||
let chain_state1 = BlockMtp::new(timestamps);
|
||||
let utxo_state1 = BlockMtp::new(utxo_timestamps);
|
||||
assert!(time_lock.is_satisfied_by(chain_state1, utxo_state1));
|
||||
|
@ -386,13 +391,13 @@ mod tests {
|
|||
assert!(!time_lock.is_satisfied_by(chain_state2, utxo_state2));
|
||||
|
||||
// Test case 3: Test with a larger value (100 intervals = 51200 seconds)
|
||||
let larger_lock = MtpInterval::from_512_second_intervals(100);
|
||||
let larger_lock = NumberOf512Seconds::from_512_second_intervals(100);
|
||||
let chain_state3 = BlockMtp::new(timestamps3);
|
||||
let utxo_state3 = BlockMtp::new(utxo_timestamps3);
|
||||
assert!(larger_lock.is_satisfied_by(chain_state3, utxo_state3));
|
||||
|
||||
// Test case 4: Overflow handling - tests that is_satisfied_by handles overflow gracefully
|
||||
let max_time_lock = MtpInterval::MAX;
|
||||
let max_time_lock = NumberOf512Seconds::MAX;
|
||||
let chain_state4 = BlockMtp::new(timestamps);
|
||||
let utxo_state4 = BlockMtp::new(utxo_timestamps);
|
||||
assert!(!max_time_lock.is_satisfied_by(chain_state4, utxo_state4));
|
||||
|
@ -402,7 +407,7 @@ mod tests {
|
|||
fn test_height_chain_state() {
|
||||
use crate::BlockHeight;
|
||||
|
||||
let height_lock = HeightInterval(10);
|
||||
let height_lock = NumberOfBlocks(10);
|
||||
|
||||
// Test case 1: Satisfaction (current_height >= utxo_height + required)
|
||||
let chain_state1 = BlockHeight::from_u32(100);
|
||||
|
@ -415,7 +420,7 @@ mod tests {
|
|||
assert!(!height_lock.is_satisfied_by(chain_state2, utxo_state2));
|
||||
|
||||
// Test case 3: Overflow handling - tests that is_satisfied_by handles overflow gracefully
|
||||
let max_height_lock = HeightInterval::MAX;
|
||||
let max_height_lock = NumberOfBlocks::MAX;
|
||||
let chain_state3 = BlockHeight::from_u32(1000);
|
||||
let utxo_state3 = BlockHeight::from_u32(80);
|
||||
assert!(!max_height_lock.is_satisfied_by(chain_state3, utxo_state3));
|
||||
|
|
|
@ -38,7 +38,7 @@ struct Structs {
|
|||
e: BlockInterval,
|
||||
f: FeeRate,
|
||||
g: absolute::Height,
|
||||
h: absolute::Mtp,
|
||||
h: absolute::MedianTimePast,
|
||||
i: relative::Height,
|
||||
j: relative::Time,
|
||||
k: Weight,
|
||||
|
@ -57,7 +57,7 @@ impl Structs {
|
|||
e: BlockInterval::MAX,
|
||||
f: FeeRate::MAX,
|
||||
g: absolute::Height::MAX,
|
||||
h: absolute::Mtp::MAX,
|
||||
h: absolute::MedianTimePast::MAX,
|
||||
i: relative::Height::MAX,
|
||||
j: relative::Time::MAX,
|
||||
k: Weight::MAX,
|
||||
|
@ -89,7 +89,7 @@ struct CommonTraits {
|
|||
e: BlockInterval,
|
||||
f: FeeRate,
|
||||
g: absolute::Height,
|
||||
h: absolute::Mtp,
|
||||
h: absolute::MedianTimePast,
|
||||
i: relative::Height,
|
||||
j: relative::Time,
|
||||
k: Weight,
|
||||
|
@ -135,7 +135,7 @@ struct Errors {
|
|||
t: amount::PossiblyConfusingDenominationError,
|
||||
u: amount::TooPreciseError,
|
||||
v: amount::UnknownDenominationError,
|
||||
w: block::TooBigForRelativeBlockHeightIntervalError,
|
||||
w: block::TooBigForRelativeHeightError,
|
||||
x: locktime::absolute::ConversionError,
|
||||
y: locktime::absolute::Height,
|
||||
z: locktime::absolute::ParseHeightError,
|
||||
|
@ -171,9 +171,7 @@ fn api_can_use_all_types_from_module_amount() {
|
|||
|
||||
#[test]
|
||||
fn api_can_use_all_types_from_module_block() {
|
||||
use bitcoin_units::block::{
|
||||
BlockHeight, BlockHeightInterval, TooBigForRelativeBlockHeightIntervalError,
|
||||
};
|
||||
use bitcoin_units::block::{BlockHeight, BlockHeightInterval, TooBigForRelativeHeightError};
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -184,7 +182,7 @@ fn api_can_use_all_types_from_module_fee_rate() {
|
|||
#[test]
|
||||
fn api_can_use_all_types_from_module_locktime_absolute() {
|
||||
use bitcoin_units::locktime::absolute::{
|
||||
ConversionError, Height, Mtp, ParseHeightError, ParseTimeError,
|
||||
ConversionError, Height, MedianTimePast, ParseHeightError, ParseTimeError,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -302,7 +300,7 @@ impl<'a> Arbitrary<'a> for Structs {
|
|||
e: BlockInterval::arbitrary(u)?,
|
||||
f: FeeRate::arbitrary(u)?,
|
||||
g: absolute::Height::arbitrary(u)?,
|
||||
h: absolute::Mtp::arbitrary(u)?,
|
||||
h: absolute::MedianTimePast::arbitrary(u)?,
|
||||
i: relative::Height::arbitrary(u)?,
|
||||
j: relative::Time::arbitrary(u)?,
|
||||
k: Weight::arbitrary(u)?,
|
||||
|
|
|
@ -47,7 +47,7 @@ struct Serde {
|
|||
a: BlockHeight,
|
||||
b: BlockInterval,
|
||||
c: absolute::Height,
|
||||
d: absolute::Mtp,
|
||||
d: absolute::MedianTimePast,
|
||||
e: relative::Height,
|
||||
f: relative::Time,
|
||||
g: Weight,
|
||||
|
@ -80,7 +80,7 @@ impl Serde {
|
|||
a: BlockHeight::MAX,
|
||||
b: BlockInterval::MAX,
|
||||
c: absolute::Height::MAX,
|
||||
d: absolute::Mtp::MAX,
|
||||
d: absolute::MedianTimePast::MAX,
|
||||
e: relative::Height::MAX,
|
||||
f: relative::Time::MAX,
|
||||
g: Weight::MAX,
|
||||
|
|
Loading…
Reference in New Issue