units: rename absolute::Mtp consensus functions
There is no "consensus encoding" for a MTP. The intention for these methods was that a user could interpret the MTP as a locktime and then consensus-encode that locktime. However, it was instead interpreted as the MTP representing a *blocktime* as it is consensus-encoded in a block header. Evidence of this misinterpretation is in several doccomments, which casually refer to the Mtp (which used to be just called Time) as a "block time", which is simply incorrect.
This commit is contained in:
parent
8ffcd2cf30
commit
5a8f33f380
|
@ -147,7 +147,7 @@ impl LockTime {
|
||||||
if units::locktime::absolute::is_block_height(n) {
|
if units::locktime::absolute::is_block_height(n) {
|
||||||
Self::Blocks(Height::from_consensus(n).expect("n is valid"))
|
Self::Blocks(Height::from_consensus(n).expect("n is valid"))
|
||||||
} else {
|
} else {
|
||||||
Self::Seconds(Mtp::from_consensus(n).expect("n is valid"))
|
Self::Seconds(Mtp::from_u32(n).expect("n is valid"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,13 +174,19 @@ impl LockTime {
|
||||||
Ok(LockTime::Blocks(height))
|
Ok(LockTime::Blocks(height))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a new `LockTime` from `n`, expecting `n` to be a valid block time.
|
#[inline]
|
||||||
|
#[deprecated(since = "TBD", note = "use `from_mtp` instead")]
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub fn from_time(n: u32) -> Result<Self, ConversionError> { Self::from_mtp(n) }
|
||||||
|
|
||||||
|
/// Constructs a new `LockTime` from `n`, expecting `n` to be a median-time-past (MTP)
|
||||||
|
/// which is in range for a locktime.
|
||||||
///
|
///
|
||||||
/// # Note
|
/// # Note
|
||||||
///
|
///
|
||||||
/// If the locktime is set to a timestamp `T`,
|
/// If the locktime is set to an MTP `T`, the transaction can be included in a block only if
|
||||||
/// the transaction can be included in a block only if the median time past (MTP) of the
|
/// the MTP of last recent 11 blocks is greater than `T`.
|
||||||
/// last 11 blocks is greater than `T`.
|
///
|
||||||
/// It is possible to broadcast the transaction once the MTP is greater than `T`.[see BIP-113]
|
/// It is possible to broadcast the transaction once the MTP is greater than `T`.[see BIP-113]
|
||||||
///
|
///
|
||||||
/// [BIP-113 Median time-past as endpoint for lock-time calculations](https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki)
|
/// [BIP-113 Median time-past as endpoint for lock-time calculations](https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki)
|
||||||
|
@ -195,8 +201,8 @@ impl LockTime {
|
||||||
/// assert!(absolute::LockTime::from_time(741521).is_err());
|
/// assert!(absolute::LockTime::from_time(741521).is_err());
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_time(n: u32) -> Result<Self, ConversionError> {
|
pub fn from_mtp(n: u32) -> Result<Self, ConversionError> {
|
||||||
let time = Mtp::from_consensus(n)?;
|
let time = Mtp::from_u32(n)?;
|
||||||
Ok(LockTime::Seconds(time))
|
Ok(LockTime::Seconds(time))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,7 +315,7 @@ impl LockTime {
|
||||||
pub fn to_consensus_u32(self) -> u32 {
|
pub fn to_consensus_u32(self) -> u32 {
|
||||||
match self {
|
match self {
|
||||||
LockTime::Blocks(ref h) => h.to_consensus_u32(),
|
LockTime::Blocks(ref h) => h.to_consensus_u32(),
|
||||||
LockTime::Seconds(ref t) => t.to_consensus_u32(),
|
LockTime::Seconds(ref t) => t.to_u32(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -410,7 +416,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn display_and_alternate() {
|
fn display_and_alternate() {
|
||||||
let lock_by_height = LockTime::from_height(741_521).unwrap();
|
let lock_by_height = LockTime::from_height(741_521).unwrap();
|
||||||
let lock_by_time = LockTime::from_time(1_653_195_600).unwrap(); // May 22nd 2022, 5am UTC.
|
let lock_by_time = LockTime::from_mtp(1_653_195_600).unwrap(); // May 22nd 2022, 5am UTC.
|
||||||
|
|
||||||
assert_eq!(format!("{}", lock_by_height), "741521");
|
assert_eq!(format!("{}", lock_by_height), "741521");
|
||||||
assert_eq!(format!("{:#}", lock_by_height), "block-height 741521");
|
assert_eq!(format!("{:#}", lock_by_height), "block-height 741521");
|
||||||
|
@ -466,9 +472,9 @@ mod tests {
|
||||||
assert!(LockTime::from_height(500_000_000).is_err()); // The threshold.
|
assert!(LockTime::from_height(500_000_000).is_err()); // The threshold.
|
||||||
assert!(LockTime::from_height(500_000_001).is_err()); // Above the threshold.
|
assert!(LockTime::from_height(500_000_001).is_err()); // Above the threshold.
|
||||||
|
|
||||||
assert!(LockTime::from_time(499_999_999).is_err()); // Below the threshold.
|
assert!(LockTime::from_mtp(499_999_999).is_err()); // Below the threshold.
|
||||||
assert!(LockTime::from_time(500_000_000).is_ok()); // The threshold.
|
assert!(LockTime::from_mtp(500_000_000).is_ok()); // The threshold.
|
||||||
assert!(LockTime::from_time(500_000_001).is_ok()); // Above the threshold.
|
assert!(LockTime::from_mtp(500_000_001).is_ok()); // Above the threshold.
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -500,7 +506,7 @@ mod tests {
|
||||||
let lock_by_height = LockTime::from(height);
|
let lock_by_height = LockTime::from(height);
|
||||||
|
|
||||||
let t: u32 = 1_653_195_600; // May 22nd, 5am UTC.
|
let t: u32 = 1_653_195_600; // May 22nd, 5am UTC.
|
||||||
let time = Mtp::from_consensus(t).unwrap();
|
let time = Mtp::from_u32(t).unwrap();
|
||||||
|
|
||||||
assert!(!lock_by_height.is_satisfied_by(height_below, time));
|
assert!(!lock_by_height.is_satisfied_by(height_below, time));
|
||||||
assert!(lock_by_height.is_satisfied_by(height, time));
|
assert!(lock_by_height.is_satisfied_by(height, time));
|
||||||
|
@ -509,9 +515,9 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn satisfied_by_time() {
|
fn satisfied_by_time() {
|
||||||
let time_before = Mtp::from_consensus(1_653_109_200).unwrap(); // "May 21th 2022, 5am UTC.
|
let time_before = Mtp::from_u32(1_653_109_200).unwrap(); // "May 21th 2022, 5am UTC.
|
||||||
let time = Mtp::from_consensus(1_653_195_600).unwrap(); // "May 22nd 2022, 5am UTC.
|
let time = Mtp::from_u32(1_653_195_600).unwrap(); // "May 22nd 2022, 5am UTC.
|
||||||
let time_after = Mtp::from_consensus(1_653_282_000).unwrap(); // "May 23rd 2022, 5am UTC.
|
let time_after = Mtp::from_u32(1_653_282_000).unwrap(); // "May 23rd 2022, 5am UTC.
|
||||||
|
|
||||||
let lock_by_time = LockTime::from(time);
|
let lock_by_time = LockTime::from(time);
|
||||||
|
|
||||||
|
|
|
@ -147,20 +147,31 @@ impl Mtp {
|
||||||
/// The maximum MTP allowable in a locktime (Sun Feb 07 2106 06:28:15 GMT+0000).
|
/// 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 = Mtp(u32::MAX);
|
||||||
|
|
||||||
/// Constructs a new [`Mtp`] from a hex string.
|
/// Constructs a new [`Mtp`] from a big-endian hex-encoded `u32`.
|
||||||
///
|
///
|
||||||
/// The input string may or may not contain a typical hex prefix e.g., `0x`.
|
/// The input string may or may not contain a typical hex prefix e.g., `0x`.
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
/// If the input string is not a valid hex representation of a block time.
|
/// If the input string is not a valid hex representation of a block time.
|
||||||
pub fn from_hex(s: &str) -> Result<Self, ParseTimeError> { parse_hex(s, Self::from_consensus) }
|
pub fn from_hex(s: &str) -> Result<Self, ParseTimeError> { parse_hex(s, Self::from_u32) }
|
||||||
|
|
||||||
/// Constructs a new block time.
|
#[deprecated(since = "TBD", note = "use `from_u32` instead")]
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub const fn from_consensus(n: u32) -> Result<Mtp, ConversionError> { Self::from_u32(n) }
|
||||||
|
|
||||||
|
#[deprecated(since = "TBD", note = "use `to_u32` instead")]
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub const fn to_consensus_u32(self) -> u32 { self.to_u32() }
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
/// **not** used to convert to or from a block timestamp, which is not a MTP.
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
/// If `n` does not encode a valid UNIX time stamp.
|
/// If `n` is not in the allowable range of MTPs in a locktime: `[500_000_000, 2^32 - 1]`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -168,11 +179,11 @@ impl Mtp {
|
||||||
/// use bitcoin_units::locktime::absolute::Mtp;
|
/// use bitcoin_units::locktime::absolute::Mtp;
|
||||||
///
|
///
|
||||||
/// let t: u32 = 1653195600; // May 22nd, 5am UTC.
|
/// let t: u32 = 1653195600; // May 22nd, 5am UTC.
|
||||||
/// let time = Mtp::from_consensus(t).expect("invalid time value");
|
/// let time = Mtp::from_u32(t).expect("invalid time value");
|
||||||
/// assert_eq!(time.to_consensus_u32(), t);
|
/// assert_eq!(time.to_consensus_u32(), t);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn from_consensus(n: u32) -> Result<Mtp, ConversionError> {
|
pub const fn from_u32(n: u32) -> Result<Mtp, ConversionError> {
|
||||||
if is_block_time(n) {
|
if is_block_time(n) {
|
||||||
Ok(Self(n))
|
Ok(Self(n))
|
||||||
} else {
|
} else {
|
||||||
|
@ -180,16 +191,16 @@ impl Mtp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts this [`Mtp`] to its inner `u32` value.
|
/// Converts this [`Mtp`] to a raw `u32` value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn to_consensus_u32(self) -> u32 { self.0 }
|
pub const fn to_u32(self) -> u32 { self.0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Mtp {
|
impl fmt::Display for Mtp {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
|
||||||
}
|
}
|
||||||
|
|
||||||
crate::impl_parse_str!(Mtp, ParseTimeError, parser(Mtp::from_consensus));
|
crate::impl_parse_str!(Mtp, ParseTimeError, parser(Mtp::from_u32));
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
impl<'de> serde::Deserialize<'de> for Mtp {
|
impl<'de> serde::Deserialize<'de> for Mtp {
|
||||||
|
@ -198,7 +209,7 @@ impl<'de> serde::Deserialize<'de> for Mtp {
|
||||||
D: serde::Deserializer<'de>,
|
D: serde::Deserializer<'de>,
|
||||||
{
|
{
|
||||||
let u = u32::deserialize(deserializer)?;
|
let u = u32::deserialize(deserializer)?;
|
||||||
Mtp::from_consensus(u).map_err(serde::de::Error::custom)
|
Mtp::from_u32(u).map_err(serde::de::Error::custom)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,7 +219,7 @@ impl serde::Serialize for Mtp {
|
||||||
where
|
where
|
||||||
S: serde::Serializer,
|
S: serde::Serializer,
|
||||||
{
|
{
|
||||||
self.to_consensus_u32().serialize(serializer)
|
self.to_u32().serialize(serializer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -431,10 +442,10 @@ impl<'a> Arbitrary<'a> for Mtp {
|
||||||
0 => Ok(Mtp::MIN),
|
0 => Ok(Mtp::MIN),
|
||||||
1 => Ok(Mtp::MAX),
|
1 => Ok(Mtp::MAX),
|
||||||
_ => {
|
_ => {
|
||||||
let min = Mtp::MIN.to_consensus_u32();
|
let min = Mtp::MIN.to_u32();
|
||||||
let max = Mtp::MAX.to_consensus_u32();
|
let max = Mtp::MAX.to_u32();
|
||||||
let t = u.int_in_range(min..=max)?;
|
let t = u.int_in_range(min..=max)?;
|
||||||
Ok(Mtp::from_consensus(t).unwrap())
|
Ok(Mtp::from_u32(t).unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -450,7 +461,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn time_from_str_hex_happy_path() {
|
fn time_from_str_hex_happy_path() {
|
||||||
let actual = Mtp::from_hex("0x6289C350").unwrap();
|
let actual = Mtp::from_hex("0x6289C350").unwrap();
|
||||||
let expected = Mtp::from_consensus(0x6289_C350).unwrap();
|
let expected = Mtp::from_u32(0x6289_C350).unwrap();
|
||||||
assert_eq!(actual, expected);
|
assert_eq!(actual, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue