diff --git a/primitives/src/locktime/relative.rs b/primitives/src/locktime/relative.rs index 8b7278c60..0bfefc83f 100644 --- a/primitives/src/locktime/relative.rs +++ b/primitives/src/locktime/relative.rs @@ -129,7 +129,8 @@ impl LockTime { pub fn to_consensus_u32(self) -> u32 { match self { LockTime::Blocks(ref h) => h.to_consensus_u32(), - LockTime::Time(ref t) => t.to_consensus_u32(), + LockTime::Time(ref t) => + Sequence::LOCK_TYPE_MASK | u32::from(t.to_512_second_intervals()), } } @@ -289,8 +290,8 @@ impl LockTime { use LockTime as L; match (self, other) { - (L::Blocks(this), L::Blocks(other)) => this.value() <= other.value(), - (L::Time(this), L::Time(other)) => this.value() <= other.value(), + (L::Blocks(this), L::Blocks(other)) => this <= other, + (L::Time(this), L::Time(other)) => this <= other, _ => false, // Not the same units. } } @@ -371,7 +372,7 @@ impl LockTime { use LockTime as L; match self { - L::Time(ref t) => Ok(t.value() <= time.value()), + L::Time(ref t) => Ok(t.to_512_second_intervals() <= time.to_512_second_intervals()), L::Blocks(height) => Err(IncompatibleTimeError { time, height }), } } diff --git a/primitives/src/sequence.rs b/primitives/src/sequence.rs index a08b31615..98e42b50f 100644 --- a/primitives/src/sequence.rs +++ b/primitives/src/sequence.rs @@ -70,7 +70,7 @@ impl Sequence { /// BIP-68 relative lock time disable flag mask. const LOCK_TIME_DISABLE_FLAG_MASK: u32 = 0x8000_0000; /// BIP-68 relative lock time type flag mask. - const LOCK_TYPE_MASK: u32 = 0x0040_0000; + pub(super) const LOCK_TYPE_MASK: u32 = 0x0040_0000; /// Returns `true` if the sequence number enables absolute lock-time ([`Transaction::lock_time`]). #[inline] @@ -263,8 +263,14 @@ impl<'a> Arbitrary<'a> for Sequence { 3 => Ok(Sequence::ENABLE_LOCKTIME_AND_RBF), 4 => Ok(Sequence::from_consensus(relative::Height::MIN.to_consensus_u32())), 5 => Ok(Sequence::from_consensus(relative::Height::MAX.to_consensus_u32())), - 6 => Ok(Sequence::from_consensus(relative::MtpInterval::MIN.to_consensus_u32())), - 7 => Ok(Sequence::from_consensus(relative::MtpInterval::MAX.to_consensus_u32())), + 6 => Ok(Sequence::from_consensus( + Sequence::LOCK_TYPE_MASK + | u32::from(relative::MtpInterval::MIN.to_512_second_intervals()), + )), + 7 => Ok(Sequence::from_consensus( + Sequence::LOCK_TYPE_MASK + | u32::from(relative::MtpInterval::MAX.to_512_second_intervals()), + )), _ => Ok(Sequence(u.arbitrary()?)), } } diff --git a/units/src/locktime/relative.rs b/units/src/locktime/relative.rs index 15dd397ae..f027acbca 100644 --- a/units/src/locktime/relative.rs +++ b/units/src/locktime/relative.rs @@ -101,6 +101,11 @@ impl MtpInterval { #[inline] pub const fn from_512_second_intervals(intervals: u16) -> Self { MtpInterval(intervals) } + /// Express the [`MtpInterval`] 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. /// @@ -138,11 +143,16 @@ impl MtpInterval { /// Returns the inner `u16` value. #[inline] #[must_use] + #[deprecated(since = "TBD", note = "use `to_512_second_intervals` instead")] + #[doc(hidden)] pub const fn value(self) -> u16 { self.0 } /// Returns the `u32` value used to encode this locktime in an nSequence field or /// argument to `OP_CHECKSEQUENCEVERIFY`. - #[inline] + #[deprecated( + since = "TBD", + note = "use `LockTime::from` followed by `to_consensus_u32` instead" + )] pub const fn to_consensus_u32(self) -> u32 { (1u32 << 22) | self.0 as u32 // cast safety: u32 is wider than u16 on all architectures } @@ -159,7 +169,7 @@ impl MtpInterval { /// - `true` if the relative‐time lock has expired by the tip’s MTP /// - `false` if the lock has not yet expired by the tip’s MTP pub fn is_satisfied_by(self, chain_tip: MtpAndHeight, utxo_mined_at: MtpAndHeight) -> bool { - match u32::from(self.value()).checked_mul(512) { + match u32::from(self.to_512_second_intervals()).checked_mul(512) { Some(seconds) => match seconds.checked_add(utxo_mined_at.to_mtp().to_u32()) { Some(required_seconds) => chain_tip.to_mtp().to_u32() >= required_seconds, None => false, @@ -245,6 +255,7 @@ mod tests { const MAXIMUM_ENCODABLE_SECONDS: u32 = u16::MAX as u32 * 512; #[test] + #[allow(deprecated_in_future)] fn sanity_check() { assert_eq!(Height::MAX.to_consensus_u32(), u32::from(u16::MAX)); assert_eq!(MtpInterval::from_512_second_intervals(100).value(), 100u16);