Repository: rust-bitcoin/rust-bitcoin
Pull request #4462 (2025-05-07 18:56:25)

Do lock time renames
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.

tcharding: Hey Andrew this is the renames agreed upon here: https://github.com/rust-bitcoin/rust-bitcoin/pull/4458#issuecomment-2858704897

I don't mind when this gets merged. Just getting acks on the names is useful so we are both on the same page.
github-actions[bot]: :rotating_light: API BREAKING CHANGE DETECTED

To see the changes click details on "Check semver breaks / PR Semver - stable toolchain" job then expand "Run semver checker script" and scroll to the end of the section.
github-actions[bot]: :rotating_light: API BREAKING CHANGE DETECTED

To see the changes click details on "Check semver breaks / PR Semver - stable toolchain" job then expand "Run semver checker script" and scroll to the end of the section.
apoelstra: I only read the commit messages, but concept ACK if the code does what you say it does.

Needs rebase.

Patch:
diff --git a/bitcoin/src/blockdata/block.rs b/bitcoin/src/blockdata/block.rs
index 3f2b86fa..7154254d 100644
--- a/bitcoin/src/blockdata/block.rs
+++ b/bitcoin/src/blockdata/block.rs
@@ -30,9 +30,7 @@
 #[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)]
diff --git a/bitcoin/src/blockdata/mod.rs b/bitcoin/src/blockdata/mod.rs
index 8255e3cc..9d904a1e 100644
--- a/bitcoin/src/blockdata/mod.rs
+++ b/bitcoin/src/blockdata/mod.rs
@@ -41,11 +41,11 @@ pub mod absolute {
 
         /// 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 relative {
 
         /// 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;
     }
 }
 
diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs
index 0c9772fa..5c8360a3 100644
--- a/bitcoin/src/blockdata/transaction.rs
+++ b/bitcoin/src/blockdata/transaction.rs
@@ -20,7 +20,7 @@
 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 @@ fn is_coinbase(&self) -> bool {
 
     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;
         }
diff --git a/primitives/src/locktime/absolute.rs b/primitives/src/locktime/absolute.rs
index fff858a1..c10d2ff7 100644
--- a/primitives/src/locktime/absolute.rs
+++ b/primitives/src/locktime/absolute.rs
@@ -16,11 +16,11 @@
 
 #[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 @@ pub fn from_consensus(n: u32) -> Self {
         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 @@ pub fn from_time(n: u32) -> Result<Self, ConversionError> { Self::from_mtp(n) }
     /// ```
     #[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 @@ pub const fn is_block_time(self) -> bool { !self.is_block_height() }
     /// # 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 @@ pub const fn is_block_time(self) -> bool { !self.is_block_height() }
     /// }
     /// ````
     #[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 @@ fn satisfied_by_height() {
         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 @@ fn satisfied_by_height() {
 
     #[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);
 
diff --git a/primitives/src/locktime/relative.rs b/primitives/src/locktime/relative.rs
index b38e2e16..2c9668d1 100644
--- a/primitives/src/locktime/relative.rs
+++ b/primitives/src/locktime/relative.rs
@@ -13,16 +13,16 @@
 
 #[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 @@
 /// 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 @@
 #[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 @@ pub fn to_sequence(self) -> Sequence { Sequence::from_consensus(self.to_consensu
 
     /// 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 @@ pub const fn from_height(n: u16) -> Self { LockTime::Blocks(HeightInterval::from
     /// [`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 @@ pub const fn from_512_second_intervals(intervals: u16) -> Self {
     /// 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 @@ pub const fn from_seconds_floor(seconds: u32) -> Result<Self, TimeOverflowError>
     /// 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 @@ pub fn is_implied_by_sequence(self, other: Sequence) -> bool {
         }
     }
 
-    /// 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 @@ pub fn is_implied_by_sequence(self, other: Sequence) -> bool {
     ///
     /// 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 @@ pub fn is_satisfied_by_height(
     /// 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 @@ pub fn is_satisfied_by_time(self, time: MtpInterval) -> Result<bool, Incompatibl
     }
 }
 
