diff --git a/bitcoin/examples/sighash.rs b/bitcoin/examples/sighash.rs index afb6b2ac2..18e63ea6a 100644 --- a/bitcoin/examples/sighash.rs +++ b/bitcoin/examples/sighash.rs @@ -1,4 +1,5 @@ use bitcoin::address::script_pubkey::ScriptBufExt as _; +use bitcoin::script::ScriptExt as _; use bitcoin::{ consensus, ecdsa, sighash, Amount, CompressedPublicKey, Script, ScriptBuf, Transaction, }; diff --git a/bitcoin/examples/taproot-psbt.rs b/bitcoin/examples/taproot-psbt.rs index 1eaf9a1b0..734c096eb 100644 --- a/bitcoin/examples/taproot-psbt.rs +++ b/bitcoin/examples/taproot-psbt.rs @@ -84,6 +84,7 @@ use bitcoin::consensus::encode; use bitcoin::key::{TapTweak, XOnlyPublicKey}; use bitcoin::opcodes::all::{OP_CHECKSIG, OP_CLTV, OP_DROP}; use bitcoin::psbt::{self, Input, Output, Psbt, PsbtSighashType}; +use bitcoin::script::ScriptExt as _; use bitcoin::secp256k1::Secp256k1; use bitcoin::sighash::{self, SighashCache, TapSighash, TapSighashType}; use bitcoin::taproot::{self, LeafVersion, TapLeafHash, TaprootBuilder, TaprootSpendInfo}; diff --git a/bitcoin/src/address/mod.rs b/bitcoin/src/address/mod.rs index 89fb1ee1c..e2495b70e 100644 --- a/bitcoin/src/address/mod.rs +++ b/bitcoin/src/address/mod.rs @@ -51,7 +51,8 @@ use crate::prelude::{String, ToOwned}; use crate::script::witness_program::WitnessProgram; use crate::script::witness_version::WitnessVersion; use crate::script::{ - self, RedeemScriptSizeError, Script, ScriptBuf, ScriptHash, WScriptHash, WitnessScriptSizeError, + self, RedeemScriptSizeError, Script, ScriptBuf, ScriptExt as _, ScriptHash, WScriptHash, + WitnessScriptSizeError, }; use crate::taproot::TapNodeHash; diff --git a/bitcoin/src/address/script_pubkey.rs b/bitcoin/src/address/script_pubkey.rs index e299bed78..edd74ee01 100644 --- a/bitcoin/src/address/script_pubkey.rs +++ b/bitcoin/src/address/script_pubkey.rs @@ -13,8 +13,8 @@ use crate::opcodes::all::*; use crate::script::witness_program::WitnessProgram; use crate::script::witness_version::WitnessVersion; use crate::script::{ - self, Builder, PushBytes, RedeemScriptSizeError, Script, ScriptBuf, ScriptHash, WScriptHash, - WitnessScriptSizeError, + self, Builder, PushBytes, RedeemScriptSizeError, Script, ScriptBuf, ScriptExt as _, ScriptHash, + WScriptHash, WitnessScriptSizeError, }; use crate::taproot::TapNodeHash; @@ -22,7 +22,7 @@ define_extension_trait! { /// Extension functionality to add scriptPubkey support to the [`Builder`] type. pub trait BuilderExt impl for Builder { /// Adds instructions to push a public key onto the stack. - fn push_key(self: Self, key: PublicKey) -> Builder { + fn push_key(self, key: PublicKey) -> Builder { if key.compressed { self.push_slice(key.inner.serialize()) } else { @@ -31,7 +31,7 @@ define_extension_trait! { } /// Adds instructions to push an XOnly public key onto the stack. - fn push_x_only_key(self: Self, x_only_key: XOnlyPublicKey) -> Builder { + fn push_x_only_key(self, x_only_key: XOnlyPublicKey) -> Builder { self.push_slice(x_only_key.serialize()) } } @@ -42,14 +42,14 @@ define_extension_trait! { pub trait ScriptExt impl for Script { /// Computes the P2WSH output corresponding to this witnessScript (aka the "witness redeem /// script"). - fn to_p2wsh(self: &Self) -> Result { + fn to_p2wsh(&self) -> Result { self.wscript_hash().map(ScriptBuf::new_p2wsh) } /// Computes P2TR output with a given internal key and a single script spending path equal to /// the current script, assuming that the script is a Tapscript. fn to_p2tr( - self: &Self, + &self, secp: &Secp256k1, internal_key: UntweakedPublicKey, ) -> ScriptBuf { @@ -59,7 +59,7 @@ define_extension_trait! { } /// Computes the P2SH output corresponding to this redeem script. - fn to_p2sh(self: &Self) -> Result { + fn to_p2sh(&self) -> Result { self.script_hash().map(ScriptBuf::new_p2sh) } @@ -67,7 +67,7 @@ define_extension_trait! { /// for a P2WPKH output. The `scriptCode` is described in [BIP143]. /// /// [BIP143]: - fn p2wpkh_script_code(self: &Self) -> Option { + fn p2wpkh_script_code(&self) -> Option { if self.is_p2wpkh() { // The `self` script is 0x00, 0x14, let bytes = &self.as_bytes()[2..]; @@ -82,14 +82,14 @@ define_extension_trait! { /// /// You can obtain the public key, if its valid, /// by calling [`p2pk_public_key()`](Self::p2pk_public_key) - fn is_p2pk(self: &Self) -> bool { self.p2pk_pubkey_bytes().is_some() } + fn is_p2pk(&self) -> bool { self.p2pk_pubkey_bytes().is_some() } /// Returns the public key if this script is P2PK with a **valid** public key. /// /// This may return `None` even when [`is_p2pk()`](Self::is_p2pk) returns true. /// This happens when the public key is invalid (e.g. the point not being on the curve). /// In this situation the script is unspendable. - fn p2pk_public_key(self: &Self) -> Option { + fn p2pk_public_key(&self) -> Option { PublicKey::from_slice(self.p2pk_pubkey_bytes()?).ok() } } @@ -98,7 +98,7 @@ define_extension_trait! { define_extension_trait! { pub(crate) trait ScriptExtPrivate impl for Script { /// Returns the bytes of the (possibly invalid) public key if this script is P2PK. - fn p2pk_pubkey_bytes(self: &Self) -> Option<&[u8]> { + fn p2pk_pubkey_bytes(&self) -> Option<&[u8]> { match self.len() { 67 if self.as_bytes()[0] == OP_PUSHBYTES_65.to_u8() && self.as_bytes()[66] == OP_CHECKSIG.to_u8() => diff --git a/bitcoin/src/bip158.rs b/bitcoin/src/bip158.rs index 9326c082e..524e55d3d 100644 --- a/bitcoin/src/bip158.rs +++ b/bitcoin/src/bip158.rs @@ -49,7 +49,7 @@ use crate::consensus::encode::VarInt; use crate::consensus::{Decodable, Encodable}; use crate::internal_macros::impl_hashencode; use crate::prelude::{BTreeSet, Borrow, Vec}; -use crate::script::Script; +use crate::script::{Script, ScriptExt as _}; use crate::transaction::OutPoint; /// Golomb encoding parameter as in BIP-158, see also https://gist.github.com/sipa/576d5f09c3b86c3b1b75598d799fc845 diff --git a/bitcoin/src/blockdata/block.rs b/bitcoin/src/blockdata/block.rs index 48314aff9..2578e3f8d 100644 --- a/bitcoin/src/blockdata/block.rs +++ b/bitcoin/src/blockdata/block.rs @@ -19,8 +19,9 @@ use crate::merkle_tree::{MerkleNode as _, TxMerkleNode, WitnessMerkleNode}; use crate::network::Params; use crate::pow::{CompactTarget, Target, Work}; use crate::prelude::Vec; +use crate::script::{self, ScriptExt as _}; use crate::transaction::{Transaction, Wtxid}; -use crate::{script, VarInt}; +use crate::VarInt; hashes::hash_newtype! { /// A bitcoin block hash. diff --git a/bitcoin/src/blockdata/script/borrowed.rs b/bitcoin/src/blockdata/script/borrowed.rs index 82b65be53..c0c4da3e6 100644 --- a/bitcoin/src/blockdata/script/borrowed.rs +++ b/bitcoin/src/blockdata/script/borrowed.rs @@ -110,27 +110,6 @@ impl Script { #[inline] pub fn as_mut_bytes(&mut self) -> &mut [u8] { &mut self.0 } - /// Creates a new script builder - pub fn builder() -> Builder { Builder::new() } - - /// Returns 160-bit hash of the script for P2SH outputs. - #[inline] - pub fn script_hash(&self) -> Result { - ScriptHash::from_script(self) - } - - /// Returns 256-bit hash of the script for P2WSH outputs. - #[inline] - pub fn wscript_hash(&self) -> Result { - WScriptHash::from_script(self) - } - - /// Computes leaf hash of tapscript. - #[inline] - pub fn tapscript_leaf_hash(&self) -> TapLeafHash { - TapLeafHash::from_script(self, LeafVersion::TapScript) - } - /// Returns the length in bytes of the script. #[inline] pub fn len(&self) -> usize { self.0.len() } @@ -143,437 +122,6 @@ impl Script { #[inline] pub fn to_bytes(&self) -> Vec { self.0.to_owned() } - /// Returns an iterator over script bytes. - #[inline] - pub fn bytes(&self) -> Bytes<'_> { Bytes(self.as_bytes().iter().copied()) } - - /// Returns witness version of the script, if any, assuming the script is a `scriptPubkey`. - /// - /// # Returns - /// - /// The witness version if this script is found to conform to the SegWit rules: - /// - /// > A scriptPubKey (or redeemScript as defined in BIP16/P2SH) that consists of a 1-byte - /// > push opcode (for 0 to 16) followed by a data push between 2 and 40 bytes gets a new - /// > special meaning. The value of the first push is called the "version byte". The following - /// > byte vector pushed is called the "witness program". - #[inline] - pub fn witness_version(&self) -> Option { - let script_len = self.0.len(); - if !(4..=42).contains(&script_len) { - return None; - } - - let ver_opcode = Opcode::from(self.0[0]); // Version 0 or PUSHNUM_1-PUSHNUM_16 - let push_opbyte = self.0[1]; // Second byte push opcode 2-40 bytes - - if push_opbyte < OP_PUSHBYTES_2.to_u8() || push_opbyte > OP_PUSHBYTES_40.to_u8() { - return None; - } - // Check that the rest of the script has the correct size - if script_len - 2 != push_opbyte as usize { - return None; - } - - WitnessVersion::try_from(ver_opcode).ok() - } - - /// Checks whether a script pubkey is a P2SH output. - #[inline] - pub fn is_p2sh(&self) -> bool { - self.0.len() == 23 - && self.0[0] == OP_HASH160.to_u8() - && self.0[1] == OP_PUSHBYTES_20.to_u8() - && self.0[22] == OP_EQUAL.to_u8() - } - - /// Checks whether a script pubkey is a P2PKH output. - #[inline] - pub fn is_p2pkh(&self) -> bool { - self.0.len() == 25 - && self.0[0] == OP_DUP.to_u8() - && self.0[1] == OP_HASH160.to_u8() - && self.0[2] == OP_PUSHBYTES_20.to_u8() - && self.0[23] == OP_EQUALVERIFY.to_u8() - && self.0[24] == OP_CHECKSIG.to_u8() - } - - /// Checks whether a script is push only. - /// - /// Note: `OP_RESERVED` (`0x50`) and all the OP_PUSHNUM operations - /// are considered push operations. - #[inline] - pub fn is_push_only(&self) -> bool { - for inst in self.instructions() { - match inst { - Err(_) => return false, - Ok(Instruction::PushBytes(_)) => {} - Ok(Instruction::Op(op)) if op.to_u8() <= 0x60 => {} - // From Bitcoin Core - // if (opcode > OP_PUSHNUM_16 (0x60)) return false - Ok(Instruction::Op(_)) => return false, - } - } - true - } - - /// Checks whether a script pubkey is a bare multisig output. - /// - /// In a bare multisig pubkey script the keys are not hashed, the script - /// is of the form: - /// - /// `2 3 OP_CHECKMULTISIG` - #[inline] - pub fn is_multisig(&self) -> bool { - let required_sigs; - - let mut instructions = self.instructions(); - if let Some(Ok(Instruction::Op(op))) = instructions.next() { - if let Some(pushnum) = op.decode_pushnum() { - required_sigs = pushnum; - } else { - return false; - } - } else { - return false; - } - - let mut num_pubkeys: u8 = 0; - while let Some(Ok(instruction)) = instructions.next() { - match instruction { - Instruction::PushBytes(_) => { - num_pubkeys += 1; - } - Instruction::Op(op) => { - if let Some(pushnum) = op.decode_pushnum() { - if pushnum != num_pubkeys { - return false; - } - } - break; - } - } - } - - if required_sigs > num_pubkeys { - return false; - } - - if let Some(Ok(Instruction::Op(op))) = instructions.next() { - if op != OP_CHECKMULTISIG { - return false; - } - } else { - return false; - } - - instructions.next().is_none() - } - - /// Checks whether a script pubkey is a Segregated Witness (segwit) program. - #[inline] - pub fn is_witness_program(&self) -> bool { self.witness_version().is_some() } - - /// Checks whether a script pubkey is a P2WSH output. - #[inline] - pub fn is_p2wsh(&self) -> bool { - self.0.len() == 34 - && self.witness_version() == Some(WitnessVersion::V0) - && self.0[1] == OP_PUSHBYTES_32.to_u8() - } - - /// Checks whether a script pubkey is a P2WPKH output. - #[inline] - pub fn is_p2wpkh(&self) -> bool { - self.0.len() == 22 - && self.witness_version() == Some(WitnessVersion::V0) - && self.0[1] == OP_PUSHBYTES_20.to_u8() - } - - /// Checks whether a script pubkey is a P2TR output. - #[inline] - pub fn is_p2tr(&self) -> bool { - self.0.len() == 34 - && self.witness_version() == Some(WitnessVersion::V1) - && self.0[1] == OP_PUSHBYTES_32.to_u8() - } - - /// Check if this is a consensus-valid OP_RETURN output. - /// - /// To validate if the OP_RETURN obeys Bitcoin Core's current standardness policy, use - /// [`is_standard_op_return()`](Self::is_standard_op_return) instead. - #[inline] - pub fn is_op_return(&self) -> bool { - match self.0.first() { - Some(b) => *b == OP_RETURN.to_u8(), - None => false, - } - } - - /// Check if this is an OP_RETURN that obeys Bitcoin Core standardness policy. - /// - /// What this function considers to be standard may change without warning pending Bitcoin Core - /// changes. - #[inline] - pub fn is_standard_op_return(&self) -> bool { self.is_op_return() && self.0.len() <= 80 } - - /// Checks whether a script is trivially known to have no satisfying input. - /// - /// This method has potentially confusing semantics and an unclear purpose, so it's going to be - /// removed. Use `is_op_return` if you want `OP_RETURN` semantics. - #[deprecated( - since = "0.32.0", - note = "The method has potentially confusing semantics and is going to be removed, you might want `is_op_return`" - )] - #[inline] - pub fn is_provably_unspendable(&self) -> bool { - use crate::opcodes::Class::{IllegalOp, ReturnOp}; - - match self.0.first() { - Some(b) => { - let first = Opcode::from(*b); - let class = first.classify(opcodes::ClassifyContext::Legacy); - - class == ReturnOp || class == IllegalOp - } - None => false, - } - } - - /// Get redeemScript following BIP16 rules regarding P2SH spending. - /// - /// This does not guarantee that this represents a P2SH input [`Script`]. - /// It merely gets the last push of the script. - /// - /// Use [`Script::is_p2sh`] on the scriptPubKey to check whether it is actually a P2SH script. - pub fn redeem_script(&self) -> Option<&Script> { - // Script must consist entirely of pushes. - if self.instructions().any(|i| i.is_err() || i.unwrap().push_bytes().is_none()) { - return None; - } - - if let Some(Ok(Instruction::PushBytes(b))) = self.instructions().last() { - Some(Script::from_bytes(b.as_bytes())) - } else { - None - } - } - - /// Returns the minimum value an output with this script should have in order to be - /// broadcastable on today’s Bitcoin network. - #[deprecated(since = "0.32.0", note = "use minimal_non_dust and friends")] - pub fn dust_value(&self) -> crate::Amount { self.minimal_non_dust() } - - /// Returns the minimum value an output with this script should have in order to be - /// broadcastable on today's Bitcoin network. - /// - /// Dust depends on the -dustrelayfee value of the Bitcoin Core node you are broadcasting to. - /// This function uses the default value of 0.00003 BTC/kB (3 sat/vByte). - /// - /// To use a custom value, use [`minimal_non_dust_custom`]. - /// - /// [`minimal_non_dust_custom`]: Script::minimal_non_dust_custom - pub fn minimal_non_dust(&self) -> crate::Amount { - self.minimal_non_dust_internal(DUST_RELAY_TX_FEE.into()) - } - - /// Returns the minimum value an output with this script should have in order to be - /// broadcastable on today's Bitcoin network. - /// - /// Dust depends on the -dustrelayfee value of the Bitcoin Core node you are broadcasting to. - /// This function lets you set the fee rate used in dust calculation. - /// - /// The current default value in Bitcoin Core (as of v26) is 3 sat/vByte. - /// - /// To use the default Bitcoin Core value, use [`minimal_non_dust`]. - /// - /// [`minimal_non_dust`]: Script::minimal_non_dust - pub fn minimal_non_dust_custom(&self, dust_relay_fee: FeeRate) -> crate::Amount { - self.minimal_non_dust_internal(dust_relay_fee.to_sat_per_kwu() * 4) - } - - fn minimal_non_dust_internal(&self, dust_relay_fee: u64) -> crate::Amount { - // This must never be lower than Bitcoin Core's GetDustThreshold() (as of v0.21) as it may - // otherwise allow users to create transactions which likely can never be broadcast/confirmed. - let sats = dust_relay_fee - .checked_mul(if self.is_op_return() { - 0 - } else if self.is_witness_program() { - 32 + 4 + 1 + (107 / 4) + 4 + // The spend cost copied from Core - 8 + // The serialized size of the TxOut's amount field - self.consensus_encode(&mut sink()).expect("sinks don't error").to_u64() // The serialized size of this script_pubkey - } else { - 32 + 4 + 1 + 107 + 4 + // The spend cost copied from Core - 8 + // The serialized size of the TxOut's amount field - self.consensus_encode(&mut sink()).expect("sinks don't error").to_u64() // The serialized size of this script_pubkey - }) - .expect("dust_relay_fee or script length should not be absurdly large") - / 1000; // divide by 1000 like in Core to get value as it cancels out DEFAULT_MIN_RELAY_TX_FEE - // Note: We ensure the division happens at the end, since Core performs the division at the end. - // This will make sure none of the implicit floor operations mess with the value. - - crate::Amount::from_sat(sats) - } - - /// Counts the sigops for this Script using accurate counting. - /// - /// In Bitcoin Core, there are two ways to count sigops, "accurate" and "legacy". - /// This method uses "accurate" counting. This means that OP_CHECKMULTISIG and its - /// verify variant count for N sigops where N is the number of pubkeys used in the - /// multisig. However, it will count for 20 sigops if CHECKMULTISIG is not preceded by an - /// OP_PUSHNUM from 1 - 16 (this would be an invalid script) - /// - /// Bitcoin Core uses accurate counting for sigops contained within redeemScripts (P2SH) - /// and witnessScripts (P2WSH) only. It uses legacy for sigops in scriptSigs and scriptPubkeys. - /// - /// (Note: Taproot scripts don't count toward the sigop count of the block, - /// nor do they have CHECKMULTISIG operations. This function does not count OP_CHECKSIGADD, - /// so do not use this to try and estimate if a Taproot script goes over the sigop budget.) - pub fn count_sigops(&self) -> usize { self.count_sigops_internal(true) } - - /// Counts the sigops for this Script using legacy counting. - /// - /// In Bitcoin Core, there are two ways to count sigops, "accurate" and "legacy". - /// This method uses "legacy" counting. This means that OP_CHECKMULTISIG and its - /// verify variant count for 20 sigops. - /// - /// Bitcoin Core uses legacy counting for sigops contained within scriptSigs and - /// scriptPubkeys. It uses accurate for redeemScripts (P2SH) and witnessScripts (P2WSH). - /// - /// (Note: Taproot scripts don't count toward the sigop count of the block, - /// nor do they have CHECKMULTISIG operations. This function does not count OP_CHECKSIGADD, - /// so do not use this to try and estimate if a Taproot script goes over the sigop budget.) - pub fn count_sigops_legacy(&self) -> usize { self.count_sigops_internal(false) } - - fn count_sigops_internal(&self, accurate: bool) -> usize { - let mut n = 0; - let mut pushnum_cache = None; - for inst in self.instructions() { - match inst { - Ok(Instruction::Op(opcode)) => { - match opcode { - // p2pk, p2pkh - OP_CHECKSIG | OP_CHECKSIGVERIFY => { - n += 1; - } - OP_CHECKMULTISIG | OP_CHECKMULTISIGVERIFY => { - match (accurate, pushnum_cache) { - (true, Some(pushnum)) => { - // Add the number of pubkeys in the multisig as sigop count - n += usize::from(pushnum); - } - _ => { - // MAX_PUBKEYS_PER_MULTISIG from Bitcoin Core - // https://github.com/bitcoin/bitcoin/blob/v25.0/src/script/script.h#L29-L30 - n += 20; - } - } - } - _ => { - pushnum_cache = opcode.decode_pushnum(); - } - } - } - Ok(Instruction::PushBytes(_)) => { - pushnum_cache = None; - } - // In Bitcoin Core it does `if (!GetOp(pc, opcode)) break;` - Err(_) => break, - } - } - - n - } - - /// Iterates over the script instructions. - /// - /// Each returned item is a nested enum covering opcodes, datapushes and errors. - /// At most one error will be returned and then the iterator will end. To instead iterate over - /// the script as sequence of bytes call the [`bytes`](Self::bytes) method. - /// - /// To force minimal pushes, use [`instructions_minimal`](Self::instructions_minimal). - #[inline] - pub fn instructions(&self) -> Instructions { - Instructions { data: self.0.iter(), enforce_minimal: false } - } - - /// Iterates over the script instructions while enforcing minimal pushes. - /// - /// This is similar to [`instructions`](Self::instructions) but an error is returned if a push - /// is not minimal. - #[inline] - pub fn instructions_minimal(&self) -> Instructions { - Instructions { data: self.0.iter(), enforce_minimal: true } - } - - /// Iterates over the script instructions and their indices. - /// - /// Unless the script contains an error, the returned item consists of an index pointing to the - /// position in the script where the instruction begins and the decoded instruction - either an - /// opcode or data push. - /// - /// To force minimal pushes, use [`Self::instruction_indices_minimal`]. - #[inline] - pub fn instruction_indices(&self) -> InstructionIndices { - InstructionIndices::from_instructions(self.instructions()) - } - - /// Iterates over the script instructions and their indices while enforcing minimal pushes. - /// - /// This is similar to [`instruction_indices`](Self::instruction_indices) but an error is - /// returned if a push is not minimal. - #[inline] - pub fn instruction_indices_minimal(&self) -> InstructionIndices { - InstructionIndices::from_instructions(self.instructions_minimal()) - } - - /// Writes the human-readable assembly representation of the script to the formatter. - pub fn fmt_asm(&self, f: &mut dyn fmt::Write) -> fmt::Result { - bytes_to_asm_fmt(self.as_ref(), f) - } - - /// Returns the human-readable assembly representation of the script. - pub fn to_asm_string(&self) -> String { - let mut buf = String::new(); - self.fmt_asm(&mut buf).unwrap(); - buf - } - - /// Formats the script as lower-case hex. - /// - /// This is a more convenient and performant way to write `format!("{:x}", script)`. - /// For better performance you should generally prefer displaying the script but if `String` is - /// required (this is common in tests) this method can be used. - pub fn to_hex_string(&self) -> String { self.as_bytes().to_lower_hex_string() } - - /// Returns the first opcode of the script (if there is any). - pub fn first_opcode(&self) -> Option { - self.as_bytes().first().copied().map(From::from) - } - - /// Iterates the script to find the last opcode. - /// - /// Returns `None` is the instruction is data push or if the script is empty. - pub(in crate::blockdata::script) fn last_opcode(&self) -> Option { - match self.instructions().last() { - Some(Ok(Instruction::Op(op))) => Some(op), - _ => None, - } - } - - /// Iterates the script to find the last pushdata. - /// - /// Returns `None` if the instruction is an opcode or if the script is empty. - pub(crate) fn last_pushdata(&self) -> Option<&PushBytes> { - match self.instructions().last() { - // Handles op codes up to (but excluding) OP_PUSHNUM_NEG. - Some(Ok(Instruction::PushBytes(bytes))) => Some(bytes), - // OP_16 (0x60) and lower are considered "pushes" by Bitcoin Core (excl. OP_RESERVED). - // However we are only interested in the pushdata so we can ignore them. - _ => None, - } - } - /// Converts a [`Box