From 08576976650f93912dbd568653c26911bcc9a69e Mon Sep 17 00:00:00 2001 From: Martin Habovstiak Date: Sun, 11 Aug 2024 15:36:54 +0200 Subject: [PATCH] Replace impl blocks with extension traits In preparation to move script types to `primitives` we replace impl block with extension traits by replacing the temporary modules with `define_extension_trait`. --- bitcoin/examples/sighash.rs | 1 + bitcoin/examples/taproot-psbt.rs | 1 + bitcoin/src/address/mod.rs | 3 +- bitcoin/src/address/script_pubkey.rs | 4 +- bitcoin/src/bip158.rs | 2 +- bitcoin/src/blockdata/block.rs | 3 +- bitcoin/src/blockdata/script/borrowed.rs | 81 +++++++++---------- bitcoin/src/blockdata/script/builder.rs | 1 + bitcoin/src/blockdata/script/owned.rs | 2 +- .../src/blockdata/script/witness_program.rs | 1 + bitcoin/src/blockdata/transaction.rs | 2 +- bitcoin/src/blockdata/witness.rs | 2 + bitcoin/src/psbt/mod.rs | 1 + bitcoin/tests/psbt-sign-taproot.rs | 1 + .../bitcoin/deserialize_script.rs | 3 +- .../bitcoin/script_bytes_to_asm_fmt.rs | 1 + 16 files changed, 60 insertions(+), 49 deletions(-) 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 89b7298aa..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; 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 dd4e7dab9..c0c4da3e6 100644 --- a/bitcoin/src/blockdata/script/borrowed.rs +++ b/bitcoin/src/blockdata/script/borrowed.rs @@ -135,31 +135,31 @@ impl Script { } } -mod tmp_pub { - use super::*; - impl Script { +crate::internal_macros::define_extension_trait! { + /// Extension functionality for the [`Script`] type. + pub trait ScriptExt impl for Script { /// Returns an iterator over script bytes. #[inline] - pub fn bytes(&self) -> Bytes<'_> { Bytes(self.as_bytes().iter().copied()) } + fn bytes(&self) -> Bytes<'_> { Bytes(self.as_bytes().iter().copied()) } /// Creates a new script builder - pub fn builder() -> Builder { Builder::new() } + fn builder() -> Builder { Builder::new() } /// Returns 160-bit hash of the script for P2SH outputs. #[inline] - pub fn script_hash(&self) -> Result { + 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 { + fn wscript_hash(&self) -> Result { WScriptHash::from_script(self) } /// Computes leaf hash of tapscript. #[inline] - pub fn tapscript_leaf_hash(&self) -> TapLeafHash { + fn tapscript_leaf_hash(&self) -> TapLeafHash { TapLeafHash::from_script(self, LeafVersion::TapScript) } @@ -174,7 +174,7 @@ mod tmp_pub { /// > 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 { + fn witness_version(&self) -> Option { let script_len = self.0.len(); if !(4..=42).contains(&script_len) { return None; @@ -196,7 +196,7 @@ mod tmp_pub { /// Checks whether a script pubkey is a P2SH output. #[inline] - pub fn is_p2sh(&self) -> bool { + fn is_p2sh(&self) -> bool { self.0.len() == 23 && self.0[0] == OP_HASH160.to_u8() && self.0[1] == OP_PUSHBYTES_20.to_u8() @@ -205,7 +205,7 @@ mod tmp_pub { /// Checks whether a script pubkey is a P2PKH output. #[inline] - pub fn is_p2pkh(&self) -> bool { + fn is_p2pkh(&self) -> bool { self.0.len() == 25 && self.0[0] == OP_DUP.to_u8() && self.0[1] == OP_HASH160.to_u8() @@ -219,7 +219,7 @@ mod tmp_pub { /// Note: `OP_RESERVED` (`0x50`) and all the OP_PUSHNUM operations /// are considered push operations. #[inline] - pub fn is_push_only(&self) -> bool { + fn is_push_only(&self) -> bool { for inst in self.instructions() { match inst { Err(_) => return false, @@ -240,7 +240,7 @@ mod tmp_pub { /// /// `2 3 OP_CHECKMULTISIG` #[inline] - pub fn is_multisig(&self) -> bool { + fn is_multisig(&self) -> bool { let required_sigs; let mut instructions = self.instructions(); @@ -288,11 +288,11 @@ mod tmp_pub { /// Checks whether a script pubkey is a Segregated Witness (segwit) program. #[inline] - pub fn is_witness_program(&self) -> bool { self.witness_version().is_some() } + 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 { + fn is_p2wsh(&self) -> bool { self.0.len() == 34 && self.witness_version() == Some(WitnessVersion::V0) && self.0[1] == OP_PUSHBYTES_32.to_u8() @@ -300,7 +300,7 @@ mod tmp_pub { /// Checks whether a script pubkey is a P2WPKH output. #[inline] - pub fn is_p2wpkh(&self) -> bool { + fn is_p2wpkh(&self) -> bool { self.0.len() == 22 && self.witness_version() == Some(WitnessVersion::V0) && self.0[1] == OP_PUSHBYTES_20.to_u8() @@ -308,7 +308,7 @@ mod tmp_pub { /// Checks whether a script pubkey is a P2TR output. #[inline] - pub fn is_p2tr(&self) -> bool { + fn is_p2tr(&self) -> bool { self.0.len() == 34 && self.witness_version() == Some(WitnessVersion::V1) && self.0[1] == OP_PUSHBYTES_32.to_u8() @@ -319,7 +319,7 @@ mod tmp_pub { /// 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 { + fn is_op_return(&self) -> bool { match self.0.first() { Some(b) => *b == OP_RETURN.to_u8(), None => false, @@ -331,7 +331,7 @@ mod tmp_pub { /// 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 } + 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. /// @@ -342,7 +342,7 @@ mod tmp_pub { 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 { + fn is_provably_unspendable(&self) -> bool { use crate::opcodes::Class::{IllegalOp, ReturnOp}; match self.0.first() { @@ -362,7 +362,7 @@ mod tmp_pub { /// 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> { + 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; @@ -378,7 +378,7 @@ mod tmp_pub { /// 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() } + 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. @@ -389,7 +389,7 @@ mod tmp_pub { /// 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 { + fn minimal_non_dust(&self) -> crate::Amount { self.minimal_non_dust_internal(DUST_RELAY_TX_FEE.into()) } @@ -404,7 +404,7 @@ mod tmp_pub { /// 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 { + 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) } @@ -422,7 +422,7 @@ mod tmp_pub { /// (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) } + fn count_sigops(&self) -> usize { self.count_sigops_internal(true) } /// Counts the sigops for this Script using legacy counting. /// @@ -436,7 +436,7 @@ mod tmp_pub { /// (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_legacy(&self) -> usize { self.count_sigops_internal(false) } /// Iterates over the script instructions. /// @@ -446,7 +446,7 @@ mod tmp_pub { /// /// To force minimal pushes, use [`instructions_minimal`](Self::instructions_minimal). #[inline] - pub fn instructions(&self) -> Instructions { + fn instructions(&self) -> Instructions { Instructions { data: self.0.iter(), enforce_minimal: false } } @@ -455,7 +455,7 @@ mod tmp_pub { /// 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 { + fn instructions_minimal(&self) -> Instructions { Instructions { data: self.0.iter(), enforce_minimal: true } } @@ -467,7 +467,7 @@ mod tmp_pub { /// /// To force minimal pushes, use [`Self::instruction_indices_minimal`]. #[inline] - pub fn instruction_indices(&self) -> InstructionIndices { + fn instruction_indices(&self) -> InstructionIndices { InstructionIndices::from_instructions(self.instructions()) } @@ -476,17 +476,17 @@ mod tmp_pub { /// 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 { + 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 { + 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 { + fn to_asm_string(&self) -> String { let mut buf = String::new(); self.fmt_asm(&mut buf).unwrap(); buf @@ -497,19 +497,18 @@ mod tmp_pub { /// 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() } + 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 { + fn first_opcode(&self) -> Option { self.as_bytes().first().copied().map(From::from) } } } -mod tmp_priv { - use super::*; - impl Script { - pub(crate) fn minimal_non_dust_internal(&self, dust_relay_fee: u64) -> crate::Amount { +crate::internal_macros::define_extension_trait! { + pub(crate) trait ScriptExtPriv impl for Script { + 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 @@ -532,7 +531,7 @@ mod tmp_priv { crate::Amount::from_sat(sats) } - pub(crate) fn count_sigops_internal(&self, accurate: bool) -> usize { + fn count_sigops_internal(&self, accurate: bool) -> usize { let mut n = 0; let mut pushnum_cache = None; for inst in self.instructions() { @@ -575,7 +574,7 @@ mod tmp_priv { /// 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 { + fn last_opcode(&self) -> Option { match self.instructions().last() { Some(Ok(Instruction::Op(op))) => Some(op), _ => None, @@ -585,7 +584,7 @@ mod tmp_priv { /// 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> { + 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), diff --git a/bitcoin/src/blockdata/script/builder.rs b/bitcoin/src/blockdata/script/builder.rs index 6d4e72806..1261266d6 100644 --- a/bitcoin/src/blockdata/script/builder.rs +++ b/bitcoin/src/blockdata/script/builder.rs @@ -7,6 +7,7 @@ use crate::locktime::absolute; use crate::opcodes::all::*; use crate::opcodes::{self, Opcode}; use crate::prelude::Vec; +use crate::script::{ScriptExt as _, ScriptExtPriv as _}; use crate::Sequence; /// An Object which can be used to construct a script piece by piece. diff --git a/bitcoin/src/blockdata/script/owned.rs b/bitcoin/src/blockdata/script/owned.rs index 99292c118..a6d283729 100644 --- a/bitcoin/src/blockdata/script/owned.rs +++ b/bitcoin/src/blockdata/script/owned.rs @@ -6,7 +6,7 @@ use core::ops::Deref; use hex::FromHex; use internals::ToU64 as _; -use super::{opcode_to_verify, Builder, Instruction, PushBytes, Script}; +use super::{opcode_to_verify, Builder, Instruction, PushBytes, Script, ScriptExtPriv as _}; use crate::opcodes::all::*; use crate::opcodes::{self, Opcode}; use crate::prelude::{Box, Vec}; diff --git a/bitcoin/src/blockdata/script/witness_program.rs b/bitcoin/src/blockdata/script/witness_program.rs index b0d5707c1..f6d66fcf4 100644 --- a/bitcoin/src/blockdata/script/witness_program.rs +++ b/bitcoin/src/blockdata/script/witness_program.rs @@ -15,6 +15,7 @@ use secp256k1::{Secp256k1, Verification}; use super::witness_version::WitnessVersion; use super::{PushBytes, Script, WScriptHash, WitnessScriptSizeError}; use crate::crypto::key::{CompressedPublicKey, TapTweak, TweakedPublicKey, UntweakedPublicKey}; +use crate::script::ScriptExt as _; use crate::taproot::TapNodeHash; /// The minimum byte size of a segregated witness program. diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs index 332a5fdc9..83459e95d 100644 --- a/bitcoin/src/blockdata/transaction.rs +++ b/bitcoin/src/blockdata/transaction.rs @@ -23,7 +23,7 @@ use crate::consensus::{encode, Decodable, Encodable}; use crate::internal_macros::{impl_consensus_encoding, impl_hashencode}; use crate::locktime::absolute::{self, Height, Time}; use crate::prelude::{Borrow, Vec}; -use crate::script::{Script, ScriptBuf}; +use crate::script::{Script, ScriptBuf, ScriptExt as _, ScriptExtPriv as _}; #[cfg(doc)] use crate::sighash::{EcdsaSighashType, TapSighashType}; use crate::witness::Witness; diff --git a/bitcoin/src/blockdata/witness.rs b/bitcoin/src/blockdata/witness.rs index 8df63b0cc..29e2054ee 100644 --- a/bitcoin/src/blockdata/witness.rs +++ b/bitcoin/src/blockdata/witness.rs @@ -13,6 +13,8 @@ use crate::consensus::encode::{Error, MAX_VEC_SIZE}; use crate::consensus::{Decodable, Encodable, WriteExt}; use crate::crypto::ecdsa; use crate::prelude::Vec; +#[cfg(doc)] +use crate::script::ScriptExt as _; use crate::taproot::{self, TAPROOT_ANNEX_PREFIX}; use crate::{Script, VarInt}; diff --git a/bitcoin/src/psbt/mod.rs b/bitcoin/src/psbt/mod.rs index 47ddafcf0..61efaec40 100644 --- a/bitcoin/src/psbt/mod.rs +++ b/bitcoin/src/psbt/mod.rs @@ -25,6 +25,7 @@ use crate::crypto::key::{PrivateKey, PublicKey}; use crate::crypto::{ecdsa, taproot}; use crate::key::{TapTweak, XOnlyPublicKey}; use crate::prelude::{btree_map, BTreeMap, BTreeSet, Borrow, Box, Vec}; +use crate::script::ScriptExt as _; use crate::sighash::{self, EcdsaSighashType, Prevouts, SighashCache}; use crate::transaction::{self, Transaction, TxOut}; use crate::{Amount, FeeRate, TapLeafHash, TapSighashType}; diff --git a/bitcoin/tests/psbt-sign-taproot.rs b/bitcoin/tests/psbt-sign-taproot.rs index 78fbcdd60..9f83d8493 100644 --- a/bitcoin/tests/psbt-sign-taproot.rs +++ b/bitcoin/tests/psbt-sign-taproot.rs @@ -7,6 +7,7 @@ use bitcoin::bip32::{DerivationPath, Fingerprint}; use bitcoin::consensus::encode::serialize_hex; use bitcoin::opcodes::all::OP_CHECKSIG; use bitcoin::psbt::{GetKey, Input, KeyRequest, PsbtSighashType, SignError}; +use bitcoin::script::ScriptExt as _; use bitcoin::taproot::{LeafVersion, TaprootBuilder, TaprootSpendInfo}; use bitcoin::transaction::Version; use bitcoin::{ diff --git a/fuzz/fuzz_targets/bitcoin/deserialize_script.rs b/fuzz/fuzz_targets/bitcoin/deserialize_script.rs index 7e189ab04..05b6e043d 100644 --- a/fuzz/fuzz_targets/bitcoin/deserialize_script.rs +++ b/fuzz/fuzz_targets/bitcoin/deserialize_script.rs @@ -1,6 +1,7 @@ use bitcoin::address::Address; use bitcoin::consensus::encode; -use bitcoin::{script, Network}; +use bitcoin::script::{self, ScriptExt as _}; +use bitcoin::Network; use honggfuzz::fuzz; fn do_test(data: &[u8]) { diff --git a/fuzz/fuzz_targets/bitcoin/script_bytes_to_asm_fmt.rs b/fuzz/fuzz_targets/bitcoin/script_bytes_to_asm_fmt.rs index 3e0bacc63..db021a76d 100644 --- a/fuzz/fuzz_targets/bitcoin/script_bytes_to_asm_fmt.rs +++ b/fuzz/fuzz_targets/bitcoin/script_bytes_to_asm_fmt.rs @@ -1,5 +1,6 @@ use std::fmt; +use bitcoin::script::ScriptExt as _; use honggfuzz::fuzz; // faster than String, we don't need to actually produce the value, just check absence of panics