-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 @@ fn from_seconds_ceil_and_floor() {
 
     #[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 @@ fn parses_correctly_to_height_or_time() {
 
     #[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 @@ fn sequence_correctly_implies() {
 
     #[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 @@ fn disabled_locktime_error() {
 
     #[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 @@ fn incompatible_height_error() {
 
     #[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 @@ fn test_locktime_chain_state() {
         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 @@ fn test_locktime_chain_state() {
         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);
diff --git a/primitives/src/sequence.rs b/primitives/src/sequence.rs
index b659c98e..7d68c7cd 100644
--- a/primitives/src/sequence.rs
+++ b/primitives/src/sequence.rs
@@ -187,7 +187,7 @@ pub fn to_consensus_u32(self) -> u32 { self.0 }
     /// 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 @@ pub fn to_relative_lock_time(self) -> Option<relative::LockTime> {
         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 @@ fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
             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()?)),
         }
diff --git a/units/src/block.rs b/units/src/block.rs
index dcb483f1..778fb1be 100644
--- a/units/src/block.rs
+++ b/units/src/block.rs
@@ -142,18 +142,18 @@ pub fn checked_sub(self, other: Self) -> Option<Self> { self.0.checked_sub(other
     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 @@ fn try_from(h: BlockHeightInterval) -> Result<Self, Self::Error> {
         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 @@ fn try_from(h: BlockHeightInterval) -> Result<Self, Self::Error> {
     /// 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 @@ pub fn checked_add(self, other: BlockMtpInterval) -> Option<Self> {
     }
 }
 
-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 @@ fn try_from(h: BlockMtp) -> Result<Self, Self::Error> { absolute::Mtp::from_u32(
 }
 
 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 @@ pub const fn to_relative_mtp_interval_floor(
     #[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 @@ pub fn checked_sub(self, other: Self) -> Option<Self> { self.0.checked_sub(other
     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 @@ fn sanity_check() {
         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());
     }
 
diff --git a/units/src/fee.rs b/units/src/fee.rs
index 6bf9fe1a..de9e5d6a 100644
--- a/units/src/fee.rs
+++ b/units/src/fee.rs
@@ -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 @@ pub fn fee_vb(self, vb: u64) -> Option<Amount> {
     ///
     /// 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);
diff --git a/units/src/locktime/absolute.rs b/units/src/locktime/absolute.rs
index 214d048a..f80ccdfe 100644
--- a/units/src/locktime/absolute.rs
+++ b/units/src/locktime/absolute.rs
@@ -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 @@ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
     }
 }
 
-#[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 @@ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
 /// 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 @@ 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
+    /// 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 @@ pub const fn to_consensus_u32(self) -> u32 { self.to_u32() }
     /// # 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 @@ pub const fn from_u32(n: u32) -> Result<Self, ConversionError> {
         }
     }
 
-    /// 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 @@ fn display(
             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 @@ fn display(
             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 @@ fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
 }
 
 #[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 @@ pub fn encode_decode_height() {
     #[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 @@ fn valid_chain_computes_mtp() {
         ];
 
         // 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);
     }
 }
diff --git a/units/src/locktime/relative.rs b/units/src/locktime/relative.rs
index af3136d0..6bd5e6c1 100644
--- a/units/src/locktime/relative.rs
+++ b/units/src/locktime/relative.rs
@@ -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 @@
 #[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 @@ pub fn is_satisfied_by(
     }
 }
 
-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 @@ pub const fn to_512_second_intervals(self) -> u16 { self.0 }
     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 @@ pub const fn from_seconds_floor(seconds: u32) -> Result<Self, TimeOverflowError>
     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 @@ pub fn is_satisfied_by(
     }
 }
 
-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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 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 @@ fn test_time_chain_state() {
 
         // 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 @@ fn test_time_chain_state() {
         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 @@ fn test_time_chain_state() {
     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 @@ fn test_height_chain_state() {
         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));


Test patch:
diff --git a/units/tests/api.rs b/units/tests/api.rs
index a1956d10..33b60bc7 100644
--- a/units/tests/api.rs
+++ b/units/tests/api.rs
@@ -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 @@ fn max() -> Self {
             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 @@ fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
             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)?,
diff --git a/units/tests/serde.rs b/units/tests/serde.rs
index 24cf9b04..e6c7d0af 100644
--- a/units/tests/serde.rs
+++ b/units/tests/serde.rs
@@ -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 @@ fn new() -> Self {
             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,