Repository: rust-bitcoin/rust-bitcoin
Pull request #1528 (2023-01-04 07:04:03)

[WIP] 1514: fix formatting in opcodes
See  #1514.




Patch:
diff --git a/bitcoin/examples/ecdsa-psbt.rs b/bitcoin/examples/ecdsa-psbt.rs
index b778251a..b6405d0b 100644
--- a/bitcoin/examples/ecdsa-psbt.rs
+++ b/bitcoin/examples/ecdsa-psbt.rs
@@ -236,14 +236,16 @@ fn update_psbt(&self, mut psbt: Psbt) -> Result<Psbt> {
     /// Finalizes the PSBT, in BIP174 parlance this is the 'Finalizer'.
     /// This is just an example. For a production-ready PSBT Finalizer, use [rust-miniscript](https://docs.rs/miniscript/latest/miniscript/psbt/trait.PsbtExt.html#tymethod.finalize)
     fn finalize_psbt(&self, mut psbt: Psbt) -> Result<Psbt> {
+        use bitcoin::psbt::serialize::Serialize;
+
         if psbt.inputs.is_empty() {
             return Err(psbt::SignError::MissingInputUtxo.into());
         }
 
         let sigs: Vec<_> = psbt.inputs[0].partial_sigs.values().collect();
         let mut script_witness: Witness = Witness::new();
-        script_witness.push(&sigs[0].to_vec());
-        script_witness.push(self.input_xpub.to_pub().to_bytes());
+        script_witness.push(&sigs[0].serialize());
+        script_witness.push(self.input_xpub.to_pub().serialize());
 
         psbt.inputs[0].final_script_witness = Some(script_witness);
 
diff --git a/bitcoin/examples/taproot-psbt.rs b/bitcoin/examples/taproot-psbt.rs
index 40e07248..64928d01 100644
--- a/bitcoin/examples/taproot-psbt.rs
+++ b/bitcoin/examples/taproot-psbt.rs
@@ -85,6 +85,7 @@
 use bitcoin::hashes::Hash;
 use bitcoin::key::XOnlyPublicKey;
 use bitcoin::opcodes::all::{OP_CHECKSIG, OP_CLTV, OP_DROP};
+use bitcoin::psbt::serialize::Serialize;
 use bitcoin::psbt::{self, Input, Output, Psbt, PsbtSighashType};
 use bitcoin::schnorr::{self, TapTweak};
 use bitcoin::secp256k1::{Message, Secp256k1};
@@ -316,7 +317,7 @@ fn generate_bip86_key_spend_tx(
     // FINALIZER
     psbt.inputs.iter_mut().for_each(|input| {
         let mut script_witness: Witness = Witness::new();
-        script_witness.push(input.tap_key_sig.unwrap().to_vec());
+        script_witness.push(input.tap_key_sig.unwrap().serialize());
         input.final_script_witness = Some(script_witness);
 
         // Clear all the data fields as per the spec.
@@ -549,7 +550,7 @@ fn refresh_tx(
             // FINALIZER
             psbt.inputs.iter_mut().for_each(|input| {
                 let mut script_witness: Witness = Witness::new();
-                script_witness.push(input.tap_key_sig.unwrap().to_vec());
+                script_witness.push(input.tap_key_sig.unwrap().serialize());
                 input.final_script_witness = Some(script_witness);
 
                 // Clear all the data fields as per the spec.
@@ -685,10 +686,10 @@ fn spend_inheritance(
         psbt.inputs.iter_mut().for_each(|input| {
             let mut script_witness: Witness = Witness::new();
             for (_, signature) in input.tap_script_sigs.iter() {
-                script_witness.push(signature.to_vec());
+                script_witness.push(signature.serialize());
             }
             for (control_block, (script, _)) in input.tap_scripts.iter() {
-                script_witness.push(script.to_bytes());
+                script_witness.push(script.serialize());
                 script_witness.push(control_block.serialize());
             }
             input.final_script_witness = Some(script_witness);
diff --git a/bitcoin/fuzz/fuzz_targets/deserialize_psbt.rs b/bitcoin/fuzz/fuzz_targets/deserialize_psbt.rs
index 284c8655..7556679b 100644
--- a/bitcoin/fuzz/fuzz_targets/deserialize_psbt.rs
+++ b/bitcoin/fuzz/fuzz_targets/deserialize_psbt.rs
@@ -1,14 +1,14 @@
 extern crate bitcoin;
 
 fn do_test(data: &[u8]) {
-    let psbt: Result<bitcoin::psbt::PartiallySignedTransaction, _> = bitcoin::psbt::Psbt::deserialize(data);
+    let psbt: Result<bitcoin::psbt::PartiallySignedTransaction, _> = bitcoin::consensus::encode::deserialize(data);
     match psbt {
         Err(_) => {},
         Ok(psbt) => {
-            let ser = bitcoin::psbt::Psbt::serialize(&psbt);
-            let deser = bitcoin::psbt::Psbt::deserialize(&ser).unwrap();
+            let ser = bitcoin::consensus::encode::serialize(&psbt);
+            let deser: bitcoin::psbt::PartiallySignedTransaction  = bitcoin::consensus::encode::deserialize(&ser).unwrap();
             // Since the fuzz data could order psbt fields differently, we compare to our deser/ser instead of data
-            assert_eq!(ser, bitcoin::psbt::Psbt::serialize(&deser));
+            assert_eq!(ser, bitcoin::consensus::encode::serialize(&deser));
         }
     }
 }
diff --git a/bitcoin/src/amount.rs b/bitcoin/src/amount.rs
index 3a7d2d0d..d1c50744 100644
--- a/bitcoin/src/amount.rs
+++ b/bitcoin/src/amount.rs
@@ -288,16 +288,6 @@ fn parse_signed_to_satoshi(
     Ok((is_negative, value))
 }
 
-fn split_amount_and_denomination(s: &str) -> Result<(&str, Denomination), ParseAmountError> {
-  let (i, j) = if let Some(i) = s.find(' ') {
-    (i, i + 1)
-  } else {
-    let i = s.find(|c: char| c.is_alphabetic()).ok_or(ParseAmountError::InvalidFormat)?;
-    (i, i)
-  };
-  Ok((&s[..i], s[j..].parse()?))
-}
-
 /// Options given by `fmt::Formatter`
 struct FormatOptions {
     fill: char,
@@ -533,8 +523,14 @@ pub fn from_str_in(s: &str, denom: Denomination) -> Result<Amount, ParseAmountEr
     /// If you want to parse only the amount without the denomination,
     /// use [Self::from_str_in].
     pub fn from_str_with_denomination(s: &str) -> Result<Amount, ParseAmountError> {
-        let (amt, denom) = split_amount_and_denomination(s)?;
-        Amount::from_str_in(amt, denom)
+        let mut split = s.splitn(3, ' ');
+        let amt_str = split.next().unwrap();
+        let denom_str = split.next().ok_or(ParseAmountError::InvalidFormat)?;
+        if split.next().is_some() {
+            return Err(ParseAmountError::InvalidFormat);
+        }
+
+        Amount::from_str_in(amt_str, denom_str.parse()?)
     }
 
     /// Express this [Amount] as a floating-point value in the given denomination.
@@ -868,8 +864,14 @@ pub fn from_str_in(s: &str, denom: Denomination) -> Result<SignedAmount, ParseAm
     /// If you want to parse only the amount without the denomination,
     /// use [Self::from_str_in].
     pub fn from_str_with_denomination(s: &str) -> Result<SignedAmount, ParseAmountError> {
-        let (amt, denom) = split_amount_and_denomination(s)?;
-        SignedAmount::from_str_in(amt, denom)
+        let mut split = s.splitn(3, ' ');
+        let amt_str = split.next().unwrap();
+        let denom_str = split.next().ok_or(ParseAmountError::InvalidFormat)?;
+        if split.next().is_some() {
+            return Err(ParseAmountError::InvalidFormat);
+        }
+
+        SignedAmount::from_str_in(amt_str, denom_str.parse()?)
     }
 
     /// Express this [SignedAmount] as a floating-point value in the given denomination.
@@ -1894,51 +1896,39 @@ fn test_unsigned_signed_conversion() {
     #[allow(clippy::inconsistent_digit_grouping)] // Group to show 100,000,000 sats per bitcoin.
     fn from_str() {
         use super::ParseAmountError as E;
-
-        assert_eq!(Amount::from_str("x BTC"), Err(E::InvalidCharacter('x')));
-        assert_eq!(Amount::from_str("xBTC"), Err(E::UnknownDenomination("xBTC".into())));
-        assert_eq!(Amount::from_str("5 BTC BTC"), Err(E::UnknownDenomination("BTC BTC".into())));
-        assert_eq!(Amount::from_str("5BTC BTC"), Err(E::InvalidCharacter('B')));
-        assert_eq!(Amount::from_str("5 5 BTC"), Err(E::UnknownDenomination("5 BTC".into())));
-
-        #[cfg_attr(rust_v_1_46, track_caller)]
-        fn case(s: &str, expected: Result<Amount, ParseAmountError>) {
-          assert_eq!(Amount::from_str(s), expected);
-          assert_eq!(Amount::from_str(&s.replace(' ', "")), expected);
-        }
-
-        #[cfg_attr(rust_v_1_46, track_caller)]
-        fn scase(s: &str, expected: Result<SignedAmount, ParseAmountError>) {
-          assert_eq!(SignedAmount::from_str(s), expected);
-          assert_eq!(SignedAmount::from_str(&s.replace(' ', "")), expected);
-        }
-
-        case("5 BCH", Err(E::UnknownDenomination("BCH".to_owned())));
-
-        case("-1 BTC", Err(E::Negative));
-        case("-0.0 BTC", Err(E::Negative));
-        case("0.123456789 BTC", Err(E::TooPrecise));
-        scase("-0.1 satoshi", Err(E::TooPrecise));
-        case("0.123456 mBTC", Err(E::TooPrecise));
-        scase("-1.001 bits", Err(E::TooPrecise));
-        scase("-200000000000 BTC", Err(E::TooBig));
-        case("18446744073709551616 sat", Err(E::TooBig));
-
-        scase("0 msat", Err(E::TooPrecise));
-        scase("-0 msat", Err(E::TooPrecise));
-        scase("000 msat", Err(E::TooPrecise));
-        scase("-000 msat", Err(E::TooPrecise));
-        case("0 msat", Err(E::TooPrecise));
-        case("-0 msat", Err(E::TooPrecise));
-        case("000 msat", Err(E::TooPrecise));
-        case("-000 msat", Err(E::TooPrecise));
-
-        case(".5 bits", Ok(Amount::from_sat(50)));
-        scase("-.5 bits", Ok(SignedAmount::from_sat(-50)));
-        case("0.00253583 BTC", Ok(Amount::from_sat(253583)));
-        scase("-5 satoshi", Ok(SignedAmount::from_sat(-5)));
-        case("0.10000000 BTC", Ok(Amount::from_sat(100_000_00)));
-        scase("-100 bits", Ok(SignedAmount::from_sat(-10_000)));
+        let p = Amount::from_str;
+        let sp = SignedAmount::from_str;
+
+        assert_eq!(p("x BTC"), Err(E::InvalidCharacter('x')));
+        assert_eq!(p("5 BTC BTC"), Err(E::InvalidFormat));
+        assert_eq!(p("5 5 BTC"), Err(E::InvalidFormat));
+
+        assert_eq!(p("5 BCH"), Err(E::UnknownDenomination("BCH".to_owned())));
+
+        assert_eq!(p("-1 BTC"), Err(E::Negative));
+        assert_eq!(p("-0.0 BTC"), Err(E::Negative));
+        assert_eq!(p("0.123456789 BTC"), Err(E::TooPrecise));
+        assert_eq!(sp("-0.1 satoshi"), Err(E::TooPrecise));
+        assert_eq!(p("0.123456 mBTC"), Err(E::TooPrecise));
+        assert_eq!(sp("-1.001 bits"), Err(E::TooPrecise));
+        assert_eq!(sp("-200000000000 BTC"), Err(E::TooBig));
+        assert_eq!(p("18446744073709551616 sat"), Err(E::TooBig));
+
+        assert_eq!(sp("0 msat"), Err(E::TooPrecise));
+        assert_eq!(sp("-0 msat"), Err(E::TooPrecise));
+        assert_eq!(sp("000 msat"), Err(E::TooPrecise));
+        assert_eq!(sp("-000 msat"), Err(E::TooPrecise));
+        assert_eq!(p("0 msat"), Err(E::TooPrecise));
+        assert_eq!(p("-0 msat"), Err(E::TooPrecise));
+        assert_eq!(p("000 msat"), Err(E::TooPrecise));
+        assert_eq!(p("-000 msat"), Err(E::TooPrecise));
+
+        assert_eq!(p(".5 bits"), Ok(Amount::from_sat(50)));
+        assert_eq!(sp("-.5 bits"), Ok(SignedAmount::from_sat(-50)));
+        assert_eq!(p("0.00253583 BTC"), Ok(Amount::from_sat(253583)));
+        assert_eq!(sp("-5 satoshi"), Ok(SignedAmount::from_sat(-5)));
+        assert_eq!(p("0.10000000 BTC"), Ok(Amount::from_sat(100_000_00)));
+        assert_eq!(sp("-100 bits"), Ok(SignedAmount::from_sat(-10_000)));
     }
 
     #[test]
@@ -2044,14 +2034,8 @@ fn to_string_with_denomination_from_str_roundtrip() {
         assert_eq!(Amount::from_str(&denom(amt, D::MilliSatoshi)), Ok(amt));
         assert_eq!(Amount::from_str(&denom(amt, D::PicoBitcoin)), Ok(amt));
 
-        assert_eq!(
-          Amount::from_str("42 satoshi BTC"),
-          Err(ParseAmountError::UnknownDenomination("satoshi BTC".into())),
-        );
-        assert_eq!(
-          SignedAmount::from_str("-42 satoshi BTC"),
-          Err(ParseAmountError::UnknownDenomination("satoshi BTC".into())),
-        );
+        assert_eq!(Amount::from_str("42 satoshi BTC"), Err(ParseAmountError::InvalidFormat));
+        assert_eq!(SignedAmount::from_str("-42 satoshi BTC"), Err(ParseAmountError::InvalidFormat));
     }
 
     #[cfg(feature = "serde")]
diff --git a/bitcoin/src/blockdata/opcodes.rs b/bitcoin/src/blockdata/opcodes.rs
index 263f479a..36120248 100644
--- a/bitcoin/src/blockdata/opcodes.rs
+++ b/bitcoin/src/blockdata/opcodes.rs
@@ -34,638 +34,302 @@ pub struct All {
     code: u8,
 }
 
-// private import so we don't have to use `all::OP_FOO` in this file.
 use self::all::*;
 
-/// Enables wildcard imports to bring into scope all opcodes and nothing else.
-///
-/// The `all` module is provided so one can use a wildcard import `use bitcoin::opcodes::all::*` to
-/// get all the `OP_FOO` opcodes without getting other types defined in `opcodes` (e.g. `All`, `Class`).
-///
-/// This module is guaranteed to never contain anything except opcode constants and all opcode
-/// constants are guaranteed to begin with OP_.
-pub mod all {
-    use super::All;
-
-    /// Push an empty array onto the stack.
-    pub const OP_PUSHBYTES_0: All = All {code: 0x00};
-    /// Push the next byte as an array onto the stack.
-    pub const OP_PUSHBYTES_1: All = All {code: 0x01};
-    /// Push the next 2 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_2: All = All {code: 0x02};
-    /// Push the next 2 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_3: All = All {code: 0x03};
-    /// Push the next 4 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_4: All = All {code: 0x04};
-    /// Push the next 5 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_5: All = All {code: 0x05};
-    /// Push the next 6 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_6: All = All {code: 0x06};
-    /// Push the next 7 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_7: All = All {code: 0x07};
-    /// Push the next 8 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_8: All = All {code: 0x08};
-    /// Push the next 9 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_9: All = All {code: 0x09};
-    /// Push the next 10 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_10: All = All {code: 0x0a};
-    /// Push the next 11 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_11: All = All {code: 0x0b};
-    /// Push the next 12 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_12: All = All {code: 0x0c};
-    /// Push the next 13 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_13: All = All {code: 0x0d};
-    /// Push the next 14 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_14: All = All {code: 0x0e};
-    /// Push the next 15 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_15: All = All {code: 0x0f};
-    /// Push the next 16 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_16: All = All {code: 0x10};
-    /// Push the next 17 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_17: All = All {code: 0x11};
-    /// Push the next 18 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_18: All = All {code: 0x12};
-    /// Push the next 19 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_19: All = All {code: 0x13};
-    /// Push the next 20 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_20: All = All {code: 0x14};
-    /// Push the next 21 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_21: All = All {code: 0x15};
-    /// Push the next 22 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_22: All = All {code: 0x16};
-    /// Push the next 23 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_23: All = All {code: 0x17};
-    /// Push the next 24 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_24: All = All {code: 0x18};
-    /// Push the next 25 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_25: All = All {code: 0x19};
-    /// Push the next 26 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_26: All = All {code: 0x1a};
-    /// Push the next 27 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_27: All = All {code: 0x1b};
-    /// Push the next 28 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_28: All = All {code: 0x1c};
-    /// Push the next 29 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_29: All = All {code: 0x1d};
-    /// Push the next 30 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_30: All = All {code: 0x1e};
-    /// Push the next 31 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_31: All = All {code: 0x1f};
-    /// Push the next 32 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_32: All = All {code: 0x20};
-    /// Push the next 33 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_33: All = All {code: 0x21};
-    /// Push the next 34 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_34: All = All {code: 0x22};
-    /// Push the next 35 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_35: All = All {code: 0x23};
-    /// Push the next 36 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_36: All = All {code: 0x24};
-    /// Push the next 37 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_37: All = All {code: 0x25};
-    /// Push the next 38 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_38: All = All {code: 0x26};
-    /// Push the next 39 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_39: All = All {code: 0x27};
-    /// Push the next 40 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_40: All = All {code: 0x28};
-    /// Push the next 41 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_41: All = All {code: 0x29};
-    /// Push the next 42 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_42: All = All {code: 0x2a};
-    /// Push the next 43 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_43: All = All {code: 0x2b};
-    /// Push the next 44 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_44: All = All {code: 0x2c};
-    /// Push the next 45 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_45: All = All {code: 0x2d};
-    /// Push the next 46 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_46: All = All {code: 0x2e};
-    /// Push the next 47 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_47: All = All {code: 0x2f};
-    /// Push the next 48 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_48: All = All {code: 0x30};
-    /// Push the next 49 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_49: All = All {code: 0x31};
-    /// Push the next 50 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_50: All = All {code: 0x32};
-    /// Push the next 51 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_51: All = All {code: 0x33};
-    /// Push the next 52 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_52: All = All {code: 0x34};
-    /// Push the next 53 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_53: All = All {code: 0x35};
-    /// Push the next 54 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_54: All = All {code: 0x36};
-    /// Push the next 55 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_55: All = All {code: 0x37};
-    /// Push the next 56 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_56: All = All {code: 0x38};
-    /// Push the next 57 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_57: All = All {code: 0x39};
-    /// Push the next 58 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_58: All = All {code: 0x3a};
-    /// Push the next 59 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_59: All = All {code: 0x3b};
-    /// Push the next 60 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_60: All = All {code: 0x3c};
-    /// Push the next 61 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_61: All = All {code: 0x3d};
-    /// Push the next 62 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_62: All = All {code: 0x3e};
-    /// Push the next 63 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_63: All = All {code: 0x3f};
-    /// Push the next 64 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_64: All = All {code: 0x40};
-    /// Push the next 65 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_65: All = All {code: 0x41};
-    /// Push the next 66 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_66: All = All {code: 0x42};
-    /// Push the next 67 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_67: All = All {code: 0x43};
-    /// Push the next 68 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_68: All = All {code: 0x44};
-    /// Push the next 69 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_69: All = All {code: 0x45};
-    /// Push the next 70 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_70: All = All {code: 0x46};
-    /// Push the next 71 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_71: All = All {code: 0x47};
-    /// Push the next 72 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_72: All = All {code: 0x48};
-    /// Push the next 73 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_73: All = All {code: 0x49};
-    /// Push the next 74 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_74: All = All {code: 0x4a};
-    /// Push the next 75 bytes as an array onto the stack.
-    pub const OP_PUSHBYTES_75: All = All {code: 0x4b};
-    /// Read the next byte as N; push the next N bytes as an array onto the stack.
-    pub const OP_PUSHDATA1: All = All {code: 0x4c};
-    /// Read the next 2 bytes as N; push the next N bytes as an array onto the stack.
-    pub const OP_PUSHDATA2: All = All {code: 0x4d};
-    /// Read the next 4 bytes as N; push the next N bytes as an array onto the stack.
-    pub const OP_PUSHDATA4: All = All {code: 0x4e};
-    /// Push the array `0x81` onto the stack.
-    pub const OP_PUSHNUM_NEG1: All = All {code: 0x4f};
-    /// Synonym for OP_RETURN.
-    pub const OP_RESERVED: All = All {code: 0x50};
-    /// Push the array `0x01` onto the stack.
-    pub const OP_PUSHNUM_1: All = All {code: 0x51};
-    /// Push the array `0x02` onto the stack.
-    pub const OP_PUSHNUM_2: All = All {code: 0x52};
-    /// Push the array `0x03` onto the stack.
-    pub const OP_PUSHNUM_3: All = All {code: 0x53};
-    /// Push the array `0x04` onto the stack.
-    pub const OP_PUSHNUM_4: All = All {code: 0x54};
-    /// Push the array `0x05` onto the stack.
-    pub const OP_PUSHNUM_5: All = All {code: 0x55};
-    /// Push the array `0x06` onto the stack.
-    pub const OP_PUSHNUM_6: All = All {code: 0x56};
-    /// Push the array `0x07` onto the stack.
-    pub const OP_PUSHNUM_7: All = All {code: 0x57};
-    /// Push the array `0x08` onto the stack.
-    pub const OP_PUSHNUM_8: All = All {code: 0x58};
-    /// Push the array `0x09` onto the stack.
-    pub const OP_PUSHNUM_9: All = All {code: 0x59};
-    /// Push the array `0x0a` onto the stack.
-    pub const OP_PUSHNUM_10: All = All {code: 0x5a};
-    /// Push the array `0x0b` onto the stack.
-    pub const OP_PUSHNUM_11: All = All {code: 0x5b};
-    /// Push the array `0x0c` onto the stack.
-    pub const OP_PUSHNUM_12: All = All {code: 0x5c};
-    /// Push the array `0x0d` onto the stack.
-    pub const OP_PUSHNUM_13: All = All {code: 0x5d};
-    /// Push the array `0x0e` onto the stack.
-    pub const OP_PUSHNUM_14: All = All {code: 0x5e};
-    /// Push the array `0x0f` onto the stack.
-    pub const OP_PUSHNUM_15: All = All {code: 0x5f};
-    /// Push the array `0x10` onto the stack.
-    pub const OP_PUSHNUM_16: All = All {code: 0x60};
-    /// Does nothing.
-    pub const OP_NOP: All = All {code: 0x61};
-    /// Synonym for OP_RETURN.
-    pub const OP_VER: All = All {code: 0x62};
-    /// Pop and execute the next statements if a nonzero element was popped.
-    pub const OP_IF: All = All {code: 0x63};
-    /// Pop and execute the next statements if a zero element was popped.
-    pub const OP_NOTIF: All = All {code: 0x64};
-    /// Fail the script unconditionally, does not even need to be executed.
-    pub const OP_VERIF: All = All {code: 0x65};
-    /// Fail the script unconditionally, does not even need to be executed.
-    pub const OP_VERNOTIF: All = All {code: 0x66};
-    /// Execute statements if those after the previous OP_IF were not, and vice-versa.
-    /// If there is no previous OP_IF, this acts as a RETURN.
-    pub const OP_ELSE: All = All {code: 0x67};
-    /// Pop and execute the next statements if a zero element was popped.
-    pub const OP_ENDIF: All = All {code: 0x68};
-    /// If the top value is zero or the stack is empty, fail; otherwise, pop the stack.
-    pub const OP_VERIFY: All = All {code: 0x69};
-    /// Fail the script immediately. (Must be executed.).
-    pub const OP_RETURN: All = All {code: 0x6a};
-    /// Pop one element from the main stack onto the alt stack.
-    pub const OP_TOALTSTACK: All = All {code: 0x6b};
-    /// Pop one element from the alt stack onto the main stack.
-    pub const OP_FROMALTSTACK: All = All {code: 0x6c};
-    /// Drops the top two stack items.
-    pub const OP_2DROP: All = All {code: 0x6d};
-    /// Duplicates the top two stack items as AB -> ABAB.
-    pub const OP_2DUP: All = All {code: 0x6e};
-    /// Duplicates the two three stack items as ABC -> ABCABC.
-    pub const OP_3DUP: All = All {code: 0x6f};
-    /// Copies the two stack items of items two spaces back to
-    /// the front, as xxAB -> ABxxAB.
-    pub const OP_2OVER: All = All {code: 0x70};
-    /// Moves the two stack items four spaces back to the front,
-    /// as xxxxAB -> ABxxxx.
-    pub const OP_2ROT: All = All {code: 0x71};
-    /// Swaps the top two pairs, as ABCD -> CDAB.
-    pub const OP_2SWAP: All = All {code: 0x72};
-    /// Duplicate the top stack element unless it is zero.
-    pub const OP_IFDUP: All = All {code: 0x73};
-    /// Push the current number of stack items onto the stack.
-    pub const OP_DEPTH: All = All {code: 0x74};
-    /// Drops the top stack item.
-    pub const OP_DROP: All = All {code: 0x75};
-    /// Duplicates the top stack item.
-    pub const OP_DUP: All = All {code: 0x76};
-    /// Drops the second-to-top stack item.
-    pub const OP_NIP: All = All {code: 0x77};
-    /// Copies the second-to-top stack item, as xA -> AxA.
-    pub const OP_OVER: All = All {code: 0x78};
-    /// Pop the top stack element as N. Copy the Nth stack element to the top.
-    pub const OP_PICK: All = All {code: 0x79};
-    /// Pop the top stack element as N. Move the Nth stack element to the top.
-    pub const OP_ROLL: All = All {code: 0x7a};
-    /// Rotate the top three stack items, as [top next1 next2] -> [next2 top next1].
-    pub const OP_ROT: All = All {code: 0x7b};
-    /// Swap the top two stack items.
-    pub const OP_SWAP: All = All {code: 0x7c};
-    /// Copy the top stack item to before the second item, as [top next] -> [top next top].
-    pub const OP_TUCK: All = All {code: 0x7d};
-    /// Fail the script unconditionally, does not even need to be executed.
-    pub const OP_CAT: All = All {code: 0x7e};
-    /// Fail the script unconditionally, does not even need to be executed.
-    pub const OP_SUBSTR: All = All {code: 0x7f};
-    /// Fail the script unconditionally, does not even need to be executed.
-    pub const OP_LEFT: All = All {code: 0x80};
-    /// Fail the script unconditionally, does not even need to be executed.
-    pub const OP_RIGHT: All = All {code: 0x81};
-    /// Pushes the length of the top stack item onto the stack.
-    pub const OP_SIZE: All = All {code: 0x82};
-    /// Fail the script unconditionally, does not even need to be executed.
-    pub const OP_INVERT: All = All {code: 0x83};
-    /// Fail the script unconditionally, does not even need to be executed.
-    pub const OP_AND: All = All {code: 0x84};
-    /// Fail the script unconditionally, does not even need to be executed.
-    pub const OP_OR: All = All {code: 0x85};
-    /// Fail the script unconditionally, does not even need to be executed.
-    pub const OP_XOR: All = All {code: 0x86};
-    /// Pushes 1 if the inputs are exactly equal, 0 otherwise.
-    pub const OP_EQUAL: All = All {code: 0x87};
-    /// Returns success if the inputs are exactly equal, failure otherwise.
-    pub const OP_EQUALVERIFY: All = All {code: 0x88};
-    /// Synonym for OP_RETURN.
-    pub const OP_RESERVED1: All = All {code: 0x89};
-    /// Synonym for OP_RETURN.
-    pub const OP_RESERVED2: All = All {code: 0x8a};
-    /// Increment the top stack element in place.
-    pub const OP_1ADD: All = All {code: 0x8b};
-    /// Decrement the top stack element in place.
-    pub const OP_1SUB: All = All {code: 0x8c};
-    /// Fail the script unconditionally, does not even need to be executed.
-    pub const OP_2MUL: All = All {code: 0x8d};
-    /// Fail the script unconditionally, does not even need to be executed.
-    pub const OP_2DIV: All = All {code: 0x8e};
-    /// Multiply the top stack item by -1 in place.
-    pub const OP_NEGATE: All = All {code: 0x8f};
-    /// Absolute value the top stack item in place.
-    pub const OP_ABS: All = All {code: 0x90};
-    /// Map 0 to 1 and everything else to 0, in place.
-    pub const OP_NOT: All = All {code: 0x91};
-    /// Map 0 to 0 and everything else to 1, in place.
-    pub const OP_0NOTEQUAL: All = All {code: 0x92};
-    /// Pop two stack items and push their sum.
-    pub const OP_ADD: All = All {code: 0x93};
-    /// Pop two stack items and push the second minus the top.
-    pub const OP_SUB: All = All {code: 0x94};
-    /// Fail the script unconditionally, does not even need to be executed.
-    pub const OP_MUL: All = All {code: 0x95};
-    /// Fail the script unconditionally, does not even need to be executed.
-    pub const OP_DIV: All = All {code: 0x96};
-    /// Fail the script unconditionally, does not even need to be executed.
-    pub const OP_MOD: All = All {code: 0x97};
-    /// Fail the script unconditionally, does not even need to be executed.
-    pub const OP_LSHIFT: All = All {code: 0x98};
-    /// Fail the script unconditionally, does not even need to be executed.
-    pub const OP_RSHIFT: All = All {code: 0x99};
-    /// Pop the top two stack items and push 1 if both are nonzero, else push 0.
-    pub const OP_BOOLAND: All = All {code: 0x9a};
-    /// Pop the top two stack items and push 1 if either is nonzero, else push 0.
-    pub const OP_BOOLOR: All = All {code: 0x9b};
-    /// Pop the top two stack items and push 1 if both are numerically equal, else push 0.
-    pub const OP_NUMEQUAL: All = All {code: 0x9c};
-    /// Pop the top two stack items and return success if both are numerically equal, else return failure.
-    pub const OP_NUMEQUALVERIFY: All = All {code: 0x9d};
-    /// Pop the top two stack items and push 0 if both are numerically equal, else push 1.
-    pub const OP_NUMNOTEQUAL: All = All {code: 0x9e};
-    /// Pop the top two items; push 1 if the second is less than the top, 0 otherwise.
-    pub const OP_LESSTHAN : All = All {code: 0x9f};
-    /// Pop the top two items; push 1 if the second is greater than the top, 0 otherwise.
-    pub const OP_GREATERTHAN : All = All {code: 0xa0};
-    /// Pop the top two items; push 1 if the second is <= the top, 0 otherwise.
-    pub const OP_LESSTHANOREQUAL : All = All {code: 0xa1};
-    /// Pop the top two items; push 1 if the second is >= the top, 0 otherwise.
-    pub const OP_GREATERTHANOREQUAL : All = All {code: 0xa2};
-    /// Pop the top two items; push the smaller.
-    pub const OP_MIN: All = All {code: 0xa3};
-    /// Pop the top two items; push the larger.
-    pub const OP_MAX: All = All {code: 0xa4};
-    /// Pop the top three items; if the top is >= the second and < the third, push 1, otherwise push 0.
-    pub const OP_WITHIN: All = All {code: 0xa5};
-    /// Pop the top stack item and push its RIPEMD160 hash.
-    pub const OP_RIPEMD160: All = All {code: 0xa6};
-    /// Pop the top stack item and push its SHA1 hash.
-    pub const OP_SHA1: All = All {code: 0xa7};
-    /// Pop the top stack item and push its SHA256 hash.
-    pub const OP_SHA256: All = All {code: 0xa8};
-    /// Pop the top stack item and push its RIPEMD(SHA256) hash.
-    pub const OP_HASH160: All = All {code: 0xa9};
-    /// Pop the top stack item and push its SHA256(SHA256) hash.
-    pub const OP_HASH256: All = All {code: 0xaa};
-    /// Ignore this and everything preceding when deciding what to sign when signature-checking.
-    pub const OP_CODESEPARATOR: All = All {code: 0xab};
-    /// <https://en.bitcoin.it/wiki/OP_CHECKSIG> pushing 1/0 for success/failure.
-    pub const OP_CHECKSIG: All = All {code: 0xac};
-    /// <https://en.bitcoin.it/wiki/OP_CHECKSIG> returning success/failure.
-    pub const OP_CHECKSIGVERIFY: All = All {code: 0xad};
-    /// Pop N, N pubkeys, M, M signatures, a dummy (due to bug in reference code), and verify that all M signatures are valid.
-    /// Push 1 for "all valid", 0 otherwise.
-    pub const OP_CHECKMULTISIG: All = All {code: 0xae};
-    /// Like the above but return success/failure.
-    pub const OP_CHECKMULTISIGVERIFY: All = All {code: 0xaf};
-    /// Does nothing.
-    pub const OP_NOP1: All = All {code: 0xb0};
-    /// <https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki>
-    pub const OP_CLTV: All = All {code: 0xb1};
-    /// <https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki>
-    pub const OP_CSV: All = All {code: 0xb2};
-    /// Does nothing.
-    pub const OP_NOP4: All = All {code: 0xb3};
-    /// Does nothing.
-    pub const OP_NOP5: All = All {code: 0xb4};
-    /// Does nothing.
-    pub const OP_NOP6: All = All {code: 0xb5};
-    /// Does nothing.
-    pub const OP_NOP7: All = All {code: 0xb6};
-    /// Does nothing.
-    pub const OP_NOP8: All = All {code: 0xb7};
-    /// Does nothing.
-    pub const OP_NOP9: All = All {code: 0xb8};
-    /// Does nothing.
-    pub const OP_NOP10: All = All {code: 0xb9};
-    // Every other opcode acts as OP_RETURN
-    /// OP_CHECKSIGADD post tapscript.
-    pub const OP_CHECKSIGADD: All = All {code: 0xba};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_187: All = All {code: 0xbb};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_188: All = All {code: 0xbc};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_189: All = All {code: 0xbd};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_190: All = All {code: 0xbe};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_191: All = All {code: 0xbf};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_192: All = All {code: 0xc0};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_193: All = All {code: 0xc1};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_194: All = All {code: 0xc2};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_195: All = All {code: 0xc3};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_196: All = All {code: 0xc4};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_197: All = All {code: 0xc5};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_198: All = All {code: 0xc6};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_199: All = All {code: 0xc7};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_200: All = All {code: 0xc8};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_201: All = All {code: 0xc9};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_202: All = All {code: 0xca};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_203: All = All {code: 0xcb};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_204: All = All {code: 0xcc};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_205: All = All {code: 0xcd};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_206: All = All {code: 0xce};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_207: All = All {code: 0xcf};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_208: All = All {code: 0xd0};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_209: All = All {code: 0xd1};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_210: All = All {code: 0xd2};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_211: All = All {code: 0xd3};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_212: All = All {code: 0xd4};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_213: All = All {code: 0xd5};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_214: All = All {code: 0xd6};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_215: All = All {code: 0xd7};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_216: All = All {code: 0xd8};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_217: All = All {code: 0xd9};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_218: All = All {code: 0xda};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_219: All = All {code: 0xdb};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_220: All = All {code: 0xdc};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_221: All = All {code: 0xdd};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_222: All = All {code: 0xde};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_223: All = All {code: 0xdf};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_224: All = All {code: 0xe0};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_225: All = All {code: 0xe1};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_226: All = All {code: 0xe2};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_227: All = All {code: 0xe3};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_228: All = All {code: 0xe4};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_229: All = All {code: 0xe5};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_230: All = All {code: 0xe6};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_231: All = All {code: 0xe7};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_232: All = All {code: 0xe8};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_233: All = All {code: 0xe9};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_234: All = All {code: 0xea};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_235: All = All {code: 0xeb};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_236: All = All {code: 0xec};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_237: All = All {code: 0xed};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_238: All = All {code: 0xee};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_239: All = All {code: 0xef};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_240: All = All {code: 0xf0};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_241: All = All {code: 0xf1};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_242: All = All {code: 0xf2};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_243: All = All {code: 0xf3};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_244: All = All {code: 0xf4};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_245: All = All {code: 0xf5};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_246: All = All {code: 0xf6};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_247: All = All {code: 0xf7};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_248: All = All {code: 0xf8};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_249: All = All {code: 0xf9};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_250: All = All {code: 0xfa};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_251: All = All {code: 0xfb};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_252: All = All {code: 0xfc};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_253: All = All {code: 0xfd};
-    /// Synonym for OP_RETURN.
-    pub const OP_RETURN_254: All = All {code: 0xfe};
-    /// Synonym for OP_RETURN.
-    pub const OP_INVALIDOPCODE: All = All {code: 0xff};
-}
+macro_rules! all_opcodes {
+    ($($op:ident => $val:expr, $doc:expr);*) => {
+        // private import so we don't have to use `all::OP_FOO` in this file.
+
+        /// Enables wildcard imports to bring into scope all opcodes and nothing else.
+        ///
+        /// The `all` module is provided so one can use a wildcard import `use bitcoin::opcodes::all::*` to
+        /// get all the `OP_FOO` opcodes without getting other types defined in `opcodes` (e.g. `All`, `Class`).
+        ///
+        /// This module is guaranteed to never contain anything except opcode constants and all opcode
+        /// constants are guaranteed to begin with OP_.
+        pub mod all {
+            use super::All;
+                $(
+                    #[doc = $doc]
+                    pub const $op: All = All { code: $val};
+                )*
+        }
 
-impl fmt::Display for All {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.write_str("OP_")?;
-        match *self {
-            All {code: x} if x <= 75 => write!(f, "PUSHBYTES_{}", self.code),
-            OP_PUSHDATA1 => write!(f, "PUSHDATA1"),
-            OP_PUSHDATA2 => write!(f, "PUSHDATA2"),
-            OP_PUSHDATA4 => write!(f, "PUSHDATA4"),
-            OP_PUSHNUM_NEG1 => write!(f, "PUSHNUM_NEG1"),
-            OP_RESERVED => write!(f, "RESERVED"),
-            All {code: x} if x >= OP_PUSHNUM_1.code && x <= OP_PUSHNUM_16.code => write!(f, "PUSHNUM_{}", x - OP_PUSHNUM_1.code + 1),
-            OP_NOP => write!(f, "NOP"),
-            OP_VER => write!(f, "VER"),
-            OP_IF => write!(f, "IF"),
-            OP_NOTIF => write!(f, "NOTIF"),
-            OP_VERIF => write!(f, "VERIF"),
-            OP_VERNOTIF => write!(f, "VERNOTIF"),
-            OP_ELSE => write!(f, "ELSE"),
-            OP_ENDIF => write!(f, "ENDIF"),
-            OP_VERIFY => write!(f, "VERIFY"),
-            OP_RETURN => write!(f, "RETURN"),
-            OP_TOALTSTACK => write!(f, "TOALTSTACK"),
-            OP_FROMALTSTACK => write!(f, "FROMALTSTACK"),
-            OP_2DROP => write!(f, "2DROP"),
-            OP_2DUP => write!(f, "2DUP"),
-            OP_3DUP => write!(f, "3DUP"),
-            OP_2OVER => write!(f, "2OVER"),
-            OP_2ROT => write!(f, "2ROT"),
-            OP_2SWAP => write!(f, "2SWAP"),
-            OP_IFDUP => write!(f, "IFDUP"),
-            OP_DEPTH => write!(f, "DEPTH"),
-            OP_DROP => write!(f, "DROP"),
-            OP_DUP => write!(f, "DUP"),
-            OP_NIP => write!(f, "NIP"),
-            OP_OVER => write!(f, "OVER"),
-            OP_PICK => write!(f, "PICK"),
-            OP_ROLL => write!(f, "ROLL"),
-            OP_ROT => write!(f, "ROT"),
-            OP_SWAP => write!(f, "SWAP"),
-            OP_TUCK => write!(f, "TUCK"),
-            OP_CAT => write!(f, "CAT"),
-            OP_SUBSTR => write!(f, "SUBSTR"),
-            OP_LEFT => write!(f, "LEFT"),
-            OP_RIGHT => write!(f, "RIGHT"),
-            OP_SIZE => write!(f, "SIZE"),
-            OP_INVERT => write!(f, "INVERT"),
-            OP_AND => write!(f, "AND"),
-            OP_OR => write!(f, "OR"),
-            OP_XOR => write!(f, "XOR"),
-            OP_EQUAL => write!(f, "EQUAL"),
-            OP_EQUALVERIFY => write!(f, "EQUALVERIFY"),
-            OP_RESERVED1 => write!(f, "RESERVED1"),
-            OP_RESERVED2 => write!(f, "RESERVED2"),
-            OP_1ADD => write!(f, "1ADD"),
-            OP_1SUB => write!(f, "1SUB"),
-            OP_2MUL => write!(f, "2MUL"),
-            OP_2DIV => write!(f, "2DIV"),
-            OP_NEGATE => write!(f, "NEGATE"),
-            OP_ABS => write!(f, "ABS"),
-            OP_NOT => write!(f, "NOT"),
-            OP_0NOTEQUAL => write!(f, "0NOTEQUAL"),
-            OP_ADD => write!(f, "ADD"),
-            OP_SUB => write!(f, "SUB"),
-            OP_MUL => write!(f, "MUL"),
-            OP_DIV => write!(f, "DIV"),
-            OP_MOD => write!(f, "MOD"),
-            OP_LSHIFT => write!(f, "LSHIFT"),
-            OP_RSHIFT => write!(f, "RSHIFT"),
-            OP_BOOLAND => write!(f, "BOOLAND"),
-            OP_BOOLOR => write!(f, "BOOLOR"),
-            OP_NUMEQUAL => write!(f, "NUMEQUAL"),
-            OP_NUMEQUALVERIFY => write!(f, "NUMEQUALVERIFY"),
-            OP_NUMNOTEQUAL => write!(f, "NUMNOTEQUAL"),
-            OP_LESSTHAN => write!(f, "LESSTHAN"),
-            OP_GREATERTHAN => write!(f, "GREATERTHAN"),
-            OP_LESSTHANOREQUAL => write!(f, "LESSTHANOREQUAL"),
-            OP_GREATERTHANOREQUAL => write!(f, "GREATERTHANOREQUAL"),
-            OP_MIN => write!(f, "MIN"),
-            OP_MAX => write!(f, "MAX"),
-            OP_WITHIN => write!(f, "WITHIN"),
-            OP_RIPEMD160 => write!(f, "RIPEMD160"),
-            OP_SHA1 => write!(f, "SHA1"),
-            OP_SHA256 => write!(f, "SHA256"),
-            OP_HASH160 => write!(f, "HASH160"),
-            OP_HASH256 => write!(f, "HASH256"),
-            OP_CODESEPARATOR => write!(f, "CODESEPARATOR"),
-            OP_CHECKSIG => write!(f, "CHECKSIG"),
-            OP_CHECKSIGVERIFY => write!(f, "CHECKSIGVERIFY"),
-            OP_CHECKMULTISIG => write!(f, "CHECKMULTISIG"),
-            OP_CHECKMULTISIGVERIFY => write!(f, "CHECKMULTISIGVERIFY"),
-            OP_CLTV => write!(f, "CLTV"),
-            OP_CSV => write!(f, "CSV"),
-            All {code: x} if (OP_NOP1.code..=OP_NOP10.code).contains(&x) => write!(f, "NOP{}", x - OP_NOP1.code + 1),
-            OP_INVALIDOPCODE => write!(f, "INVALIDOPCODE"),
-            OP_CHECKSIGADD => write!(f, "CHECKSIGADD"),
-            All {code: x} => write!(f, "RETURN_{}", x),
+        impl fmt::Display for All {
+            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+                 match *self {
+                   $(
+                        $op => fmt::Display::fmt(stringify!($op), f),
+                    )+
+                }
+            }
         }
+
     }
 }
 
+all_opcodes! {
+    OP_PUSHBYTES_0 => 0x00, "Push an empty array onto the stack.";
+    OP_PUSHBYTES_1 => 0x01, "Push the next byte as an array onto the stack.";
+    OP_PUSHBYTES_2 => 0x02, "Push the next 2 bytes as an array onto the stack.";
+    OP_PUSHBYTES_3 => 0x03, "Push the next 3 bytes as an array onto the stack.";
+    OP_PUSHBYTES_4 => 0x04, "Push the next 4 bytes as an array onto the stack.";
+    OP_PUSHBYTES_5 => 0x05, "Push the next 5 bytes as an array onto the stack.";
+    OP_PUSHBYTES_6 => 0x06, "Push the next 6 bytes as an array onto the stack.";
+    OP_PUSHBYTES_7 => 0x07, "Push the next 7 bytes as an array onto the stack.";
+    OP_PUSHBYTES_8 => 0x08, "Push the next 8 bytes as an array onto the stack.";
+    OP_PUSHBYTES_9 => 0x09, "Push the next 9 bytes as an array onto the stack.";
+    OP_PUSHBYTES_10 => 0x0a, "Push the next 10 bytes as an array onto the stack.";
+    OP_PUSHBYTES_11 => 0x0b, "Push the next 11 bytes as an array onto the stack.";
+    OP_PUSHBYTES_12 => 0x0c, "Push the next 12 bytes as an array onto the stack.";
+    OP_PUSHBYTES_13 => 0x0d, "Push the next 13 bytes as an array onto the stack.";
+    OP_PUSHBYTES_14 => 0x0e, "Push the next 14 bytes as an array onto the stack.";
+    OP_PUSHBYTES_15 => 0x0f, "Push the next 15 bytes as an array onto the stack.";
+    OP_PUSHBYTES_16 => 0x10, "Push the next 16 bytes as an array onto the stack.";
+    OP_PUSHBYTES_17 => 0x11, "Push the next 17 bytes as an array onto the stack.";
+    OP_PUSHBYTES_18 => 0x12, "Push the next 18 bytes as an array onto the stack.";
+    OP_PUSHBYTES_19 => 0x13, "Push the next 19 bytes as an array onto the stack.";
+    OP_PUSHBYTES_20 => 0x14, "Push the next 20 bytes as an array onto the stack.";
+    OP_PUSHBYTES_21 => 0x15, "Push the next 21 bytes as an array onto the stack.";
+    OP_PUSHBYTES_22 => 0x16, "Push the next 22 bytes as an array onto the stack.";
+    OP_PUSHBYTES_23 => 0x17, "Push the next 23 bytes as an array onto the stack.";
+    OP_PUSHBYTES_24 => 0x18, "Push the next 24 bytes as an array onto the stack.";
+    OP_PUSHBYTES_25 => 0x19, "Push the next 25 bytes as an array onto the stack.";
+    OP_PUSHBYTES_26 => 0x1a, "Push the next 26 bytes as an array onto the stack.";
+    OP_PUSHBYTES_27 => 0x1b, "Push the next 27 bytes as an array onto the stack.";
+    OP_PUSHBYTES_28 => 0x1c, "Push the next 28 bytes as an array onto the stack.";
+    OP_PUSHBYTES_29 => 0x1d, "Push the next 29 bytes as an array onto the stack.";
+    OP_PUSHBYTES_30 => 0x1e, "Push the next 30 bytes as an array onto the stack.";
+    OP_PUSHBYTES_31 => 0x1f, "Push the next 31 bytes as an array onto the stack.";
+    OP_PUSHBYTES_32 => 0x20, "Push the next 32 bytes as an array onto the stack.";
+    OP_PUSHBYTES_33 => 0x21, "Push the next 33 bytes as an array onto the stack.";
+    OP_PUSHBYTES_34 => 0x22, "Push the next 34 bytes as an array onto the stack.";
+    OP_PUSHBYTES_35 => 0x23, "Push the next 35 bytes as an array onto the stack.";
+    OP_PUSHBYTES_36 => 0x24, "Push the next 36 bytes as an array onto the stack.";
+    OP_PUSHBYTES_37 => 0x25, "Push the next 37 bytes as an array onto the stack.";
+    OP_PUSHBYTES_38 => 0x26, "Push the next 38 bytes as an array onto the stack.";
+    OP_PUSHBYTES_39 => 0x27, "Push the next 39 bytes as an array onto the stack.";
+    OP_PUSHBYTES_40 => 0x28, "Push the next 40 bytes as an array onto the stack.";
+    OP_PUSHBYTES_41 => 0x29, "Push the next 41 bytes as an array onto the stack.";
+    OP_PUSHBYTES_42 => 0x2a, "Push the next 42 bytes as an array onto the stack.";
+    OP_PUSHBYTES_43 => 0x2b, "Push the next 43 bytes as an array onto the stack.";
+    OP_PUSHBYTES_44 => 0x2c, "Push the next 44 bytes as an array onto the stack.";
+    OP_PUSHBYTES_45 => 0x2d, "Push the next 45 bytes as an array onto the stack.";
+    OP_PUSHBYTES_46 => 0x2e, "Push the next 46 bytes as an array onto the stack.";
+    OP_PUSHBYTES_47 => 0x2f, "Push the next 47 bytes as an array onto the stack.";
+    OP_PUSHBYTES_48 => 0x30, "Push the next 48 bytes as an array onto the stack.";
+    OP_PUSHBYTES_49 => 0x31, "Push the next 49 bytes as an array onto the stack.";
+    OP_PUSHBYTES_50 => 0x32, "Push the next 50 bytes as an array onto the stack.";
+    OP_PUSHBYTES_51 => 0x33, "Push the next 51 bytes as an array onto the stack.";
+    OP_PUSHBYTES_52 => 0x34, "Push the next 52 bytes as an array onto the stack.";
+    OP_PUSHBYTES_53 => 0x35, "Push the next 53 bytes as an array onto the stack.";
+    OP_PUSHBYTES_54 => 0x36, "Push the next 54 bytes as an array onto the stack.";
+    OP_PUSHBYTES_55 => 0x37, "Push the next 55 bytes as an array onto the stack.";
+    OP_PUSHBYTES_56 => 0x38, "Push the next 56 bytes as an array onto the stack.";
+    OP_PUSHBYTES_57 => 0x39, "Push the next 57 bytes as an array onto the stack.";
+    OP_PUSHBYTES_58 => 0x3a, "Push the next 58 bytes as an array onto the stack.";
+    OP_PUSHBYTES_59 => 0x3b, "Push the next 59 bytes as an array onto the stack.";
+    OP_PUSHBYTES_60 => 0x3c, "Push the next 60 bytes as an array onto the stack.";
+    OP_PUSHBYTES_61 => 0x3d, "Push the next 61 bytes as an array onto the stack.";
+    OP_PUSHBYTES_62 => 0x3e, "Push the next 62 bytes as an array onto the stack.";
+    OP_PUSHBYTES_63 => 0x3f, "Push the next 63 bytes as an array onto the stack.";
+    OP_PUSHBYTES_64 => 0x40, "Push the next 64 bytes as an array onto the stack.";
+    OP_PUSHBYTES_65 => 0x41, "Push the next 65 bytes as an array onto the stack.";
+    OP_PUSHBYTES_66 => 0x42, "Push the next 66 bytes as an array onto the stack.";
+    OP_PUSHBYTES_67 => 0x43, "Push the next 67 bytes as an array onto the stack.";
+    OP_PUSHBYTES_68 => 0x44, "Push the next 68 bytes as an array onto the stack.";
+    OP_PUSHBYTES_69 => 0x45, "Push the next 69 bytes as an array onto the stack.";
+    OP_PUSHBYTES_70 => 0x46, "Push the next 70 bytes as an array onto the stack.";
+    OP_PUSHBYTES_71 => 0x47, "Push the next 71 bytes as an array onto the stack.";
+    OP_PUSHBYTES_72 => 0x48, "Push the next 72 bytes as an array onto the stack.";
+    OP_PUSHBYTES_73 => 0x49, "Push the next 73 bytes as an array onto the stack.";
+    OP_PUSHBYTES_74 => 0x4a, "Push the next 74 bytes as an array onto the stack.";
+    OP_PUSHBYTES_75 => 0x4b, "Push the next 75 bytes as an array onto the stack.";
+    OP_PUSHDATA1 => 0x4c, "Read the next byte as N; push the next N bytes as an array onto the stack.";
+    OP_PUSHDATA2 => 0x4d, "Read the next 2 bytes as N; push the next N bytes as an array onto the stack.";
+    OP_PUSHDATA4 => 0x4e, "Read the next 4 bytes as N; push the next N bytes as an array onto the stack.";
+    OP_PUSHNUM_NEG1 => 0x4f, "Push the array `0x81` onto the stack.";
+    OP_RESERVED => 0x50, "Synonym for OP_RETURN.";
+    OP_PUSHNUM_1 => 0x51, "Push the array `0x01` onto the stack.";
+    OP_PUSHNUM_2 => 0x52, "the array `0x02` onto the stack.";
+    OP_PUSHNUM_3 => 0x53, "Push the array `0x03` onto the stack.";
+    OP_PUSHNUM_4 => 0x54, "Push the array `0x04` onto the stack.";
+    OP_PUSHNUM_5 => 0x55, "Push the array `0x05` onto the stack.";
+    OP_PUSHNUM_6 => 0x56, "Push the array `0x06` onto the stack.";
+    OP_PUSHNUM_7 => 0x57, "Push the array `0x07` onto the stack.";
+    OP_PUSHNUM_8 => 0x58, "Push the array `0x08` onto the stack.";
+    OP_PUSHNUM_9 => 0x59, "Push the array `0x09` onto the stack.";
+    OP_PUSHNUM_10 => 0x5a, "Push the array `0x0a` onto the stack.";
+    OP_PUSHNUM_11 => 0x5b, "Push the array `0x0b` onto the stack.";
+    OP_PUSHNUM_12 => 0x5c, "Push the array `0x0c` onto the stack.";
+    OP_PUSHNUM_13 => 0x5d, "Push the array `0x0d` onto the stack.";
+    OP_PUSHNUM_14 => 0x5e, "Push the array `0x0e` onto the stack.";
+    OP_PUSHNUM_15 => 0x5f, "Push the array `0x0f` onto the stack.";
+    OP_PUSHNUM_16 => 0x60, "Push the array `0x10` onto the stack.";
+    OP_NOP => 0x61, "Does nothing.";
+    OP_VER => 0x62, "Synonym for OP_RETURN.";
+    OP_IF => 0x63, "Pop and execute the next statements if a nonzero element was popped.";
+    OP_NOTIF => 0x64, "Pop and execute the next statements if a zero element was popped.";
+    OP_VERIF => 0x65, "Fail the script unconditionally, does not even need to be executed.";
+    OP_VERNOTIF => 0x66, "Fail the script unconditionally, does not even need to be executed.";
+    OP_ELSE => 0x67, "Execute statements if those after the previous OP_IF were not, and vice-versa. \
+             If there is no previous OP_IF, this acts as a RETURN.";
+    OP_ENDIF => 0x68, "Pop and execute the next statements if a zero element was popped.";
+    OP_VERIFY => 0x69, "If the top value is zero or the stack is empty, fail; otherwise, pop the stack.";
+    OP_RETURN => 0x6a, "Fail the script immediately. (Must be executed.).";
+    OP_TOALTSTACK => 0x6b, "Pop one element from the main stack onto the alt stack.";
+    OP_FROMALTSTACK => 0x6c, "Pop one element from the alt stack onto the main stack.";
+    OP_2DROP => 0x6d, "Drops the top two stack items.";
+    OP_2DUP => 0x6e, "Duplicates the top two stack items as AB -> ABAB.";
+    OP_3DUP => 0x6f, "Duplicates the two three stack items as ABC -> ABCABC.";
+    OP_2OVER => 0x70, "Copies the two stack items of items two spaces back to the front, as xxAB -> ABxxAB.";
+    OP_2ROT => 0x71, "Moves the two stack items four spaces back to the front, as xxxxAB -> ABxxxx.";
+    OP_2SWAP => 0x72, "Swaps the top two pairs, as ABCD -> CDAB.";
+    OP_IFDUP => 0x73, "Duplicate the top stack element unless it is zero.";
+    OP_DEPTH => 0x74, "Push the current number of stack items onto the stack.";
+    OP_DROP => 0x75, "Drops the top stack item.";
+    OP_DUP => 0x76, "Duplicates the top stack item.";
+    OP_NIP => 0x77, "Drops the second-to-top stack item.";
+    OP_OVER => 0x78, "Copies the second-to-top stack item, as xA -> AxA.";
+    OP_PICK => 0x79, "Pop the top stack element as N. Copy the Nth stack element to the top.";
+    OP_ROLL => 0x7a, "Pop the top stack element as N. Move the Nth stack element to the top.";
+    OP_ROT => 0x7b, "Rotate the top three stack items, as [top next1 next2] -> [next2 top next1].";
+    OP_SWAP => 0x7c, "Swap the top two stack items.";
+    OP_TUCK => 0x7d, "Copy the top stack item to before the second item, as [top next] -> [top next top].";
+    OP_CAT => 0x7e, "Fail the script unconditionally, does not even need to be executed.";
+    OP_SUBSTR => 0x7f, "Fail the script unconditionally, does not even need to be executed.";
+    OP_LEFT => 0x80, "Fail the script unconditionally, does not even need to be executed.";
+    OP_RIGHT => 0x81, "Fail the script unconditionally, does not even need to be executed.";
+    OP_SIZE => 0x82, "Pushes the length of the top stack item onto the stack.";
+    OP_INVERT => 0x83, "Fail the script unconditionally, does not even need to be executed.";
+    OP_AND => 0x84, "Fail the script unconditionally, does not even need to be executed.";
+    OP_OR => 0x85, "Fail the script unconditionally, does not even need to be executed.";
+    OP_XOR => 0x86, "Fail the script unconditionally, does not even need to be executed.";
+    OP_EQUAL => 0x87, "Pushes 1 if the inputs are exactly equal, 0 otherwise.";
+    OP_EQUALVERIFY => 0x88, "Returns success if the inputs are exactly equal, failure otherwise.";
+    OP_RESERVED1 => 0x89, "Synonym for OP_RETURN.";
+    OP_RESERVED2 => 0x8a, "Synonym for OP_RETURN.";
+    OP_1ADD => 0x8b, "Increment the top stack element in place.";
+    OP_1SUB => 0x8c, "Decrement the top stack element in place.";
+    OP_2MUL => 0x8d, "Fail the script unconditionally, does not even need to be executed.";
+    OP_2DIV => 0x8e, "Fail the script unconditionally, does not even need to be executed.";
+    OP_NEGATE => 0x8f, "Multiply the top stack item by -1 in place.";
+    OP_ABS => 0x90, "Absolute value the top stack item in place.";
+    OP_NOT => 0x91, "Map 0 to 1 and everything else to 0, in place.";
+    OP_0NOTEQUAL => 0x92, "Map 0 to 0 and everything else to 1, in place.";
+    OP_ADD => 0x93, "Pop two stack items and push their sum.";
+    OP_SUB => 0x94, "Pop two stack items and push the second minus the top.";
+    OP_MUL => 0x95, "Fail the script unconditionally, does not even need to be executed.";
+    OP_DIV => 0x96, "Fail the script unconditionally, does not even need to be executed.";
+    OP_MOD => 0x97, "Fail the script unconditionally, does not even need to be executed.";
+    OP_LSHIFT => 0x98, "Fail the script unconditionally, does not even need to be executed.";
+    OP_RSHIFT => 0x99, "Fail the script unconditionally, does not even need to be executed.";
+    OP_BOOLAND => 0x9a, "Pop the top two stack items and push 1 if both are nonzero, else push 0.";
+    OP_BOOLOR => 0x9b, "Pop the top two stack items and push 1 if either is nonzero, else push 0.";
+    OP_NUMEQUAL => 0x9c, "Pop the top two stack items and push 1 if both are numerically equal, else push 0.";
+    OP_NUMEQUALVERIFY => 0x9d, "Pop the top two stack items and return success if both are numerically equal, else return failure.";
+    OP_NUMNOTEQUAL => 0x9e, "Pop the top two stack items and push 0 if both are numerically equal, else push 1.";
+    OP_LESSTHAN  => 0x9f, "Pop the top two items; push 1 if the second is less than the top, 0 otherwise.";
+    OP_GREATERTHAN  => 0xa0, "Pop the top two items; push 1 if the second is greater than the top, 0 otherwise.";
+    OP_LESSTHANOREQUAL  => 0xa1, "Pop the top two items; push 1 if the second is <= the top, 0 otherwise.";
+    OP_GREATERTHANOREQUAL  => 0xa2, "Pop the top two items; push 1 if the second is >= the top, 0 otherwise.";
+    OP_MIN => 0xa3, "Pop the top two items; push the smaller.";
+    OP_MAX => 0xa4, "Pop the top two items; push the larger.";
+    OP_WITHIN => 0xa5, "Pop the top three items; if the top is >= the second and < the third, push 1, otherwise push 0.";
+    OP_RIPEMD160 => 0xa6, "Pop the top stack item and push its RIPEMD160 hash.";
+    OP_SHA1 => 0xa7, "Pop the top stack item and push its SHA1 hash.";
+    OP_SHA256 => 0xa8, "Pop the top stack item and push its SHA256 hash.";
+    OP_HASH160 => 0xa9, "Pop the top stack item and push its RIPEMD(SHA256) hash.";
+    OP_HASH256 => 0xaa, "Pop the top stack item and push its SHA256(SHA256) hash.";
+    OP_CODESEPARATOR => 0xab, "Ignore this and everything preceding when deciding what to sign when signature-checking.";
+    OP_CHECKSIG => 0xac, "<https://en.bitcoin.it/wiki/OP_CHECKSIG> pushing 1/0 for success/failure.";
+    OP_CHECKSIGVERIFY => 0xad, "<https://en.bitcoin.it/wiki/OP_CHECKSIG> returning success/failure.";
+    OP_CHECKMULTISIG => 0xae, "Pop N, N pubkeys, M, M signatures, a dummy (due to bug in reference code), \
+                      and verify that all M signatures are valid. Push 1 for 'all valid', 0 otherwise.";
+    OP_CHECKMULTISIGVERIFY => 0xaf, "Like the above but return success/failure.";
+    OP_NOP1 => 0xb0, "Does nothing.";
+    OP_CLTV => 0xb1, "<https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki>";
+    OP_CSV => 0xb2, "<https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki>";
+    OP_NOP4 => 0xb3, "Does nothing.";
+    OP_NOP5 => 0xb4, "Does nothing.";
+    OP_NOP6 => 0xb5, "Does nothing.";
+    OP_NOP7 => 0xb6, "Does nothing.";
+    OP_NOP8 => 0xb7, "Does nothing.";
+    OP_NOP9 => 0xb8, "Does nothing.";
+    OP_NOP10 => 0xb9, "Does nothing.";
+    // Every other opcode acts as OP_RETURN
+    OP_CHECKSIGADD => 0xba, "OP_CHECKSIGADD post tapscript.";
+    OP_RETURN_187 => 0xbb, "Synonym for OP_RETURN.";
+    OP_RETURN_188 => 0xbc, "Synonym for OP_RETURN.";
+    OP_RETURN_189 => 0xbd, "Synonym for OP_RETURN.";
+    OP_RETURN_190 => 0xbe, "Synonym for OP_RETURN.";
+    OP_RETURN_191 => 0xbf, "Synonym for OP_RETURN.";
+    OP_RETURN_192 => 0xc0, "Synonym for OP_RETURN.";
+    OP_RETURN_193 => 0xc1, "Synonym for OP_RETURN.";
+    OP_RETURN_194 => 0xc2, "Synonym for OP_RETURN.";
+    OP_RETURN_195 => 0xc3, "Synonym for OP_RETURN.";
+    OP_RETURN_196 => 0xc4, "Synonym for OP_RETURN.";
+    OP_RETURN_197 => 0xc5, "Synonym for OP_RETURN.";
+    OP_RETURN_198 => 0xc6, "Synonym for OP_RETURN.";
+    OP_RETURN_199 => 0xc7, "Synonym for OP_RETURN.";
+    OP_RETURN_200 => 0xc8, "Synonym for OP_RETURN.";
+    OP_RETURN_201 => 0xc9, "Synonym for OP_RETURN.";
+    OP_RETURN_202 => 0xca, "Synonym for OP_RETURN.";
+    OP_RETURN_203 => 0xcb, "Synonym for OP_RETURN.";
+    OP_RETURN_204 => 0xcc, "Synonym for OP_RETURN.";
+    OP_RETURN_205 => 0xcd, "Synonym for OP_RETURN.";
+    OP_RETURN_206 => 0xce, "Synonym for OP_RETURN.";
+    OP_RETURN_207 => 0xcf, "Synonym for OP_RETURN.";
+    OP_RETURN_208 => 0xd0, "Synonym for OP_RETURN.";
+    OP_RETURN_209 => 0xd1, "Synonym for OP_RETURN.";
+    OP_RETURN_210 => 0xd2, "Synonym for OP_RETURN.";
+    OP_RETURN_211 => 0xd3, "Synonym for OP_RETURN.";
+    OP_RETURN_212 => 0xd4, "Synonym for OP_RETURN.";
+    OP_RETURN_213 => 0xd5, "Synonym for OP_RETURN.";
+    OP_RETURN_214 => 0xd6, "Synonym for OP_RETURN.";
+    OP_RETURN_215 => 0xd7, "Synonym for OP_RETURN.";
+    OP_RETURN_216 => 0xd8, "Synonym for OP_RETURN.";
+    OP_RETURN_217 => 0xd9, "Synonym for OP_RETURN.";
+    OP_RETURN_218 => 0xda, "Synonym for OP_RETURN.";
+    OP_RETURN_219 => 0xdb, "Synonym for OP_RETURN.";
+    OP_RETURN_220 => 0xdc, "Synonym for OP_RETURN.";
+    OP_RETURN_221 => 0xdd, "Synonym for OP_RETURN.";
+    OP_RETURN_222 => 0xde, "Synonym for OP_RETURN.";
+    OP_RETURN_223 => 0xdf, "Synonym for OP_RETURN.";
+    OP_RETURN_224 => 0xe0, "Synonym for OP_RETURN.";
+    OP_RETURN_225 => 0xe1, "Synonym for OP_RETURN.";
+    OP_RETURN_226 => 0xe2, "Synonym for OP_RETURN.";
+    OP_RETURN_227 => 0xe3, "Synonym for OP_RETURN.";
+    OP_RETURN_228 => 0xe4, "Synonym for OP_RETURN.";
+    OP_RETURN_229 => 0xe5, "Synonym for OP_RETURN.";
+    OP_RETURN_230 => 0xe6, "Synonym for OP_RETURN.";
+    OP_RETURN_231 => 0xe7, "Synonym for OP_RETURN.";
+    OP_RETURN_232 => 0xe8, "Synonym for OP_RETURN.";
+    OP_RETURN_233 => 0xe9, "Synonym for OP_RETURN.";
+    OP_RETURN_234 => 0xea, "Synonym for OP_RETURN.";
+    OP_RETURN_235 => 0xeb, "Synonym for OP_RETURN.";
+    OP_RETURN_236 => 0xec, "Synonym for OP_RETURN.";
+    OP_RETURN_237 => 0xed, "Synonym for OP_RETURN.";
+    OP_RETURN_238 => 0xee, "Synonym for OP_RETURN.";
+    OP_RETURN_239 => 0xef, "Synonym for OP_RETURN.";
+    OP_RETURN_240 => 0xf0, "Synonym for OP_RETURN.";
+    OP_RETURN_241 => 0xf1, "Synonym for OP_RETURN.";
+    OP_RETURN_242 => 0xf2, "Synonym for OP_RETURN.";
+    OP_RETURN_243 => 0xf3, "Synonym for OP_RETURN.";
+    OP_RETURN_244 => 0xf4, "Synonym for OP_RETURN.";
+    OP_RETURN_245 => 0xf5, "Synonym for OP_RETURN.";
+    OP_RETURN_246 => 0xf6, "Synonym for OP_RETURN.";
+    OP_RETURN_247 => 0xf7, "Synonym for OP_RETURN.";
+    OP_RETURN_248 => 0xf8, "Synonym for OP_RETURN.";
+    OP_RETURN_249 => 0xf9, "Synonym for OP_RETURN.";
+    OP_RETURN_250 => 0xfa, "Synonym for OP_RETURN.";
+    OP_RETURN_251 => 0xfb, "Synonym for OP_RETURN.";
+    OP_RETURN_252 => 0xfc, "Synonym for OP_RETURN.";
+    OP_RETURN_253 => 0xfd, "Synonym for OP_RETURN.";
+    OP_RETURN_254 => 0xfe, "Synonym for OP_RETURN.";
+    OP_INVALIDOPCODE => 0xff, "Synonym for OP_RETURN."
+}
+
 /// Classification context for the opcode.
 ///
 /// Some opcodes like [`OP_RESERVED`] abort the script in `ClassifyContext::Legacy` context,
@@ -885,6 +549,13 @@ macro_rules! roundtrip {
         }
     }
 
+    #[test]
+    fn formatting_works() {
+            let op = all::OP_NOP;
+            let s = format!("{:>10}", op);
+            assert_eq!(s, "    OP_NOP");
+    }
+
     #[test]
     fn classify_test() {
         let op174 = OP_CHECKMULTISIG;
diff --git a/bitcoin/src/psbt/macros.rs b/bitcoin/src/psbt/macros.rs
index dd820e81..ddfce8aa 100644
--- a/bitcoin/src/psbt/macros.rs
+++ b/bitcoin/src/psbt/macros.rs
@@ -2,7 +2,7 @@
 
 #[allow(unused_macros)]
 macro_rules! hex_psbt {
-    ($s:expr) => { <$crate::psbt::PartiallySignedTransaction>::deserialize(&<$crate::prelude::Vec<u8> as $crate::hashes::hex::FromHex>::from_hex($s).unwrap()) };
+    ($s:expr) => { $crate::consensus::deserialize::<$crate::psbt::PartiallySignedTransaction>(&<$crate::prelude::Vec<u8> as $crate::hashes::hex::FromHex>::from_hex($s).unwrap()) };
 }
 
 macro_rules! combine {
@@ -40,37 +40,29 @@ fn serialize(&self) -> $crate::prelude::Vec<u8> {
     };
 }
 
-macro_rules! impl_psbtmap_serialize {
+macro_rules! impl_psbtmap_consensus_encoding {
     ($thing:ty) => {
-        impl $crate::psbt::serialize::Serialize for $thing {
-            fn serialize(&self) -> Vec<u8> {
-                self.serialize_map()
-            }
-        }
-    };
-}
-
-macro_rules! impl_psbtmap_deserialize {
-    ($thing:ty) => {
-        impl $crate::psbt::serialize::Deserialize for $thing {
-            fn deserialize(bytes: &[u8]) -> Result<Self, $crate::consensus::encode::Error> {
-                let mut decoder = crate::io::Cursor::new(bytes);
-                Self::decode(&mut decoder)
+        impl $crate::consensus::Encodable for $thing {
+            fn consensus_encode<W: $crate::io::Write + ?Sized>(
+                &self,
+                w: &mut W,
+            ) -> Result<usize, $crate::io::Error> {
+                self.consensus_encode_map(w)
             }
         }
     };
 }
 
-macro_rules! impl_psbtmap_decoding {
+macro_rules! impl_psbtmap_consensus_decoding {
     ($thing:ty) => {
-        impl $thing {
-            pub(crate) fn decode<R: $crate::io::Read + ?Sized>(
+        impl $crate::consensus::Decodable for $thing {
+            fn consensus_decode<R: $crate::io::Read + ?Sized>(
                 r: &mut R,
             ) -> Result<Self, $crate::consensus::encode::Error> {
                 let mut rv: Self = core::default::Default::default();
 
                 loop {
-                    match $crate::psbt::raw::Pair::decode(r) {
+                    match $crate::consensus::Decodable::consensus_decode(r) {
                         Ok(pair) => rv.insert_pair(pair)?,
                         Err($crate::consensus::encode::Error::Psbt($crate::psbt::Error::NoMorePairs)) => return Ok(rv),
                         Err(e) => return Err(e),
@@ -81,11 +73,10 @@ pub(crate) fn decode<R: $crate::io::Read + ?Sized>(
     };
 }
 
-macro_rules! impl_psbtmap_ser_de_serialize {
+macro_rules! impl_psbtmap_consensus_enc_dec_oding {
     ($thing:ty) => {
-        impl_psbtmap_decoding!($thing);
-        impl_psbtmap_serialize!($thing);
-        impl_psbtmap_deserialize!($thing);
+        impl_psbtmap_consensus_decoding!($thing);
+        impl_psbtmap_consensus_encoding!($thing);
     };
 }
 
diff --git a/bitcoin/src/psbt/map/global.rs b/bitcoin/src/psbt/map/global.rs
index 6074bd65..eb317718 100644
--- a/bitcoin/src/psbt/map/global.rs
+++ b/bitcoin/src/psbt/map/global.rs
@@ -7,8 +7,8 @@
 use crate::io::{self, Cursor, Read};
 
 use crate::blockdata::transaction::Transaction;
+use crate::consensus::{encode, Encodable, Decodable};
 use crate::consensus::encode::MAX_VEC_SIZE;
-use crate::consensus::{encode, Decodable};
 use crate::psbt::map::Map;
 use crate::psbt::{raw, Error, PartiallySignedTransaction};
 use crate::bip32::{ExtendedPubKey, Fingerprint, DerivationPath, ChildNumber};
@@ -23,7 +23,7 @@
 const PSBT_GLOBAL_PROPRIETARY: u8 = 0xFC;
 
 impl Map for PartiallySignedTransaction {
-    fn get_pairs(&self) -> Vec<raw::Pair> {
+    fn get_pairs(&self) -> Result<Vec<raw::Pair>, io::Error> {
         let mut rv: Vec<raw::Pair> = Default::default();
 
         rv.push(raw::Pair {
@@ -35,10 +35,10 @@ fn get_pairs(&self) -> Vec<raw::Pair> {
                 // Manually serialized to ensure 0-input txs are serialized
                 // without witnesses.
                 let mut ret = Vec::new();
-                ret.extend(encode::serialize(&self.unsigned_tx.version));
-                ret.extend(encode::serialize(&self.unsigned_tx.input));
-                ret.extend(encode::serialize(&self.unsigned_tx.output));
-                ret.extend(encode::serialize(&self.unsigned_tx.lock_time));
+                self.unsigned_tx.version.consensus_encode(&mut ret)?;
+                self.unsigned_tx.input.consensus_encode(&mut ret)?;
+                self.unsigned_tx.output.consensus_encode(&mut ret)?;
+                self.unsigned_tx.lock_time.consensus_encode(&mut ret)?;
                 ret
             },
         });
@@ -83,12 +83,12 @@ fn get_pairs(&self) -> Vec<raw::Pair> {
             });
         }
 
-        rv
+        Ok(rv)
     }
 }
 
 impl PartiallySignedTransaction {
-    pub(crate) fn decode_global<R: io::Read + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
+    pub(crate) fn consensus_decode_global<R: io::Read + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
         let mut r = r.take(MAX_VEC_SIZE as u64);
         let mut tx: Option<Transaction> = None;
         let mut version: Option<u32> = None;
@@ -97,7 +97,7 @@ pub(crate) fn decode_global<R: io::Read + ?Sized>(r: &mut R) -> Result<Self, enc
         let mut proprietary: BTreeMap<raw::ProprietaryKey, Vec<u8>> = Default::default();
 
         loop {
-            match raw::Pair::decode(&mut r) {
+            match raw::Pair::consensus_decode(&mut r) {
                 Ok(pair) => {
                     match pair.key.type_value {
                         PSBT_GLOBAL_UNSIGNED_TX => {
diff --git a/bitcoin/src/psbt/map/input.rs b/bitcoin/src/psbt/map/input.rs
index fcc18538..b2cc5e23 100644
--- a/bitcoin/src/psbt/map/input.rs
+++ b/bitcoin/src/psbt/map/input.rs
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: CC0-1.0
 
 use crate::prelude::*;
+use crate::io;
 
 use core::fmt;
 use core::str::FromStr;
@@ -393,7 +394,7 @@ pub fn combine(&mut self, other: Self) {
 }
 
 impl Map for Input {
-    fn get_pairs(&self) -> Vec<raw::Pair> {
+    fn get_pairs(&self) -> Result<Vec<raw::Pair>, io::Error> {
         let mut rv: Vec<raw::Pair> = Default::default();
 
         impl_psbt_get_pair! {
@@ -485,11 +486,11 @@ fn get_pairs(&self) -> Vec<raw::Pair> {
             });
         }
 
-        rv
+        Ok(rv)
     }
 }
 
-impl_psbtmap_ser_de_serialize!(Input);
+impl_psbtmap_consensus_enc_dec_oding!(Input);
 
 fn psbt_insert_hash_pair<H>(
     map: &mut BTreeMap<H, Vec<u8>>,
diff --git a/bitcoin/src/psbt/map/mod.rs b/bitcoin/src/psbt/map/mod.rs
index ebc1c236..d22dc226 100644
--- a/bitcoin/src/psbt/map/mod.rs
+++ b/bitcoin/src/psbt/map/mod.rs
@@ -2,6 +2,9 @@
 
 use crate::prelude::*;
 
+use crate::io;
+
+use crate::consensus::encode;
 use crate::psbt::raw;
 
 mod global;
@@ -11,26 +14,18 @@
 pub use self::input::{Input, PsbtSighashType};
 pub use self::output::{Output, TapTree, IncompleteTapTree};
 
-use super::serialize::Serialize;
-
 /// A trait that describes a PSBT key-value map.
 pub(super) trait Map {
     /// Attempt to get all key-value pairs.
-    fn get_pairs(&self) -> Vec<raw::Pair>;
-
-    /// Serialize Psbt binary map data according to BIP-174 specification.
-    ///
-    /// <map> := <keypair>* 0x00
-    ///
-    /// Why is the separator here 0x00 instead of 0xff? The separator here is used to distinguish between each chunk of data.
-    /// A separator of 0x00 would mean that the unserializer can read it as a key length of 0, which would never occur with
-    /// actual keys. It can thus be used as a separator and allow for easier unserializer implementation.
-    fn serialize_map(&self) -> Vec<u8> {
-        let mut buf = Vec::new();
-        for pair in Map::get_pairs(self) {
-            buf.extend(&pair.serialize());
+    fn get_pairs(&self) -> Result<Vec<raw::Pair>, io::Error>;
+
+    /// Encodes map data with bitcoin consensus encoding.
+    fn consensus_encode_map<W: io::Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
+        let mut len = 0;
+        for pair in Map::get_pairs(self)? {
+            len += encode::Encodable::consensus_encode(&pair, w)?;
         }
-        buf.push(0x00_u8);
-        buf
+
+        Ok(len + encode::Encodable::consensus_encode(&0x00_u8, w)?)
     }
 }
diff --git a/bitcoin/src/psbt/map/output.rs b/bitcoin/src/psbt/map/output.rs
index d360ac4d..b321fbfd 100644
--- a/bitcoin/src/psbt/map/output.rs
+++ b/bitcoin/src/psbt/map/output.rs
@@ -4,6 +4,8 @@
 use core;
 use core::convert::TryFrom;
 
+use crate::io;
+
 use crate::blockdata::script::ScriptBuf;
 use crate::consensus::encode;
 use secp256k1::XOnlyPublicKey;
@@ -277,7 +279,7 @@ pub fn combine(&mut self, other: Self) {
 }
 
 impl Map for Output {
-    fn get_pairs(&self) -> Vec<raw::Pair> {
+    fn get_pairs(&self) -> Result<Vec<raw::Pair>, io::Error> {
         let mut rv: Vec<raw::Pair> = Default::default();
 
         impl_psbt_get_pair! {
@@ -318,8 +320,8 @@ fn get_pairs(&self) -> Vec<raw::Pair> {
             });
         }
 
-        rv
+        Ok(rv)
     }
 }
 
-impl_psbtmap_ser_de_serialize!(Output);
+impl_psbtmap_consensus_enc_dec_oding!(Output);
diff --git a/bitcoin/src/psbt/mod.rs b/bitcoin/src/psbt/mod.rs
index 42ba1e53..ba85ef4e 100644
--- a/bitcoin/src/psbt/mod.rs
+++ b/bitcoin/src/psbt/mod.rs
@@ -17,9 +17,11 @@
 use bitcoin_internals::write_err;
 
 use crate::{prelude::*, Amount};
+use crate::io;
 
 use crate::blockdata::script::ScriptBuf;
 use crate::blockdata::transaction::{Transaction, TxOut};
+use crate::consensus::{encode, Encodable, Decodable};
 use crate::bip32::{self, ExtendedPrivKey, ExtendedPubKey, KeySource};
 use crate::crypto::ecdsa;
 use crate::crypto::key::{PublicKey, PrivateKey};
@@ -37,6 +39,7 @@
 
 mod map;
 pub use self::map::{Input, Output, TapTree, PsbtSighashType, IncompleteTapTree};
+use self::map::Map;
 
 /// Partially signed transaction, commonly referred to as a PSBT.
 pub type Psbt = PartiallySignedTransaction;
@@ -748,7 +751,7 @@ mod display_from_str {
     use super::PartiallySignedTransaction;
     use core::fmt::{Display, Formatter, self};
     use core::str::FromStr;
-    use crate::consensus::encode::Error;
+    use crate::consensus::encode::{Error, self};
     use base64::display::Base64Display;
     use bitcoin_internals::write_err;
 
@@ -790,7 +793,7 @@ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
     #[cfg_attr(docsrs, doc(cfg(feature = "base64")))]
     impl Display for PartiallySignedTransaction {
         fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
-            write!(f, "{}", Base64Display::with_config(&self.serialize(), base64::STANDARD))
+            write!(f, "{}", Base64Display::with_config(&encode::serialize(self), base64::STANDARD))
         }
     }
 
@@ -800,7 +803,7 @@ impl FromStr for PartiallySignedTransaction {
 
         fn from_str(s: &str) -> Result<Self, Self::Err> {
             let data = base64::decode(s).map_err(PsbtParseError::Base64Encoding)?;
-            PartiallySignedTransaction::deserialize(&data).map_err(PsbtParseError::PsbtEncoding)
+            encode::deserialize(&data).map_err(PsbtParseError::PsbtEncoding)
         }
     }
 }
@@ -808,6 +811,72 @@ fn from_str(s: &str) -> Result<Self, Self::Err> {
 #[cfg_attr(docsrs, doc(cfg(feature = "base64")))]
 pub use self::display_from_str::PsbtParseError;
 
+impl Encodable for PartiallySignedTransaction {
+    fn consensus_encode<W: io::Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
+        let mut len = 0;
+        len += b"psbt".consensus_encode(w)?;
+
+        len += 0xff_u8.consensus_encode(w)?;
+
+        len += self.consensus_encode_map(w)?;
+
+        for i in &self.inputs {
+            len += i.consensus_encode(w)?;
+        }
+
+        for i in &self.outputs {
+            len += i.consensus_encode(w)?;
+        }
+
+        Ok(len)
+    }
+}
+
+impl Decodable for PartiallySignedTransaction {
+    fn consensus_decode_from_finite_reader<R: io::Read + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
+        let magic: [u8; 4] = Decodable::consensus_decode(r)?;
+
+        if *b"psbt" != magic {
+            return Err(Error::InvalidMagic.into());
+        }
+
+        if 0xff_u8 != u8::consensus_decode(r)? {
+            return Err(Error::InvalidSeparator.into());
+        }
+
+        let mut global = PartiallySignedTransaction::consensus_decode_global(r)?;
+        global.unsigned_tx_checks()?;
+
+        let inputs: Vec<Input> = {
+            let inputs_len: usize = global.unsigned_tx.input.len();
+
+            let mut inputs: Vec<Input> = Vec::with_capacity(inputs_len);
+
+            for _ in 0..inputs_len {
+                inputs.push(Decodable::consensus_decode(r)?);
+            }
+
+            inputs
+        };
+
+        let outputs: Vec<Output> = {
+            let outputs_len: usize = global.unsigned_tx.output.len();
+
+            let mut outputs: Vec<Output> = Vec::with_capacity(outputs_len);
+
+            for _ in 0..outputs_len {
+                outputs.push(Decodable::consensus_decode(r)?);
+            }
+
+            outputs
+        };
+
+        global.inputs = inputs;
+        global.outputs = outputs;
+        Ok(global)
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -816,7 +885,6 @@ mod tests {
     use crate::hashes::hex::FromHex;
     use crate::hashes::{sha256, hash160, Hash, ripemd160};
     use crate::hash_types::Txid;
-    use crate::psbt::serialize::{Serialize, Deserialize};
 
     use secp256k1::{Secp256k1, self};
     #[cfg(feature = "rand-std")]
@@ -825,6 +893,7 @@ mod tests {
     use crate::blockdata::script::ScriptBuf;
     use crate::blockdata::transaction::{Transaction, TxIn, TxOut, OutPoint, Sequence};
     use crate::network::constants::Network::Bitcoin;
+    use crate::consensus::encode::{deserialize, serialize, serialize_hex};
     use crate::bip32::{ChildNumber, ExtendedPrivKey, ExtendedPubKey, KeySource};
     use crate::psbt::map::{Output, Input};
     use crate::psbt::raw;
@@ -850,7 +919,7 @@ fn trivial_psbt() {
             inputs: vec![],
             outputs: vec![],
         };
-        assert_eq!(psbt.serialize_hex(), "70736274ff01000a0200000000000000000000");
+        assert_eq!(serialize_hex(&psbt), "70736274ff01000a0200000000000000000000");
     }
 
     #[test]
@@ -898,7 +967,7 @@ fn serialize_then_deserialize_output() {
             ..Default::default()
         };
 
-        let actual = Output::deserialize(&expected.serialize()).unwrap();
+        let actual: Output = deserialize(&serialize(&expected)).unwrap();
 
         assert_eq!(expected, actual);
     }
@@ -943,7 +1012,8 @@ fn serialize_then_deserialize_global() {
             outputs: vec![Output::default(), Output::default()],
         };
 
-        let actual: Psbt = Psbt::deserialize(&expected.serialize()).unwrap();
+        let actual: PartiallySignedTransaction = deserialize(&serialize(&expected)).unwrap();
+
         assert_eq!(expected, actual);
     }
 
@@ -957,7 +1027,7 @@ fn serialize_then_deserialize_psbtkvpair() {
             value: vec![69u8, 42u8, 4u8],
         };
 
-        let actual = raw::Pair::deserialize(&expected.serialize()).unwrap();
+        let actual: raw::Pair = deserialize(&serialize(&expected)).unwrap();
 
         assert_eq!(expected, actual);
     }
@@ -966,7 +1036,7 @@ fn serialize_then_deserialize_psbtkvpair() {
     fn deserialize_and_serialize_psbt_with_two_partial_sigs() {
         let hex = "70736274ff0100890200000001207ae985d787dfe6143d5c58fad79cc7105e0e799fcf033b7f2ba17e62d7b3200000000000ffffffff02563d03000000000022002019899534b9a011043c0dd57c3ff9a381c3522c5f27c6a42319085b56ca543a1d6adc020000000000220020618b47a07ebecca4e156edb1b9ea7c24bdee0139fc049237965ffdaf56d5ee73000000000001012b801a0600000000002200201148e93e9315e37dbed2121be5239257af35adc03ffdfc5d914b083afa44dab82202025fe7371376d53cf8a2783917c28bf30bd690b0a4d4a207690093ca2b920ee076473044022007e06b362e89912abd4661f47945430739b006a85d1b2a16c01dc1a4bd07acab022061576d7aa834988b7ab94ef21d8eebd996ea59ea20529a19b15f0c9cebe3d8ac01220202b3fe93530020a8294f0e527e33fbdff184f047eb6b5a1558a352f62c29972f8a473044022002787f926d6817504431ee281183b8119b6845bfaa6befae45e13b6d430c9d2f02202859f149a6cd26ae2f03a107e7f33c7d91730dade305fe077bae677b5d44952a01010547522102b3fe93530020a8294f0e527e33fbdff184f047eb6b5a1558a352f62c29972f8a21025fe7371376d53cf8a2783917c28bf30bd690b0a4d4a207690093ca2b920ee07652ae0001014752210283ef76537f2d58ae3aa3a4bd8ae41c3f230ccadffb1a0bd3ca504d871cff05e7210353d79cc0cb1396f4ce278d005f16d948e02a6aec9ed1109f13747ecb1507b37b52ae00010147522102b3937241777b6665e0d694e52f9c1b188433641df852da6fc42187b5d8a368a321034cdd474f01cc5aa7ff834ad8bcc882a87e854affc775486bc2a9f62e8f49bd7852ae00";
         let psbt: PartiallySignedTransaction = hex_psbt!(hex).unwrap();
-        assert_eq!(hex, psbt.serialize_hex());
+        assert_eq!(hex, serialize_hex(&psbt));
     }
 
     #[cfg(feature = "serde")]
@@ -1077,6 +1147,7 @@ mod bip_vectors {
 
         use crate::blockdata::script::ScriptBuf;
         use crate::blockdata::transaction::{Transaction, TxIn, TxOut, OutPoint, Sequence};
+        use crate::consensus::encode::serialize_hex;
         use crate::blockdata::locktime::absolute;
         use crate::psbt::map::{Map, Input, Output};
         use crate::psbt::{raw, PartiallySignedTransaction, Error};
@@ -1251,7 +1322,7 @@ fn valid_vector_1() {
 
             let base16str = "70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab300000000000000";
 
-            assert_eq!(unserialized.serialize_hex(), base16str);
+            assert_eq!(serialize_hex(&unserialized), base16str);
             assert_eq!(unserialized, hex_psbt!(base16str).unwrap());
 
             #[cfg(feature = "base64")] {
@@ -1282,7 +1353,7 @@ fn valid_vector_2() {
             assert_eq!(redeem_script.to_p2sh(), expected_out);
 
             for output in psbt.outputs {
-                assert_eq!(output.get_pairs().len(), 0)
+                assert_eq!(output.get_pairs().unwrap().len(), 0)
             }
         }
 
@@ -1328,7 +1399,7 @@ fn valid_vector_4() {
             assert_eq!(redeem_script.to_p2sh(), expected_out);
 
             for output in psbt.outputs {
-                assert!(!output.get_pairs().is_empty())
+                assert!(!output.get_pairs().unwrap().is_empty())
             }
         }
 
@@ -1381,6 +1452,7 @@ fn valid_vector_6() {
 
     mod bip_371_vectors {
         use super::*;
+        use super::serialize;
 
         #[test]
         fn invalid_vectors() {
@@ -1410,8 +1482,8 @@ fn invalid_vectors() {
         }
 
         fn rtt_psbt(psbt: PartiallySignedTransaction) {
-            let enc = Psbt::serialize(&psbt);
-            let psbt2 = Psbt::deserialize(&enc).unwrap();
+            let enc = serialize(&psbt);
+            let psbt2 = deserialize::<PartiallySignedTransaction>(&enc).unwrap();
             assert_eq!(psbt, psbt2);
         }
 
@@ -1562,7 +1634,7 @@ fn serialize_and_deserialize_preimage_psbt() {
         unserialized.inputs[0].hash160_preimages = hash160_preimages;
         unserialized.inputs[0].sha256_preimages = sha256_preimages;
 
-        let rtt: PartiallySignedTransaction = hex_psbt!(&unserialized.serialize_hex()).unwrap();
+        let rtt: PartiallySignedTransaction = hex_psbt!(&serialize_hex(&unserialized)).unwrap();
         assert_eq!(rtt, unserialized);
 
         // Now add an ripemd160 with incorrect preimage
@@ -1571,7 +1643,7 @@ fn serialize_and_deserialize_preimage_psbt() {
         unserialized.inputs[0].ripemd160_preimages = ripemd160_preimages;
 
         // Now the roundtrip should fail as the preimage is incorrect.
-        let rtt: Result<PartiallySignedTransaction, _> = hex_psbt!(&unserialized.serialize_hex());
+        let rtt: Result<PartiallySignedTransaction, _> = hex_psbt!(&serialize_hex(&unserialized));
         assert!(rtt.is_err());
     }
 
@@ -1584,7 +1656,7 @@ fn serialize_and_deserialize_proprietary() {
             key: b"test".to_vec(),
         }, b"test".to_vec());
         assert!(!psbt.proprietary.is_empty());
-        let rtt: PartiallySignedTransaction = hex_psbt!(&psbt.serialize_hex()).unwrap();
+        let rtt: PartiallySignedTransaction = hex_psbt!(&serialize_hex(&psbt)).unwrap();
         assert!(!rtt.proprietary.is_empty());
     }
 
diff --git a/bitcoin/src/psbt/raw.rs b/bitcoin/src/psbt/raw.rs
index 49a1ddc1..0d2e4202 100644
--- a/bitcoin/src/psbt/raw.rs
+++ b/bitcoin/src/psbt/raw.rs
@@ -10,13 +10,11 @@
 use core::fmt;
 use core::convert::TryFrom;
 
-use crate::io::{self, Cursor};
+use crate::io;
 use crate::consensus::encode::{self, ReadExt, WriteExt, Decodable, Encodable, VarInt, serialize, deserialize, MAX_VEC_SIZE};
 use crate::hashes::hex;
 use crate::psbt::Error;
 
-use super::serialize::{Serialize, Deserialize};
-
 /// A PSBT key in its raw byte form.
 #[derive(Debug, PartialEq, Hash, Eq, Clone, Ord, PartialOrd)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
@@ -25,21 +23,18 @@ pub struct Key {
     /// The type of this PSBT key.
     pub type_value: u8,
     /// The key itself in raw byte form.
-    /// `<key> := <keylen> <keytype> <keydata>`
     #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::hex_bytes"))]
     pub key: Vec<u8>,
 }
 
 /// A PSBT key-value pair in its raw byte form.
-/// `<keypair> := <key> <value>`
 #[derive(Debug, PartialEq, Eq)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
 pub struct Pair {
     /// The key of this key-value pair.
     pub key: Key,
-    /// The value data of this key-value pair in raw byte form.
-    /// `<value> := <valuelen> <valuedata>`
+    /// The value of this key-value pair in raw byte form.
     #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::hex_bytes"))]
     pub value: Vec<u8>,
 }
@@ -71,8 +66,8 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-impl Key {
-    pub(crate) fn decode<R: io::Read + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
+impl Decodable for Key {
+    fn consensus_decode<R: io::Read + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
         let VarInt(byte_size): VarInt = Decodable::consensus_decode(r)?;
 
         if byte_size == 0 {
@@ -99,42 +94,32 @@ pub(crate) fn decode<R: io::Read + ?Sized>(r: &mut R) -> Result<Self, encode::Er
     }
 }
 
-impl Serialize for Key {
-    fn serialize(&self) -> Vec<u8> {
-        let mut buf = Vec::new();
-        VarInt((self.key.len() + 1) as u64).consensus_encode(&mut buf).expect("in-memory writers don't error");
+impl Encodable for Key {
+    fn consensus_encode<W: io::Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
+        let mut len = 0;
+        len += VarInt((self.key.len() + 1) as u64).consensus_encode(w)?;
 
-        self.type_value.consensus_encode(&mut buf).expect("in-memory writers don't error");
+        len += self.type_value.consensus_encode(w)?;
 
         for key in &self.key {
-            key.consensus_encode(&mut buf).expect("in-memory writers don't error");
+            len += key.consensus_encode(w)?
         }
 
-        buf
-    }
-}
-
-impl Serialize for Pair {
-    fn serialize(&self) -> Vec<u8> {
-        let mut buf = Vec::new();
-        buf.extend(self.key.serialize());
-        // <value> := <valuelen> <valuedata>
-        self.value.consensus_encode(&mut buf).unwrap();
-        buf
+        Ok(len)
     }
 }
 
-impl Deserialize for Pair {
-    fn deserialize(bytes: &[u8]) -> Result<Self, encode::Error> {
-        let mut decoder = Cursor::new(bytes);
-        Pair::decode(&mut decoder)
+impl Encodable for Pair {
+    fn consensus_encode<W: io::Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
+        let len = self.key.consensus_encode(w)?;
+        Ok(len + self.value.consensus_encode(w)?)
     }
 }
 
-impl Pair {
-    pub(crate) fn decode<R: io::Read + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
+impl Decodable for Pair {
+    fn consensus_decode<R: io::Read + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
         Ok(Pair {
-            key: Key::decode(r)?,
+            key: Decodable::consensus_decode(r)?,
             value: Decodable::consensus_decode(r)?,
         })
     }
diff --git a/bitcoin/src/psbt/serialize.rs b/bitcoin/src/psbt/serialize.rs
index c0a8c66b..7b4ff52f 100644
--- a/bitcoin/src/psbt/serialize.rs
+++ b/bitcoin/src/psbt/serialize.rs
@@ -2,8 +2,8 @@
 
 //! PSBT serialization.
 //!
-//! Traits to serialize PSBT values to and from raw bytes
-//! according to the BIP-174 specification.
+//! Defines traits used for (de)serializing PSBT values into/from raw
+//! bytes from/as PSBT key-value pairs.
 //!
 
 use core::convert::TryInto;
@@ -20,102 +20,26 @@
 use crate::bip32::{ChildNumber, Fingerprint, KeySource};
 use crate::hashes::{hash160, ripemd160, sha256, sha256d, Hash};
 use crate::crypto::{ecdsa, schnorr};
-use crate::psbt::{self, Error, PartiallySignedTransaction};
+use crate::psbt;
 use crate::taproot::{TapBranchHash, TapLeafHash, ControlBlock, LeafVersion};
 use crate::crypto::key::PublicKey;
 
-use super::map::{Map, Input, Output, TapTree, PsbtSighashType};
-use super::Psbt;
+use super::map::{TapTree, PsbtSighashType};
 
 use crate::taproot::TaprootBuilder;
 /// A trait for serializing a value as raw data for insertion into PSBT
-/// key-value maps.
-pub(crate) trait Serialize {
+/// key-value pairs.
+pub trait Serialize {
     /// Serialize a value as raw data.
     fn serialize(&self) -> Vec<u8>;
 }
 
-/// A trait for deserializing a value from raw data in PSBT key-value maps.
-pub(crate) trait Deserialize: Sized {
+/// A trait for deserializing a value from raw data in PSBT key-value pairs.
+pub trait Deserialize: Sized {
     /// Deserialize a value from raw data.
     fn deserialize(bytes: &[u8]) -> Result<Self, encode::Error>;
 }
 
-impl PartiallySignedTransaction {
-    /// Serialize a value as bytes in hex.
-    pub fn serialize_hex(&self) -> String {
-        bitcoin_hashes::hex::ToHex::to_hex(&self.serialize()[..])
-    }
-
-    /// Serialize as raw binary data
-    pub fn serialize(&self) -> Vec<u8> {
-        let mut buf: Vec<u8> = Vec::new();
-
-        //  <magic>
-        buf.extend(b"psbt");
-
-        buf.push(0xff_u8);
-
-        buf.extend(self.serialize_map());
-
-        for i in &self.inputs {
-            buf.extend(i.serialize_map());
-        }
-
-        for i in &self.outputs {
-            buf.extend(i.serialize_map());
-        }
-
-        buf
-    }
-
-
-    /// Deserialize a value from raw binary data.
-    pub fn deserialize(bytes: &[u8]) -> Result<Self, encode::Error> {
-        const MAGIC_BYTES: &[u8] = b"psbt";
-        if bytes.get(0..MAGIC_BYTES.len()) != Some(MAGIC_BYTES) {
-            return Err(Error::InvalidMagic.into());
-        }
-
-        const PSBT_SERPARATOR: u8 = 0xff_u8;
-        if bytes.get(MAGIC_BYTES.len()) != Some(&PSBT_SERPARATOR) {
-            return Err(Error::InvalidSeparator.into());
-        }
-
-        let mut d = bytes.get(5..).ok_or(Error::NoMorePairs)?;
-
-        let mut global = Psbt::decode_global(&mut d)?;
-        global.unsigned_tx_checks()?;
-
-        let inputs: Vec<Input> = {
-            let inputs_len: usize = (global.unsigned_tx.input).len();
-
-            let mut inputs: Vec<Input> = Vec::with_capacity(inputs_len);
-
-            for _ in 0..inputs_len {
-                inputs.push(Input::decode(&mut d)?);
-            }
-
-            inputs
-        };
-
-        let outputs: Vec<Output> = {
-            let outputs_len: usize = (global.unsigned_tx.output).len();
-
-            let mut outputs: Vec<Output> = Vec::with_capacity(outputs_len);
-
-            for _ in 0..outputs_len {
-                outputs.push(Output::decode(&mut d)?);
-            }
-
-            outputs
-        };
-
-        global.inputs = inputs;
-        global.outputs = outputs;
-        Ok(global)
-    }
-}
 impl_psbt_de_serialize!(Transaction);
 impl_psbt_de_serialize!(TxOut);
 impl_psbt_de_serialize!(Witness);
@@ -478,11 +402,4 @@ fn can_deserialize_non_standard_psbt_sighash_type() {
         let sighash = PsbtSighashType::deserialize(&non_standard_sighash);
         assert!(sighash.is_ok())
     }
-
-    #[test]
-    #[should_panic(expected = "InvalidMagic")]
-    fn invalid_vector_1() {
-        let hex_psbt = b"0200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf6000000006a473044022070b2245123e6bf474d60c5b50c043d4c691a5d2435f09a34a7662a9dc251790a022001329ca9dacf280bdf30740ec0390422422c81cb45839457aeb76fc12edd95b3012102657d118d3357b8e0f4c2cd46db7b39f6d9c38d9a70abcb9b2de5dc8dbfe4ce31feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300";
-        PartiallySignedTransaction::deserialize(hex_psbt).unwrap();
-    }
 }


Test patch:
diff --git a/bitcoin/tests/psbt.rs b/bitcoin/tests/psbt.rs
index 389f1727..d14bea47 100644
--- a/bitcoin/tests/psbt.rs
+++ b/bitcoin/tests/psbt.rs
@@ -26,7 +26,7 @@ macro_rules! hex_script {
 
 macro_rules! hex_psbt {
     ($s:expr) => {
-        Psbt::deserialize(&<Vec<u8> as FromHex>::from_hex($s).unwrap())
+        deserialize::<Psbt>(&<Vec<u8> as FromHex>::from_hex($s).unwrap())
     };
 }
 
@@ -397,10 +397,10 @@ fn combine_lexicographically() {
     let expected_psbt = hex_psbt!(expected_psbt_hex).unwrap();
 
     let v = Vec::from_hex(psbt_1_hex).unwrap();
-    let mut psbt_1 = Psbt::deserialize(&v).expect("failed to deserialize psbt 1");
+    let mut psbt_1: Psbt = deserialize(&v).expect("failed to deserialize psbt 1");
 
     let v = Vec::from_hex(psbt_2_hex).unwrap();
-    let psbt_2 = Psbt::deserialize(&v).expect("failed to deserialize psbt 2");
+    let psbt_2: Psbt = deserialize(&v).expect("failed to deserialize psbt 2");
 
     psbt_1.combine(psbt_2).expect("failed to combine PSBTs");
 
@@ -417,14 +417,16 @@ fn sign(mut psbt: Psbt, keys: BTreeMap<bitcoin::PublicKey, PrivateKey>) -> Psbt
 /// Finalizes a PSBT accord to the Input Finalizer role described in BIP 174.
 /// This is just a test. For a production-ready PSBT Finalizer, use [rust-miniscript](https://docs.rs/miniscript/latest/miniscript/psbt/trait.PsbtExt.html#tymethod.finalize)
 fn finalize_psbt(mut psbt: Psbt) -> Psbt {
+    use bitcoin::psbt::serialize::Serialize;
+
     // Input 0: legacy UTXO
 
     let sigs: Vec<_> = psbt.inputs[0].partial_sigs.values().collect();
     let script_sig = script::Builder::new()
         .push_opcode(OP_0) // OP_CHECKMULTISIG bug pops +1 value when evaluating so push OP_0.
-        .push_slice(&sigs[0].to_vec())
-        .push_slice(&sigs[1].to_vec())
-        .push_slice(psbt.inputs[0].redeem_script.clone().unwrap().as_bytes())
+        .push_slice(&sigs[0].serialize())
+        .push_slice(&sigs[1].serialize())
+        .push_slice(&psbt.inputs[0].redeem_script.clone().unwrap().serialize())
         .into_script();
 
     psbt.inputs[0].final_script_sig = Some(script_sig);
@@ -437,7 +439,7 @@ fn finalize_psbt(mut psbt: Psbt) -> Psbt {
     // Input 1: SegWit UTXO
 
     let script_sig = script::Builder::new()
-        .push_slice(psbt.inputs[1].redeem_script.clone().unwrap().as_bytes())
+        .push_slice(&psbt.inputs[1].redeem_script.clone().unwrap().serialize())
         .into_script();
 
     psbt.inputs[1].final_script_sig = Some(script_sig);
@@ -446,9 +448,9 @@ fn finalize_psbt(mut psbt: Psbt) -> Psbt {
         let sigs: Vec<_> = psbt.inputs[1].partial_sigs.values().collect();
         let mut script_witness = Witness::new();
         script_witness.push([]); // Push 0x00 to the stack.
-        script_witness.push(&sigs[1].to_vec());
-        script_witness.push(&sigs[0].to_vec());
-        script_witness.push(psbt.inputs[1].witness_script.clone().unwrap().as_bytes());
+        script_witness.push(&sigs[1].serialize());
+        script_witness.push(&sigs[0].serialize());
+        script_witness.push(&psbt.inputs[1].witness_script.clone().unwrap().serialize());
 
         script_witness
     };