relative locktime: add "obvious" constructors

Adds constructors to allow directly creating locktimes from time or
block counts; adds a flooring constructor to Time to match the ceiling
one; adds an explicit constructor to Height since the From<u16> was not
very discoverable.
This commit is contained in:
Andrew Poelstra 2024-03-18 12:55:33 +00:00
parent f02b1dac5b
commit f27e675e1e
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
2 changed files with 62 additions and 1 deletions

View File

@ -43,6 +43,48 @@ pub enum LockTime {
} }
impl LockTime { 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(Height::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.
/// Constructs a `LockTime` from `n`, expecting `n` to be a 16-bit count of blocks.
#[inline]
pub const fn from_height(n: u16) -> Self { LockTime::Blocks(Height::from_height(n)) }
/// Constructs a `LockTime` from `n`, expecting `n` to be a count of 512-second intervals.
///
/// This function is a little awkward to use, and users may wish to instead use
/// [`Self::from_seconds_floor`] or [`Self::from_seconds_ceil`].
#[inline]
pub const fn from_512_second_intervals(intervals: u16) -> Self {
LockTime::Time(Time::from_512_second_intervals(intervals))
}
/// Create a [`LockTime`] from seconds, converting the seconds into 512 second interval
/// with truncating division.
///
/// # Errors
///
/// Will return an error if the input cannot be encoded in 16 bits.
#[inline]
pub fn from_seconds_floor(seconds: u32) -> Result<Self, TimeOverflowError> {
Time::from_seconds_floor(seconds).map(LockTime::Time)
}
/// Create a [`LockTime`] from seconds, converting the seconds into 512 second interval
/// with ceiling division.
///
/// # Errors
///
/// Will return an error if the input cannot be encoded in 16 bits.
#[inline]
pub fn from_seconds_ceil(seconds: u32) -> Result<Self, TimeOverflowError> {
Time::from_seconds_ceil(seconds).map(LockTime::Time)
}
/// Returns true if this [`relative::LockTime`] is satisfied by either height or time. /// Returns true if this [`relative::LockTime`] is satisfied by either height or time.
/// ///
/// # Examples /// # Examples

View File

@ -22,6 +22,10 @@ impl Height {
/// The maximum relative block height. /// The maximum relative block height.
pub const MAX: Self = Height(u16::max_value()); pub const MAX: Self = Height(u16::max_value());
/// Create a [`Height`] using a count of blocks.
#[inline]
pub const fn from_height(blocks: u16) -> Self { Height(blocks) }
/// Returns the inner `u16` value. /// Returns the inner `u16` value.
#[inline] #[inline]
pub fn value(self) -> u16 { self.0 } pub fn value(self) -> u16 { self.0 }
@ -59,7 +63,22 @@ impl Time {
/// ///
/// Encoding finer granularity of time for relative lock-times is not supported in Bitcoin. /// Encoding finer granularity of time for relative lock-times is not supported in Bitcoin.
#[inline] #[inline]
pub fn from_512_second_intervals(intervals: u16) -> Self { Time(intervals) } pub const fn from_512_second_intervals(intervals: u16) -> Self { Time(intervals) }
/// Create a [`Time`] from seconds, converting the seconds into 512 second interval with
/// truncating division.
///
/// # Errors
///
/// Will return an error if the input cannot be encoded in 16 bits.
#[inline]
pub fn from_seconds_floor(seconds: u32) -> Result<Self, TimeOverflowError> {
if let Ok(interval) = u16::try_from(seconds / 512) {
Ok(Time::from_512_second_intervals(interval))
} else {
Err(TimeOverflowError { seconds })
}
}
/// Create a [`Time`] from seconds, converting the seconds into 512 second interval with ceiling /// Create a [`Time`] from seconds, converting the seconds into 512 second interval with ceiling
/// division. /// division.