Repository: rust-bitcoin/rust-bitcoin
Pull request #4428 (2025-05-01 19:55:04)

Use NumOpResult instead of Option
Prefer the more descriptive NumOpResult return type over Option where return types are fallible.

Closes https://github.com/rust-bitcoin/rust-bitcoin/issues/4419

coveralls: ## Pull Request Test Coverage Report for [Build 14782407797](https://coveralls.io/builds/73477403)


### Details

* **12** of **21**   **(57.14%)**  changed or added relevant lines in **3** files are covered.
* **1** unchanged line in **1** file lost coverage.
* Overall coverage remained the same at **84.169%**

---

|  Changes Missing Coverage | Covered Lines | Changed/Added Lines | % |
| :-----|--------------|--------|---: |
| [units/src/result.rs](https://coveralls.io/builds/73477403/source?filename=units%2Fsrc%2Fresult.rs#L270) | 0 | 1 | 0.0%
| [units/src/fee.rs](https://coveralls.io/builds/73477403/source?filename=units%2Fsrc%2Ffee.rs#L131) | 11 | 19 | 57.89%
<!-- | **Total:** | **12** | **21** | **57.14%** | -->

|  Files with Coverage Reduction | New Missed Lines | % |
| :-----|--------------|--: |
| [bitcoin/src/psbt/mod.rs](https://coveralls.io/builds/73477403/source?filename=bitcoin%2Fsrc%2Fpsbt%2Fmod.rs#L857) | 1 | 86.01% |
<!-- | **Total:** | **1** |  | -->

|  Totals | [![Coverage Status](https://coveralls.io/builds/73477403/badge)](https://coveralls.io/builds/73477403) |
| :-- | --: |
| Change from base [Build 14756442335](https://coveralls.io/builds/73453804): |  0.0% |
| Covered Lines: | 22873 |
| Relevant Lines: | 27175 |

---
##### 💛  - [Coveralls](https://coveralls.io)

yancyribbens: Thanks for the feedback, removed from draft.
tcharding: PR description still includes 'draft'
tcharding: We don't want patch 1. Instead you can use `while_doing` if you patch it to make it const. 

```rust
    pub(crate) const fn while_doing(op: MathOp) -> Self { NumOpError(op) }
```

Patch:
diff --git a/.cargo/mutants.toml b/.cargo/mutants.toml
index adb7e9f4..f4c71f56 100644
--- a/.cargo/mutants.toml
+++ b/.cargo/mutants.toml
@@ -4,15 +4,12 @@ exclude_globs = [
     "units/src/amount/verification.rs" # kani tests
 ]
 exclude_re = [
-    "impl Arbitrary",
     "impl Debug",
-    "impl fmt::Debug",
+    "impl Arbitrary",
     "impl Display",
-    "impl fmt::Display",
     ".*Error",
     "deserialize", # Skip serde mutation tests
     "Iterator", # Mutating operations in an iterator can result in an infinite loop
-    "match arm", "match guard", # New addition in cargo-mutants 25.0.1 deletes match arms and replaces match guards even in excluded functions
 
     # ----------------------------------Crate-specific exclusions----------------------------------
     # Units
diff --git a/.github/workflows/cargo-semver-checks-version b/.github/workflows/cargo-semver-checks-version
index 72a8a631..9b0025a7 100644
--- a/.github/workflows/cargo-semver-checks-version
+++ b/.github/workflows/cargo-semver-checks-version
@@ -1,1 +1,1 @@
-0.41.0
+0.40.0
diff --git a/README.md b/README.md
index 1a287bda..5cfe2c98 100644
--- a/README.md
+++ b/README.md
@@ -41,7 +41,7 @@ trustworthiness of each of your dependencies, including this one.
 This library **must not** be used for consensus code (i.e. fully validating blockchain data). It
 technically supports doing this, but doing so is very ill-advised because there are many deviations,
 known and unknown, between this library and the Bitcoin Core reference implementation. In a
-consensus based cryptocurrency, such as Bitcoin, it is critical that all parties are using the same
+consensus based cryptocurrency such as Bitcoin it is critical that all parties are using the same
 rules to validate data, and this library is simply unable to implement the same rules as Core.
 
 Given the complexity of both C++ and Rust, it is unlikely that this will ever be fixed, and there
@@ -68,11 +68,11 @@ and to expand on existing docs would be extremely appreciated.
 
 Contributions are generally welcome. If you intend to make larger changes please discuss them in an
 issue before PRing them to avoid duplicate work and architectural mismatches. If you have any
-questions or ideas you want to discuss, please join us in
+questions or ideas you want to discuss please join us in
 [#bitcoin-rust](https://web.libera.chat/?channel=#bitcoin-rust) on
 [libera.chat](https://libera.chat).
 
-For more information, please see [`CONTRIBUTING.md`](./CONTRIBUTING.md).
+For more information please see [`CONTRIBUTING.md`](./CONTRIBUTING.md).
 
 ## Minimum Supported Rust Version (MSRV)
 
@@ -83,7 +83,7 @@ Use `Cargo-minimal.lock` to build the MSRV by copying to `Cargo.lock` and buildi
 ## External dependencies
 
 We integrate with a few external libraries, most notably `serde`. These
-are available via feature flags. To ensure compatibility and MSRV stability, we
+are available via feature flags. To ensure compatibility and MSRV stability we
 provide two lock files as a means of inspecting compatible versions:
 `Cargo-minimal.lock` containing minimal versions of dependencies and
 `Cargo-recent.lock` containing recent versions of dependencies tested in our CI.
@@ -152,8 +152,8 @@ developers, especially new contributors looking for something to work on, we do:
 - Mutation testing with [`cargo-mutants`](https://github.com/sourcefrog/cargo-mutants)
 - Code verification with [`Kani`](https://github.com/model-checking/kani)
 
-There are always more tests to write and more bugs to find. PRs are extremely welcomed.
-Please consider testing code as a first-class citizen. We definitely do take PRs
+There are always more tests to write and more bugs to find, contributions to our testing efforts
+extremely welcomed. Please consider testing code a first class citizen, we definitely do take PRs
 improving and cleaning up test code.
 
 ### Unit/Integration tests
@@ -178,7 +178,7 @@ We have started using [kani](https://github.com/model-checking/kani), install wi
 
 ## Pull Requests
 
-Every PR needs at least two reviews to get merged. During the review phase, maintainers and
+Every PR needs at least two reviews to get merged. During the review phase maintainers and
 contributors are likely to leave comments and request changes. Please try to address them, otherwise
 your PR might get closed without merging after a longer time of inactivity. If your PR isn't ready
 for review yet please mark it by prefixing the title with `WIP: `.
@@ -201,7 +201,7 @@ to your githooks folder or run `just githooks-install` to copy them all.
 
 Since the altcoin landscape includes projects which [frequently appear and disappear, and are poorly
 designed anyway](https://download.wpsoftware.net/bitcoin/alts.pdf) we do not support any altcoins.
-Supporting Bitcoin properly is already difficult enough, and we do not want to increase the
+Supporting Bitcoin properly is already difficult enough and we do not want to increase the
 maintenance burden and decrease API stability by adding support for other coins.
 
 Our code is public domain so by all means fork it and go wild :)
diff --git a/bitcoin/CHANGELOG.md b/bitcoin/CHANGELOG.md
index 9409bfe0..d47088a2 100644
--- a/bitcoin/CHANGELOG.md
+++ b/bitcoin/CHANGELOG.md
@@ -41,7 +41,7 @@ For changes to our dependencies included in this release see:
 - Add `Address::into_unchecked` [#3640](https://github.com/rust-bitcoin/rust-bitcoin/pull/3640)
 - Mark `checked_` functions as const [#3636](https://github.com/rust-bitcoin/rust-bitcoin/pull/3636)
 - Mark functions const in `fee_rate` [#3627](https://github.com/rust-bitcoin/rust-bitcoin/pull/3627)
-- Mark functions const [#3608](https://github.com/rust-bitcoin/rust-bitcoin/pull/3608)
+- Mark funtions const [#3608](https://github.com/rust-bitcoin/rust-bitcoin/pull/3608)
 - Add constructor to `FeeRate` [#3604](https://github.com/rust-bitcoin/rust-bitcoin/pull/3604)
 - Fix bug in witness stack getters [#3601](https://github.com/rust-bitcoin/rust-bitcoin/pull/3601)
 - Split `checked_div_by_weight` into floor and ceiling version [#3587](https://github.com/rust-bitcoin/rust-bitcoin/pull/3587)
diff --git a/bitcoin/Cargo.toml b/bitcoin/Cargo.toml
index 075ddbd8..9e28cfb5 100644
--- a/bitcoin/Cargo.toml
+++ b/bitcoin/Cargo.toml
@@ -94,9 +94,5 @@ name = "sighash"
 name = "io"
 required-features = ["std"]
 
-[[example]]
-name = "script"
-required-features = ["std"]
-
 [lints.rust]
 unexpected_cfgs = { level = "deny", check-cfg = ['cfg(bench)', 'cfg(fuzzing)', 'cfg(kani)'] }
diff --git a/bitcoin/examples/bip32.rs b/bitcoin/examples/bip32.rs
index 7cde6c64..9df5ef67 100644
--- a/bitcoin/examples/bip32.rs
+++ b/bitcoin/examples/bip32.rs
@@ -33,12 +33,12 @@ fn main() {
     let secp = Secp256k1::preallocated_new(buf.as_mut_slice()).unwrap();
 
     // calculate root key from seed
-    let root = Xpriv::new_master(NetworkKind::Main, &seed);
+    let root = Xpriv::new_master(NetworkKind::Main, &seed).unwrap();
     println!("Root key: {}", root);
 
     // derive child xpub
     let path = "84h/0h/0h".parse::<DerivationPath>().unwrap();
-    let child = root.derive_xpriv(&secp, &path).expect("only deriving three steps");
+    let child = root.derive_xpriv(&secp, &path);
     println!("Child at {}: {}", path, child);
     let xpub = Xpub::from_xpriv(&secp, &child);
     println!("Public key at {}: {}", path, xpub);
diff --git a/bitcoin/examples/ecdsa-psbt-simple.rs b/bitcoin/examples/ecdsa-psbt-simple.rs
index 21b9f6ca..ac5d84b4 100644
--- a/bitcoin/examples/ecdsa-psbt-simple.rs
+++ b/bitcoin/examples/ecdsa-psbt-simple.rs
@@ -62,12 +62,11 @@ fn get_external_address_xpriv<C: Signing>(
 ) -> Xpriv {
     let derivation_path =
         BIP84_DERIVATION_PATH.into_derivation_path().expect("valid derivation path");
-    let child_xpriv =
-        master_xpriv.derive_xpriv(secp, &derivation_path).expect("only deriving three steps");
+    let child_xpriv = master_xpriv.derive_xpriv(secp, &derivation_path);
     let external_index = ChildNumber::ZERO_NORMAL;
     let idx = ChildNumber::from_normal_idx(index).expect("valid index number");
 
-    child_xpriv.derive_xpriv(secp, &[external_index, idx]).expect("only deriving two more steps")
+    child_xpriv.derive_xpriv(secp, &[external_index, idx])
 }
 
 // Derive the internal address xpriv.
@@ -78,12 +77,11 @@ fn get_internal_address_xpriv<C: Signing>(
 ) -> Xpriv {
     let derivation_path =
         BIP84_DERIVATION_PATH.into_derivation_path().expect("valid derivation path");
-    let child_xpriv =
-        master_xpriv.derive_xpriv(secp, &derivation_path).expect("only deriving three steps");
+    let child_xpriv = master_xpriv.derive_xpriv(secp, &derivation_path);
     let internal_index = ChildNumber::ONE_NORMAL;
     let idx = ChildNumber::from_normal_idx(index).expect("valid index number");
 
-    child_xpriv.derive_xpriv(secp, &[internal_index, idx]).expect("only deriving two more steps")
+    child_xpriv.derive_xpriv(secp, &[internal_index, idx])
 }
 
 // The address to send to.
diff --git a/bitcoin/examples/ecdsa-psbt.rs b/bitcoin/examples/ecdsa-psbt.rs
index 1abdf675..5aa05ea9 100644
--- a/bitcoin/examples/ecdsa-psbt.rs
+++ b/bitcoin/examples/ecdsa-psbt.rs
@@ -118,12 +118,11 @@ fn new<C: Signing>(secp: &Secp256k1<C>, xpriv: &str) -> Result<ExportData> {
         // Hardened children require secret data to derive.
 
         let path = "84h/0h/0h".into_derivation_path()?;
-        let account_0_xpriv =
-            master_xpriv.derive_xpriv(secp, &path).expect("derivation path is short");
+        let account_0_xpriv = master_xpriv.derive_xpriv(secp, &path);
         let account_0_xpub = Xpub::from_xpriv(secp, &account_0_xpriv);
 
         let path = INPUT_UTXO_DERIVATION_PATH.into_derivation_path()?;
-        let input_xpriv = master_xpriv.derive_xpriv(secp, &path).expect("derivation path is short");
+        let input_xpriv = master_xpriv.derive_xpriv(secp, &path);
         let input_xpub = Xpub::from_xpriv(secp, &input_xpriv);
 
         let wallet = ColdStorage { master_xpriv, master_xpub };
@@ -276,7 +275,7 @@ fn input_derivation_path() -> Result<DerivationPath> {
 }
 
 fn previous_output() -> TxOut {
-    let script_pubkey = ScriptBuf::from_hex_no_length_prefix(INPUT_UTXO_SCRIPT_PUBKEY)
+    let script_pubkey = ScriptBuf::from_hex(INPUT_UTXO_SCRIPT_PUBKEY)
         .expect("failed to parse input utxo scriptPubkey");
     let amount = INPUT_UTXO_VALUE.parse::<Amount>().expect("failed to parse input utxo value");
 
diff --git a/bitcoin/examples/script.rs b/bitcoin/examples/script.rs
deleted file mode 100644
index de72033d..00000000
--- a/bitcoin/examples/script.rs
+++ /dev/null
@@ -1,75 +0,0 @@
-// SPDX-License-Identifier: CC0-1.0
-
-//! Demonstrates the API for parsing and formatting Bitcoin scripts.
-//!
-//! Bitcoin script is conceptually a vector of bytes. As such it is consensus encoded with a compact
-//! size encoded length prefix. See [CompactSize].
-//!
-//! [`CompactSize`]: <https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer>
-
-use bitcoin::consensus::encode;
-use bitcoin::key::WPubkeyHash;
-use bitcoin::script::{self, ScriptBufExt, ScriptExt};
-use bitcoin::ScriptBuf;
-
-fn main() {
-    let pk = "b472a266d0bd89c13706a4132ccfb16f7c3b9fcb".parse::<WPubkeyHash>().unwrap();
-
-    // TL;DR Use `to_hex_string` and `from_hex`.
-    let script_code = script::p2wpkh_script_code(pk);
-    let hex = script_code.to_hex_string();
-    let decoded = ScriptBuf::from_hex(&hex).unwrap();
-    assert_eq!(decoded, script_code);
-
-    // Writes the script as human-readable eg, OP_DUP OP_HASH160 OP_PUSHBYTES_20 ...
-    println!("human-readable script: {}", script_code);
-
-    // We do not implement parsing scripts from human-readable format.
-    // let decoded = s.parse::<ScriptBuf>().unwrap();
-
-    // This is equivalent to consensus encoding i.e., includes the length prefix.
-    let hex_lower_hex_trait = format!("{:x}", script_code);
-    println!("hex created using `LowerHex`: {}", hex_lower_hex_trait);
-
-    // The `deserialize_hex` function requires the length prefix.
-    assert_eq!(encode::deserialize_hex::<ScriptBuf>(&hex_lower_hex_trait).unwrap(), script_code);
-    // And so does `from_hex`.
-    assert_eq!(ScriptBuf::from_hex(&hex_lower_hex_trait).unwrap(), script_code);
-
-    // And we also provide an explicit constructor that does not use the length prefix.
-    let other = ScriptBuf::from_hex_no_length_prefix(&hex_lower_hex_trait).unwrap();
-    // Without a prefix the script parses but its not the one we meant.
-    assert_ne!(other, script_code);
-
-    // This is consensus encoding i.e., includes the length prefix.
-    let hex_inherent = script_code.to_hex_string(); // Defined in `ScriptExt`.
-    println!("hex created using inherent `to_hex_string`: {}", hex_inherent);
-
-    // The inverse of `to_hex_string` is `from_hex`.
-    let decoded = ScriptBuf::from_hex(&hex_inherent).unwrap(); // Defined in `ScriptBufExt`.
-    assert_eq!(decoded, script_code);
-    // We can also parse the output of `to_hex_string` using `deserialize_hex`.
-    let decoded = encode::deserialize_hex::<ScriptBuf>(&hex_inherent).unwrap();
-    assert_eq!(decoded, script_code);
-
-    // We also support encode/decode using `consensus::encode` functions.
-    let encoded = encode::serialize_hex(&script_code);
-    println!("hex created using consensus::encode::serialize_hex: {}", encoded);
-
-    let decoded: ScriptBuf = encode::deserialize_hex(&encoded).unwrap();
-    assert_eq!(decoded, script_code);
-    // And we can mix these to calls because both include the length prefix.
-    let decoded = ScriptBuf::from_hex(&encoded).unwrap();
-    assert_eq!(decoded, script_code);
-
-    // Encode/decode using a byte vector.
-    let encoded = encode::serialize(&script_code);
-    assert_eq!(&encoded[1..], script_code.as_bytes()); // Shows that prefix is the first byte.
-    let decoded: ScriptBuf = encode::deserialize(&encoded).unwrap();
-    assert_eq!(decoded, script_code);
-
-    // to/from bytes excludes the prefix, these are not encoding/decoding functions so this is sane.
-    let bytes = script_code.to_bytes();
-    let got = ScriptBuf::from_bytes(bytes);
-    assert_eq!(got, script_code);
-}
diff --git a/bitcoin/examples/sign-tx-taproot.rs b/bitcoin/examples/sign-tx-taproot.rs
index 2abb4d58..06a3fab1 100644
--- a/bitcoin/examples/sign-tx-taproot.rs
+++ b/bitcoin/examples/sign-tx-taproot.rs
@@ -71,7 +71,7 @@ fn main() {
     // Sign the sighash using the secp256k1 library (exported by rust-bitcoin).
     let tweaked: TweakedKeypair = keypair.tap_tweak(&secp, None);
     let msg = Message::from(sighash);
-    let signature = secp.sign_schnorr(msg.as_ref(), tweaked.as_keypair());
+    let signature = secp.sign_schnorr(msg.as_ref(), &tweaked.to_inner());
 
     // Update the witness stack.
     let signature = bitcoin::taproot::Signature { signature, sighash_type };
diff --git a/bitcoin/examples/taproot-psbt-simple.rs b/bitcoin/examples/taproot-psbt-simple.rs
index d2ca8f9e..8181573a 100644
--- a/bitcoin/examples/taproot-psbt-simple.rs
+++ b/bitcoin/examples/taproot-psbt-simple.rs
@@ -60,12 +60,11 @@ fn get_external_address_xpriv<C: Signing>(
 ) -> Xpriv {
     let derivation_path =
         BIP86_DERIVATION_PATH.into_derivation_path().expect("valid derivation path");
-    let child_xpriv =
-        master_xpriv.derive_xpriv(secp, &derivation_path).expect("only deriving three steps");
+    let child_xpriv = master_xpriv.derive_xpriv(secp, &derivation_path);
     let external_index = ChildNumber::ZERO_NORMAL;
     let idx = ChildNumber::from_normal_idx(index).expect("valid index number");
 
-    child_xpriv.derive_xpriv(secp, &[external_index, idx]).expect("only deriving two more steps")
+    child_xpriv.derive_xpriv(secp, &[external_index, idx])
 }
 
 // Derive the internal address xpriv.
@@ -76,12 +75,11 @@ fn get_internal_address_xpriv<C: Signing>(
 ) -> Xpriv {
     let derivation_path =
         BIP86_DERIVATION_PATH.into_derivation_path().expect("valid derivation path");
-    let child_xpriv =
-        master_xpriv.derive_xpriv(secp, &derivation_path).expect("only deriving three steps");
+    let child_xpriv = master_xpriv.derive_xpriv(secp, &derivation_path);
     let internal_index = ChildNumber::ONE_NORMAL;
     let idx = ChildNumber::from_normal_idx(index).expect("valid index number");
 
-    child_xpriv.derive_xpriv(secp, &[internal_index, idx]).expect("only deriving two more steps")
+    child_xpriv.derive_xpriv(secp, &[internal_index, idx])
 }
 
 // Get the Taproot Key Origin.
diff --git a/bitcoin/examples/taproot-psbt.rs b/bitcoin/examples/taproot-psbt.rs
index 75bb0b8b..92af8515 100644
--- a/bitcoin/examples/taproot-psbt.rs
+++ b/bitcoin/examples/taproot-psbt.rs
@@ -257,7 +257,7 @@ fn generate_bip86_key_spend_tx(
 
     let mut input = Input {
         witness_utxo: {
-            let script_pubkey = ScriptBuf::from_hex_no_length_prefix(input_utxo.script_pubkey)
+            let script_pubkey = ScriptBuf::from_hex(input_utxo.script_pubkey)
                 .expect("failed to parse input utxo scriptPubkey");
             Some(TxOut { value: from_amount, script_pubkey })
         },
@@ -275,7 +275,7 @@ fn generate_bip86_key_spend_tx(
     for input in [&input_utxo].iter() {
         input_txouts.push(TxOut {
             value: input.amount,
-            script_pubkey: ScriptBuf::from_hex_no_length_prefix(input.script_pubkey)?,
+            script_pubkey: ScriptBuf::from_hex(input.script_pubkey)?,
         });
     }
 
@@ -299,7 +299,7 @@ fn generate_bip86_key_spend_tx(
                 .ok_or("missing Taproot key origin")?;
 
             let secret_key =
-                master_xpriv.derive_xpriv(secp, &derivation_path)?.to_private_key().inner;
+                master_xpriv.derive_xpriv(secp, &derivation_path).to_private_key().inner;
             sign_psbt_taproot(
                 secret_key,
                 input.tap_internal_key.unwrap(),
@@ -333,7 +333,7 @@ fn generate_bip86_key_spend_tx(
     tx.verify(|_| {
         Some(TxOut {
             value: from_amount,
-            script_pubkey: ScriptBuf::from_hex_no_length_prefix(input_utxo.script_pubkey).unwrap(),
+            script_pubkey: ScriptBuf::from_hex(input_utxo.script_pubkey).unwrap(),
         })
     })
     .expect("failed to verify transaction");
@@ -393,11 +393,8 @@ fn create_inheritance_funding_tx(
         // We use some other derivation path in this example for our inheritance protocol. The important thing is to ensure
         // that we use an unhardened path so we can make use of xpubs.
         let derivation_path = format!("101/1/0/0/{}", self.next).parse::<DerivationPath>()?;
-        let internal_keypair = self
-            .master_xpriv
-            .derive_xpriv(&self.secp, &derivation_path)
-            .expect("derivation path is short")
-            .to_keypair(&self.secp);
+        let internal_keypair =
+            self.master_xpriv.derive_xpriv(&self.secp, &derivation_path).to_keypair(&self.secp);
         let beneficiary_key =
             self.beneficiary_xpub.derive_xpub(&self.secp, &derivation_path)?.to_x_only_public_key();
 
@@ -489,7 +486,6 @@ fn refresh_tx(
             let new_internal_keypair = self
                 .master_xpriv
                 .derive_xpriv(&self.secp, &new_derivation_path)
-                .expect("derivation path is short")
                 .to_keypair(&self.secp);
             let beneficiary_key = self
                 .beneficiary_xpub
@@ -542,7 +538,6 @@ fn refresh_tx(
                 let secret_key = self
                     .master_xpriv
                     .derive_xpriv(&self.secp, &derivation_path)
-                    .expect("derivation path is short")
                     .to_private_key()
                     .inner;
                 sign_psbt_taproot(
@@ -665,11 +660,8 @@ fn spend_inheritance(
         for (x_only_pubkey, (leaf_hashes, (_, derivation_path))) in
             &psbt.inputs[0].tap_key_origins.clone()
         {
-            let secret_key = self
-                .master_xpriv
-                .derive_xpriv(&self.secp, &derivation_path)?
-                .to_private_key()
-                .inner;
+            let secret_key =
+                self.master_xpriv.derive_xpriv(&self.secp, &derivation_path).to_private_key().inner;
             for lh in leaf_hashes {
                 let sighash_type = TapSighashType::All;
                 let hash = SighashCache::new(&unsigned_tx).taproot_script_spend_signature_hash(
@@ -752,7 +744,7 @@ fn sign_psbt_taproot(
 ) {
     let keypair = secp256k1::Keypair::from_seckey_slice(secp, secret_key.as_ref()).unwrap();
     let keypair = match leaf_hash {
-        None => keypair.tap_tweak(secp, psbt_input.tap_merkle_root).to_keypair(),
+        None => keypair.tap_tweak(secp, psbt_input.tap_merkle_root).to_inner(),
         Some(_) => keypair, // no tweak for script spend
     };
 
diff --git a/bitcoin/src/address/mod.rs b/bitcoin/src/address/mod.rs
index b178612d..167de229 100644
--- a/bitcoin/src/address/mod.rs
+++ b/bitcoin/src/address/mod.rs
@@ -1053,10 +1053,7 @@ fn p2pkh_address_58() {
 
         assert_eq!(
             addr.script_pubkey(),
-            ScriptBuf::from_hex_no_length_prefix(
-                "76a914162c5ea71c0b23f5b9022ef047c4a86470a5b07088ac"
-            )
-            .unwrap()
+            ScriptBuf::from_hex("76a914162c5ea71c0b23f5b9022ef047c4a86470a5b07088ac").unwrap()
         );
         assert_eq!(&addr.to_string(), "132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM");
         assert_eq!(addr.address_type(), Some(AddressType::P2pkh));
@@ -1085,8 +1082,7 @@ fn p2sh_address_58() {
 
         assert_eq!(
             addr.script_pubkey(),
-            ScriptBuf::from_hex_no_length_prefix("a914162c5ea71c0b23f5b9022ef047c4a86470a5b07087")
-                .unwrap(),
+            ScriptBuf::from_hex("a914162c5ea71c0b23f5b9022ef047c4a86470a5b07087").unwrap(),
         );
         assert_eq!(&addr.to_string(), "33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k");
         assert_eq!(addr.address_type(), Some(AddressType::P2sh));
@@ -1095,7 +1091,7 @@ fn p2sh_address_58() {
 
     #[test]
     fn p2sh_parse() {
-        let script = ScriptBuf::from_hex_no_length_prefix("552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae").unwrap();
+        let script = ScriptBuf::from_hex("552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae").unwrap();
         let addr = Address::p2sh(&script, NetworkKind::Test).unwrap();
         assert_eq!(&addr.to_string(), "2N3zXjbwdTcPsJiy8sUK9FhWJhqQCxA8Jjr");
         assert_eq!(addr.address_type(), Some(AddressType::P2sh));
@@ -1104,7 +1100,7 @@ fn p2sh_parse() {
 
     #[test]
     fn p2sh_parse_for_large_script() {
-        let script = ScriptBuf::from_hex_no_length_prefix("552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123").unwrap();
+        let script = ScriptBuf::from_hex("552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123").unwrap();
         let res = Address::p2sh(&script, NetworkKind::Test);
         assert_eq!(res.unwrap_err().invalid_size(), script.len())
     }
@@ -1124,7 +1120,7 @@ fn p2wpkh() {
     #[test]
     fn p2wsh() {
         // stolen from Bitcoin transaction 5df912fda4becb1c29e928bec8d64d93e9ba8efa9b5b405bd683c86fd2c65667
-        let script = ScriptBuf::from_hex_no_length_prefix("52210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae").unwrap();
+        let script = ScriptBuf::from_hex("52210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae").unwrap();
         let addr = Address::p2wsh(&script, KnownHrp::Mainnet).expect("script is valid");
         assert_eq!(
             &addr.to_string(),
@@ -1149,7 +1145,7 @@ fn p2shwpkh() {
     #[test]
     fn p2shwsh() {
         // stolen from Bitcoin transaction f9ee2be4df05041d0e0a35d7caa3157495ca4f93b233234c9967b6901dacf7a9
-        let script = ScriptBuf::from_hex_no_length_prefix("522103e5529d8eaa3d559903adb2e881eb06c86ac2574ffa503c45f4e942e2a693b33e2102e5f10fcdcdbab211e0af6a481f5532536ec61a5fdbf7183770cf8680fe729d8152ae").unwrap();
+        let script = ScriptBuf::from_hex("522103e5529d8eaa3d559903adb2e881eb06c86ac2574ffa503c45f4e942e2a693b33e2102e5f10fcdcdbab211e0af6a481f5532536ec61a5fdbf7183770cf8680fe729d8152ae").unwrap();
         let addr = Address::p2shwsh(&script, NetworkKind::Main).expect("script is valid");
         assert_eq!(&addr.to_string(), "36EqgNnsWW94SreZgBWc1ANC6wpFZwirHr");
         assert_eq!(addr.address_type(), Some(AddressType::P2sh));
@@ -1238,10 +1234,7 @@ fn json_serialize() {
         assert_eq!(addr.to_string(), into.to_string());
         assert_eq!(
             into.script_pubkey(),
-            ScriptBuf::from_hex_no_length_prefix(
-                "76a914162c5ea71c0b23f5b9022ef047c4a86470a5b07088ac"
-            )
-            .unwrap()
+            ScriptBuf::from_hex("76a914162c5ea71c0b23f5b9022ef047c4a86470a5b07088ac").unwrap()
         );
 
         let addr =
@@ -1255,8 +1248,7 @@ fn json_serialize() {
         assert_eq!(addr.to_string(), into.to_string());
         assert_eq!(
             into.script_pubkey(),
-            ScriptBuf::from_hex_no_length_prefix("a914162c5ea71c0b23f5b9022ef047c4a86470a5b07087")
-                .unwrap()
+            ScriptBuf::from_hex("a914162c5ea71c0b23f5b9022ef047c4a86470a5b07087").unwrap()
         );
 
         let addr: Address<NetworkUnchecked> =
@@ -1286,7 +1278,7 @@ fn json_serialize() {
         assert_eq!(addr.to_string(), into.to_string());
         assert_eq!(
             into.script_pubkey(),
-            ScriptBuf::from_hex_no_length_prefix(
+            ScriptBuf::from_hex(
                 "00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262"
             )
             .unwrap()
@@ -1305,8 +1297,7 @@ fn json_serialize() {
         assert_eq!(addr.to_string(), into.to_string());
         assert_eq!(
             into.script_pubkey(),
-            ScriptBuf::from_hex_no_length_prefix("001454d26dddb59c7073c6a197946ea1841951fa7a74")
-                .unwrap()
+            ScriptBuf::from_hex("001454d26dddb59c7073c6a197946ea1841951fa7a74").unwrap()
         );
     }
 
@@ -1485,15 +1476,13 @@ fn is_related_to_xonly_pubkey() {
     fn fail_address_from_script() {
         use crate::witness_program;
 
-        let bad_p2wpkh =
-            ScriptBuf::from_hex_no_length_prefix("15000014dbc5b0a8f9d4353b4b54c3db48846bb15abfec")
-                .unwrap();
-        let bad_p2wsh = ScriptBuf::from_hex_no_length_prefix(
+        let bad_p2wpkh = ScriptBuf::from_hex("0014dbc5b0a8f9d4353b4b54c3db48846bb15abfec").unwrap();
+        let bad_p2wsh = ScriptBuf::from_hex(
             "00202d4fa2eb233d008cc83206fa2f4f2e60199000f5b857a835e3172323385623",
         )
         .unwrap();
         let invalid_segwitv0_script =
-            ScriptBuf::from_hex_no_length_prefix("001161458e330389cd0437ee9fe3641d70cc18").unwrap();
+            ScriptBuf::from_hex("001161458e330389cd0437ee9fe3641d70cc18").unwrap();
         let expected = Err(FromScriptError::UnrecognizedScript);
 
         assert_eq!(Address::from_script(&bad_p2wpkh, Network::Bitcoin), expected);
diff --git a/bitcoin/src/bip32.rs b/bitcoin/src/bip32.rs
index 12be7a31..7d20f58a 100644
--- a/bitcoin/src/bip32.rs
+++ b/bitcoin/src/bip32.rs
@@ -148,11 +148,11 @@ impl ChildNumber {
     /// [0, 2^31 - 1].
     ///
     /// [`Normal`]: #variant.Normal
-    pub fn from_normal_idx(index: u32) -> Result<Self, IndexOutOfRangeError> {
+    pub fn from_normal_idx(index: u32) -> Result<Self, Error> {
         if index & (1 << 31) == 0 {
             Ok(ChildNumber::Normal { index })
         } else {
-            Err(IndexOutOfRangeError { index })
+            Err(Error::InvalidChildNumber(index))
         }
     }
 
@@ -160,11 +160,11 @@ pub fn from_normal_idx(index: u32) -> Result<Self, IndexOutOfRangeError> {
     /// [0, 2^31 - 1].
     ///
     /// [`Hardened`]: #variant.Hardened
-    pub fn from_hardened_idx(index: u32) -> Result<Self, IndexOutOfRangeError> {
+    pub fn from_hardened_idx(index: u32) -> Result<Self, Error> {
         if index & (1 << 31) == 0 {
             Ok(ChildNumber::Hardened { index })
         } else {
-            Err(IndexOutOfRangeError { index })
+            Err(Error::InvalidChildNumber(index))
         }
     }
 
@@ -184,10 +184,7 @@ pub fn is_hardened(&self) -> bool {
     }
 
     /// Returns the child number that is a single increment from this one.
-    pub fn increment(self) -> Result<ChildNumber, IndexOutOfRangeError> {
-        // Bare addition in this function is okay, because we have an invariant that
-        // `index` is always within [0, 2^31 - 1]. FIXME this is not actually an
-        // invariant because the fields are public.
+    pub fn increment(self) -> Result<ChildNumber, Error> {
         match self {
             ChildNumber::Normal { index: idx } => ChildNumber::from_normal_idx(idx + 1),
             ChildNumber::Hardened { index: idx } => ChildNumber::from_hardened_idx(idx + 1),
@@ -228,18 +225,16 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 }
 
 impl FromStr for ChildNumber {
-    type Err = ParseChildNumberError;
+    type Err = Error;
 
-    fn from_str(inp: &str) -> Result<Self, Self::Err> {
+    fn from_str(inp: &str) -> Result<ChildNumber, Error> {
         let is_hardened = inp.chars().last().map_or(false, |l| l == '\'' || l == 'h');
         Ok(if is_hardened {
             ChildNumber::from_hardened_idx(
-                inp[0..inp.len() - 1].parse().map_err(ParseChildNumberError::ParseInt)?,
-            )
-            .map_err(ParseChildNumberError::IndexOutOfRange)?
+                inp[0..inp.len() - 1].parse().map_err(|_| Error::InvalidChildNumberFormat)?,
+            )?
         } else {
-            ChildNumber::from_normal_idx(inp.parse().map_err(ParseChildNumberError::ParseInt)?)
-                .map_err(ParseChildNumberError::IndexOutOfRange)?
+            ChildNumber::from_normal_idx(inp.parse().map_err(|_| Error::InvalidChildNumberFormat)?)?
         })
     }
 }
@@ -272,7 +267,7 @@ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
 /// derivation path
 pub trait IntoDerivationPath {
     /// Converts a given type into a [`DerivationPath`] with possible error
-    fn into_derivation_path(self) -> Result<DerivationPath, ParseChildNumberError>;
+    fn into_derivation_path(self) -> Result<DerivationPath, Error>;
 }
 
 /// A BIP-32 derivation path.
@@ -300,17 +295,15 @@ impl<T> IntoDerivationPath for T
 where
     T: Into<DerivationPath>,
 {
-    fn into_derivation_path(self) -> Result<DerivationPath, ParseChildNumberError> {
-        Ok(self.into())
-    }
+    fn into_derivation_path(self) -> Result<DerivationPath, Error> { Ok(self.into()) }
 }
 
 impl IntoDerivationPath for String {
-    fn into_derivation_path(self) -> Result<DerivationPath, ParseChildNumberError> { self.parse() }
+    fn into_derivation_path(self) -> Result<DerivationPath, Error> { self.parse() }
 }
 
 impl IntoDerivationPath for &'_ str {
-    fn into_derivation_path(self) -> Result<DerivationPath, ParseChildNumberError> { self.parse() }
+    fn into_derivation_path(self) -> Result<DerivationPath, Error> { self.parse() }
 }
 
 impl From<Vec<ChildNumber>> for DerivationPath {
@@ -345,9 +338,9 @@ fn as_ref(&self) -> &[ChildNumber] { &self.0 }
 }
 
 impl FromStr for DerivationPath {
-    type Err = ParseChildNumberError;
+    type Err = Error;
 
-    fn from_str(path: &str) -> Result<Self, Self::Err> {
+    fn from_str(path: &str) -> Result<DerivationPath, Error> {
         if path.is_empty() || path == "m" || path == "m/" {
             return Ok(vec![].into());
         }
@@ -355,7 +348,7 @@ fn from_str(path: &str) -> Result<Self, Self::Err> {
         let path = path.strip_prefix("m/").unwrap_or(path);
 
         let parts = path.split('/');
-        let ret: Result<Vec<ChildNumber>, _> = parts.map(str::parse).collect();
+        let ret: Result<Vec<ChildNumber>, Error> = parts.map(str::parse).collect();
         Ok(DerivationPath(ret?))
     }
 }
@@ -503,15 +496,27 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self,
 /// A BIP32 error
 #[derive(Debug, Clone, PartialEq, Eq)]
 #[non_exhaustive]
-pub enum ParseError {
+pub enum Error {
+    /// A pk->pk derivation was attempted on a hardened key
+    CannotDeriveFromHardenedKey,
     /// A secp256k1 error occurred
     Secp256k1(secp256k1::Error),
+    /// A child number was provided that was out of range
+    InvalidChildNumber(u32),
+    /// Invalid childnumber format.
+    InvalidChildNumberFormat,
+    /// Invalid derivation path format.
+    InvalidDerivationPathFormat,
     /// Unknown version magic bytes
     UnknownVersion([u8; 4]),
     /// Encoded extended key data has wrong length
     WrongExtendedKeyLength(usize),
     /// Base58 encoding error
     Base58(base58::Error),
+    /// Hexadecimal decoding error
+    Hex(hex::HexToArrayError),
+    /// `PublicKey` hex should be 66 or 130 digits long.
+    InvalidPublicKeyHexLength(usize),
     /// Base58 decoded data was an invalid length.
     InvalidBase58PayloadLength(InvalidBase58PayloadLengthError),
     /// Invalid private key prefix (byte 45 must be 0)
@@ -522,20 +527,29 @@ pub enum ParseError {
     NonZeroChildNumberForMasterKey,
 }
 
-impl From<Infallible> for ParseError {
+impl From<Infallible> for Error {
     fn from(never: Infallible) -> Self { match never {} }
 }
 
-impl fmt::Display for ParseError {
+impl fmt::Display for Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        use ParseError::*;
+        use Error::*;
 
         match *self {
+            CannotDeriveFromHardenedKey =>
+                f.write_str("cannot derive hardened key from public key"),
             Secp256k1(ref e) => write_err!(f, "secp256k1 error"; e),
+            InvalidChildNumber(ref n) =>
+                write!(f, "child number {} is invalid (not within [0, 2^31 - 1])", n),
+            InvalidChildNumberFormat => f.write_str("invalid child number format"),
+            InvalidDerivationPathFormat => f.write_str("invalid derivation path format"),
             UnknownVersion(ref bytes) => write!(f, "unknown version magic bytes: {:?}", bytes),
             WrongExtendedKeyLength(ref len) =>
                 write!(f, "encoded extended key data has wrong length {}", len),
             Base58(ref e) => write_err!(f, "base58 encoding error"; e),
+            Hex(ref e) => write_err!(f, "Hexadecimal decoding error"; e),
+            InvalidPublicKeyHexLength(got) =>
+                write!(f, "PublicKey hex should be 66 or 130 digits long, got: {}", got),
             InvalidBase58PayloadLength(ref e) => write_err!(f, "base58 payload"; e),
             InvalidPrivateKeyPrefix =>
                 f.write_str("invalid private key prefix, byte 45 must be 0 as required by BIP-32"),
@@ -547,15 +561,22 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 }
 
 #[cfg(feature = "std")]
-impl std::error::Error for ParseError {
+impl std::error::Error for Error {
     fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
-        use ParseError::*;
+        use Error::*;
 
         match *self {
             Secp256k1(ref e) => Some(e),
             Base58(ref e) => Some(e),
+            Hex(ref e) => Some(e),
             InvalidBase58PayloadLength(ref e) => Some(e),
-            UnknownVersion(_) | WrongExtendedKeyLength(_) => None,
+            CannotDeriveFromHardenedKey
+            | InvalidChildNumber(_)
+            | InvalidChildNumberFormat
+            | InvalidDerivationPathFormat
+            | UnknownVersion(_)
+            | WrongExtendedKeyLength(_)
+            | InvalidPublicKeyHexLength(_) => None,
             InvalidPrivateKeyPrefix => None,
             NonZeroParentFingerprintForMasterKey => None,
             NonZeroChildNumberForMasterKey => None,
@@ -563,121 +584,35 @@ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
     }
 }
 
-impl From<secp256k1::Error> for ParseError {
-    fn from(e: secp256k1::Error) -> ParseError { ParseError::Secp256k1(e) }
-}
-
-impl From<base58::Error> for ParseError {
-    fn from(err: base58::Error) -> Self { ParseError::Base58(err) }
-}
-
-impl From<InvalidBase58PayloadLengthError> for ParseError {
-    fn from(e: InvalidBase58PayloadLengthError) -> ParseError {
-        Self::InvalidBase58PayloadLength(e)
-    }
-}
-
-/// A BIP32 error
-#[derive(Debug, Clone, PartialEq, Eq)]
-#[non_exhaustive]
-pub enum DerivationError {
-    /// Attempted to derive a hardened child from an xpub.
-    ///
-    /// You can only derive hardened children from xprivs.
-    CannotDeriveHardenedChild,
-    /// Attempted to derive a child of depth 256 or higher.
-    ///
-    /// There is no way to encode such xkeys.
-    MaximumDepthExceeded,
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for DerivationError {}
-
-impl fmt::Display for DerivationError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            Self::CannotDeriveHardenedChild =>
-                f.write_str("cannot derive hardened child of public key"),
-            Self::MaximumDepthExceeded => f.write_str("cannot derive child of depth 256 or higher"),
-        }
-    }
-}
-
-/// Out-of-range index when constructing a child number.
-///
-/// *Indices* are always in the range [0, 2^31 - 1]. Normal child numbers have the
-/// same range, while hardened child numbers lie in the range [2^31, 2^32 - 1].
-#[derive(Debug, Clone, PartialEq, Eq)]
-#[non_exhaustive]
-pub struct IndexOutOfRangeError {
-    /// The index that was out of range for a child number.
-    pub index: u32,
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for IndexOutOfRangeError {}
-
-impl From<Infallible> for IndexOutOfRangeError {
-    fn from(never: Infallible) -> Self { match never {} }
-}
-
-impl fmt::Display for IndexOutOfRangeError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "index {} out of range [0, 2^31 - 1] (do you have an hardened child number, rather than an index?)", self.index)
-    }
-}
-
-/// Error parsing a child number.
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum ParseChildNumberError {
-    /// Parsed the child number as an integer, but the integer was out of range.
-    IndexOutOfRange(IndexOutOfRangeError),
-    /// Failed to parse the child number as an integer.
-    ParseInt(core::num::ParseIntError),
+impl From<secp256k1::Error> for Error {
+    fn from(e: secp256k1::Error) -> Error { Error::Secp256k1(e) }
 }
 
-impl From<Infallible> for ParseChildNumberError {
-    fn from(never: Infallible) -> Self { match never {} }
+impl From<base58::Error> for Error {
+    fn from(err: base58::Error) -> Self { Error::Base58(err) }
 }
 
-#[cfg(feature = "std")]
-impl std::error::Error for ParseChildNumberError {
-    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
-        match *self {
-            Self::IndexOutOfRange(ref e) => Some(e),
-            Self::ParseInt(ref e) => Some(e),
-        }
-    }
-}
-
-impl fmt::Display for ParseChildNumberError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            Self::IndexOutOfRange(ref e) => e.fmt(f),
-            Self::ParseInt(ref e) => e.fmt(f),
-        }
-    }
+impl From<InvalidBase58PayloadLengthError> for Error {
+    fn from(e: InvalidBase58PayloadLengthError) -> Error { Self::InvalidBase58PayloadLength(e) }
 }
 
 impl Xpriv {
     /// Constructs a new master key from a seed value
-    pub fn new_master(network: impl Into<NetworkKind>, seed: &[u8]) -> Xpriv {
+    pub fn new_master(network: impl Into<NetworkKind>, seed: &[u8]) -> Result<Xpriv, Error> {
         let mut engine = HmacEngine::<sha512::HashEngine>::new(b"Bitcoin seed");
         engine.input(seed);
         let hmac = engine.finalize();
 
-        Xpriv {
+        Ok(Xpriv {
             network: network.into(),
             depth: 0,
             parent_fingerprint: Default::default(),
             child_number: ChildNumber::ZERO_NORMAL,
             private_key: secp256k1::SecretKey::from_byte_array(
                 hmac.as_byte_array().split_array::<32, 32>().0,
-            )
-            .expect("cryptographically unreachable"),
+            )?,
             chain_code: ChainCode::from_hmac(hmac),
-        }
+        })
     }
 
     /// Constructs a new ECDSA compressed private key matching internal secret key representation.
@@ -709,7 +644,7 @@ pub fn derive_priv<C: secp256k1::Signing, P: AsRef<[ChildNumber]>>(
         &self,
         secp: &Secp256k1<C>,
         path: &P,
-    ) -> Result<Xpriv, DerivationError> {
+    ) -> Xpriv {
         self.derive_xpriv(secp, path)
     }
 
@@ -720,20 +655,16 @@ pub fn derive_xpriv<C: secp256k1::Signing, P: AsRef<[ChildNumber]>>(
         &self,
         secp: &Secp256k1<C>,
         path: &P,
-    ) -> Result<Xpriv, DerivationError> {
+    ) -> Xpriv {
         let mut sk: Xpriv = *self;
         for cnum in path.as_ref() {
-            sk = sk.ckd_priv(secp, *cnum)?;
+            sk = sk.ckd_priv(secp, *cnum)
         }
-        Ok(sk)
+        sk
     }
 
     /// Private->Private child key derivation
-    fn ckd_priv<C: secp256k1::Signing>(
-        &self,
-        secp: &Secp256k1<C>,
-        i: ChildNumber,
-    ) -> Result<Xpriv, DerivationError> {
+    fn ckd_priv<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>, i: ChildNumber) -> Xpriv {
         let mut engine = HmacEngine::<sha512::HashEngine>::new(&self.chain_code[..]);
         match i {
             ChildNumber::Normal { .. } => {
@@ -757,30 +688,30 @@ fn ckd_priv<C: secp256k1::Signing>(
         let tweaked =
             sk.add_tweak(&self.private_key.into()).expect("statistically impossible to hit");
 
-        Ok(Xpriv {
+        Xpriv {
             network: self.network,
-            depth: self.depth.checked_add(1).ok_or(DerivationError::MaximumDepthExceeded)?,
+            depth: self.depth + 1,
             parent_fingerprint: self.fingerprint(secp),
             child_number: i,
             private_key: tweaked,
             chain_code: ChainCode::from_hmac(hmac),
-        })
+        }
     }
 
     /// Decoding extended private key from binary data according to BIP 32
-    pub fn decode(data: &[u8]) -> Result<Xpriv, ParseError> {
+    pub fn decode(data: &[u8]) -> Result<Xpriv, Error> {
         let Common { network, depth, parent_fingerprint, child_number, chain_code, key } =
             Common::decode(data)?;
 
         let network = match network {
             VERSION_BYTES_MAINNET_PRIVATE => NetworkKind::Main,
             VERSION_BYTES_TESTNETS_PRIVATE => NetworkKind::Test,
-            unknown => return Err(ParseError::UnknownVersion(unknown)),
+            unknown => return Err(Error::UnknownVersion(unknown)),
         };
 
         let (&zero, private_key) = key.split_first();
         if zero != 0 {
-            return Err(ParseError::InvalidPrivateKeyPrefix);
+            return Err(Error::InvalidPrivateKeyPrefix);
         }
 
         Ok(Xpriv {
@@ -863,7 +794,7 @@ pub fn derive_pub<C: secp256k1::Verification, P: AsRef<[ChildNumber]>>(
         &self,
         secp: &Secp256k1<C>,
         path: &P,
-    ) -> Result<Xpub, DerivationError> {
+    ) -> Result<Xpub, Error> {
         self.derive_xpub(secp, path)
     }
 
@@ -874,7 +805,7 @@ pub fn derive_xpub<C: secp256k1::Verification, P: AsRef<[ChildNumber]>>(
         &self,
         secp: &Secp256k1<C>,
         path: &P,
-    ) -> Result<Xpub, DerivationError> {
+    ) -> Result<Xpub, Error> {
         let mut pk: Xpub = *self;
         for cnum in path.as_ref() {
             pk = pk.ckd_pub(secp, *cnum)?
@@ -886,9 +817,9 @@ pub fn derive_xpub<C: secp256k1::Verification, P: AsRef<[ChildNumber]>>(
     pub fn ckd_pub_tweak(
         &self,
         i: ChildNumber,
-    ) -> Result<(secp256k1::SecretKey, ChainCode), DerivationError> {
+    ) -> Result<(secp256k1::SecretKey, ChainCode), Error> {
         match i {
-            ChildNumber::Hardened { .. } => Err(DerivationError::CannotDeriveHardenedChild),
+            ChildNumber::Hardened { .. } => Err(Error::CannotDeriveFromHardenedKey),
             ChildNumber::Normal { index: n } => {
                 let mut engine = HmacEngine::<sha512::HashEngine>::new(&self.chain_code[..]);
                 engine.input(&self.public_key.serialize()[..]);
@@ -897,8 +828,7 @@ pub fn ckd_pub_tweak(
                 let hmac = engine.finalize();
                 let private_key = secp256k1::SecretKey::from_byte_array(
                     hmac.as_byte_array().split_array::<32, 32>().0,
-                )
-                .expect("cryptographically unreachable");
+                )?;
                 let chain_code = ChainCode::from_hmac(hmac);
                 Ok((private_key, chain_code))
             }
@@ -910,14 +840,13 @@ pub fn ckd_pub<C: secp256k1::Verification>(
         &self,
         secp: &Secp256k1<C>,
         i: ChildNumber,
-    ) -> Result<Xpub, DerivationError> {
+    ) -> Result<Xpub, Error> {
         let (sk, chain_code) = self.ckd_pub_tweak(i)?;
-        let tweaked =
-            self.public_key.add_exp_tweak(secp, &sk.into()).expect("cryptographically unreachable");
+        let tweaked = self.public_key.add_exp_tweak(secp, &sk.into())?;
 
         Ok(Xpub {
             network: self.network,
-            depth: self.depth.checked_add(1).ok_or(DerivationError::MaximumDepthExceeded)?,
+            depth: self.depth + 1,
             parent_fingerprint: self.fingerprint(),
             child_number: i,
             public_key: tweaked,
@@ -926,14 +855,14 @@ pub fn ckd_pub<C: secp256k1::Verification>(
     }
 
     /// Decoding extended public key from binary data according to BIP 32
-    pub fn decode(data: &[u8]) -> Result<Xpub, ParseError> {
+    pub fn decode(data: &[u8]) -> Result<Xpub, Error> {
         let Common { network, depth, parent_fingerprint, child_number, chain_code, key } =
             Common::decode(data)?;
 
         let network = match network {
             VERSION_BYTES_MAINNET_PUBLIC => NetworkKind::Main,
             VERSION_BYTES_TESTNETS_PUBLIC => NetworkKind::Test,
-            unknown => return Err(ParseError::UnknownVersion(unknown)),
+            unknown => return Err(Error::UnknownVersion(unknown)),
         };
 
         Ok(Xpub {
@@ -979,9 +908,9 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 }
 
 impl FromStr for Xpriv {
-    type Err = ParseError;
+    type Err = Error;
 
-    fn from_str(inp: &str) -> Result<Xpriv, ParseError> {
+    fn from_str(inp: &str) -> Result<Xpriv, Error> {
         let data = base58::decode_check(inp)?;
 
         if data.len() != 78 {
@@ -999,9 +928,9 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 }
 
 impl FromStr for Xpub {
-    type Err = ParseError;
+    type Err = Error;
 
-    fn from_str(inp: &str) -> Result<Xpub, ParseError> {
+    fn from_str(inp: &str) -> Result<Xpub, Error> {
         let data = base58::decode_check(inp)?;
 
         if data.len() != 78 {
@@ -1057,9 +986,9 @@ struct Common {
 }
 
 impl Common {
-    fn decode(data: &[u8]) -> Result<Self, ParseError> {
+    fn decode(data: &[u8]) -> Result<Self, Error> {
         let data: &[u8; 78] =
-            data.try_into().map_err(|_| ParseError::WrongExtendedKeyLength(data.len()))?;
+            data.try_into().map_err(|_| Error::WrongExtendedKeyLength(data.len()))?;
 
         let (&network, data) = data.split_array::<4, 74>();
         let (&depth, data) = data.split_first::<73>();
@@ -1069,11 +998,11 @@ fn decode(data: &[u8]) -> Result<Self, ParseError> {
 
         if depth == 0 {
             if parent_fingerprint != [0u8; 4] {
-                return Err(ParseError::NonZeroParentFingerprintForMasterKey);
+                return Err(Error::NonZeroParentFingerprintForMasterKey);
             }
 
             if child_number != [0u8; 4] {
-                return Err(ParseError::NonZeroChildNumberForMasterKey);
+                return Err(Error::NonZeroChildNumberForMasterKey);
             }
         }
 
@@ -1099,25 +1028,13 @@ mod tests {
 
     #[test]
     fn parse_derivation_path() {
-        assert!(matches!(
-            "n/0'/0".parse::<DerivationPath>(),
-            Err(ParseChildNumberError::ParseInt(..)),
-        ));
-        assert!(matches!(
-            "4/m/5".parse::<DerivationPath>(),
-            Err(ParseChildNumberError::ParseInt(..)),
-        ));
-        assert!(matches!(
-            "//3/0'".parse::<DerivationPath>(),
-            Err(ParseChildNumberError::ParseInt(..)),
-        ));
-        assert!(matches!(
-            "0h/0x".parse::<DerivationPath>(),
-            Err(ParseChildNumberError::ParseInt(..)),
-        ));
+        assert_eq!("n/0'/0".parse::<DerivationPath>(), Err(Error::InvalidChildNumberFormat));
+        assert_eq!("4/m/5".parse::<DerivationPath>(), Err(Error::InvalidChildNumberFormat));
+        assert_eq!("//3/0'".parse::<DerivationPath>(), Err(Error::InvalidChildNumberFormat));
+        assert_eq!("0h/0x".parse::<DerivationPath>(), Err(Error::InvalidChildNumberFormat));
         assert_eq!(
             "2147483648".parse::<DerivationPath>(),
-            Err(ParseChildNumberError::IndexOutOfRange(IndexOutOfRangeError { index: 2147483648 })),
+            Err(Error::InvalidChildNumber(2147483648))
         );
 
         assert_eq!(DerivationPath::master(), "".parse::<DerivationPath>().unwrap());
@@ -1191,26 +1108,23 @@ fn test_path<C: secp256k1::Signing + secp256k1::Verification>(
         expected_sk: &str,
         expected_pk: &str,
     ) {
-        let mut sk = Xpriv::new_master(network, seed);
+        let mut sk = Xpriv::new_master(network, seed).unwrap();
         let mut pk = Xpub::from_xpriv(secp, &sk);
 
         // Check derivation convenience method for Xpriv
-        assert_eq!(&sk.derive_xpriv(secp, &path).unwrap().to_string()[..], expected_sk);
+        assert_eq!(&sk.derive_xpriv(secp, &path).to_string()[..], expected_sk);
 
         // Check derivation convenience method for Xpub, should error
         // appropriately if any ChildNumber is hardened
         if path.0.iter().any(|cnum| cnum.is_hardened()) {
-            assert_eq!(
-                pk.derive_xpub(secp, &path),
-                Err(DerivationError::CannotDeriveHardenedChild)
-            );
+            assert_eq!(pk.derive_xpub(secp, &path), Err(Error::CannotDeriveFromHardenedKey));
         } else {
             assert_eq!(&pk.derive_xpub(secp, &path).unwrap().to_string()[..], expected_pk);
         }
 
         // Derive keys, checking hardened and non-hardened derivation one-by-one
         for &num in path.0.iter() {
-            sk = sk.ckd_priv(secp, num).unwrap();
+            sk = sk.ckd_priv(secp, num);
             match num {
                 Normal { .. } => {
                     let pk2 = pk.ckd_pub(secp, num).unwrap();
@@ -1218,10 +1132,7 @@ fn test_path<C: secp256k1::Signing + secp256k1::Verification>(
                     assert_eq!(pk, pk2);
                 }
                 Hardened { .. } => {
-                    assert_eq!(
-                        pk.ckd_pub(secp, num),
-                        Err(DerivationError::CannotDeriveHardenedChild)
-                    );
+                    assert_eq!(pk.ckd_pub(secp, num), Err(Error::CannotDeriveFromHardenedKey));
                     pk = Xpub::from_xpriv(secp, &sk);
                 }
             }
@@ -1247,9 +1158,9 @@ fn increment() {
 
         let max = (1 << 31) - 1;
         let cn = ChildNumber::from_normal_idx(max).unwrap();
-        assert_eq!(cn.increment(), Err(IndexOutOfRangeError { index: 1 << 31 }),);
+        assert_eq!(cn.increment().err(), Some(Error::InvalidChildNumber(1 << 31)));
         let cn = ChildNumber::from_hardened_idx(max).unwrap();
-        assert_eq!(cn.increment(), Err(IndexOutOfRangeError { index: 1 << 31 }),);
+        assert_eq!(cn.increment().err(), Some(Error::InvalidChildNumber(1 << 31)));
 
         let cn = ChildNumber::from_normal_idx(350).unwrap();
         let path = "42'".parse::<DerivationPath>().unwrap();
@@ -1379,7 +1290,7 @@ fn test_reject_xpriv_with_non_zero_byte_at_index_45() {
         assert!(result.is_err());
 
         match result {
-            Err(ParseError::InvalidPrivateKeyPrefix) => {}
+            Err(Error::InvalidPrivateKeyPrefix) => {}
             _ => panic!("Expected InvalidPrivateKeyPrefix error, got {:?}", result),
         }
     }
@@ -1390,7 +1301,7 @@ fn test_reject_xpriv_with_zero_depth_and_non_zero_index() {
         assert!(result.is_err());
 
         match result {
-            Err(ParseError::NonZeroChildNumberForMasterKey) => {}
+            Err(Error::NonZeroChildNumberForMasterKey) => {}
             _ => panic!("Expected NonZeroChildNumberForMasterKey error, got {:?}", result),
         }
     }
@@ -1401,7 +1312,7 @@ fn test_reject_xpriv_with_zero_depth_and_non_zero_parent_fingerprint() {
         assert!(result.is_err());
 
         match result {
-            Err(ParseError::NonZeroParentFingerprintForMasterKey) => {}
+            Err(Error::NonZeroParentFingerprintForMasterKey) => {}
             _ => panic!("Expected NonZeroParentFingerprintForMasterKey error, got {:?}", result),
         }
     }
diff --git a/bitcoin/src/blockdata/block.rs b/bitcoin/src/blockdata/block.rs
index 5fd59aa3..b88f2a19 100644
--- a/bitcoin/src/blockdata/block.rs
+++ b/bitcoin/src/blockdata/block.rs
@@ -30,7 +30,7 @@
 #[doc(inline)]
 pub use primitives::block::{Block, Checked, Unchecked, Validation, Version, BlockHash, Header, WitnessCommitment};
 #[doc(inline)]
-pub use units::block::{BlockHeight, BlockInterval, TooBigForRelativeBlockHeightIntervalError};
+pub use units::block::{BlockHeight, BlockInterval, TooBigForRelativeBlockHeightError};
 
 impl_hashencode!(BlockHash);
 
diff --git a/bitcoin/src/blockdata/mod.rs b/bitcoin/src/blockdata/mod.rs
index 8255e3cc..ab3b6746 100644
--- a/bitcoin/src/blockdata/mod.rs
+++ b/bitcoin/src/blockdata/mod.rs
@@ -41,11 +41,7 @@ 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};
-
-        #[deprecated(since = "TBD", note = "use `Mtp` instead")]
-        #[doc(hidden)]
-        pub type Time = Mtp;
+        pub use primitives::locktime::absolute::{ConversionError, Height, LockTime, ParseHeightError, ParseTimeError, Time};
 
         impl Encodable for LockTime {
             #[inline]
@@ -71,17 +67,9 @@ 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, Height, IncompatibleHeightError, IncompatibleTimeError,
+            LockTime, Time, TimeOverflowError,
         };
-
-        #[deprecated(since = "TBD", note = "use `Mtp` instead")]
-        #[doc(hidden)]
-        pub type Height = HeightInterval;
-
-        #[deprecated(since = "TBD", note = "use `Mtp` instead")]
-        #[doc(hidden)]
-        pub type Time = MtpInterval;
     }
 }
 
diff --git a/bitcoin/src/blockdata/script/borrowed.rs b/bitcoin/src/blockdata/script/borrowed.rs
index cb8ded5a..481145e8 100644
--- a/bitcoin/src/blockdata/script/borrowed.rs
+++ b/bitcoin/src/blockdata/script/borrowed.rs
@@ -2,7 +2,6 @@
 
 use core::fmt;
 
-use hex::DisplayHex as _;
 use internals::ToU64 as _;
 
 use super::witness_version::WitnessVersion;
@@ -10,11 +9,11 @@
     Builder, Instruction, InstructionIndices, Instructions, PushBytes, RedeemScriptSizeError,
     ScriptHash, WScriptHash, WitnessScriptSizeError,
 };
-use crate::consensus::{self, Encodable};
+use crate::consensus::Encodable;
 use crate::opcodes::all::*;
 use crate::opcodes::{self, Opcode};
 use crate::policy::{DUST_RELAY_TX_FEE, MAX_OP_RETURN_RELAY};
-use crate::prelude::{sink, String, ToString};
+use crate::prelude::{sink, DisplayHex, String, ToString};
 use crate::taproot::{LeafVersion, TapLeafHash};
 use crate::{Amount, FeeRate};
 
@@ -375,16 +374,12 @@ fn fmt_asm(&self, f: &mut dyn fmt::Write) -> fmt::Result {
         #[deprecated(since = "TBD", note = "use `to_string()` instead")]
         fn to_asm_string(&self) -> String { self.to_string() }
 
-        /// Consensus encodes the script as lower-case hex.
-        fn to_hex_string(&self) -> String { consensus::encode::serialize_hex(self) }
-
-        /// Consensus encodes the script as lower-case hex.
+        /// Formats the script as lower-case hex.
         ///
-        /// This is **not** consensus encoding, you likely want to use `to_hex_string`. The returned
-        /// hex string will not include the length prefix.
-        fn to_hex_string_no_length_prefix(&self) -> String {
-            self.as_bytes().to_lower_hex_string()
-        }
+        /// This is a more convenient and performant way to write `format!("{:x}", script)`.
+        /// For better performance you should generally prefer displaying the script but if `String` is
+        /// required (this is common in tests) this method can be used.
+        fn to_hex_string(&self) -> String { self.as_bytes().to_lower_hex_string() }
 
         /// Returns the first opcode of the script (if there is any).
         fn first_opcode(&self) -> Option<Opcode> {
diff --git a/bitcoin/src/blockdata/script/owned.rs b/bitcoin/src/blockdata/script/owned.rs
index 49357d32..7d4c9b97 100644
--- a/bitcoin/src/blockdata/script/owned.rs
+++ b/bitcoin/src/blockdata/script/owned.rs
@@ -3,11 +3,10 @@
 #[cfg(doc)]
 use core::ops::Deref;
 
-use hex::FromHex as _;
+use hex::FromHex;
 use internals::ToU64 as _;
 
 use super::{opcode_to_verify, Builder, Instruction, PushBytes, ScriptExtPriv as _};
-use crate::consensus;
 use crate::opcodes::all::*;
 use crate::opcodes::{self, Opcode};
 use crate::prelude::Vec;
@@ -28,17 +27,7 @@ fn new_op_return<T: AsRef<PushBytes>>(data: T) -> Self {
         }
 
         /// Constructs a new [`ScriptBuf`] from a hex string.
-        ///
-        /// The input string is expected to be consensus encoded i.e., includes the length prefix.
-        fn from_hex(s: &str) -> Result<ScriptBuf, consensus::FromHexError> {
-            consensus::encode::deserialize_hex(s)
-        }
-
-        /// Constructs a new [`ScriptBuf`] from a hex string.
-        ///
-        /// This is **not** consensus encoding. If your hex string is a consensus encode script then
-        /// use `ScriptBuf::from_hex`.
-        fn from_hex_no_length_prefix(s: &str) -> Result<ScriptBuf, hex::HexToBytesError> {
+        fn from_hex(s: &str) -> Result<ScriptBuf, hex::HexToBytesError> {
             let v = Vec::from_hex(s)?;
             Ok(ScriptBuf::from_bytes(v))
         }
diff --git a/bitcoin/src/blockdata/script/witness_program.rs b/bitcoin/src/blockdata/script/witness_program.rs
index 79a22dc8..f2780f85 100644
--- a/bitcoin/src/blockdata/script/witness_program.rs
+++ b/bitcoin/src/blockdata/script/witness_program.rs
@@ -101,13 +101,13 @@ pub fn p2tr<C: Verification>(
         merkle_root: Option<TapNodeHash>,
     ) -> Self {
         let (output_key, _parity) = internal_key.tap_tweak(secp, merkle_root);
-        let pubkey = output_key.as_x_only_public_key().serialize();
+        let pubkey = output_key.to_inner().serialize();
         WitnessProgram::new_p2tr(pubkey)
     }
 
     /// Constructs a new [`WitnessProgram`] from a tweaked key for a P2TR output.
     pub fn p2tr_tweaked(output_key: TweakedPublicKey) -> Self {
-        let pubkey = output_key.as_x_only_public_key().serialize();
+        let pubkey = output_key.to_inner().serialize();
         WitnessProgram::new_p2tr(pubkey)
     }
 
diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs
index ff2d7d19..4aeec130 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, Time};
 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: Time) -> 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: Time) -> bool {
         if !self.is_lock_time_enabled() {
             return true;
         }
@@ -779,7 +779,7 @@ pub fn effective_value(
     value: Amount,
 ) -> Option<SignedAmount> {
     let weight = input_weight_prediction.total_weight();
-    let signed_input_fee = fee_rate.to_fee(weight)?.to_signed();
+    let signed_input_fee = fee_rate.to_fee(weight).ok()?.to_signed();
     value.to_signed().checked_sub(signed_input_fee)
 }
 
diff --git a/bitcoin/src/crypto/key.rs b/bitcoin/src/crypto/key.rs
index fe62e258..45a23294 100644
--- a/bitcoin/src/crypto/key.rs
+++ b/bitcoin/src/crypto/key.rs
@@ -887,18 +887,9 @@ pub fn dangerous_assume_tweaked(key: XOnlyPublicKey) -> TweakedPublicKey {
         TweakedPublicKey(key)
     }
 
-    #[doc(hidden)]
-    #[deprecated(since="0.33.0", note="use to_x_only_public_key() instead")]
+    /// Returns the underlying public key.
     pub fn to_inner(self) -> XOnlyPublicKey { self.0 }
 
-    /// Returns the underlying x-only public key.
-    #[inline]
-    pub fn to_x_only_public_key(self) -> XOnlyPublicKey { self.0 }
-
-    /// Returns a reference to the underlying x-only public key.
-    #[inline]
-    pub fn as_x_only_public_key(&self) -> &XOnlyPublicKey { &self.0 }
-
     /// Serializes the key as a byte-encoded pair of values. In compressed form
     /// the y-coordinate is represented by only a single bit, as x determines
     /// it up to one bit.
@@ -915,17 +906,9 @@ impl TweakedKeypair {
     #[inline]
     pub fn dangerous_assume_tweaked(pair: Keypair) -> TweakedKeypair { TweakedKeypair(pair) }
 
-    #[doc(hidden)]
-    #[deprecated(since="0.33.0", note="use to_keypair() instead")]
-    pub fn to_inner(self) -> Keypair { self.0 }
-
     /// Returns the underlying key pair.
     #[inline]
-    pub fn to_keypair(self) -> Keypair { self.0 }
-
-    /// Returns a reference to the underlying key pair.
-    #[inline]
-    pub fn as_keypair(&self) -> &Keypair { &self.0 }
+    pub fn to_inner(self) -> Keypair { self.0 }
 
     /// Returns the [`TweakedPublicKey`] and its [`Parity`] for this [`TweakedKeypair`].
     #[inline]
diff --git a/bitcoin/src/crypto/sighash.rs b/bitcoin/src/crypto/sighash.rs
index e2ea1a0c..b9181676 100644
--- a/bitcoin/src/crypto/sighash.rs
+++ b/bitcoin/src/crypto/sighash.rs
@@ -1832,7 +1832,7 @@ fn test_taproot_sighash(
 
         let leaf_hash = match (script_hex, script_leaf_hash) {
             (Some(script_hex), _) => {
-                let script_inner = ScriptBuf::from_hex_no_length_prefix(script_hex).unwrap();
+                let script_inner = ScriptBuf::from_hex(script_hex).unwrap();
                 Some(ScriptPath::with_defaults(&script_inner).leaf_hash())
             }
             (_, Some(script_leaf_hash)) => Some(script_leaf_hash.parse::<TapLeafHash>().unwrap()),
@@ -2089,9 +2089,7 @@ fn bip143_p2wpkh() {
             ),
         ).unwrap();
 
-        let spk =
-            ScriptBuf::from_hex_no_length_prefix("00141d0f172a0ecb48aee1be1f2687d2963ae33f71a1")
-                .unwrap();
+        let spk = ScriptBuf::from_hex("00141d0f172a0ecb48aee1be1f2687d2963ae33f71a1").unwrap();
         let value = Amount::from_sat_u32(600_000_000);
 
         let mut cache = SighashCache::new(&tx);
@@ -2132,8 +2130,7 @@ fn bip143_p2wpkh_nested_in_p2sh() {
         ).unwrap();
 
         let redeem_script =
-            ScriptBuf::from_hex_no_length_prefix("001479091972186c449eb1ded22b78e40d009bdf0089")
-                .unwrap();
+            ScriptBuf::from_hex("001479091972186c449eb1ded22b78e40d009bdf0089").unwrap();
         let value = Amount::from_sat_u32(1_000_000_000);
 
         let mut cache = SighashCache::new(&tx);
@@ -2174,7 +2171,7 @@ fn bip143_p2wsh_nested_in_p2sh_data() -> (Transaction, ScriptBuf, Amount) {
         ))
         .unwrap();
 
-        let witness_script = ScriptBuf::from_hex_no_length_prefix(
+        let witness_script = ScriptBuf::from_hex(
             "56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28\
              bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b\
              9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58\
diff --git a/bitcoin/src/psbt/mod.rs b/bitcoin/src/psbt/mod.rs
index b9d6a936..9b3dfad5 100644
--- a/bitcoin/src/psbt/mod.rs
+++ b/bitcoin/src/psbt/mod.rs
@@ -448,7 +448,7 @@ fn bip32_sign_schnorr<C, K, T>(
                     let (msg, sighash_type) = self.sighash_taproot(input_index, cache, None)?;
                     let key_pair = Keypair::from_secret_key(secp, &sk.inner)
                         .tap_tweak(secp, input.tap_merkle_root)
-                        .to_keypair();
+                        .to_inner();
 
                     #[cfg(feature = "rand-std")]
                     let signature = secp.sign_schnorr(msg.as_ref(), &key_pair);
@@ -775,14 +775,14 @@ fn get_key<C: Signing>(
             KeyRequest::XOnlyPubkey(_) => Err(GetKeyError::NotSupported),
             KeyRequest::Bip32((fingerprint, path)) => {
                 let key = if self.fingerprint(secp) == *fingerprint {
-                    let k = self.derive_xpriv(secp, &path).map_err(GetKeyError::Bip32)?;
+                    let k = self.derive_xpriv(secp, &path);
                     Some(k.to_private_key())
                 } else if self.parent_fingerprint == *fingerprint
                     && !path.is_empty()
                     && path[0] == self.child_number
                 {
                     let path = DerivationPath::from_iter(path.into_iter().skip(1).copied());
-                    let k = self.derive_xpriv(secp, &path).map_err(GetKeyError::Bip32)?;
+                    let k = self.derive_xpriv(secp, &path);
                     Some(k.to_private_key())
                 } else {
                     None
@@ -915,8 +915,8 @@ fn get_key<C: Signing>(
 #[derive(Debug, Clone, PartialEq, Eq)]
 #[non_exhaustive]
 pub enum GetKeyError {
-    /// A bip32 derivation error.
-    Bip32(bip32::DerivationError),
+    /// A bip32 error.
+    Bip32(bip32::Error),
     /// The GetKey operation is not supported for this key request.
     NotSupported,
 }
@@ -930,7 +930,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         use GetKeyError::*;
 
         match *self {
-            Bip32(ref e) => write_err!(f, "bip32 derivation"; e),
+            Bip32(ref e) => write_err!(f, "a bip23 error"; e),
             NotSupported =>
                 f.write_str("the GetKey operation is not supported for this key request"),
         }
@@ -949,6 +949,10 @@ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
     }
 }
 
+impl From<bip32::Error> for GetKeyError {
+    fn from(e: bip32::Error) -> Self { GetKeyError::Bip32(e) }
+}
+
 /// The various output types supported by the Bitcoin network.
 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
 #[non_exhaustive]
@@ -1332,7 +1336,7 @@ fn psbt_with_values(input: u64, output: u64) -> Psbt {
                 }],
                 output: vec![TxOut {
                     value: Amount::from_sat(output).unwrap(),
-                    script_pubkey: ScriptBuf::from_hex_no_length_prefix(
+                    script_pubkey: ScriptBuf::from_hex(
                         "a9143545e6e33b832c47050f24d3eeb93c9c03948bc787",
                     )
                     .unwrap(),
@@ -1346,7 +1350,7 @@ fn psbt_with_values(input: u64, output: u64) -> Psbt {
             inputs: vec![Input {
                 witness_utxo: Some(TxOut {
                     value: Amount::from_sat(input).unwrap(),
-                    script_pubkey: ScriptBuf::from_hex_no_length_prefix(
+                    script_pubkey: ScriptBuf::from_hex(
                         "a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587",
                     )
                     .unwrap(),
@@ -1436,7 +1440,7 @@ fn serialize_then_deserialize_output() {
 
         let mut hd_keypaths: BTreeMap<secp256k1::PublicKey, KeySource> = Default::default();
 
-        let mut sk: Xpriv = Xpriv::new_master(NetworkKind::Main, &seed);
+        let mut sk: Xpriv = Xpriv::new_master(NetworkKind::Main, &seed).unwrap();
 
         let fprint = sk.fingerprint(secp);
 
@@ -1451,7 +1455,7 @@ fn serialize_then_deserialize_output() {
             ChildNumber::from_normal_idx(31337).unwrap(),
         ];
 
-        sk = sk.derive_xpriv(secp, &dpath).unwrap();
+        sk = sk.derive_xpriv(secp, &dpath);
 
         let pk = Xpub::from_xpriv(secp, &sk);
 
@@ -1459,16 +1463,10 @@ fn serialize_then_deserialize_output() {
 
         let expected: Output = Output {
             redeem_script: Some(
-                ScriptBuf::from_hex_no_length_prefix(
-                    "76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac",
-                )
-                .unwrap(),
+                ScriptBuf::from_hex("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap(),
             ),
             witness_script: Some(
-                ScriptBuf::from_hex_no_length_prefix(
-                    "a9143545e6e33b832c47050f24d3eeb93c9c03948bc787",
-                )
-                .unwrap(),
+                ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(),
             ),
             bip32_derivation: hd_keypaths,
             ..Default::default()
@@ -1499,14 +1497,14 @@ fn serialize_then_deserialize_global() {
                 output: vec![
                     TxOut {
                         value: Amount::from_sat_u32(99_999_699),
-                        script_pubkey: ScriptBuf::from_hex_no_length_prefix(
+                        script_pubkey: ScriptBuf::from_hex(
                             "76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac",
                         )
                         .unwrap(),
                     },
                     TxOut {
                         value: Amount::from_sat_u32(100_000_000),
-                        script_pubkey: ScriptBuf::from_hex_no_length_prefix(
+                        script_pubkey: ScriptBuf::from_hex(
                             "a9143545e6e33b832c47050f24d3eeb93c9c03948bc787",
                         )
                         .unwrap(),
@@ -1563,10 +1561,8 @@ fn serde_psbt() {
                         .unwrap(),
                     vout: 1,
                 },
-                script_sig: ScriptBuf::from_hex_no_length_prefix(
-                    "160014be18d152a9b012039daf3da7de4f53349eecb985",
-                )
-                .unwrap(),
+                script_sig: ScriptBuf::from_hex("160014be18d152a9b012039daf3da7de4f53349eecb985")
+                    .unwrap(),
                 sequence: Sequence::MAX,
                 witness: Witness::from_slice(&[hex!(
                     "03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105"
@@ -1574,7 +1570,7 @@ fn serde_psbt() {
             }],
             output: vec![TxOut {
                 value: Amount::from_sat(190_303_501_938).unwrap(),
-                script_pubkey: ScriptBuf::from_hex_no_length_prefix(
+                script_pubkey: ScriptBuf::from_hex(
                     "a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587",
                 )
                 .unwrap(),
@@ -1625,7 +1621,7 @@ fn serde_psbt() {
                     non_witness_utxo: Some(tx),
                     witness_utxo: Some(TxOut {
                         value: Amount::from_sat(190_303_501_938).unwrap(),
-                        script_pubkey: ScriptBuf::from_hex_no_length_prefix("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(),
+                        script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(),
                     }),
                     sighash_type: Some("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY".parse::<PsbtSighashType>().unwrap()),
                     redeem_script: Some(vec![0x51].into()),
@@ -1750,11 +1746,11 @@ fn valid_vector_1() {
                     output: vec![
                         TxOut {
                             value: Amount::from_sat_u32(99_999_699),
-                            script_pubkey: ScriptBuf::from_hex_no_length_prefix("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap(),
+                            script_pubkey: ScriptBuf::from_hex("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap(),
                         },
                         TxOut {
                             value: Amount::from_sat_u32(100_000_000),
-                            script_pubkey: ScriptBuf::from_hex_no_length_prefix("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(),
+                            script_pubkey: ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(),
                         },
                     ],
                 },
@@ -1774,7 +1770,7 @@ fn valid_vector_1() {
                                         txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389".parse().unwrap(),
                                         vout: 1,
                                     },
-                                    script_sig: ScriptBuf::from_hex_no_length_prefix("160014be18d152a9b012039daf3da7de4f53349eecb985").unwrap(),
+                                    script_sig: ScriptBuf::from_hex("160014be18d152a9b012039daf3da7de4f53349eecb985").unwrap(),
                                     sequence: Sequence::MAX,
                                     witness: Witness::from_slice(&[
                                         hex!("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01").as_slice(),
@@ -1786,7 +1782,7 @@ fn valid_vector_1() {
                                         txid: "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886".parse().unwrap(),
                                         vout: 1,
                                     },
-                                    script_sig: ScriptBuf::from_hex_no_length_prefix("160014fe3e9ef1a745e974d902c4355943abcb34bd5353").unwrap(),
+                                    script_sig: ScriptBuf::from_hex("160014fe3e9ef1a745e974d902c4355943abcb34bd5353").unwrap(),
                                     sequence: Sequence::MAX,
                                     witness: Witness::from_slice(&[
                                         hex!("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01").as_slice(),
@@ -1797,11 +1793,11 @@ fn valid_vector_1() {
                             output: vec![
                                 TxOut {
                                     value: Amount::from_sat_u32(200_000_000),
-                                    script_pubkey: ScriptBuf::from_hex_no_length_prefix("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac").unwrap(),
+                                    script_pubkey: ScriptBuf::from_hex("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac").unwrap(),
                                 },
                                 TxOut {
                                     value: Amount::from_sat(190_303_501_938).unwrap(),
-                                    script_pubkey: ScriptBuf::from_hex_no_length_prefix("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(),
+                                    script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(),
                                 },
                             ],
                         }),
@@ -1842,10 +1838,8 @@ fn valid_vector_2() {
             assert!(&psbt.inputs[0].final_script_sig.is_some());
 
             let redeem_script = psbt.inputs[1].redeem_script.as_ref().unwrap();
-            let expected_out = ScriptBuf::from_hex_no_length_prefix(
-                "a9143545e6e33b832c47050f24d3eeb93c9c03948bc787",
-            )
-            .unwrap();
+            let expected_out =
+                ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap();
 
             assert!(redeem_script.is_p2wpkh());
             assert_eq!(
@@ -1890,10 +1884,8 @@ fn valid_vector_4() {
             assert!(&psbt.inputs[1].final_script_sig.is_none());
 
             let redeem_script = psbt.inputs[1].redeem_script.as_ref().unwrap();
-            let expected_out = ScriptBuf::from_hex_no_length_prefix(
-                "a9143545e6e33b832c47050f24d3eeb93c9c03948bc787",
-            )
-            .unwrap();
+            let expected_out =
+                ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap();
 
             assert!(redeem_script.is_p2wpkh());
             assert_eq!(
@@ -1917,10 +1909,8 @@ fn valid_vector_5() {
             assert!(&psbt.inputs[0].final_script_sig.is_none());
 
             let redeem_script = psbt.inputs[0].redeem_script.as_ref().unwrap();
-            let expected_out = ScriptBuf::from_hex_no_length_prefix(
-                "a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87",
-            )
-            .unwrap();
+            let expected_out =
+                ScriptBuf::from_hex("a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87").unwrap();
 
             assert!(redeem_script.is_p2wsh());
             assert_eq!(
@@ -2089,11 +2079,11 @@ fn serialize_and_deserialize_preimage_psbt() {
                 output: vec![
                     TxOut {
                         value: Amount::from_sat_u32(99_999_699),
-                        script_pubkey: ScriptBuf::from_hex_no_length_prefix("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap(),
+                        script_pubkey: ScriptBuf::from_hex("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap(),
                     },
                     TxOut {
                         value: Amount::from_sat_u32(100_000_000),
-                        script_pubkey: ScriptBuf::from_hex_no_length_prefix("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(),
+                        script_pubkey: ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(),
                     },
                 ],
             },
@@ -2113,7 +2103,7 @@ fn serialize_and_deserialize_preimage_psbt() {
                                     txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389".parse().unwrap(),
                                     vout: 1,
                                 },
-                                script_sig: ScriptBuf::from_hex_no_length_prefix("160014be18d152a9b012039daf3da7de4f53349eecb985").unwrap(),
+                                script_sig: ScriptBuf::from_hex("160014be18d152a9b012039daf3da7de4f53349eecb985").unwrap(),
                                 sequence: Sequence::MAX,
                                 witness: Witness::from_slice(&[
                                     hex!("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01").as_slice(),
@@ -2125,7 +2115,7 @@ fn serialize_and_deserialize_preimage_psbt() {
                                     txid: "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886".parse().unwrap(),
                                     vout: 1,
                                 },
-                                script_sig: ScriptBuf::from_hex_no_length_prefix("160014fe3e9ef1a745e974d902c4355943abcb34bd5353").unwrap(),
+                                script_sig: ScriptBuf::from_hex("160014fe3e9ef1a745e974d902c4355943abcb34bd5353").unwrap(),
                                 sequence: Sequence::MAX,
                                 witness: Witness::from_slice(&[
                                     hex!("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01").as_slice(),
@@ -2136,11 +2126,11 @@ fn serialize_and_deserialize_preimage_psbt() {
                         output: vec![
                             TxOut {
                                 value: Amount::from_sat_u32(200_000_000),
-                                script_pubkey: ScriptBuf::from_hex_no_length_prefix("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac").unwrap(),
+                                script_pubkey: ScriptBuf::from_hex("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac").unwrap(),
                             },
                             TxOut {
                                 value: Amount::from_sat(190_303_501_938).unwrap(),
-                                script_pubkey: ScriptBuf::from_hex_no_length_prefix("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(),
+                                script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(),
                             },
                         ],
                     }),
diff --git a/bitcoin/src/psbt/serialize.rs b/bitcoin/src/psbt/serialize.rs
index bc582a14..25eef99c 100644
--- a/bitcoin/src/psbt/serialize.rs
+++ b/bitcoin/src/psbt/serialize.rs
@@ -414,7 +414,7 @@ pub fn compose_taproot_builder<'map>(
         let mut val = opcode;
         let mut builder = TaprootBuilder::new();
         for depth in depth_map {
-            let script = ScriptBuf::from_hex_no_length_prefix(&format!("{:02x}", val)).unwrap();
+            let script = ScriptBuf::from_hex(&format!("{:02x}", val)).unwrap();
             builder = builder.add_leaf(*depth, script).unwrap();
             let (new_val, _) = val.overflowing_add(1);
             val = new_val;
@@ -429,7 +429,7 @@ fn taptree_hidden() {
         builder = builder
             .add_leaf_with_ver(
                 3,
-                ScriptBuf::from_hex_no_length_prefix("b9").unwrap(),
+                ScriptBuf::from_hex("b9").unwrap(),
                 LeafVersion::from_consensus(0xC2).unwrap(),
             )
             .unwrap();
@@ -443,7 +443,7 @@ fn taptree_roundtrip() {
         builder = builder
             .add_leaf_with_ver(
                 3,
-                ScriptBuf::from_hex_no_length_prefix("b9").unwrap(),
+                ScriptBuf::from_hex("b9").unwrap(),
                 LeafVersion::from_consensus(0xC2).unwrap(),
             )
             .unwrap();
diff --git a/bitcoin/src/taproot/mod.rs b/bitcoin/src/taproot/mod.rs
index 78a4f8a5..e4a60a35 100644
--- a/bitcoin/src/taproot/mod.rs
+++ b/bitcoin/src/taproot/mod.rs
@@ -1781,10 +1781,10 @@ fn _verify_tap_commitments(
     ) {
         let out_pk = out_spk_hex[4..].parse::<XOnlyPublicKey>().unwrap();
         let out_pk = TweakedPublicKey::dangerous_assume_tweaked(out_pk);
-        let script = ScriptBuf::from_hex_no_length_prefix(script_hex).unwrap();
+        let script = ScriptBuf::from_hex(script_hex).unwrap();
         let control_block = ControlBlock::from_hex(control_block_hex).unwrap();
         assert_eq!(control_block_hex, control_block.serialize().to_lower_hex_string());
-        assert!(control_block.verify_taproot_commitment(secp, out_pk.to_x_only_public_key(), &script));
+        assert!(control_block.verify_taproot_commitment(secp, out_pk.to_inner(), &script));
     }
 
     #[test]
@@ -1847,11 +1847,11 @@ fn build_huffman_tree() {
             .unwrap();
 
         let script_weights = [
-            (10, ScriptBuf::from_hex_no_length_prefix("51").unwrap()), // semantics of script don't matter for this test
-            (20, ScriptBuf::from_hex_no_length_prefix("52").unwrap()),
-            (20, ScriptBuf::from_hex_no_length_prefix("53").unwrap()),
-            (30, ScriptBuf::from_hex_no_length_prefix("54").unwrap()),
-            (19, ScriptBuf::from_hex_no_length_prefix("55").unwrap()),
+            (10, ScriptBuf::from_hex("51").unwrap()), // semantics of script don't matter for this test
+            (20, ScriptBuf::from_hex("52").unwrap()),
+            (20, ScriptBuf::from_hex("53").unwrap()),
+            (30, ScriptBuf::from_hex("54").unwrap()),
+            (19, ScriptBuf::from_hex("55").unwrap()),
         ];
         let tree_info =
             TaprootSpendInfo::with_huffman_tree(&secp, internal_key, script_weights.clone())
@@ -1872,10 +1872,7 @@ fn build_huffman_tree() {
                 *length,
                 tree_info
                     .script_map
-                    .get(&(
-                        ScriptBuf::from_hex_no_length_prefix(script).unwrap(),
-                        LeafVersion::TapScript
-                    ))
+                    .get(&(ScriptBuf::from_hex(script).unwrap(), LeafVersion::TapScript))
                     .expect("Present Key")
                     .iter()
                     .next()
@@ -1893,7 +1890,7 @@ fn build_huffman_tree() {
             let ctrl_block = tree_info.control_block(&ver_script).unwrap();
             assert!(ctrl_block.verify_taproot_commitment(
                 &secp,
-                output_key.to_x_only_public_key(),
+                output_key.to_inner(),
                 &ver_script.0
             ))
         }
@@ -1916,11 +1913,11 @@ fn taptree_builder() {
         //                                   /  \    /  \
         //                                  A    B  C  / \
         //                                            D   E
-        let a = ScriptBuf::from_hex_no_length_prefix("51").unwrap();
-        let b = ScriptBuf::from_hex_no_length_prefix("52").unwrap();
-        let c = ScriptBuf::from_hex_no_length_prefix("53").unwrap();
-        let d = ScriptBuf::from_hex_no_length_prefix("54").unwrap();
-        let e = ScriptBuf::from_hex_no_length_prefix("55").unwrap();
+        let a = ScriptBuf::from_hex("51").unwrap();
+        let b = ScriptBuf::from_hex("52").unwrap();
+        let c = ScriptBuf::from_hex("53").unwrap();
+        let d = ScriptBuf::from_hex("54").unwrap();
+        let e = ScriptBuf::from_hex("55").unwrap();
         let builder = builder.add_leaf(2, a.clone()).unwrap();
         let builder = builder.add_leaf(2, b.clone()).unwrap();
         let builder = builder.add_leaf(2, c.clone()).unwrap();
@@ -1967,7 +1964,7 @@ fn taptree_builder() {
             let ctrl_block = tree_info.control_block(&ver_script).unwrap();
             assert!(ctrl_block.verify_taproot_commitment(
                 &secp,
-                output_key.to_x_only_public_key(),
+                output_key.to_inner(),
                 &ver_script.0
             ))
         }
@@ -2028,8 +2025,7 @@ fn process_script_trees(
                     builder = process_script_trees(leaf, builder, leaves, depth + 1);
                 }
             } else {
-                let script =
-                    ScriptBuf::from_hex_no_length_prefix(v["script"].as_str().unwrap()).unwrap();
+                let script = ScriptBuf::from_hex(v["script"].as_str().unwrap()).unwrap();
                 let ver =
                     LeafVersion::from_consensus(v["leafVersion"].as_u64().unwrap() as u8).unwrap();
                 leaves.push((script.clone(), ver));
@@ -2083,10 +2079,8 @@ fn process_script_trees(
                 .unwrap();
             let expected_tweak =
                 arr["intermediary"]["tweak"].as_str().unwrap().parse::<TapTweakHash>().unwrap();
-            let expected_spk = ScriptBuf::from_hex_no_length_prefix(
-                arr["expected"]["scriptPubKey"].as_str().unwrap(),
-            )
-            .unwrap();
+            let expected_spk =
+                ScriptBuf::from_hex(arr["expected"]["scriptPubKey"].as_str().unwrap()).unwrap();
             let expected_addr = arr["expected"]["bip350Address"]
                 .as_str()
                 .unwrap()
@@ -2099,7 +2093,7 @@ fn process_script_trees(
             let addr = Address::p2tr(secp, internal_key, merkle_root, KnownHrp::Mainnet);
             let spk = addr.script_pubkey();
 
-            assert_eq!(expected_output_key, output_key.to_x_only_public_key());
+            assert_eq!(expected_output_key, output_key.to_inner());
             assert_eq!(expected_tweak, tweak);
             assert_eq!(expected_addr, addr);
             assert_eq!(expected_spk, spk);
diff --git a/githooks/post-merge b/githooks/post-merge
index 2d78934d..0ca51829 100755
--- a/githooks/post-merge
+++ b/githooks/post-merge
@@ -22,7 +22,7 @@ do
 			>&2 cat <<- EOF
 			==================================================
 			Project githooks have changed. Please inspect the
-			changes and re-run \`just githooks-install\` if
+			changes and re-reun \`just githooks-install\` if
 			they are legitimate.
 
 			Remove $HOOKS_DIR/post-merge to skip this warning
diff --git a/primitives/src/locktime/absolute.rs b/primitives/src/locktime/absolute.rs
index fff858a1..d6434ed8 100644
--- a/primitives/src/locktime/absolute.rs
+++ b/primitives/src/locktime/absolute.rs
@@ -16,11 +16,7 @@
 
 #[rustfmt::skip]                // Keep public re-exports separate.
 #[doc(inline)]
-pub use units::locktime::absolute::{ConversionError, Height, ParseHeightError, ParseTimeError, Mtp, LOCK_TIME_THRESHOLD};
-
-#[deprecated(since = "TBD", note = "use `Mtp` instead")]
-#[doc(hidden)]
-pub type Time = Mtp;
+pub use units::locktime::absolute::{ConversionError, Height, ParseHeightError, ParseTimeError, Time, LOCK_TIME_THRESHOLD};
 
 /// An absolute lock time value, representing either a block height or a UNIX timestamp (seconds
 /// since epoch).
@@ -83,7 +79,7 @@ pub enum LockTime {
     /// assert!(n.is_block_time());
     /// assert_eq!(n.to_consensus_u32(), seconds);
     /// ```
-    Seconds(Mtp),
+    Seconds(Time),
 }
 
 impl LockTime {
@@ -145,9 +141,9 @@ pub fn from_unprefixed_hex(s: &str) -> Result<Self, UnprefixedHexError> {
     #[allow(clippy::missing_panics_doc)]
     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"))
+            Self::Blocks(Height::from_consensus(n).expect("n is valid"))
         } else {
-            Self::Seconds(Mtp::from_u32(n).expect("n is valid"))
+            Self::Seconds(Time::from_consensus(n).expect("n is valid"))
         }
     }
 
@@ -170,23 +166,17 @@ pub fn from_consensus(n: u32) -> Self {
     /// ```
     #[inline]
     pub fn from_height(n: u32) -> Result<Self, ConversionError> {
-        let height = Height::from_u32(n)?;
+        let height = Height::from_consensus(n)?;
         Ok(LockTime::Blocks(height))
     }
 
-    #[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.
+    /// Constructs a new `LockTime` from `n`, expecting `n` to be a valid block time.
     ///
     /// # Note
     ///
-    /// If the locktime is set to an MTP `T`, the transaction can be included in a block only if
-    /// the MTP of last recent 11 blocks is greater than `T`.
-    ///
+    /// If the locktime is set to a timestamp `T`,
+    /// the transaction can be included in a block only if the median time past (MTP) of the
+    /// last 11 blocks is greater than `T`.
     /// 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)
@@ -201,8 +191,8 @@ pub fn from_time(n: u32) -> Result<Self, ConversionError> { Self::from_mtp(n) }
     /// assert!(absolute::LockTime::from_time(741521).is_err());
     /// ```
     #[inline]
-    pub fn from_mtp(n: u32) -> Result<Self, ConversionError> {
-        let time = Mtp::from_u32(n)?;
+    pub fn from_time(n: u32) -> Result<Self, ConversionError> {
+        let time = Time::from_consensus(n)?;
         Ok(LockTime::Seconds(time))
     }
 
@@ -239,7 +229,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::Time { 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 +237,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: Time) -> bool {
         use LockTime as L;
 
         match self {
@@ -263,15 +253,9 @@ pub fn is_satisfied_by(self, height: Height, time: Mtp) -> bool {
     /// two lock times (same unit) then the larger lock time being satisfied implies (in a
     /// mathematical sense) the smaller one being satisfied.
     ///
-    /// This function serves multiple purposes:
-    ///
-    /// * When evaluating `OP_CHECKLOCKTIMEVERIFY` the argument must be less than or equal to the
-    ///   transactions nLockTime. If using this function to validate a script `self` is the argument
-    ///   to `CLTV` and `other` is the transaction nLockTime.
-    ///
-    /// * If you wish to check a lock time against various other locks e.g., filtering out locks
-    ///   which cannot be satisfied. Can also be used to remove the smaller value of two
-    ///   `OP_CHECKLOCKTIMEVERIFY` operations within one branch of the script.
+    /// This function is useful if you wish to check a lock time against various other locks e.g.,
+    /// filtering out locks which cannot be satisfied. Can also be used to remove the smaller value
+    /// of two `OP_CHECKLOCKTIMEVERIFY` operations within one branch of the script.
     ///
     /// # Examples
     ///
@@ -320,8 +304,8 @@ pub fn is_implied_by(self, other: LockTime) -> bool {
     #[inline]
     pub fn to_consensus_u32(self) -> u32 {
         match self {
-            LockTime::Blocks(ref h) => h.to_u32(),
-            LockTime::Seconds(ref t) => t.to_u32(),
+            LockTime::Blocks(ref h) => h.to_consensus_u32(),
+            LockTime::Seconds(ref t) => t.to_consensus_u32(),
         }
     }
 }
@@ -333,9 +317,9 @@ impl From<Height> for LockTime {
     fn from(h: Height) -> Self { LockTime::Blocks(h) }
 }
 
-impl From<Mtp> for LockTime {
+impl From<Time> for LockTime {
     #[inline]
-    fn from(t: Mtp) -> Self { LockTime::Seconds(t) }
+    fn from(t: Time) -> Self { LockTime::Seconds(t) }
 }
 
 impl fmt::Debug for LockTime {
@@ -422,7 +406,7 @@ mod tests {
     #[test]
     fn display_and_alternate() {
         let lock_by_height = LockTime::from_height(741_521).unwrap();
-        let lock_by_time = LockTime::from_mtp(1_653_195_600).unwrap(); // May 22nd 2022, 5am UTC.
+        let lock_by_time = LockTime::from_time(1_653_195_600).unwrap(); // May 22nd 2022, 5am UTC.
 
         assert_eq!(format!("{}", lock_by_height), "741521");
         assert_eq!(format!("{:#}", lock_by_height), "block-height 741521");
@@ -478,9 +462,9 @@ fn invalid_locktime_type() {
         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_mtp(499_999_999).is_err()); // Below the threshold.
-        assert!(LockTime::from_mtp(500_000_000).is_ok()); // The threshold.
-        assert!(LockTime::from_mtp(500_000_001).is_ok()); // Above the threshold.
+        assert!(LockTime::from_time(499_999_999).is_err()); // Below the threshold.
+        assert!(LockTime::from_time(500_000_000).is_ok()); // The threshold.
+        assert!(LockTime::from_time(500_000_001).is_ok()); // Above the threshold.
     }
 
     #[test]
@@ -505,14 +489,14 @@ fn parses_correctly_to_height_or_time() {
 
     #[test]
     fn satisfied_by_height() {
-        let height_below = Height::from_u32(700_000).unwrap();
-        let height = Height::from_u32(750_000).unwrap();
-        let height_above = Height::from_u32(800_000).unwrap();
+        let height_below = Height::from_consensus(700_000).unwrap();
+        let height = Height::from_consensus(750_000).unwrap();
+        let height_above = Height::from_consensus(800_000).unwrap();
 
         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 = Time::from_consensus(t).unwrap();
 
         assert!(!lock_by_height.is_satisfied_by(height_below, time));
         assert!(lock_by_height.is_satisfied_by(height, time));
@@ -521,13 +505,13 @@ 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 = Time::from_consensus(1_653_109_200).unwrap(); // "May 21th 2022, 5am UTC.
+        let time = Time::from_consensus(1_653_195_600).unwrap(); // "May 22nd 2022, 5am UTC.
+        let time_after = Time::from_consensus(1_653_282_000).unwrap(); // "May 23rd 2022, 5am UTC.
 
         let lock_by_time = LockTime::from(time);
 
-        let height = Height::from_u32(800_000).unwrap();
+        let height = Height::from_consensus(800_000).unwrap();
 
         assert!(!lock_by_time.is_satisfied_by(height, time_before));
         assert!(lock_by_time.is_satisfied_by(height, time));
diff --git a/primitives/src/locktime/relative.rs b/primitives/src/locktime/relative.rs
index 053e883c..59dfdd0d 100644
--- a/primitives/src/locktime/relative.rs
+++ b/primitives/src/locktime/relative.rs
@@ -13,16 +13,7 @@
 
 #[rustfmt::skip]                // Keep public re-exports separate.
 #[doc(inline)]
-pub use units::locktime::relative::{HeightInterval, MtpInterval, TimeOverflowError};
-use units::mtp_height::MtpAndHeight;
-
-#[deprecated(since = "TBD", note = "use `Mtp` instead")]
-#[doc(hidden)]
-pub type Height = HeightInterval;
-
-#[deprecated(since = "TBD", note = "use `Mtp` instead")]
-#[doc(hidden)]
-pub type Time = MtpInterval;
+pub use units::locktime::relative::{Height, Time, TimeOverflowError};
 
 /// A relative lock time value, representing either a block height or time (512 second intervals).
 ///
@@ -44,49 +35,31 @@
 ///
 /// ```
 /// use bitcoin_primitives::relative;
-/// use bitcoin_primitives::BlockTime;
-/// use bitcoin_primitives::BlockHeight;
-/// use units::mtp_height::MtpAndHeight;
 /// let lock_by_height = relative::LockTime::from_height(144); // 144 blocks, approx 24h.
 /// assert!(lock_by_height.is_block_height());
 ///
 /// let lock_by_time = relative::LockTime::from_512_second_intervals(168); // 168 time intervals, approx 24h.
 /// assert!(lock_by_time.is_block_time());
 ///
-/// fn generate_timestamps(start: u32, step: u16) -> [BlockTime; 11] {
-///     let mut timestamps = [BlockTime::from_u32(0); 11];
-///     for (i, ts) in timestamps.iter_mut().enumerate() {
-///         *ts = BlockTime::from_u32(start.saturating_sub((step * i as u16).into()));
-///     }
-///     timestamps
-/// }
-/// // time extracted from BlockHeader
-/// let timestamps: [BlockTime; 11] = generate_timestamps(1_600_000_000, 200);
-/// let utxo_timestamps: [BlockTime; 11] = generate_timestamps(1_599_000_000, 200);
-///
-/// let current_height = BlockHeight::from(100);
-/// let utxo_height = BlockHeight::from(80);
-///
-/// let chain_tip = MtpAndHeight::new(current_height, timestamps);
-/// let utxo_mined_at = MtpAndHeight::new(utxo_height, utxo_timestamps);
-/// let locktime = relative::LockTime::Time(relative::MtpInterval::from_512_second_intervals(10));
-///
-/// // Check if locktime is satisfied
-/// assert!(locktime.is_satisfied_by(chain_tip, utxo_mined_at));
+/// // Check if a lock time is satisfied by a given height or time.
+/// let height = relative::Height::from(150);
+/// let time = relative::Time::from_512_second_intervals(200);
+/// assert!(lock_by_height.is_satisfied_by(height, time));
+/// assert!(lock_by_time.is_satisfied_by(height, time));
 /// ```
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 pub enum LockTime {
     /// A block height lock time value.
-    Blocks(HeightInterval),
+    Blocks(Height),
     /// A 512 second time interval value.
-    Time(MtpInterval),
+    Time(Time),
 }
 
 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(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.
@@ -132,9 +105,8 @@ pub fn from_consensus(n: u32) -> Result<Self, DisabledLockTimeError> {
     #[inline]
     pub fn to_consensus_u32(self) -> u32 {
         match self {
-            LockTime::Blocks(ref h) => u32::from(h.to_height()),
-            LockTime::Time(ref t) =>
-                Sequence::LOCK_TYPE_MASK | u32::from(t.to_512_second_intervals()),
+            LockTime::Blocks(ref h) => h.to_consensus_u32(),
+            LockTime::Time(ref t) => t.to_consensus_u32(),
         }
     }
 
@@ -165,7 +137,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(Height::from_height(n)) }
 
     /// Constructs a new `LockTime` from `n`, expecting `n` to be a count of 512-second intervals.
     ///
@@ -173,7 +145,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(Time::from_512_second_intervals(intervals))
     }
 
     /// Construct a new [`LockTime`] from seconds, converting the seconds into 512 second interval
@@ -184,7 +156,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 Time::from_seconds_floor(seconds) {
             Ok(time) => Ok(LockTime::Time(time)),
             Err(e) => Err(e),
         }
@@ -198,7 +170,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 Time::from_seconds_ceil(seconds) {
             Ok(time) => Ok(LockTime::Time(time)),
             Err(e) => Err(e),
         }
@@ -221,42 +193,29 @@ pub const fn is_block_height(self) -> bool { matches!(self, LockTime::Blocks(_))
     #[inline]
     pub const fn is_block_time(self) -> bool { !self.is_block_height() }
 
-    /// Returns true if this [`relative::LockTime`] is satisfied by the given chain state.
+    /// Returns true if this [`relative::LockTime`] is satisfied by either height or time.
+    ///
     /// # Examples
     ///
     /// ```rust
-    /// # use bitcoin_primitives::locktime::relative::HeightInterval;
-    /// # use bitcoin_primitives::relative::Time;
-    /// # use units::mtp_height::MtpAndHeight;
-    /// # use bitcoin_primitives::BlockHeight;
-    /// # use bitcoin_primitives::relative::LockTime;
-    /// # use bitcoin_primitives::BlockTime;
-    ///
-    /// fn generate_timestamps(start: u32, step: u16) -> [BlockTime; 11] {
-    ///     let mut timestamps = [BlockTime::from_u32(0); 11];
-    ///     for (i, ts) in timestamps.iter_mut().enumerate() {
-    ///         *ts = BlockTime::from_u32(start.saturating_sub((step * i as u16).into()));
-    ///     }
-    ///     timestamps
-    /// }
-    /// // time extracted from BlockHeader
-    /// let timestamps: [BlockTime; 11] = generate_timestamps(1_600_000_000, 200);
-    /// let utxo_timestamps: [BlockTime; 11] = generate_timestamps(1_599_000_000, 200);
-    ///
-    /// let current_height = BlockHeight::from_u32(100);
-    /// let utxo_height = BlockHeight::from_u32(80);
-    ///
-    /// let chain_tip = MtpAndHeight::new(current_height, timestamps);
-    /// let utxo_mined_at = MtpAndHeight::new(utxo_height, utxo_timestamps);
-    /// let locktime = LockTime::Time(Time::from_512_second_intervals(10));
-    ///
-    /// // Check if locktime is satisfied
-    /// assert!(locktime.is_satisfied_by(chain_tip, utxo_mined_at));
+    /// # use bitcoin_primitives::Sequence;
+    /// # use bitcoin_primitives::relative;
+    ///
+    /// # let required_height = 100;       // 100 blocks.
+    /// # let intervals = 70;     // Approx 10 hours.
+    /// # let current_height = || relative::Height::from(required_height + 10);
+    /// # let current_time = || relative::Time::from_512_second_intervals(intervals + 10);
+    /// # let lock = Sequence::from_height(required_height).to_relative_lock_time().expect("valid height");
+    ///
+    /// // Users that have chain data can get the current height and time to check against a lock.
+    /// assert!(lock.is_satisfied_by(current_height(), current_time()));
     /// ```
-    pub fn is_satisfied_by(self, chain_tip: MtpAndHeight, utxo_mined_at: MtpAndHeight) -> bool {
-        match self {
-            LockTime::Blocks(blocks) => blocks.is_satisfied_by(chain_tip, utxo_mined_at),
-            LockTime::Time(time) => time.is_satisfied_by(chain_tip, utxo_mined_at),
+    #[inline]
+    pub fn is_satisfied_by(self, h: Height, t: Time) -> bool {
+        if let Ok(true) = self.is_satisfied_by_height(h) {
+            true
+        } else {
+            matches!(self.is_satisfied_by_time(t), Ok(true))
         }
     }
 
@@ -294,8 +253,8 @@ pub fn is_implied_by(self, other: LockTime) -> bool {
         use LockTime as L;
 
         match (self, other) {
-            (L::Blocks(this), L::Blocks(other)) => this <= other,
-            (L::Time(this), L::Time(other)) => this <= other,
+            (L::Blocks(this), L::Blocks(other)) => this.value() <= other.value(),
+            (L::Time(this), L::Time(other)) => this.value() <= other.value(),
             _ => false, // Not the same units.
         }
     }
@@ -329,7 +288,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 [`Height`].
     ///
     /// # Errors
     ///
@@ -343,17 +302,14 @@ 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::Height::from(required_height + 1)).expect("a height"));
     /// ```
     #[inline]
-    pub fn is_satisfied_by_height(
-        self,
-        height: HeightInterval,
-    ) -> Result<bool, IncompatibleHeightError> {
+    pub fn is_satisfied_by_height(self, height: Height) -> Result<bool, IncompatibleHeightError> {
         use LockTime as L;
 
         match self {
-            L::Blocks(required_height) => Ok(required_height <= height),
+            L::Blocks(ref required_height) => Ok(required_height.value() <= height.value()),
             L::Time(time) => Err(IncompatibleHeightError { height, time }),
         }
     }
@@ -375,24 +331,24 @@ 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: Time) -> Result<bool, IncompatibleTimeError> {
         use LockTime as L;
 
         match self {
-            L::Time(ref t) => Ok(t.to_512_second_intervals() <= time.to_512_second_intervals()),
+            L::Time(ref t) => Ok(t.value() <= time.value()),
             L::Blocks(height) => Err(IncompatibleTimeError { time, height }),
         }
     }
 }
 
-impl From<HeightInterval> for LockTime {
+impl From<Height> for LockTime {
     #[inline]
-    fn from(h: HeightInterval) -> Self { LockTime::Blocks(h) }
+    fn from(h: Height) -> Self { LockTime::Blocks(h) }
 }
 
-impl From<MtpInterval> for LockTime {
+impl From<Time> for LockTime {
     #[inline]
-    fn from(t: MtpInterval) -> Self { LockTime::Time(t) }
+    fn from(t: Time) -> Self { LockTime::Time(t) }
 }
 
 impl fmt::Display for LockTime {
@@ -452,17 +408,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: Height,
     /// The inner time value of the lock-by-blocktime lock.
-    time: MtpInterval,
+    time: Time,
 }
 
 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) -> Height { self.height }
 
     /// Returns the time value of the lock-by-blocktime lock.
-    pub fn expected(&self) -> MtpInterval { self.time }
+    pub fn expected(&self) -> Time { self.time }
 }
 
 impl fmt::Display for IncompatibleHeightError {
@@ -483,17 +439,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: Time,
     /// The inner height value of the lock-by-blockheight lock.
-    height: HeightInterval,
+    height: Height,
 }
 
 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) -> Time { self.time }
 
     /// Returns the height value of the lock-by-blockheight lock.
-    pub fn expected(&self) -> HeightInterval { self.height }
+    pub fn expected(&self) -> Height { self.height }
 }
 
 impl fmt::Display for IncompatibleTimeError {
@@ -512,8 +468,6 @@ impl std::error::Error for IncompatibleTimeError {}
 
 #[cfg(test)]
 mod tests {
-    use units::{BlockHeight, BlockTime};
-
     use super::*;
 
     #[test]
@@ -548,10 +502,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 = Height::from(10);
+        let height2 = Height::from(11);
+        let time1 = Time::from_512_second_intervals(70);
+        let time2 = Time::from_512_second_intervals(71);
 
         let lock_by_height1 = LockTime::from(height1);
         let lock_by_height2 = LockTime::from(height2);
@@ -571,36 +525,54 @@ fn parses_correctly_to_height_or_time() {
         assert!(!lock_by_time1.is_same_unit(lock_by_height1));
     }
 
+    #[test]
+    fn satisfied_by_height() {
+        let height = Height::from(10);
+        let time = Time::from_512_second_intervals(70);
+
+        let lock_by_height = LockTime::from(height);
+
+        assert!(!lock_by_height.is_satisfied_by(Height::from(9), time));
+        assert!(lock_by_height.is_satisfied_by(Height::from(10), time));
+        assert!(lock_by_height.is_satisfied_by(Height::from(11), time));
+    }
+
+    #[test]
+    fn satisfied_by_time() {
+        let height = Height::from(10);
+        let time = Time::from_512_second_intervals(70);
+
+        let lock_by_time = LockTime::from(time);
+
+        assert!(!lock_by_time.is_satisfied_by(height, Time::from_512_second_intervals(69)));
+        assert!(lock_by_time.is_satisfied_by(height, Time::from_512_second_intervals(70)));
+        assert!(lock_by_time.is_satisfied_by(height, Time::from_512_second_intervals(71)));
+    }
+
     #[test]
     fn height_correctly_implies() {
-        let height = HeightInterval::from(10);
+        let height = Height::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(Height::from(9))));
+        assert!(lock_by_height.is_implied_by(LockTime::from(Height::from(10))));
+        assert!(lock_by_height.is_implied_by(LockTime::from(Height::from(11))));
     }
 
     #[test]
     fn time_correctly_implies() {
-        let time = MtpInterval::from_512_second_intervals(70);
+        let time = Time::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(Time::from_512_second_intervals(69))));
+        assert!(lock_by_time.is_implied_by(LockTime::from(Time::from_512_second_intervals(70))));
+        assert!(lock_by_time.is_implied_by(LockTime::from(Time::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 = Height::from(10);
+        let time = Time::from_512_second_intervals(70);
 
         let lock_by_height = LockTime::from(height);
         let lock_by_time = LockTime::from(time);
@@ -621,8 +593,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 = Time::from_512_second_intervals(70);
+        let height = Height::from(10);
 
         let lock_by_time = LockTime::from(time);
         assert!(!lock_by_time.is_implied_by(LockTime::from(height)));
@@ -661,8 +633,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 = Height::from(10);
+        let time = Time::from_512_second_intervals(70);
         let lock_by_time = LockTime::from(time);
         let err = lock_by_time.is_satisfied_by_height(height).unwrap_err();
 
@@ -673,8 +645,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 = Height::from(10);
+        let time = Time::from_512_second_intervals(70);
         let lock_by_height = LockTime::from(height);
         let err = lock_by_height.is_satisfied_by_time(time).unwrap_err();
 
@@ -682,52 +654,4 @@ fn incompatible_time_error() {
         assert_eq!(err.expected(), height);
         assert!(!format!("{}", err).is_empty());
     }
-
-    #[test]
-    fn test_locktime_chain_state() {
-        fn generate_timestamps(start: u32, step: u16) -> [BlockTime; 11] {
-            let mut timestamps = [BlockTime::from_u32(0); 11];
-            for (i, ts) in timestamps.iter_mut().enumerate() {
-                *ts = BlockTime::from_u32(start.saturating_sub((step * i as u16).into()));
-            }
-            timestamps
-        }
-
-        let timestamps: [BlockTime; 11] = generate_timestamps(1_600_000_000, 200);
-        let utxo_timestamps: [BlockTime; 11] = generate_timestamps(1_599_000_000, 200);
-
-        let chain_tip = MtpAndHeight::new(BlockHeight::from_u32(100), timestamps);
-        let utxo_mined_at = MtpAndHeight::new(BlockHeight::from_u32(80), utxo_timestamps);
-
-        let lock1 = LockTime::Blocks(HeightInterval::from(10));
-        assert!(lock1.is_satisfied_by(chain_tip, utxo_mined_at));
-
-        let lock2 = LockTime::Blocks(HeightInterval::from(21));
-        assert!(!lock2.is_satisfied_by(chain_tip, utxo_mined_at));
-
-        let lock3 = LockTime::Time(MtpInterval::from_512_second_intervals(10));
-        assert!(lock3.is_satisfied_by(chain_tip, utxo_mined_at));
-
-        let lock4 = LockTime::Time(MtpInterval::from_512_second_intervals(20000));
-        assert!(!lock4.is_satisfied_by(chain_tip, utxo_mined_at));
-
-        assert!(LockTime::ZERO.is_satisfied_by(chain_tip, utxo_mined_at));
-        assert!(LockTime::from_512_second_intervals(0).is_satisfied_by(chain_tip, utxo_mined_at));
-
-        let lock6 = LockTime::from_seconds_floor(5000).unwrap();
-        assert!(lock6.is_satisfied_by(chain_tip, utxo_mined_at));
-
-        let max_height_lock = LockTime::Blocks(HeightInterval::MAX);
-        assert!(!max_height_lock.is_satisfied_by(chain_tip, utxo_mined_at));
-
-        let max_time_lock = LockTime::Time(MtpInterval::MAX);
-        assert!(!max_time_lock.is_satisfied_by(chain_tip, utxo_mined_at));
-
-        let max_chain_tip =
-            MtpAndHeight::new(BlockHeight::from_u32(u32::MAX), generate_timestamps(u32::MAX, 100));
-        let max_utxo_mined_at =
-            MtpAndHeight::new(BlockHeight::MAX, generate_timestamps(u32::MAX, 100));
-        assert!(!max_height_lock.is_satisfied_by(max_chain_tip, max_utxo_mined_at));
-        assert!(!max_time_lock.is_satisfied_by(max_chain_tip, max_utxo_mined_at));
-    }
 }
diff --git a/primitives/src/script/mod.rs b/primitives/src/script/mod.rs
index 473b85cb..012b4f44 100644
--- a/primitives/src/script/mod.rs
+++ b/primitives/src/script/mod.rs
@@ -431,12 +431,9 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self.as
 
 #[cfg(feature = "hex")]
 impl fmt::LowerHex for Script {
-    // Currently we drop all formatter options.
     #[inline]
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let compact = internals::compact_size::encode(self.as_bytes().len());
-        write!(f, "{:x}", compact.as_slice().as_hex())?;
-        write!(f, "{:x}", self.as_bytes().as_hex())
+        fmt::LowerHex::fmt(&self.as_bytes().as_hex(), f)
     }
 }
 #[cfg(feature = "alloc")]
@@ -454,12 +451,9 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(self.a
 
 #[cfg(feature = "hex")]
 impl fmt::UpperHex for Script {
-    // Currently we drop all formatter options.
     #[inline]
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let compact = internals::compact_size::encode(self.as_bytes().len());
-        write!(f, "{:X}", compact.as_slice().as_hex())?;
-        write!(f, "{:X}", self.as_bytes().as_hex())
+        fmt::UpperHex::fmt(&self.as_bytes().as_hex(), f)
     }
 }
 
@@ -511,8 +505,7 @@ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
         S: serde::Serializer,
     {
         if serializer.is_human_readable() {
-            // Do not call LowerHex because we don't want to add the len prefix.
-            serializer.collect_str(&format_args!("{}", self.as_bytes().as_hex()))
+            serializer.collect_str(&format_args!("{:x}", self))
         } else {
             serializer.serialize_bytes(self.as_bytes())
         }
@@ -803,8 +796,8 @@ fn script_display() {
 
         #[cfg(feature = "hex")]
         {
-            assert_eq!(format!("{:x}", script), "0300a1b2");
-            assert_eq!(format!("{:X}", script), "0300A1B2");
+            assert_eq!(format!("{:x}", script), "00a1b2");
+            assert_eq!(format!("{:X}", script), "00A1B2");
         }
         assert!(!format!("{:?}", script).is_empty());
     }
@@ -816,8 +809,8 @@ fn scriptbuf_display() {
 
         #[cfg(feature = "hex")]
         {
-            assert_eq!(format!("{:x}", script_buf), "0300a1b2");
-            assert_eq!(format!("{:X}", script_buf), "0300A1B2");
+            assert_eq!(format!("{:x}", script_buf), "00a1b2");
+            assert_eq!(format!("{:X}", script_buf), "00A1B2");
         }
         assert!(!format!("{:?}", script_buf).is_empty());
     }
@@ -935,7 +928,7 @@ fn legacy_opcode() {
     fn script_to_hex() {
         let script = Script::from_bytes(&[0xa1, 0xb2, 0xc3]);
         let hex = script.to_hex();
-        assert_eq!(hex, "03a1b2c3");
+        assert_eq!(hex, "a1b2c3");
     }
 
     #[test]
@@ -944,6 +937,6 @@ fn script_to_hex() {
     fn scriptbuf_to_hex() {
         let script = ScriptBuf::from_bytes(vec![0xa1, 0xb2, 0xc3]);
         let hex = script.to_hex();
-        assert_eq!(hex, "03a1b2c3");
+        assert_eq!(hex, "a1b2c3");
     }
 }
diff --git a/primitives/src/sequence.rs b/primitives/src/sequence.rs
index b659c98e..df291b7e 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.
-    pub(super) const LOCK_TYPE_MASK: u32 = 0x0040_0000;
+    const LOCK_TYPE_MASK: u32 = 0x0040_0000;
 
     /// Returns `true` if the sequence number enables absolute lock-time ([`Transaction::lock_time`]).
     #[inline]
@@ -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::{Height, LockTime, Time};
 
         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(Time::from_512_second_intervals(lock_value)))
         } else {
-            Some(LockTime::from(HeightInterval::from(lock_value)))
+            Some(LockTime::from(Height::from(lock_value)))
         }
     }
 
@@ -261,16 +261,10 @@ 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()))),
-            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()),
-            )),
+            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::Time::MIN.to_consensus_u32())),
+            7 => Ok(Sequence::from_consensus(relative::Time::MAX.to_consensus_u32())),
             _ => Ok(Sequence(u.arbitrary()?)),
         }
     }
@@ -360,11 +354,4 @@ fn sequence_formatting() {
         let sequence_u32: u32 = sequence.into();
         assert_eq!(sequence_u32, 0x7FFF_FFFF);
     }
-
-    #[test]
-    fn sequence_display() {
-        let sequence = Sequence(0x7FFF_FFFF);
-        let want: u32 = 0x7FFF_FFFF;
-        assert_eq!(format!("{}", sequence), want.to_string());
-    }
 }
diff --git a/primitives/src/transaction.rs b/primitives/src/transaction.rs
index 10176ef7..2727551d 100644
--- a/primitives/src/transaction.rs
+++ b/primitives/src/transaction.rs
@@ -748,19 +748,4 @@ fn canonical_vout() {
         assert!(parse_vout("01").is_err()); // Leading zero not allowed
         assert!(parse_vout("+1").is_err()); // Non digits not allowed
     }
-
-    #[test]
-    #[cfg(feature = "alloc")]
-    #[cfg(feature = "hex")]
-    fn outpoint_display_roundtrip() {
-        let outpoint_str = "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20:1";
-        let outpoint: OutPoint = outpoint_str.parse().unwrap();
-        assert_eq!(format!("{}", outpoint), outpoint_str);
-    }
-
-    #[test]
-    fn version_display() {
-        let version = Version(123);
-        assert_eq!(format!("{}", version), "123");
-    }
 }
diff --git a/units/src/block.rs b/units/src/block.rs
index 000f0995..5d0dc90b 100644
--- a/units/src/block.rs
+++ b/units/src/block.rs
@@ -70,7 +70,7 @@ impl From<absolute::Height> for BlockHeight {
     /// An absolute locktime block height has a maximum value of [`absolute::LOCK_TIME_THRESHOLD`]
     /// (500,000,000) where as a [`BlockHeight`] is a thin wrapper around a `u32`, the two types are
     /// not interchangeable.
-    fn from(h: absolute::Height) -> Self { Self::from_u32(h.to_u32()) }
+    fn from(h: absolute::Height) -> Self { Self::from_u32(h.to_consensus_u32()) }
 }
 
 impl TryFrom<BlockHeight> for absolute::Height {
@@ -82,7 +82,7 @@ impl TryFrom<BlockHeight> for absolute::Height {
     /// (500,000,000) where as a [`BlockHeight`] is a thin wrapper around a `u32`, the two types are
     /// not interchangeable.
     fn try_from(h: BlockHeight) -> Result<Self, Self::Error> {
-        absolute::Height::from_u32(h.to_u32())
+        absolute::Height::from_consensus(h.to_u32())
     }
 }
 
@@ -129,48 +129,47 @@ impl From<BlockInterval> for u32 {
     fn from(height: BlockInterval) -> Self { height.to_u32() }
 }
 
-impl From<relative::HeightInterval> for BlockInterval {
-    /// Converts a [`locktime::relative::HeightInterval`] to a [`BlockInterval`].
+impl From<relative::Height> for BlockInterval {
+    /// Converts a [`locktime::relative::Height`] to a [`BlockInterval`].
     ///
     /// A relative locktime block height has a maximum value of `u16::MAX` where as a
     /// [`BlockInterval`] 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::Height) -> Self { Self::from_u32(h.value().into()) }
 }
 
-impl TryFrom<BlockInterval> for relative::HeightInterval {
-    type Error = TooBigForRelativeBlockHeightIntervalError;
+impl TryFrom<BlockInterval> for relative::Height {
+    type Error = TooBigForRelativeBlockHeightError;
 
-    /// Converts a [`BlockInterval`] to a [`locktime::relative::HeightInterval`].
+    /// Converts a [`BlockInterval`] to a [`locktime::relative::Height`].
     ///
     /// A relative locktime block height has a maximum value of `u16::MAX` where as a
     /// [`BlockInterval`] is a thin wrapper around a `u32`, the two types are not interchangeable.
     fn try_from(h: BlockInterval) -> Result<Self, Self::Error> {
         let h = h.to_u32();
-
         if h > u32::from(u16::MAX) {
-            return Err(TooBigForRelativeBlockHeightIntervalError(h));
+            return Err(TooBigForRelativeBlockHeightError(h));
         }
-        Ok(relative::HeightInterval::from(h as u16)) // Cast ok, value checked above.
+        Ok(relative::Height::from(h as u16)) // Cast ok, value checked above.
     }
 }
 
 /// 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 TooBigForRelativeBlockHeightError(u32);
 
-impl fmt::Display for TooBigForRelativeBlockHeightIntervalError {
+impl fmt::Display for TooBigForRelativeBlockHeightError {
     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::Height::MAX
         )
     }
 }
 
 #[cfg(feature = "std")]
-impl std::error::Error for TooBigForRelativeBlockHeightIntervalError {}
+impl std::error::Error for TooBigForRelativeBlockHeightError {}
 
 crate::internal_macros::impl_op_for_references! {
     // height - height = interval
@@ -280,14 +279,14 @@ fn sanity_check() {
         let interval: u32 = BlockInterval(100).into();
         assert_eq!(interval, 100);
 
-        let interval_from_height: BlockInterval = relative::HeightInterval::from(10u16).into();
+        let interval_from_height: BlockInterval = relative::Height::from(10u16).into();
         assert_eq!(interval_from_height.to_u32(), 10u32);
 
         let invalid_height_greater =
-            relative::HeightInterval::try_from(BlockInterval(u32::from(u16::MAX) + 1));
+            relative::Height::try_from(BlockInterval(u32::from(u16::MAX) + 1));
         assert!(invalid_height_greater.is_err());
 
-        let valid_height = relative::HeightInterval::try_from(BlockInterval(u32::from(u16::MAX)));
+        let valid_height = relative::Height::try_from(BlockInterval(u32::from(u16::MAX)));
         assert!(valid_height.is_ok());
     }
 
diff --git a/units/src/fee.rs b/units/src/fee.rs
index f7eee0af..6bf9fe1a 100644
--- a/units/src/fee.rs
+++ b/units/src/fee.rs
@@ -14,6 +14,7 @@
 use core::ops;
 
 use NumOpResult as R;
+use crate::NumOpError as E;
 
 use crate::{Amount, FeeRate, MathOp, NumOpResult, OptionExt, Weight};
 
@@ -114,12 +115,11 @@ pub const fn checked_div_by_fee_rate_ceil(self, fee_rate: FeeRate) -> Option<Wei
 }
 
 impl FeeRate {
-    /// Calculates the fee by multiplying this fee rate by weight, in weight units, returning [`None`]
-    /// if an overflow occurred.
+    /// Calculates the fee by multiplying this fee rate by weight, in weight units, returning
+    /// [`NumOpResult::Error`] if an overflow occurred.
     ///
     /// This is equivalent to `Self::checked_mul_by_weight()`.
-    #[must_use]
-    pub fn to_fee(self, weight: Weight) -> Option<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.
@@ -127,7 +127,9 @@ pub fn to_fee(self, weight: Weight) -> Option<Amount> { self.checked_mul_by_weig
     /// This is equivalent to `Self::checked_mul_by_weight()`.
     #[must_use]
     #[deprecated(since = "TBD", note = "use `to_fee()` instead")]
-    pub fn fee_wu(self, weight: Weight) -> Option<Amount> { self.checked_mul_by_weight(weight) }
+    pub fn fee_wu(self, weight: Weight) -> Option<Amount> {
+        self.checked_mul_by_weight(weight).ok()
+    }
 
     /// Calculates the fee by multiplying this fee rate by weight, in virtual bytes, returning [`None`]
     /// if an overflow occurred.
@@ -137,7 +139,7 @@ pub fn fee_wu(self, weight: Weight) -> Option<Amount> { self.checked_mul_by_weig
     #[must_use]
     #[deprecated(since = "TBD", note = "use Weight::from_vb and then `to_fee()` instead")]
     pub fn fee_vb(self, vb: u64) -> Option<Amount> {
-        Weight::from_vb(vb).and_then(|w| self.to_fee(w))
+        Weight::from_vb(vb).and_then(|w| self.to_fee(w).ok())
     }
 
     /// Checked weight multiplication.
@@ -146,20 +148,16 @@ pub fn fee_vb(self, vb: u64) -> Option<Amount> {
     /// fee is a non-integer amount, the amount is rounded up, ensuring that the transaction fee is
     /// enough instead of falling short if rounded down.
     ///
-    /// Returns [`None`] if overflow occurred.
-    #[must_use]
-    pub const fn checked_mul_by_weight(self, weight: Weight) -> Option<Amount> {
-        // No `?` operator in const context.
-        match self.to_sat_per_kwu().checked_mul(weight.to_wu()) {
-            Some(mul_res) => match mul_res.checked_add(999) {
-                Some(add_res) => match Amount::from_sat(add_res / 1000) {
-                    Ok(fee) => Some(fee),
-                    Err(_) => None,
-                },
-                None => None,
-            },
-            None => None,
+    /// 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(round_up) = fee.checked_add(999) {
+                if let Ok(ret) = Amount::from_sat(round_up / 1_000) {
+                    return NumOpResult::Valid(ret);
+                }
+            }
         }
+        NumOpResult::Error(E::while_doing(MathOp::Mul))
     }
 }
 
@@ -167,7 +165,7 @@ pub const fn checked_mul_by_weight(self, weight: Weight) -> Option<Amount> {
     impl ops::Mul<FeeRate> for Weight {
         type Output = NumOpResult<Amount>;
         fn mul(self, rhs: FeeRate) -> Self::Output {
-            rhs.checked_mul_by_weight(self).valid_or_error(MathOp::Mul)
+            rhs.checked_mul_by_weight(self)
         }
     }
     impl ops::Mul<FeeRate> for NumOpResult<Weight> {
@@ -204,7 +202,7 @@ fn mul(self, rhs: NumOpResult<FeeRate>) -> Self::Output {
     impl ops::Mul<Weight> for FeeRate {
         type Output = NumOpResult<Amount>;
         fn mul(self, rhs: Weight) -> Self::Output {
-            self.checked_mul_by_weight(rhs).valid_or_error(MathOp::Mul)
+            self.checked_mul_by_weight(rhs)
         }
     }
     impl ops::Mul<Weight> for NumOpResult<FeeRate> {
@@ -329,8 +327,7 @@ impl Weight {
     /// enough instead of falling short if rounded down.
     ///
     /// Returns [`None`] if overflow occurred.
-    #[must_use]
-    pub const fn checked_mul_by_fee_rate(self, fee_rate: FeeRate) -> Option<Amount> {
+    pub const fn checked_mul_by_fee_rate(self, fee_rate: FeeRate) -> NumOpResult<Amount> {
         fee_rate.checked_mul_by_weight(self)
     }
 }
@@ -348,7 +345,7 @@ fn fee_rate_div_by_weight() {
     #[test]
     fn fee_wu() {
         let fee_overflow = FeeRate::from_sat_per_kwu(10).to_fee(Weight::MAX);
-        assert!(fee_overflow.is_none());
+        assert!(fee_overflow.is_error());
 
         let fee_rate = FeeRate::from_sat_per_vb(2).unwrap();
         let weight = Weight::from_vb(3).unwrap();
@@ -365,7 +362,7 @@ fn checked_weight_mul() {
         assert_eq!(Amount::from_sat_u32(100), fee);
 
         let fee = FeeRate::from_sat_per_kwu(10).checked_mul_by_weight(Weight::MAX);
-        assert!(fee.is_none());
+        assert!(fee.is_error());
 
         let weight = Weight::from_vb(3).unwrap();
         let fee_rate = FeeRate::from_sat_per_vb(3).unwrap();
diff --git a/units/src/lib.rs b/units/src/lib.rs
index 41c33b01..b00a254c 100644
--- a/units/src/lib.rs
+++ b/units/src/lib.rs
@@ -48,7 +48,6 @@ pub mod _core {
 pub mod block;
 pub mod fee_rate;
 pub mod locktime;
-pub mod mtp_height;
 pub mod parse;
 pub mod time;
 pub mod weight;
diff --git a/units/src/locktime/absolute.rs b/units/src/locktime/absolute.rs
index 1df4b04c..153aa0e3 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 [`Time`] types used by the `rust-bitcoin` `absolute::LockTime` type.
 
 use core::convert::Infallible;
 use core::fmt;
@@ -45,22 +45,15 @@ impl Height {
     /// # Errors
     ///
     /// If the input string is not a valid hex representation of a block height.
-    pub fn from_hex(s: &str) -> Result<Self, ParseHeightError> { parse_hex(s, Self::from_u32) }
-
-    #[deprecated(since = "TBD", note = "use `from_u32` instead")]
-    #[doc(hidden)]
-    pub const fn from_consensus(n: u32) -> Result<Self, 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() }
+    pub fn from_hex(s: &str) -> Result<Self, ParseHeightError> {
+        parse_hex(s, Self::from_consensus)
+    }
 
-    /// Constructs a new block height directly from a `u32` value.
+    /// Constructs a new block height.
     ///
     /// # Errors
     ///
-    /// If `n` does not represent a block height within the valid range for a locktime:
-    /// `[0, 499_999_999]`.
+    /// If `n` does not represent a valid block height value.
     ///
     /// # Examples
     ///
@@ -68,11 +61,11 @@ pub const fn to_consensus_u32(self) -> u32 { self.to_u32() }
     /// use bitcoin_units::locktime::absolute::Height;
     ///
     /// let h: u32 = 741521;
-    /// let height = Height::from_u32(h).expect("invalid height value");
+    /// let height = Height::from_consensus(h).expect("invalid height value");
     /// assert_eq!(height.to_consensus_u32(), h);
     /// ```
     #[inline]
-    pub const fn from_u32(n: u32) -> Result<Height, ConversionError> {
+    pub const fn from_consensus(n: u32) -> Result<Height, ConversionError> {
         if is_block_height(n) {
             Ok(Self(n))
         } else {
@@ -80,16 +73,16 @@ pub const fn from_u32(n: u32) -> Result<Height, ConversionError> {
         }
     }
 
-    /// Converts this [`Height`] to a raw `u32` value.
+    /// Converts this [`Height`] to its inner `u32` value.
     #[inline]
-    pub const fn to_u32(self) -> u32 { self.0 }
+    pub const fn to_consensus_u32(self) -> u32 { self.0 }
 }
 
 impl fmt::Display for Height {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
 }
 
-crate::impl_parse_str!(Height, ParseHeightError, parser(Height::from_u32));
+crate::impl_parse_str!(Height, ParseHeightError, parser(Height::from_consensus));
 
 /// Error returned when parsing block height fails.
 #[derive(Debug, Clone, Eq, PartialEq)]
@@ -118,7 +111,7 @@ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
         D: serde::Deserializer<'de>,
     {
         let u = u32::deserialize(deserializer)?;
-        Height::from_u32(u).map_err(serde::de::Error::custom)
+        Height::from_consensus(u).map_err(serde::de::Error::custom)
     }
 }
 
@@ -128,69 +121,51 @@ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
     where
         S: serde::Serializer,
     {
-        self.to_u32().serialize(serializer)
+        self.to_consensus_u32().serialize(serializer)
     }
 }
 
-#[deprecated(since = "TBD", note = "use `Mtp` instead")]
-#[doc(hidden)]
-pub type Time = Mtp;
-
-/// The median timestamp of 11 consecutive blocks, representing "the timestamp" of the
-/// final block for locktime-checking purposes.
+/// A UNIX timestamp, seconds since epoch, guaranteed to always contain a valid time value.
 ///
-/// Time-based locktimes are not measured against the timestamps in individual block
-/// headers, since these are not monotone and may be subject to miner manipulation.
-/// Instead, locktimes use the "median-time-past" (MTP) of the most recent 11 blocks,
-/// a quantity which is required by consensus to be monotone and which is difficult
-/// for any individual miner to manipulate.
+/// Note that there is no manipulation of the inner value during construction or when using
+/// `to_consensus_u32()`. Said another way, `Time(x)` means 'x seconds since epoch' _not_ '(x -
+/// threshold) seconds since epoch'.
 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub struct Mtp(u32);
+pub struct Time(u32);
 
-impl Mtp {
-    /// The minimum MTP allowable in a locktime (Tue Nov 05 1985 00:53:20 GMT+0000).
-    pub const MIN: Self = Mtp(LOCK_TIME_THRESHOLD);
+impl Time {
+    /// The minimum absolute block time (Tue Nov 05 1985 00:53:20 GMT+0000).
+    pub const MIN: Self = Time(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);
+    /// The maximum absolute block time (Sun Feb 07 2106 06:28:15 GMT+0000).
+    pub const MAX: Self = Time(u32::MAX);
 
-    /// Constructs a new [`Mtp`] from a big-endian hex-encoded `u32`.
+    /// Constructs a new [`Time`] from a hex string.
     ///
     /// The input string may or may not contain a typical hex prefix e.g., `0x`.
     ///
     /// # Errors
     ///
     /// 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_u32) }
-
-    #[deprecated(since = "TBD", note = "use `from_u32` instead")]
-    #[doc(hidden)]
-    pub const fn from_consensus(n: u32) -> Result<Self, ConversionError> { Self::from_u32(n) }
+    pub fn from_hex(s: &str) -> Result<Self, ParseTimeError> { parse_hex(s, Self::from_consensus) }
 
-    #[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.
+    /// Constructs a new block time.
     ///
     /// # Errors
     ///
-    /// If `n` is not in the allowable range of MTPs in a locktime: `[500_000_000, 2^32 - 1]`.
+    /// If `n` does not encode a valid UNIX time stamp.
     ///
     /// # Examples
     ///
     /// ```rust
-    /// use bitcoin_units::locktime::absolute::Mtp;
+    /// use bitcoin_units::locktime::absolute::Time;
     ///
     /// let t: u32 = 1653195600; // May 22nd, 5am UTC.
-    /// let time = Mtp::from_u32(t).expect("invalid time value");
+    /// let time = Time::from_consensus(t).expect("invalid time value");
     /// assert_eq!(time.to_consensus_u32(), t);
     /// ```
     #[inline]
-    pub const fn from_u32(n: u32) -> Result<Self, ConversionError> {
+    pub const fn from_consensus(n: u32) -> Result<Time, ConversionError> {
         if is_block_time(n) {
             Ok(Self(n))
         } else {
@@ -198,35 +173,35 @@ pub const fn from_u32(n: u32) -> Result<Self, ConversionError> {
         }
     }
 
-    /// Converts this [`Mtp`] to a raw `u32` value.
+    /// Converts this [`Time`] to its inner `u32` value.
     #[inline]
-    pub const fn to_u32(self) -> u32 { self.0 }
+    pub const fn to_consensus_u32(self) -> u32 { self.0 }
 }
 
-impl fmt::Display for Mtp {
+impl fmt::Display for Time {
     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!(Time, ParseTimeError, parser(Time::from_consensus));
 
 #[cfg(feature = "serde")]
-impl<'de> serde::Deserialize<'de> for Mtp {
+impl<'de> serde::Deserialize<'de> for Time {
     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)
+        Time::from_consensus(u).map_err(serde::de::Error::custom)
     }
 }
 
 #[cfg(feature = "serde")]
-impl serde::Serialize for Mtp {
+impl serde::Serialize for Time {
     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
     where
         S: serde::Serializer,
     {
-        self.to_u32().serialize(serializer)
+        self.to_consensus_u32().serialize(serializer)
     }
 }
 
@@ -367,11 +342,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/Time (<subject> is above limit <upper_bound>)"
                 write!(
                     f,
                     "{} ({} is above limit {})",
-                    input.display_cannot_parse("absolute Height/Mtp"),
+                    input.display_cannot_parse("absolute Height/Time"),
                     subject,
                     upper_bound
                 )
@@ -379,17 +354,17 @@ 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/Time (<subject> is below limit <lower_bound>)"
                 write!(
                     f,
                     "{} ({} is below limit {})",
-                    input.display_cannot_parse("absolute Height/Mtp"),
+                    input.display_cannot_parse("absolute Height/Time"),
                     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/Time"), subject)
             }
             E::Conversion(value) if *value < i64::from(lower_bound) => {
                 write!(f, "{} {} is below limit {}", subject, value, lower_bound)
@@ -432,27 +407,27 @@ fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
             0 => Ok(Height::MIN),
             1 => Ok(Height::MAX),
             _ => {
-                let min = Height::MIN.to_u32();
-                let max = Height::MAX.to_u32();
+                let min = Height::MIN.to_consensus_u32();
+                let max = Height::MAX.to_consensus_u32();
                 let h = u.int_in_range(min..=max)?;
-                Ok(Height::from_u32(h).unwrap())
+                Ok(Height::from_consensus(h).unwrap())
             }
         }
     }
 }
 
 #[cfg(feature = "arbitrary")]
-impl<'a> Arbitrary<'a> for Mtp {
+impl<'a> Arbitrary<'a> for Time {
     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(Time::MIN),
+            1 => Ok(Time::MAX),
             _ => {
-                let min = Mtp::MIN.to_u32();
-                let max = Mtp::MAX.to_u32();
+                let min = Time::MIN.to_consensus_u32();
+                let max = Time::MAX.to_consensus_u32();
                 let t = u.int_in_range(min..=max)?;
-                Ok(Mtp::from_u32(t).unwrap())
+                Ok(Time::from_consensus(t).unwrap())
             }
         }
     }
@@ -467,21 +442,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 = Time::from_hex("0x6289C350").unwrap();
+        let expected = Time::from_consensus(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 = Time::from_hex("6289C350").unwrap();
+        assert_eq!(time, Time(0x6289_C350));
     }
 
     #[test]
     fn time_from_str_hex_invalid_hex_should_err() {
         let hex = "0xzb93";
-        let result = Mtp::from_hex(hex);
+        let result = Time::from_hex(hex);
         assert!(result.is_err());
     }
 
@@ -525,18 +500,7 @@ pub fn encode_decode_height() {
     #[test]
     #[cfg(feature = "serde")]
     pub fn encode_decode_time() {
-        serde_round_trip!(Mtp::MIN);
-        serde_round_trip!(Mtp::MAX);
-    }
-
-    #[test]
-    #[cfg(feature = "alloc")]
-    fn locktime_unit_display() {
-        use alloc::format;
-        let blocks = LockTimeUnit::Blocks;
-        let seconds = LockTimeUnit::Seconds;
-
-        assert_eq!(format!("{}", blocks), "expected lock-by-blockheight (must be < 500000000)");
-        assert_eq!(format!("{}", seconds), "expected lock-by-blocktime (must be >= 500000000)");
+        serde_round_trip!(Time::MIN);
+        serde_round_trip!(Time::MAX);
     }
 }
diff --git a/units/src/locktime/relative.rs b/units/src/locktime/relative.rs
index 47dde70a..9b1abadf 100644
--- a/units/src/locktime/relative.rs
+++ b/units/src/locktime/relative.rs
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: CC0-1.0
 
-//! Provides [`Height`] and [`MtpInterval`] types used by the `rust-bitcoin` `relative::LockTime` type.
+//! Provides [`Height`] and [`Time`] types used by the `rust-bitcoin` `relative::LockTime` type.
 
 use core::fmt;
 
@@ -9,118 +9,73 @@
 #[cfg(feature = "serde")]
 use serde::{Deserialize, Serialize};
 
-use crate::mtp_height::MtpAndHeight;
-
-#[deprecated(since = "TBD", note = "use `HeightIterval` instead")]
-#[doc(hidden)]
-pub type Height = HeightInterval;
-
 /// 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 Height(u16);
 
-impl HeightInterval {
+impl Height {
     /// Relative block height 0, can be included in any block.
-    pub const ZERO: Self = Self(0);
+    pub const ZERO: Self = Height(0);
 
     /// The minimum relative block height (0), can be included in any block.
     pub const MIN: Self = Self::ZERO;
 
     /// The maximum relative block height.
-    pub const MAX: Self = Self(u16::MAX);
-
-    /// Constructs a new [`HeightInterval`] using a count of blocks.
-    #[inline]
-    pub const fn from_height(blocks: u16) -> Self { Self(blocks) }
+    pub const MAX: Self = Height(u16::MAX);
 
-    /// Express the [`Height`] as a count of blocks.
+    /// Constructs a new [`Height`] using a count of blocks.
     #[inline]
-    #[must_use]
-    pub const fn to_height(self) -> u16 { self.0 }
+    pub const fn from_height(blocks: u16) -> Self { Height(blocks) }
 
     /// Returns the inner `u16` value.
     #[inline]
     #[must_use]
-    #[deprecated(since = "TBD", note = "use `to_height` 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`.
-    #[deprecated(
-        since = "TBD",
-        note = "use `LockTime::from` followed by `to_consensus_u32` instead"
-    )]
+    #[inline]
     pub const fn to_consensus_u32(self) -> u32 {
         self.0 as u32 // cast safety: u32 is wider than u16 on all architectures
     }
-
-    /// Determines whether a relative‐height locktime has matured, taking into account
-    /// both the chain tip and the height at which the UTXO was confirmed.
-    ///
-    /// # Parameters
-    /// - `self` – The relative block‐height delay (`h`) required after confirmation.
-    /// - `chain_tip` – The current chain state (contains the tip height).
-    /// - `utxo_mined_at` – The chain state at the UTXO’s confirmation block (contains that height).
-    ///
-    /// # Returns
-    /// - `true` if a UTXO locked by `self` can be spent in a block after `chain_tip`.
-    /// - `false` if the UTXO is still locked at `chain_tip`.
-    pub fn is_satisfied_by(self, chain_tip: MtpAndHeight, utxo_mined_at: MtpAndHeight) -> bool {
-        // let chain_tip_height = BlockHeight::from(chain_tip);
-        // let utxo_mined_at_height = BlockHeight::from(utxo_mined_at);
-        match u32::from(self.to_height()).checked_add(utxo_mined_at.to_height().to_u32()) {
-            Some(target_height) => chain_tip.to_height().to_u32() >= target_height,
-            None => false,
-        }
-    }
 }
 
-impl From<u16> for HeightInterval {
+impl From<u16> for Height {
     #[inline]
-    fn from(value: u16) -> Self { HeightInterval(value) }
+    fn from(value: u16) -> Self { Height(value) }
 }
 
-crate::impl_parse_str_from_int_infallible!(HeightInterval, u16, from);
+crate::impl_parse_str_from_int_infallible!(Height, u16, from);
 
-impl fmt::Display for HeightInterval {
+impl fmt::Display for Height {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
 }
 
-#[deprecated(since = "TBD", note = "use `Mtp` instead")]
-#[doc(hidden)]
-pub type Time = MtpInterval;
-
 /// 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 Time(u16);
 
-impl MtpInterval {
+impl Time {
     /// Relative block time 0, can be included in any block.
-    pub const ZERO: Self = MtpInterval(0);
+    pub const ZERO: Self = Time(0);
 
     /// The minimum relative block time (0), can be included in any block.
-    pub const MIN: Self = MtpInterval::ZERO;
+    pub const MIN: Self = Time::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 = Time(u16::MAX);
 
-    /// Constructs a new [`MtpInterval`] using time intervals where each interval is equivalent to 512 seconds.
+    /// Constructs a new [`Time`] 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) }
-
-    /// 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 }
+    pub const fn from_512_second_intervals(intervals: u16) -> Self { Time(intervals) }
 
-    /// Constructs a new [`MtpInterval`] from seconds, converting the seconds into 512 second interval with
+    /// Constructs a new [`Time`] from seconds, converting the seconds into 512 second interval with
     /// truncating division.
     ///
     /// # Errors
@@ -131,13 +86,13 @@ 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(Time::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
+    /// Constructs a new [`Time`] from seconds, converting the seconds into 512 second intervals with
     /// ceiling division.
     ///
     /// # Errors
@@ -148,7 +103,7 @@ 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(Time::from_512_second_intervals(interval as u16)) // Cast checked above, needed by const code.
         } else {
             Err(TimeOverflowError { seconds })
         }
@@ -157,52 +112,26 @@ pub const fn from_seconds_ceil(seconds: u32) -> Result<Self, TimeOverflowError>
     /// 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`.
-    #[deprecated(
-        since = "TBD",
-        note = "use `LockTime::from` followed by `to_consensus_u32` instead"
-    )]
+    #[inline]
     pub const fn to_consensus_u32(self) -> u32 {
         (1u32 << 22) | self.0 as u32 // cast safety: u32 is wider than u16 on all architectures
     }
-
-    /// Determines whether a relative‑time lock has matured, taking into account both
-    /// the UTXO’s Median Time Past at confirmation and the required delay.
-    ///
-    /// # Parameters
-    /// - `self` – The relative time delay (`t`) in 512‑second intervals.
-    /// - `chain_tip` – The current chain state, providing the tip’s MTP.
-    /// - `utxo_mined_at` – The chain state at the UTXO’s confirmation, providing its MTP.
-    ///
-    /// # Returns
-    /// - `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.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,
-            },
-            None => false,
-        }
-    }
 }
 
-crate::impl_parse_str_from_int_infallible!(MtpInterval, u16, from_512_second_intervals);
+crate::impl_parse_str_from_int_infallible!(Time, u16, from_512_second_intervals);
 
-impl fmt::Display for MtpInterval {
+impl fmt::Display for Time {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
 }
 
 /// Error returned when the input time in seconds was too large to be encoded to a 16 bit 512 second interval.
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub struct TimeOverflowError {
-    /// Time interval value in seconds that overflowed.
+    /// Time value in seconds that overflowed.
     // Private because we maintain an invariant that the `seconds` value does actually overflow.
     pub(crate) seconds: u32,
 }
@@ -233,27 +162,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 Height {
     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(Height::MIN),
+            1 => Ok(Height::MAX),
+            _ => Ok(Height::from_height(u16::arbitrary(u)?)),
         }
     }
 }
 
 #[cfg(feature = "arbitrary")]
-impl<'a> Arbitrary<'a> for MtpInterval {
+impl<'a> Arbitrary<'a> for Time {
     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(Time::MIN),
+            1 => Ok(Time::MAX),
+            _ => Ok(Time::from_512_second_intervals(u16::arbitrary(u)?)),
         }
     }
 }
@@ -264,146 +193,76 @@ mod tests {
     use internals::serde_round_trip;
 
     use super::*;
-    use crate::{BlockHeight, BlockTime};
 
     const MAXIMUM_ENCODABLE_SECONDS: u32 = u16::MAX as u32 * 512;
 
     #[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!(Height::MAX.to_consensus_u32(), u32::from(u16::MAX));
+        assert_eq!(Time::from_512_second_intervals(100).value(), 100u16);
+        assert_eq!(Time::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 = Time::from_seconds_ceil(100).unwrap();
+        let expected = Time(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 = Time::from_seconds_ceil(MAXIMUM_ENCODABLE_SECONDS).unwrap();
+        let expected = Time(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 = Time::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 = Time::from_seconds_floor(100).unwrap();
+        let expected = Time(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 = Time::from_seconds_floor(512).unwrap();
+        let expected = Time(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 = Time::from_seconds_floor(MAXIMUM_ENCODABLE_SECONDS + 511).unwrap();
+        let expected = Time(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 = Time::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!(Height::ZERO);
+        serde_round_trip!(Height::MIN);
+        serde_round_trip!(Height::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);
-    }
-
-    fn generate_timestamps(start: u32, step: u16) -> [BlockTime; 11] {
-        let mut timestamps = [BlockTime::from_u32(0); 11];
-        for (i, ts) in timestamps.iter_mut().enumerate() {
-            *ts = BlockTime::from_u32(start.saturating_sub((step * i as u16).into()));
-        }
-        timestamps
-    }
-
-    #[test]
-    fn test_time_chain_state() {
-        let timestamps: [BlockTime; 11] = generate_timestamps(1_600_000_000, 200);
-        let utxo_timestamps: [BlockTime; 11] = generate_timestamps(1_599_000_000, 200);
-
-        let timestamps2: [BlockTime; 11] = generate_timestamps(1_599_995_119, 200);
-        let utxo_timestamps2: [BlockTime; 11] = generate_timestamps(1_599_990_000, 200);
-
-        let timestamps3: [BlockTime; 11] = generate_timestamps(1_600_050_000, 200);
-        let utxo_timestamps3: [BlockTime; 11] = generate_timestamps(1_599_990_000, 200);
-
-        // 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 chain_state1 = MtpAndHeight::new(BlockHeight::from_u32(100), timestamps);
-        let utxo_state1 = MtpAndHeight::new(BlockHeight::from_u32(80), utxo_timestamps);
-        assert!(time_lock.is_satisfied_by(chain_state1, utxo_state1));
-
-        // Test case 2: Not satisfied (current_mtp < utxo_mtp + required_seconds)
-        let chain_state2 = MtpAndHeight::new(BlockHeight::from_u32(100), timestamps2);
-        let utxo_state2 = MtpAndHeight::new(BlockHeight::from_u32(80), utxo_timestamps2);
-        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 chain_state3 = MtpAndHeight::new(BlockHeight::from_u32(100), timestamps3);
-        let utxo_state3 = MtpAndHeight::new(BlockHeight::from_u32(80), 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 chain_state4 = MtpAndHeight::new(BlockHeight::from_u32(100), timestamps);
-        let utxo_state4 = MtpAndHeight::new(BlockHeight::from_u32(80), utxo_timestamps);
-        assert!(!max_time_lock.is_satisfied_by(chain_state4, utxo_state4));
-    }
-
-    #[test]
-    fn test_height_chain_state() {
-        let timestamps: [BlockTime; 11] = generate_timestamps(1_600_000_000, 200);
-        let utxo_timestamps: [BlockTime; 11] = generate_timestamps(1_599_000_000, 200);
-
-        let height_lock = HeightInterval(10);
-
-        // Test case 1: Satisfaction (current_height >= utxo_height + required)
-        let chain_state1 = MtpAndHeight::new(BlockHeight::from_u32(100), timestamps);
-        let utxo_state1 = MtpAndHeight::new(BlockHeight::from_u32(80), utxo_timestamps);
-        assert!(height_lock.is_satisfied_by(chain_state1, utxo_state1));
-
-        // Test case 2: Not satisfied (current_height < utxo_height + required)
-        let chain_state2 = MtpAndHeight::new(BlockHeight::from_u32(89), timestamps);
-        let utxo_state2 = MtpAndHeight::new(BlockHeight::from_u32(80), utxo_timestamps);
-        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 chain_state3 = MtpAndHeight::new(BlockHeight::from_u32(1000), timestamps);
-        let utxo_state3 = MtpAndHeight::new(BlockHeight::from_u32(80), utxo_timestamps);
-        assert!(!max_height_lock.is_satisfied_by(chain_state3, utxo_state3));
+        serde_round_trip!(Time::ZERO);
+        serde_round_trip!(Time::MIN);
+        serde_round_trip!(Time::MAX);
     }
 }
diff --git a/units/src/mtp_height.rs b/units/src/mtp_height.rs
deleted file mode 100644
index 74b7705a..00000000
--- a/units/src/mtp_height.rs
+++ /dev/null
@@ -1,68 +0,0 @@
-// SPDX-License-Identifier: CC0-1.0
-
-//! Median Time Past (MTP) and height - used for working lock times.
-
-use crate::{BlockHeight, BlockTime};
-
-/// A structure containing both Median Time Past (MTP) and current
-/// absolute block height, used for validating relative locktimes.
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub struct MtpAndHeight {
-    /// The Median Time Past (median of the last 11 blocks' timestamps)
-    mtp: BlockTime,
-    /// The current block height,
-    height: BlockHeight,
-}
-
-impl MtpAndHeight {
-    /// Constructs an [`MtpAndHeight`] by computing the median‐time‐past from the last 11 block timestamps
-    ///
-    /// # Parameters
-    ///
-    /// * `height` - The absolute height of the chain tip
-    /// * `timestamps` - An array of timestamps from the most recent 11 blocks, where
-    ///   - `timestamps[0]` is the timestamp at height `height - 10`
-    ///   - `timestamps[1]` is the timestamp at height `height - 9`
-    ///   - …
-    ///   - `timestamps[10]` is the timestamp at height `height`
-    pub fn new(height: BlockHeight, timestamps: [BlockTime; 11]) -> Self {
-        let mut mtp_timestamps = timestamps;
-        mtp_timestamps.sort_unstable();
-        let mtp = mtp_timestamps[5];
-
-        MtpAndHeight { mtp, height }
-    }
-
-    /// Returns the median-time-past component.
-    pub fn to_mtp(self) -> BlockTime { self.mtp }
-
-    /// Returns the block-height component.
-    pub fn to_height(self) -> BlockHeight { self.height }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    fn valid_chain_computes_mtp() {
-        let height = BlockHeight::from_u32(100);
-        let timestamps = [
-            BlockTime::from_u32(10),
-            BlockTime::from_u32(3),
-            BlockTime::from_u32(5),
-            BlockTime::from_u32(8),
-            BlockTime::from_u32(1),
-            BlockTime::from_u32(4),
-            BlockTime::from_u32(6),
-            BlockTime::from_u32(9),
-            BlockTime::from_u32(2),
-            BlockTime::from_u32(7),
-            BlockTime::from_u32(0),
-        ];
-
-        let result = MtpAndHeight::new(height, timestamps);
-        assert_eq!(result.height, height);
-        assert_eq!(result.mtp.to_u32(), 5);
-    }
-}
diff --git a/units/src/result.rs b/units/src/result.rs
index e3e82021..a7d02e88 100644
--- a/units/src/result.rs
+++ b/units/src/result.rs
@@ -203,7 +203,7 @@ fn valid_or_error(self, op: MathOp) -> NumOpResult<$ty> {
 
 impl NumOpError {
     /// Creates a [`NumOpError`] caused by `op`.
-    pub(crate) fn while_doing(op: MathOp) -> Self { NumOpError(op) }
+    pub(crate) const fn while_doing(op: MathOp) -> Self { NumOpError(op) }
 
     /// Returns `true` if this operation error'ed due to overflow.
     pub fn is_overflow(self) -> bool { self.0.is_overflow() }


Test patch:
diff --git a/bitcoin/src/blockdata/script/tests.rs b/bitcoin/src/blockdata/script/tests.rs
index 51d24b25..fe2c75f8 100644
--- a/bitcoin/src/blockdata/script/tests.rs
+++ b/bitcoin/src/blockdata/script/tests.rs
@@ -203,10 +203,7 @@ fn script_builder() {
         .push_opcode(OP_EQUALVERIFY)
         .push_opcode(OP_CHECKSIG)
         .into_script();
-    assert_eq!(
-        script.to_hex_string_no_length_prefix(),
-        "76a91416e1ae70ff0fa102905d4af297f6912bda6cce1988ac"
-    );
+    assert_eq!(script.to_hex_string(), "76a91416e1ae70ff0fa102905d4af297f6912bda6cce1988ac");
 }
 
 #[test]
@@ -239,7 +236,7 @@ fn script_generators() {
     let op_return = ScriptBuf::new_op_return(data);
     assert!(op_return.is_op_return());
     assert_eq!(
-        op_return.to_hex_string_no_length_prefix(),
+        op_return.to_hex_string(),
         "6a24aa21a9ed20280f53f2d21663cac89e6bd2ad19edbabb048cda08e73ed19e9268d0afea2a"
     );
 }
@@ -247,42 +244,42 @@ fn script_generators() {
 #[test]
 fn script_builder_verify() {
     let simple = Builder::new().push_verify().into_script();
-    assert_eq!(simple.to_hex_string_no_length_prefix(), "69");
+    assert_eq!(simple.to_hex_string(), "69");
     let simple2 = Builder::from(vec![]).push_verify().into_script();
-    assert_eq!(simple2.to_hex_string_no_length_prefix(), "69");
+    assert_eq!(simple2.to_hex_string(), "69");
 
     let nonverify = Builder::new().push_verify().push_verify().into_script();
-    assert_eq!(nonverify.to_hex_string_no_length_prefix(), "6969");
+    assert_eq!(nonverify.to_hex_string(), "6969");
     let nonverify2 = Builder::from(vec![0x69]).push_verify().into_script();
-    assert_eq!(nonverify2.to_hex_string_no_length_prefix(), "6969");
+    assert_eq!(nonverify2.to_hex_string(), "6969");
 
     let equal = Builder::new().push_opcode(OP_EQUAL).push_verify().into_script();
-    assert_eq!(equal.to_hex_string_no_length_prefix(), "88");
+    assert_eq!(equal.to_hex_string(), "88");
     let equal2 = Builder::from(vec![0x87]).push_verify().into_script();
-    assert_eq!(equal2.to_hex_string_no_length_prefix(), "88");
+    assert_eq!(equal2.to_hex_string(), "88");
 
     let numequal = Builder::new().push_opcode(OP_NUMEQUAL).push_verify().into_script();
-    assert_eq!(numequal.to_hex_string_no_length_prefix(), "9d");
+    assert_eq!(numequal.to_hex_string(), "9d");
     let numequal2 = Builder::from(vec![0x9c]).push_verify().into_script();
-    assert_eq!(numequal2.to_hex_string_no_length_prefix(), "9d");
+    assert_eq!(numequal2.to_hex_string(), "9d");
 
     let checksig = Builder::new().push_opcode(OP_CHECKSIG).push_verify().into_script();
-    assert_eq!(checksig.to_hex_string_no_length_prefix(), "ad");
+    assert_eq!(checksig.to_hex_string(), "ad");
     let checksig2 = Builder::from(vec![0xac]).push_verify().into_script();
-    assert_eq!(checksig2.to_hex_string_no_length_prefix(), "ad");
+    assert_eq!(checksig2.to_hex_string(), "ad");
 
     let checkmultisig = Builder::new().push_opcode(OP_CHECKMULTISIG).push_verify().into_script();
-    assert_eq!(checkmultisig.to_hex_string_no_length_prefix(), "af");
+    assert_eq!(checkmultisig.to_hex_string(), "af");
     let checkmultisig2 = Builder::from(vec![0xae]).push_verify().into_script();
-    assert_eq!(checkmultisig2.to_hex_string_no_length_prefix(), "af");
+    assert_eq!(checkmultisig2.to_hex_string(), "af");
 
     let trick_slice = Builder::new()
         .push_slice([0xae]) // OP_CHECKMULTISIG
         .push_verify()
         .into_script();
-    assert_eq!(trick_slice.to_hex_string_no_length_prefix(), "01ae69");
+    assert_eq!(trick_slice.to_hex_string(), "01ae69");
     let trick_slice2 = Builder::from(vec![0x01, 0xae]).push_verify().into_script();
-    assert_eq!(trick_slice2.to_hex_string_no_length_prefix(), "01ae69");
+    assert_eq!(trick_slice2.to_hex_string(), "01ae69");
 }
 
 #[test]
@@ -376,7 +373,7 @@ fn non_minimal_scriptints() {
 
 #[test]
 fn script_hashes() {
-    let script = ScriptBuf::from_hex_no_length_prefix("410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac").unwrap();
+    let script = ScriptBuf::from_hex("410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac").unwrap();
     assert_eq!(
         script.script_hash().unwrap().to_string(),
         "8292bcfbef1884f73c813dfe9c82fd7e814291ea"
@@ -386,12 +383,10 @@ fn script_hashes() {
         "3e1525eb183ad4f9b3c5fa3175bdca2a52e947b135bbb90383bf9f6408e2c324"
     );
     assert_eq!(
-        ScriptBuf::from_hex_no_length_prefix(
-            "20d85a959b0290bf19bb89ed43c916be835475d013da4b362117393e25a48229b8ac"
-        )
-        .unwrap()
-        .tapscript_leaf_hash()
-        .to_string(),
+        ScriptBuf::from_hex("20d85a959b0290bf19bb89ed43c916be835475d013da4b362117393e25a48229b8ac")
+            .unwrap()
+            .tapscript_leaf_hash()
+            .to_string(),
         "5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21"
     );
 }
@@ -399,50 +394,40 @@ fn script_hashes() {
 #[test]
 fn provably_unspendable() {
     // p2pk
-    assert!(!ScriptBuf::from_hex_no_length_prefix("410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac").unwrap().is_op_return());
-    assert!(!ScriptBuf::from_hex_no_length_prefix("4104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac").unwrap().is_op_return());
+    assert!(!ScriptBuf::from_hex("410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac").unwrap().is_op_return());
+    assert!(!ScriptBuf::from_hex("4104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac").unwrap().is_op_return());
     // p2pkhash
-    assert!(!ScriptBuf::from_hex_no_length_prefix(
-        "76a914ee61d57ab51b9d212335b1dba62794ac20d2bcf988ac"
-    )
-    .unwrap()
-    .is_op_return());
-    assert!(ScriptBuf::from_hex_no_length_prefix(
-        "6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87"
-    )
-    .unwrap()
-    .is_op_return());
+    assert!(!ScriptBuf::from_hex("76a914ee61d57ab51b9d212335b1dba62794ac20d2bcf988ac")
+        .unwrap()
+        .is_op_return());
+    assert!(ScriptBuf::from_hex("6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87")
+        .unwrap()
+        .is_op_return());
 }
 
 #[test]
 fn op_return() {
-    assert!(ScriptBuf::from_hex_no_length_prefix(
-        "6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87"
-    )
-    .unwrap()
-    .is_op_return());
-    assert!(!ScriptBuf::from_hex_no_length_prefix(
-        "76a914ee61d57ab51b9d212335b1dba62794ac20d2bcf988ac"
-    )
-    .unwrap()
-    .is_op_return());
-    assert!(!ScriptBuf::from_hex_no_length_prefix("").unwrap().is_op_return());
+    assert!(ScriptBuf::from_hex("6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87")
+        .unwrap()
+        .is_op_return());
+    assert!(!ScriptBuf::from_hex("76a914ee61d57ab51b9d212335b1dba62794ac20d2bcf988ac")
+        .unwrap()
+        .is_op_return());
+    assert!(!ScriptBuf::from_hex("").unwrap().is_op_return());
 }
 
 #[test]
 fn standard_op_return() {
-    assert!(ScriptBuf::from_hex_no_length_prefix(
-        "6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87"
-    )
-    .unwrap()
-    .is_standard_op_return());
-    assert!(ScriptBuf::from_hex_no_length_prefix("6a48656c6c6f2c2074686973206973206d7920666972737420636f6e747269627574696f6e20746f207275737420626974636f696e2e20506c6561736520617070726f7665206d79205052206672656e")
+    assert!(ScriptBuf::from_hex("6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87")
         .unwrap()
         .is_standard_op_return());
-    assert!(ScriptBuf::from_hex_no_length_prefix("6a48656c6c6f2c2074686973206973206d7920666972737420636f6e747269627574696f6e20746f207275737420626974636f696e2e20506c6561736520617070726f7665206d79205052206672656e21")
+    assert!(ScriptBuf::from_hex("6a48656c6c6f2c2074686973206973206d7920666972737420636f6e747269627574696f6e20746f207275737420626974636f696e2e20506c6561736520617070726f7665206d79205052206672656e")
         .unwrap()
         .is_standard_op_return());
-    assert!(!ScriptBuf::from_hex_no_length_prefix("6a48656c6c6f2c2074686973206973206d7920666972737420636f6e747269627574696f6e20746f207275737420626974636f696e2e20506c6561736520617070726f7665206d79205052206672656e21524f42")
+    assert!(ScriptBuf::from_hex("6a48656c6c6f2c2074686973206973206d7920666972737420636f6e747269627574696f6e20746f207275737420626974636f696e2e20506c6561736520617070726f7665206d79205052206672656e21")
+        .unwrap()
+        .is_standard_op_return());
+    assert!(!ScriptBuf::from_hex("6a48656c6c6f2c2074686973206973206d7920666972737420636f6e747269627574696f6e20746f207275737420626974636f696e2e20506c6561736520617070726f7665206d79205052206672656e21524f42")
         .unwrap()
         .is_standard_op_return());
 }
@@ -452,48 +437,46 @@ fn multisig() {
     // First multisig? 1-of-2
     // In block 164467, txid 60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1
     assert!(
-        ScriptBuf::from_hex_no_length_prefix("514104cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4410461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af52ae")
+        ScriptBuf::from_hex("514104cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4410461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af52ae")
             .unwrap()
             .is_multisig()
     );
     // 2-of-2
     assert!(
-        ScriptBuf::from_hex_no_length_prefix("5221021c4ac2ecebc398e390e07f045aac5cc421f82f0739c1ce724d3d53964dc6537d21023a2e9155e0b62f76737605504819a2b4e5ce20653f6c397d7a178ae42ba702f452ae")
+        ScriptBuf::from_hex("5221021c4ac2ecebc398e390e07f045aac5cc421f82f0739c1ce724d3d53964dc6537d21023a2e9155e0b62f76737605504819a2b4e5ce20653f6c397d7a178ae42ba702f452ae")
             .unwrap()
             .is_multisig()
     );
 
     // Extra opcode after OP_CHECKMULTISIG
     assert!(
-        !ScriptBuf::from_hex_no_length_prefix("5221021c4ac2ecebc398e390e07f045aac5cc421f82f0739c1ce724d3d53964dc6537d21023a2e9155e0b62f76737605504819a2b4e5ce20653f6c397d7a178ae42ba702f452ae52")
+        !ScriptBuf::from_hex("5221021c4ac2ecebc398e390e07f045aac5cc421f82f0739c1ce724d3d53964dc6537d21023a2e9155e0b62f76737605504819a2b4e5ce20653f6c397d7a178ae42ba702f452ae52")
             .unwrap()
             .is_multisig()
     );
     // Required sigs > num pubkeys
     assert!(
-        !ScriptBuf::from_hex_no_length_prefix("5321021c4ac2ecebc398e390e07f045aac5cc421f82f0739c1ce724d3d53964dc6537d21023a2e9155e0b62f76737605504819a2b4e5ce20653f6c397d7a178ae42ba702f452ae")
+        !ScriptBuf::from_hex("5321021c4ac2ecebc398e390e07f045aac5cc421f82f0739c1ce724d3d53964dc6537d21023a2e9155e0b62f76737605504819a2b4e5ce20653f6c397d7a178ae42ba702f452ae")
             .unwrap()
             .is_multisig()
     );
     // Num pubkeys != pushnum
     assert!(
-        !ScriptBuf::from_hex_no_length_prefix("5221021c4ac2ecebc398e390e07f045aac5cc421f82f0739c1ce724d3d53964dc6537d21023a2e9155e0b62f76737605504819a2b4e5ce20653f6c397d7a178ae42ba702f453ae")
+        !ScriptBuf::from_hex("5221021c4ac2ecebc398e390e07f045aac5cc421f82f0739c1ce724d3d53964dc6537d21023a2e9155e0b62f76737605504819a2b4e5ce20653f6c397d7a178ae42ba702f453ae")
             .unwrap()
             .is_multisig()
     );
 
     // Taproot hash from another test
-    assert!(!ScriptBuf::from_hex_no_length_prefix(
+    assert!(!ScriptBuf::from_hex(
         "20d85a959b0290bf19bb89ed43c916be835475d013da4b362117393e25a48229b8ac"
     )
     .unwrap()
     .is_multisig());
     // OP_RETURN from another test
-    assert!(!ScriptBuf::from_hex_no_length_prefix(
-        "6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87"
-    )
-    .unwrap()
-    .is_multisig());
+    assert!(!ScriptBuf::from_hex("6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87")
+        .unwrap()
+        .is_multisig());
 }
 
 #[test]
@@ -501,7 +484,7 @@ fn multisig() {
 fn script_json_serialize() {
     use serde_json;
 
-    let original = ScriptBuf::from_hex_no_length_prefix("827651a0698faaa9a8a7a687").unwrap();
+    let original = ScriptBuf::from_hex("827651a0698faaa9a8a7a687").unwrap();
     let json = serde_json::to_value(&original).unwrap();
     assert_eq!(json, serde_json::Value::String("827651a0698faaa9a8a7a687".to_owned()));
     let des = serde_json::from_value::<ScriptBuf>(json).unwrap();
@@ -511,36 +494,27 @@ fn script_json_serialize() {
 #[test]
 fn script_asm() {
     assert_eq!(
-        ScriptBuf::from_hex_no_length_prefix("6363636363686868686800").unwrap().to_string(),
+        ScriptBuf::from_hex("6363636363686868686800").unwrap().to_string(),
         "OP_IF OP_IF OP_IF OP_IF OP_IF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_0"
     );
-    assert_eq!(ScriptBuf::from_hex_no_length_prefix("2102715e91d37d239dea832f1460e91e368115d8ca6cc23a7da966795abad9e3b699ac").unwrap().to_string(),
+    assert_eq!(ScriptBuf::from_hex("2102715e91d37d239dea832f1460e91e368115d8ca6cc23a7da966795abad9e3b699ac").unwrap().to_string(),
                "OP_PUSHBYTES_33 02715e91d37d239dea832f1460e91e368115d8ca6cc23a7da966795abad9e3b699 OP_CHECKSIG");
     // Elements Alpha peg-out transaction with some signatures removed for brevity. Mainly to test PUSHDATA1
-    assert_eq!(ScriptBuf::from_hex_no_length_prefix("0047304402202457e78cc1b7f50d0543863c27de75d07982bde8359b9e3316adec0aec165f2f02200203fd331c4e4a4a02f48cf1c291e2c0d6b2f7078a784b5b3649fca41f8794d401004cf1552103244e602b46755f24327142a0517288cebd159eccb6ccf41ea6edf1f601e9af952103bbbacc302d19d29dbfa62d23f37944ae19853cf260c745c2bea739c95328fcb721039227e83246bd51140fe93538b2301c9048be82ef2fb3c7fc5d78426ed6f609ad210229bf310c379b90033e2ecb07f77ecf9b8d59acb623ab7be25a0caed539e2e6472103703e2ed676936f10b3ce9149fa2d4a32060fb86fa9a70a4efe3f21d7ab90611921031e9b7c6022400a6bb0424bbcde14cff6c016b91ee3803926f3440abf5c146d05210334667f975f55a8455d515a2ef1c94fdfa3315f12319a14515d2a13d82831f62f57ae").unwrap().to_string(),
+    assert_eq!(ScriptBuf::from_hex("0047304402202457e78cc1b7f50d0543863c27de75d07982bde8359b9e3316adec0aec165f2f02200203fd331c4e4a4a02f48cf1c291e2c0d6b2f7078a784b5b3649fca41f8794d401004cf1552103244e602b46755f24327142a0517288cebd159eccb6ccf41ea6edf1f601e9af952103bbbacc302d19d29dbfa62d23f37944ae19853cf260c745c2bea739c95328fcb721039227e83246bd51140fe93538b2301c9048be82ef2fb3c7fc5d78426ed6f609ad210229bf310c379b90033e2ecb07f77ecf9b8d59acb623ab7be25a0caed539e2e6472103703e2ed676936f10b3ce9149fa2d4a32060fb86fa9a70a4efe3f21d7ab90611921031e9b7c6022400a6bb0424bbcde14cff6c016b91ee3803926f3440abf5c146d05210334667f975f55a8455d515a2ef1c94fdfa3315f12319a14515d2a13d82831f62f57ae").unwrap().to_string(),
                "OP_0 OP_PUSHBYTES_71 304402202457e78cc1b7f50d0543863c27de75d07982bde8359b9e3316adec0aec165f2f02200203fd331c4e4a4a02f48cf1c291e2c0d6b2f7078a784b5b3649fca41f8794d401 OP_0 OP_PUSHDATA1 552103244e602b46755f24327142a0517288cebd159eccb6ccf41ea6edf1f601e9af952103bbbacc302d19d29dbfa62d23f37944ae19853cf260c745c2bea739c95328fcb721039227e83246bd51140fe93538b2301c9048be82ef2fb3c7fc5d78426ed6f609ad210229bf310c379b90033e2ecb07f77ecf9b8d59acb623ab7be25a0caed539e2e6472103703e2ed676936f10b3ce9149fa2d4a32060fb86fa9a70a4efe3f21d7ab90611921031e9b7c6022400a6bb0424bbcde14cff6c016b91ee3803926f3440abf5c146d05210334667f975f55a8455d515a2ef1c94fdfa3315f12319a14515d2a13d82831f62f57ae");
     // Various weird scripts found in transaction 6d7ed9914625c73c0288694a6819196a27ef6c08f98e1270d975a8e65a3dc09a
     // which triggered overflow bugs on 32-bit machines in script formatting in the past.
+    assert_eq!(ScriptBuf::from_hex("01").unwrap().to_string(), "OP_PUSHBYTES_1 <push past end>");
+    assert_eq!(ScriptBuf::from_hex("0201").unwrap().to_string(), "OP_PUSHBYTES_2 <push past end>");
+    assert_eq!(ScriptBuf::from_hex("4c").unwrap().to_string(), "<unexpected end>");
+    assert_eq!(ScriptBuf::from_hex("4c0201").unwrap().to_string(), "OP_PUSHDATA1 <push past end>");
+    assert_eq!(ScriptBuf::from_hex("4d").unwrap().to_string(), "<unexpected end>");
     assert_eq!(
-        ScriptBuf::from_hex_no_length_prefix("01").unwrap().to_string(),
-        "OP_PUSHBYTES_1 <push past end>"
-    );
-    assert_eq!(
-        ScriptBuf::from_hex_no_length_prefix("0201").unwrap().to_string(),
-        "OP_PUSHBYTES_2 <push past end>"
-    );
-    assert_eq!(ScriptBuf::from_hex_no_length_prefix("4c").unwrap().to_string(), "<unexpected end>");
-    assert_eq!(
-        ScriptBuf::from_hex_no_length_prefix("4c0201").unwrap().to_string(),
-        "OP_PUSHDATA1 <push past end>"
-    );
-    assert_eq!(ScriptBuf::from_hex_no_length_prefix("4d").unwrap().to_string(), "<unexpected end>");
-    assert_eq!(
-        ScriptBuf::from_hex_no_length_prefix("4dffff01").unwrap().to_string(),
+        ScriptBuf::from_hex("4dffff01").unwrap().to_string(),
         "OP_PUSHDATA2 <push past end>"
     );
     assert_eq!(
-        ScriptBuf::from_hex_no_length_prefix("4effffffff01").unwrap().to_string(),
+        ScriptBuf::from_hex("4effffffff01").unwrap().to_string(),
         "OP_PUSHDATA4 <push past end>"
     );
 }
@@ -548,83 +522,69 @@ fn script_asm() {
 #[test]
 fn script_buf_collect() {
     assert_eq!(&core::iter::empty::<Instruction<'_>>().collect::<ScriptBuf>(), Script::new());
-    let script = ScriptBuf::from_hex_no_length_prefix("0047304402202457e78cc1b7f50d0543863c27de75d07982bde8359b9e3316adec0aec165f2f02200203fd331c4e4a4a02f48cf1c291e2c0d6b2f7078a784b5b3649fca41f8794d401004cf1552103244e602b46755f24327142a0517288cebd159eccb6ccf41ea6edf1f601e9af952103bbbacc302d19d29dbfa62d23f37944ae19853cf260c745c2bea739c95328fcb721039227e83246bd51140fe93538b2301c9048be82ef2fb3c7fc5d78426ed6f609ad210229bf310c379b90033e2ecb07f77ecf9b8d59acb623ab7be25a0caed539e2e6472103703e2ed676936f10b3ce9149fa2d4a32060fb86fa9a70a4efe3f21d7ab90611921031e9b7c6022400a6bb0424bbcde14cff6c016b91ee3803926f3440abf5c146d05210334667f975f55a8455d515a2ef1c94fdfa3315f12319a14515d2a13d82831f62f57ae").unwrap();
+    let script = ScriptBuf::from_hex("0047304402202457e78cc1b7f50d0543863c27de75d07982bde8359b9e3316adec0aec165f2f02200203fd331c4e4a4a02f48cf1c291e2c0d6b2f7078a784b5b3649fca41f8794d401004cf1552103244e602b46755f24327142a0517288cebd159eccb6ccf41ea6edf1f601e9af952103bbbacc302d19d29dbfa62d23f37944ae19853cf260c745c2bea739c95328fcb721039227e83246bd51140fe93538b2301c9048be82ef2fb3c7fc5d78426ed6f609ad210229bf310c379b90033e2ecb07f77ecf9b8d59acb623ab7be25a0caed539e2e6472103703e2ed676936f10b3ce9149fa2d4a32060fb86fa9a70a4efe3f21d7ab90611921031e9b7c6022400a6bb0424bbcde14cff6c016b91ee3803926f3440abf5c146d05210334667f975f55a8455d515a2ef1c94fdfa3315f12319a14515d2a13d82831f62f57ae").unwrap();
     assert_eq!(script.instructions().collect::<Result<ScriptBuf, _>>().unwrap(), script);
 }
 
 #[test]
 fn script_p2sh_p2p2k_template() {
     // random outputs I picked out of the mempool
-    assert!(ScriptBuf::from_hex_no_length_prefix(
-        "76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac"
-    )
-    .unwrap()
-    .is_p2pkh());
-    assert!(!ScriptBuf::from_hex_no_length_prefix(
-        "76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac"
-    )
-    .unwrap()
-    .is_p2sh());
-    assert!(!ScriptBuf::from_hex_no_length_prefix(
-        "76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ad"
-    )
-    .unwrap()
-    .is_p2pkh());
-    assert!(!ScriptBuf::from_hex_no_length_prefix("").unwrap().is_p2pkh());
-    assert!(ScriptBuf::from_hex_no_length_prefix("a914acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87")
+    assert!(ScriptBuf::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac")
+        .unwrap()
+        .is_p2pkh());
+    assert!(!ScriptBuf::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac")
+        .unwrap()
+        .is_p2sh());
+    assert!(!ScriptBuf::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ad")
+        .unwrap()
+        .is_p2pkh());
+    assert!(!ScriptBuf::from_hex("").unwrap().is_p2pkh());
+    assert!(ScriptBuf::from_hex("a914acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87")
+        .unwrap()
+        .is_p2sh());
+    assert!(!ScriptBuf::from_hex("a914acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87")
+        .unwrap()
+        .is_p2pkh());
+    assert!(!ScriptBuf::from_hex("a314acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87")
         .unwrap()
         .is_p2sh());
-    assert!(!ScriptBuf::from_hex_no_length_prefix(
-        "a914acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87"
-    )
-    .unwrap()
-    .is_p2pkh());
-    assert!(!ScriptBuf::from_hex_no_length_prefix(
-        "a314acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87"
-    )
-    .unwrap()
-    .is_p2sh());
 }
 
 #[test]
 fn script_p2pk() {
-    assert!(ScriptBuf::from_hex_no_length_prefix(
+    assert!(ScriptBuf::from_hex(
         "21021aeaf2f8638a129a3156fbe7e5ef635226b0bafd495ff03afe2c843d7e3a4b51ac"
     )
     .unwrap()
     .is_p2pk());
-    assert!(ScriptBuf::from_hex_no_length_prefix("410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac").unwrap().is_p2pk());
+    assert!(ScriptBuf::from_hex("410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac").unwrap().is_p2pk());
 }
 
 #[test]
 fn p2sh_p2wsh_conversion() {
     // Test vectors taken from Core tests/data/script_tests.json
     // bare p2wsh
-    let witness_script = ScriptBuf::from_hex_no_length_prefix("410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac").unwrap();
-    let expected_without = ScriptBuf::from_hex_no_length_prefix(
-        "0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64",
-    )
-    .unwrap();
+    let witness_script = ScriptBuf::from_hex("410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac").unwrap();
+    let expected_without =
+        ScriptBuf::from_hex("0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64")
+            .unwrap();
     assert!(witness_script.to_p2wsh().unwrap().is_p2wsh());
     assert_eq!(witness_script.to_p2wsh().unwrap(), expected_without);
 
     // p2sh
-    let redeem_script = ScriptBuf::from_hex_no_length_prefix("0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8").unwrap();
+    let redeem_script = ScriptBuf::from_hex("0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8").unwrap();
     let expected_p2shout =
-        ScriptBuf::from_hex_no_length_prefix("a91491b24bf9f5288532960ac687abb035127b1d28a587")
-            .unwrap();
+        ScriptBuf::from_hex("a91491b24bf9f5288532960ac687abb035127b1d28a587").unwrap();
     assert!(redeem_script.to_p2sh().unwrap().is_p2sh());
     assert_eq!(redeem_script.to_p2sh().unwrap(), expected_p2shout);
 
     // p2sh-p2wsh
-    let witness_script = ScriptBuf::from_hex_no_length_prefix("410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac").unwrap();
-    let expected_without = ScriptBuf::from_hex_no_length_prefix(
-        "0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64",
-    )
-    .unwrap();
-    let expected_out =
-        ScriptBuf::from_hex_no_length_prefix("a914f386c2ba255cc56d20cfa6ea8b062f8b5994551887")
+    let witness_script = ScriptBuf::from_hex("410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac").unwrap();
+    let expected_without =
+        ScriptBuf::from_hex("0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64")
             .unwrap();
+    let expected_out =
+        ScriptBuf::from_hex("a914f386c2ba255cc56d20cfa6ea8b062f8b5994551887").unwrap();
     assert!(witness_script.to_p2sh().unwrap().is_p2sh());
     assert_eq!(witness_script.to_p2wsh().unwrap(), expected_without);
     assert_eq!(witness_script.to_p2wsh().unwrap().to_p2sh().unwrap(), expected_out);
@@ -640,12 +600,12 @@ macro_rules! unwrap_all {
 
 #[test]
 fn iterator() {
-    let zero = ScriptBuf::from_hex_no_length_prefix("00").unwrap();
-    let zeropush = ScriptBuf::from_hex_no_length_prefix("0100").unwrap();
+    let zero = ScriptBuf::from_hex("00").unwrap();
+    let zeropush = ScriptBuf::from_hex("0100").unwrap();
 
-    let nonminimal = ScriptBuf::from_hex_no_length_prefix("4c0169b2").unwrap(); // PUSHDATA1 for no reason
-    let minimal = ScriptBuf::from_hex_no_length_prefix("0169b2").unwrap(); // minimal
-    let nonminimal_alt = ScriptBuf::from_hex_no_length_prefix("026900b2").unwrap(); // non-minimal number but minimal push (should be OK)
+    let nonminimal = ScriptBuf::from_hex("4c0169b2").unwrap(); // PUSHDATA1 for no reason
+    let minimal = ScriptBuf::from_hex("0169b2").unwrap(); // minimal
+    let nonminimal_alt = ScriptBuf::from_hex("026900b2").unwrap(); // non-minimal number but minimal push (should be OK)
 
     let v_zero: Result<Vec<_>, Error> = zero.instruction_indices_minimal().collect();
     let v_zeropush: Result<Vec<_>, Error> = zeropush.instruction_indices_minimal().collect();
diff --git a/bitcoin/tests/bip_174.rs b/bitcoin/tests/bip_174.rs
index 10fb81ac..49565865 100644
--- a/bitcoin/tests/bip_174.rs
+++ b/bitcoin/tests/bip_174.rs
@@ -22,9 +22,7 @@ fn hex_psbt(s: &str) -> Psbt {
 }
 
 #[track_caller]
-fn hex_script(s: &str) -> ScriptBuf {
-    ScriptBuf::from_hex_no_length_prefix(s).expect("valid hex digits")
-}
+fn hex_script(s: &str) -> ScriptBuf { ScriptBuf::from_hex(s).expect("valid hex digits") }
 
 #[test]
 fn bip174_psbt_workflow() {
@@ -122,7 +120,7 @@ fn build_extended_private_key() -> Xpriv {
     let xpriv = extended_private_key.parse::<Xpriv>().unwrap();
 
     let sk = PrivateKey::from_wif(seed).unwrap();
-    let seeded = Xpriv::new_master(NetworkKind::Test, &sk.inner.secret_bytes());
+    let seeded = Xpriv::new_master(NetworkKind::Test, &sk.inner.secret_bytes()).unwrap();
     assert_eq!(xpriv, seeded);
 
     xpriv
@@ -183,13 +181,13 @@ struct TvInput {
             TxOut {
                 value: Amount::from_str_in(output_0.amount, Denomination::Bitcoin)
                     .expect("failed to parse amount"),
-                script_pubkey: ScriptBuf::from_hex_no_length_prefix(output_0.script_pubkey)
+                script_pubkey: ScriptBuf::from_hex(output_0.script_pubkey)
                     .expect("failed to parse script"),
             },
             TxOut {
                 value: Amount::from_str_in(output_1.amount, Denomination::Bitcoin)
                     .expect("failed to parse amount"),
-                script_pubkey: ScriptBuf::from_hex_no_length_prefix(output_1.script_pubkey)
+                script_pubkey: ScriptBuf::from_hex(output_1.script_pubkey)
                     .expect("failed to parse script"),
             },
         ],
@@ -317,8 +315,7 @@ fn parse_and_verify_keys(
 
         let path =
             derivation_path.into_derivation_path().expect("failed to convert derivation path");
-        let derived_priv =
-            ext_priv.derive_xpriv(secp, &path).expect("derivation path too long").to_private_key();
+        let derived_priv = ext_priv.derive_xpriv(secp, &path).to_private_key();
         assert_eq!(wif_priv, derived_priv);
         let derived_pub = derived_priv.public_key(secp);
         key_map.insert(derived_pub, derived_priv);
diff --git a/bitcoin/tests/serde.rs b/bitcoin/tests/serde.rs
index f9e7e4a6..25c89306 100644
--- a/bitcoin/tests/serde.rs
+++ b/bitcoin/tests/serde.rs
@@ -226,10 +226,8 @@ fn serde_regression_psbt() {
                     .unwrap(),
                 vout: 1,
             },
-            script_sig: ScriptBuf::from_hex_no_length_prefix(
-                "160014be18d152a9b012039daf3da7de4f53349eecb985",
-            )
-            .unwrap(),
+            script_sig: ScriptBuf::from_hex("160014be18d152a9b012039daf3da7de4f53349eecb985")
+                .unwrap(),
             sequence: Sequence::from_consensus(4294967295),
             witness: Witness::from_slice(&[Vec::from_hex(
                 "03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105",
@@ -238,10 +236,8 @@ fn serde_regression_psbt() {
         }],
         output: vec![TxOut {
             value: Amount::from_sat(190_303_501_938).unwrap(),
-            script_pubkey: ScriptBuf::from_hex_no_length_prefix(
-                "a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587",
-            )
-            .unwrap(),
+            script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587")
+                .unwrap(),
         }],
     };
     let unknown: BTreeMap<raw::Key, Vec<u8>> =
@@ -287,7 +283,7 @@ fn serde_regression_psbt() {
             non_witness_utxo: Some(tx),
             witness_utxo: Some(TxOut {
                 value: Amount::from_sat(190_303_501_938).unwrap(),
-                script_pubkey: ScriptBuf::from_hex_no_length_prefix("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(),
+                script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(),
             }),
             sighash_type: Some(PsbtSighashType::from("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY".parse::<EcdsaSighashType>().unwrap())),
             redeem_script: Some(vec![0x51].into()),
diff --git a/units/src/amount/tests.rs b/units/src/amount/tests.rs
index 8f93de9d..a9b19c13 100644
--- a/units/src/amount/tests.rs
+++ b/units/src/amount/tests.rs
@@ -13,7 +13,7 @@
 use ::serde::{Deserialize, Serialize};
 
 use super::*;
-use crate::{MathOp, NumOpResult};
+use crate::NumOpResult;
 #[cfg(feature = "alloc")]
 use crate::{FeeRate, Weight};
 
@@ -120,75 +120,6 @@ fn from_int_btc() {
     assert_eq!(ssat(-200_000_000), amt);
 }
 
-#[test]
-#[cfg(feature = "alloc")]
-fn display_display_struct() {
-    let display_fixed_btc = Display {
-        sats_abs: 100_000_000,
-        is_negative: false,
-        style: DisplayStyle::FixedDenomination {
-            denomination: Denomination::Bitcoin,
-            show_denomination: true,
-        },
-    };
-    assert_eq!(format!("{}", display_fixed_btc), "1 BTC");
-
-    let display_fixed_sat = Display {
-        sats_abs: 1,
-        is_negative: false,
-        style: DisplayStyle::FixedDenomination {
-            denomination: Denomination::Satoshi,
-            show_denomination: true,
-        },
-    };
-    assert_eq!(format!("{}", display_fixed_sat), "1 satoshi");
-
-    let display_dynamic_btc = Display {
-        sats_abs: 100_000_000,
-        is_negative: false,
-        style: DisplayStyle::DynamicDenomination,
-    };
-    assert_eq!(format!("{}", display_dynamic_btc), "1 BTC");
-
-    let display_dynamic_sat = Display {
-        sats_abs: 99_999_999,
-        is_negative: false,
-        style: DisplayStyle::DynamicDenomination,
-    };
-    assert_eq!(format!("{}", display_dynamic_sat), "99999999 satoshi");
-
-    let display_negative_btc = Display {
-        sats_abs: 100_000_000,
-        is_negative: true,
-        style: DisplayStyle::DynamicDenomination,
-    };
-    assert_eq!(format!("{}", display_negative_btc), "-1 BTC");
-
-    let display_negative_sat = Display {
-        sats_abs: 99_999_999,
-        is_negative: true,
-        style: DisplayStyle::DynamicDenomination,
-    };
-    assert_eq!(format!("{}", display_negative_sat), "-99999999 satoshi");
-}
-
-#[test]
-#[cfg(feature = "alloc")]
-fn display_math_op() {
-    let cases = [
-        (MathOp::Add, "add"),
-        (MathOp::Sub, "sub"),
-        (MathOp::Mul, "mul"),
-        (MathOp::Div, "div"),
-        (MathOp::Rem, "rem"),
-        (MathOp::Neg, "neg"),
-    ];
-
-    for (op, expected) in cases {
-        assert_eq!(format!("{}", op), expected);
-    }
-}
-
 #[test]
 fn amount_try_from_signed_amount() {
     let sa_positive = ssat(123);
diff --git a/units/tests/api.rs b/units/tests/api.rs
index 41b39bb4..46a16e42 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::Time,
     i: relative::Height,
     j: relative::Time,
     k: Weight,
@@ -55,7 +55,7 @@ fn max() -> Self {
             e: BlockInterval::MAX,
             f: FeeRate::MAX,
             g: absolute::Height::MAX,
-            h: absolute::Mtp::MAX,
+            h: absolute::Time::MAX,
             i: relative::Height::MAX,
             j: relative::Time::MAX,
             k: Weight::MAX,
@@ -85,7 +85,7 @@ struct CommonTraits {
     e: BlockInterval,
     f: FeeRate,
     g: absolute::Height,
-    h: absolute::Mtp,
+    h: absolute::Time,
     i: relative::Height,
     j: relative::Time,
     k: Weight,
@@ -128,7 +128,7 @@ struct Errors {
     t: amount::PossiblyConfusingDenominationError,
     u: amount::TooPreciseError,
     v: amount::UnknownDenominationError,
-    w: block::TooBigForRelativeBlockHeightIntervalError,
+    w: block::TooBigForRelativeBlockHeightError,
     x: locktime::absolute::ConversionError,
     y: locktime::absolute::Height,
     z: locktime::absolute::ParseHeightError,
@@ -163,9 +163,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, BlockInterval, TooBigForRelativeBlockHeightIntervalError,
-    };
+    use bitcoin_units::block::{BlockHeight, BlockInterval, TooBigForRelativeBlockHeightError};
 }
 
 #[test]
@@ -176,7 +174,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, ParseHeightError, ParseTimeError, Time,
     };
 }
 
@@ -293,7 +291,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::Time::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..d807bcc7 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::Time,
     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::Time::MAX,
             e: relative::Height::MAX,
             f: relative::Time::MAX,
             g: Weight::MAX,
diff --git a/units/tests/str.rs b/units/tests/str.rs
index 98e06f72..0b365af2 100644
--- a/units/tests/str.rs
+++ b/units/tests/str.rs
@@ -3,7 +3,6 @@
 //! Do basic regression tests on the `Display` and `FromStr` impls.
 
 use bitcoin_units::locktime::{absolute, relative};
-use bitcoin_units::amount::Denomination;
 use bitcoin_units::{Amount, BlockHeight, BlockInterval, FeeRate, SignedAmount, Weight};
 
 macro_rules! check {
@@ -25,9 +24,6 @@ fn $test_name() {
     amount_unsigned_one_sat, Amount, Amount::ONE_SAT, "0.00000001 BTC";
     amount_unsigned_max_money, Amount, Amount::MAX, "21000000 BTC";
 
-    denomination_btc, Denomination, Denomination::BTC, "BTC";
-    denomination_sat, Denomination, Denomination::SAT, "satoshi";
-
     amount_signed_one_sat, SignedAmount, SignedAmount::ONE_SAT, "0.00000001 BTC";
     amount_signed_max_money, SignedAmount, SignedAmount::MAX, "21000000 BTC";
 
@@ -41,17 +37,11 @@ fn $test_name() {
     fee_rate_max, FeeRate, FeeRate::MAX, "18446744073709551615";
     fee_rate_dust, FeeRate, FeeRate::DUST, "750";
 
-    lock_by_height_absolute_min, absolute::Height, absolute::Height::MIN, "0";
-    lock_by_height_absolute_max, absolute::Height, absolute::Height::MAX, "499999999";
-
-    lock_by_height_relative_min, relative::Height, relative::Height::MIN, "0";
-    lock_by_height_relative_max, relative::Height, relative::Height::MAX, "65535";
-
-    lock_by_time_absolute_min, absolute::Time, absolute::Time::MIN, "500000000";
-    lock_by_time_absolute_max, absolute::Time, absolute::Time::MAX, "4294967295";
+    lock_time_absolute_min, absolute::Height, absolute::Height::MIN, "0";
+    lock_time_absolute_max, absolute::Height, absolute::Height::MAX, "499999999";
 
-    lock_by_time_relative_min, relative::Time, relative::Time::MIN, "0";
-    lock_by_time_relative_max, relative::Time, relative::Time::MAX, "65535";
+    lock_time_relative_min, relative::Height, relative::Height::MIN, "0";
+    lock_time_relative_max, relative::Height, relative::Height::MAX, "65535";
 
     weight_min, Weight, Weight::MIN, "0";
     weight_max, Weight, Weight::MAX, "18446744073709551615";