From 3344cf6be2903018998b78337cb2b9e0304224dd Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Fri, 20 Jan 2023 10:57:29 +1100 Subject: [PATCH 1/8] Favour $reverse instead of $reversed Currently we have two things that are the same but use different identifiers, use `$reverse` instead of `$reversed`. --- hashes/src/internal_macros.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hashes/src/internal_macros.rs b/hashes/src/internal_macros.rs index 48ebd608..bfb05db7 100644 --- a/hashes/src/internal_macros.rs +++ b/hashes/src/internal_macros.rs @@ -53,7 +53,7 @@ pub(crate) use arr_newtype_fmt_impl; /// Arguments: /// /// * `$bits` - number of bits this hash type has -/// * `$reversed` - `bool` - `true` if the hash type should be displayed backwards, `false` +/// * `$reverse` - `bool` - `true` if the hash type should be displayed backwards, `false` /// otherwise. /// * `$gen: $gent` - generic type(s) and trait bound(s) /// @@ -67,7 +67,7 @@ pub(crate) use arr_newtype_fmt_impl; /// `internal_new` is required so that types with more than one field are constructible. /// `internal_engine` is required to initialize the engine for given hash type. macro_rules! hash_trait_impls { - ($bits:expr, $reversed:expr $(, $gen:ident: $gent:ident)*) => { + ($bits:expr, $reverse:expr $(, $gen:ident: $gent:ident)*) => { impl<$($gen: $gent),*> Hash<$($gen),*> { /// Displays hex forwards, regardless of how this type would display it naturally. /// @@ -111,7 +111,7 @@ macro_rules! hash_trait_impls { type Inner = [u8; $bits / 8]; const LEN: usize = $bits / 8; - const DISPLAY_BACKWARD: bool = $reversed; + const DISPLAY_BACKWARD: bool = $reverse; fn engine() -> Self::Engine { Self::internal_engine() @@ -159,14 +159,14 @@ pub(crate) use hash_trait_impls; /// Arguments: /// /// * `$bits` - the number of bits of the hash type -/// * `$reversed` - `true` if the hash should be displayed backwards, `false` otherwise +/// * `$reverse` - `true` if the hash should be displayed backwards, `false` otherwise /// * `$doc` - doc string to put on the type /// * `$schemars` - a literal that goes into `schema_with`. /// /// The `from_engine` free-standing function is still required with this macro. See the doc of /// [`hash_trait_impls`]. macro_rules! hash_type { - ($bits:expr, $reversed:expr, $doc:literal, $schemars:literal) => { + ($bits:expr, $reverse:expr, $doc:literal, $schemars:literal) => { #[doc = $doc] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "schemars", derive(crate::schemars::JsonSchema))] @@ -186,7 +186,7 @@ macro_rules! hash_type { } } - crate::internal_macros::hash_trait_impls!($bits, $reversed); + crate::internal_macros::hash_trait_impls!($bits, $reverse); } } pub(crate) use hash_type; From 5e3abc5e1153494a04e9a2ede132afab4c071d09 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Fri, 20 Jan 2023 16:43:23 +1100 Subject: [PATCH 2/8] Fix feature gating on unit tests Currently we have incorrect feature gating on unit tests and imports leading to unused import warnings. --- hashes/src/hex.rs | 4 +--- hashes/src/sha256d.rs | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/hashes/src/hex.rs b/hashes/src/hex.rs index b244a79c..b907f690 100644 --- a/hashes/src/hex.rs +++ b/hashes/src/hex.rs @@ -204,13 +204,12 @@ impl_fromhex_array!(384); impl_fromhex_array!(512); #[cfg(test)] +#[cfg(any(feature = "std", feature = "alloc"))] mod tests { use super::*; - #[cfg(any(feature = "std", feature = "alloc"))] use internals::hex::exts::DisplayHex; #[test] - #[cfg(any(feature = "std", feature = "alloc"))] fn hex_roundtrip() { let expected = "0123456789abcdef"; let expected_up = "0123456789ABCDEF"; @@ -232,7 +231,6 @@ mod tests { } #[test] - #[cfg(any(feature = "std", feature = "alloc"))] fn hex_error() { let oddlen = "0123456789abcdef0"; let badchar1 = "Z123456789abcdef"; diff --git a/hashes/src/sha256d.rs b/hashes/src/sha256d.rs index 103b264b..90ee2727 100644 --- a/hashes/src/sha256d.rs +++ b/hashes/src/sha256d.rs @@ -43,12 +43,10 @@ fn from_engine(e: sha256::HashEngine) -> Hash { #[cfg(test)] mod tests { - use crate::sha256; - #[test] #[cfg(any(feature = "std", feature = "alloc"))] fn test() { - use crate::{sha256d, Hash, HashEngine}; + use crate::{sha256, sha256d, Hash, HashEngine}; use crate::hex::FromHex; #[derive(Clone)] From 7e85452cd983fcf49907d988710d48c115719f30 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Fri, 20 Jan 2023 11:10:51 +1100 Subject: [PATCH 3/8] hashes: Implement std::error::Error We have old Rust 1.29 error handling code still in `hashes`. Implement `std::error::Error` for the `hex::Error` and `error::Error` types in line with "modern" Rust 1.41.1 error handling. --- hashes/src/error.rs | 12 ++++++++++++ hashes/src/hex.rs | 12 ++++++++++++ hashes/src/impls.rs | 20 +++----------------- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/hashes/src/error.rs b/hashes/src/error.rs index fb393251..790def1d 100644 --- a/hashes/src/error.rs +++ b/hashes/src/error.rs @@ -31,3 +31,15 @@ impl fmt::Display for Error { } } } + +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use self::Error::*; + + match self { + InvalidLength(_, _) => None, + } + } +} diff --git a/hashes/src/hex.rs b/hashes/src/hex.rs index b907f690..8df507c3 100644 --- a/hashes/src/hex.rs +++ b/hashes/src/hex.rs @@ -47,6 +47,18 @@ impl fmt::Display for Error { } } +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use self::Error::*; + + match self { + InvalidChar(_) | OddLengthString(_) | InvalidLength(_, _) => None, + } + } +} + /// Trait for objects that can be deserialized from hex strings. pub trait FromHex: Sized { /// Produces an object from a byte iterator. diff --git a/hashes/src/impls.rs b/hashes/src/impls.rs index b7a7ff7c..41c636c3 100644 --- a/hashes/src/impls.rs +++ b/hashes/src/impls.rs @@ -18,26 +18,12 @@ //! #[cfg(feature = "std")] -use std::{error, io}; +use std::io; #[cfg(not(feature = "std"))] -use core2::{error, io}; +use core2::io; -use crate::{Error, HashEngine, hex, sha1, sha256, sha512, ripemd160, siphash24, hmac}; - -impl error::Error for Error { - #[cfg(feature = "std")] - fn cause(&self) -> Option<&error::Error> { None } - #[cfg(feature = "std")] - fn description(&self) -> &str { "`std::error::description` is deprecated" } -} - -impl error::Error for hex::Error { - #[cfg(feature = "std")] - fn cause(&self) -> Option<&error::Error> { None } - #[cfg(feature = "std")] - fn description(&self) -> &str { "`std::error::description` is deprecated" } -} +use crate::{HashEngine, sha1, sha256, sha512, ripemd160, siphash24, hmac}; impl io::Write for sha1::HashEngine { fn flush(&mut self) -> io::Result<()> { Ok(()) } From 5ab5c264d27e8be4a3d7ed6d8918422237ad7758 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Fri, 20 Jan 2023 11:17:10 +1100 Subject: [PATCH 4/8] Use fully qualified path in macro It is easier to maintain code if macros use the fully qualified path to types and functions instead of relying on code that uses the macro to import said type or function. --- hashes/src/hash160.rs | 2 +- hashes/src/internal_macros.rs | 4 ++-- hashes/src/ripemd160.rs | 2 +- hashes/src/sha1.rs | 2 +- hashes/src/sha256d.rs | 2 +- hashes/src/sha256t.rs | 2 +- hashes/src/sha512.rs | 2 +- hashes/src/sha512_256.rs | 2 +- hashes/src/siphash24.rs | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/hashes/src/hash160.rs b/hashes/src/hash160.rs index 91da3a89..4181c69c 100644 --- a/hashes/src/hash160.rs +++ b/hashes/src/hash160.rs @@ -24,7 +24,7 @@ use core::str; use core::ops::Index; use core::slice::SliceIndex; -use crate::{Error, hex, ripemd160, sha256}; +use crate::{Error, ripemd160, sha256}; crate::internal_macros::hash_type! { 160, diff --git a/hashes/src/internal_macros.rs b/hashes/src/internal_macros.rs index bfb05db7..4f0ff284 100644 --- a/hashes/src/internal_macros.rs +++ b/hashes/src/internal_macros.rs @@ -87,9 +87,9 @@ macro_rules! hash_trait_impls { } impl<$($gen: $gent),*> str::FromStr for Hash<$($gen),*> { - type Err = hex::Error; + type Err = $crate::hex::Error; fn from_str(s: &str) -> Result { - hex::FromHex::from_hex(s) + $crate::hex::FromHex::from_hex(s) } } diff --git a/hashes/src/ripemd160.rs b/hashes/src/ripemd160.rs index 712eecc2..7e75243c 100644 --- a/hashes/src/ripemd160.rs +++ b/hashes/src/ripemd160.rs @@ -25,7 +25,7 @@ use core::convert::TryInto; use core::ops::Index; use core::slice::SliceIndex; -use crate::{Error, HashEngine as _, hex}; +use crate::{Error, HashEngine as _}; crate::internal_macros::hash_type! { 160, diff --git a/hashes/src/sha1.rs b/hashes/src/sha1.rs index d2aa2e5a..44538439 100644 --- a/hashes/src/sha1.rs +++ b/hashes/src/sha1.rs @@ -20,7 +20,7 @@ use core::convert::TryInto; use core::ops::Index; use core::slice::SliceIndex; -use crate::{Error, HashEngine as _, hex}; +use crate::{Error, HashEngine as _}; crate::internal_macros::hash_type! { 160, diff --git a/hashes/src/sha256d.rs b/hashes/src/sha256d.rs index 90ee2727..d55aaf37 100644 --- a/hashes/src/sha256d.rs +++ b/hashes/src/sha256d.rs @@ -19,7 +19,7 @@ use core::str; use core::ops::Index; use core::slice::SliceIndex; -use crate::{Error, hex, sha256}; +use crate::{Error, sha256}; crate::internal_macros::hash_type! { 256, diff --git a/hashes/src/sha256t.rs b/hashes/src/sha256t.rs index 59035542..42ba7d6b 100644 --- a/hashes/src/sha256t.rs +++ b/hashes/src/sha256t.rs @@ -20,7 +20,7 @@ use core::marker::PhantomData; use core::ops::Index; use core::slice::SliceIndex; -use crate::{Error, hex, sha256}; +use crate::{Error, sha256}; type HashEngine = sha256::HashEngine; diff --git a/hashes/src/sha512.rs b/hashes/src/sha512.rs index 6a1b8a72..ffc84805 100644 --- a/hashes/src/sha512.rs +++ b/hashes/src/sha512.rs @@ -25,7 +25,7 @@ use core::convert::TryInto; use core::ops::Index; use core::slice::SliceIndex; -use crate::{Error, HashEngine as _, hex}; +use crate::{Error, HashEngine as _}; crate::internal_macros::hash_trait_impls!(512, false); diff --git a/hashes/src/sha512_256.rs b/hashes/src/sha512_256.rs index 939887c0..4ba40b04 100644 --- a/hashes/src/sha512_256.rs +++ b/hashes/src/sha512_256.rs @@ -28,7 +28,7 @@ use core::str; use core::ops::Index; use core::slice::SliceIndex; -use crate::{hex, sha512, sha512::BLOCK_SIZE, Error}; +use crate::{sha512, sha512::BLOCK_SIZE, Error}; /// Engine to compute SHA512/256 hash function. /// diff --git a/hashes/src/siphash24.rs b/hashes/src/siphash24.rs index e46abec0..2729665a 100644 --- a/hashes/src/siphash24.rs +++ b/hashes/src/siphash24.rs @@ -24,7 +24,7 @@ use core::{cmp, mem, ptr, str}; use core::ops::Index; use core::slice::SliceIndex; -use crate::{Error, Hash as _, HashEngine as _, hex}; +use crate::{Error, Hash as _, HashEngine as _}; crate::internal_macros::hash_type! { 64, From 83e1c40c4d79462e690a7c8e936977c90d36951c Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Fri, 20 Jan 2023 12:33:56 +1100 Subject: [PATCH 5/8] Remove script:: prefix from unambiguous types There is no need to qualify `Script` and `ScriptBuf` with the `script::` prefix, remove it. --- bitcoin/src/address.rs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/bitcoin/src/address.rs b/bitcoin/src/address.rs index 5c04b20c..0d2f13e7 100644 --- a/bitcoin/src/address.rs +++ b/bitcoin/src/address.rs @@ -41,9 +41,9 @@ use crate::blockdata::constants::{ MAX_SCRIPT_ELEMENT_SIZE, PUBKEY_ADDRESS_PREFIX_MAIN, PUBKEY_ADDRESS_PREFIX_TEST, SCRIPT_ADDRESS_PREFIX_MAIN, SCRIPT_ADDRESS_PREFIX_TEST, }; +use crate::blockdata::opcodes; use crate::blockdata::opcodes::all::*; -use crate::blockdata::script::Instruction; -use crate::blockdata::{opcodes, script}; +use crate::blockdata::script::{self, Instruction, Script, ScriptBuf}; use crate::crypto::key::PublicKey; use crate::crypto::schnorr::{TapTweak, TweakedPublicKey, UntweakedPublicKey}; use crate::error::ParseIntError; @@ -432,7 +432,7 @@ impl WitnessProgram { impl Payload { /// Constructs a [Payload] from an output script (`scriptPubkey`). - pub fn from_script(script: &script::Script) -> Result { + pub fn from_script(script: &Script) -> Result { Ok(if script.is_p2pkh() { let mut hash_inner = [0u8; 20]; hash_inner.copy_from_slice(&script.as_bytes()[3..23]); @@ -455,12 +455,12 @@ impl Payload { } /// Generates a script pubkey spending to this [Payload]. - pub fn script_pubkey(&self) -> script::ScriptBuf { + pub fn script_pubkey(&self) -> ScriptBuf { match *self { - Payload::PubkeyHash(ref hash) => script::ScriptBuf::new_p2pkh(hash), - Payload::ScriptHash(ref hash) => script::ScriptBuf::new_p2sh(hash), + Payload::PubkeyHash(ref hash) => ScriptBuf::new_p2pkh(hash), + Payload::ScriptHash(ref hash) => ScriptBuf::new_p2sh(hash), Payload::WitnessProgram(ref prog) => - script::ScriptBuf::new_witness_program(prog) + ScriptBuf::new_witness_program(prog) } } @@ -470,7 +470,7 @@ impl Payload { /// Creates a pay to script hash P2SH payload from a script #[inline] - pub fn p2sh(script: &script::Script) -> Result { + pub fn p2sh(script: &Script) -> Result { if script.len() > MAX_SCRIPT_ELEMENT_SIZE { return Err(Error::ExcessiveScriptSize); } @@ -496,7 +496,7 @@ impl Payload { } /// Create a witness pay to script hash payload. - pub fn p2wsh(script: &script::Script) -> Payload { + pub fn p2wsh(script: &Script) -> Payload { let prog = WitnessProgram::new( WitnessVersion::V0, script.wscript_hash().as_ref().to_vec() @@ -505,7 +505,7 @@ impl Payload { } /// Create a pay to script payload that embeds a witness pay to script hash address - pub fn p2shwsh(script: &script::Script) -> Payload { + pub fn p2shwsh(script: &Script) -> Payload { let ws = script::Builder::new().push_int(0).push_slice(script.wscript_hash().as_ref()).into_script(); @@ -820,7 +820,7 @@ impl Address { /// This address type was introduced with BIP16 and is the popular type to implement multi-sig /// these days. #[inline] - pub fn p2sh(script: &script::Script, network: Network) -> Result { + pub fn p2sh(script: &Script, network: Network) -> Result { Ok(Address::new(network, Payload::p2sh(script)?)) } @@ -845,14 +845,14 @@ impl Address { } /// Creates a witness pay to script hash address. - pub fn p2wsh(script: &script::Script, network: Network) -> Address { + pub fn p2wsh(script: &Script, network: Network) -> Address { Address::new(network, Payload::p2wsh(script)) } /// Creates a pay to script address that embeds a witness pay to script hash address. /// /// This is a segwit address type that looks familiar (as p2sh) to legacy clients. - pub fn p2shwsh(script: &script::Script, network: Network) -> Address { + pub fn p2shwsh(script: &Script, network: Network) -> Address { Address::new(network, Payload::p2shwsh(script)) } @@ -905,12 +905,12 @@ impl Address { pub fn is_standard(&self) -> bool { self.address_type().is_some() } /// Constructs an [`Address`] from an output script (`scriptPubkey`). - pub fn from_script(script: &script::Script, network: Network) -> Result { + pub fn from_script(script: &Script, network: Network) -> Result { Ok(Address::new(network, Payload::from_script(script)?)) } /// Generates a script pubkey spending to this address. - pub fn script_pubkey(&self) -> script::ScriptBuf { self.payload.script_pubkey() } + pub fn script_pubkey(&self) -> ScriptBuf { self.payload.script_pubkey() } /// Creates a URI string *bitcoin:address* optimized to be encoded in QR codes. /// From 3e70c01826e01619bbb121ac01fdafded0ff29ba Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Fri, 20 Jan 2023 15:19:54 +1100 Subject: [PATCH 6/8] Manually format a bunch of vecs In preparation for modifying some unit test data structures, manually format the code so it is uniform. Move elements added to a vec with `vec!` onto a new line so they all line up and one can better see what fields go where. Refactor only, no logic changes. --- bitcoin/src/psbt/mod.rs | 442 +++++++++++++++++++++------------------- 1 file changed, 234 insertions(+), 208 deletions(-) diff --git a/bitcoin/src/psbt/mod.rs b/bitcoin/src/psbt/mod.rs index d239a780..622a6e2e 100644 --- a/bitcoin/src/psbt/mod.rs +++ b/bitcoin/src/psbt/mod.rs @@ -908,17 +908,19 @@ mod tests { unsigned_tx: Transaction { version: 2, lock_time: absolute::LockTime::from_consensus(1257139), - input: vec![TxIn { - previous_output: OutPoint { - txid: Txid::from_hex( - "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126", - ).unwrap(), - vout: 0, - }, - script_sig: ScriptBuf::new(), - sequence: Sequence::ENABLE_LOCKTIME_NO_RBF, - witness: Witness::default(), - }], + input: vec![ + TxIn { + previous_output: OutPoint { + txid: Txid::from_hex( + "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126", + ).unwrap(), + vout: 0, + }, + script_sig: ScriptBuf::new(), + sequence: Sequence::ENABLE_LOCKTIME_NO_RBF, + witness: Witness::default(), + } + ], output: vec![ TxOut { value: 99999699, @@ -980,15 +982,17 @@ mod tests { let tx = Transaction { version: 1, lock_time: absolute::LockTime::ZERO, - input: vec![TxIn { - previous_output: OutPoint { - txid: Txid::from_hex("e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389").unwrap(), - vout: 1, - }, - script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"), - sequence: Sequence::MAX, - witness: Witness::from_slice(&[hex!("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105")]), - }], + input: vec![ + TxIn { + previous_output: OutPoint { + txid: Txid::from_hex("e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389").unwrap(), + vout: 1, + }, + script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"), + sequence: Sequence::MAX, + witness: Witness::from_slice(&[hex!("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105")]), + } + ], output: vec![ TxOut { value: 190303501938, @@ -1032,35 +1036,39 @@ mod tests { proprietary: proprietary.clone(), unknown: unknown.clone(), - inputs: vec![Input { - non_witness_utxo: Some(tx), - witness_utxo: Some(TxOut { - value: 190303501938, - script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"), - }), - sighash_type: Some("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY".parse::().unwrap().into()), - redeem_script: Some(vec![0x51].into()), - witness_script: None, - partial_sigs: vec![( - "0339880dc92394b7355e3d0439fa283c31de7590812ea011c4245c0674a685e883".parse().unwrap(), - "304402204f67e2afb76142d44fae58a2495d33a3419daa26cd0db8d04f3452b63289ac0f022010762a9fb67e94cc5cad9026f6dc99ff7f070f4278d30fbc7d0c869dd38c7fe701".parse().unwrap(), - )].into_iter().collect(), - bip32_derivation: keypaths.clone(), - final_script_witness: Some(Witness::from_slice(&[vec![1, 3], vec![5]])), - ripemd160_preimages: vec![(ripemd160::Hash::hash(&[]), vec![1, 2])].into_iter().collect(), - sha256_preimages: vec![(sha256::Hash::hash(&[]), vec![1, 2])].into_iter().collect(), - hash160_preimages: vec![(hash160::Hash::hash(&[]), vec![1, 2])].into_iter().collect(), - hash256_preimages: vec![(sha256d::Hash::hash(&[]), vec![1, 2])].into_iter().collect(), - proprietary: proprietary.clone(), - unknown: unknown.clone(), - ..Default::default() - }], - outputs: vec![Output { - bip32_derivation: keypaths, - proprietary, - unknown, - ..Default::default() - }], + inputs: vec![ + Input { + non_witness_utxo: Some(tx), + witness_utxo: Some(TxOut { + value: 190303501938, + script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"), + }), + sighash_type: Some("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY".parse::().unwrap().into()), + redeem_script: Some(vec![0x51].into()), + witness_script: None, + partial_sigs: vec![( + "0339880dc92394b7355e3d0439fa283c31de7590812ea011c4245c0674a685e883".parse().unwrap(), + "304402204f67e2afb76142d44fae58a2495d33a3419daa26cd0db8d04f3452b63289ac0f022010762a9fb67e94cc5cad9026f6dc99ff7f070f4278d30fbc7d0c869dd38c7fe701".parse().unwrap(), + )].into_iter().collect(), + bip32_derivation: keypaths.clone(), + final_script_witness: Some(Witness::from_slice(&[vec![1, 3], vec![5]])), + ripemd160_preimages: vec![(ripemd160::Hash::hash(&[]), vec![1, 2])].into_iter().collect(), + sha256_preimages: vec![(sha256::Hash::hash(&[]), vec![1, 2])].into_iter().collect(), + hash160_preimages: vec![(hash160::Hash::hash(&[]), vec![1, 2])].into_iter().collect(), + hash256_preimages: vec![(sha256d::Hash::hash(&[]), vec![1, 2])].into_iter().collect(), + proprietary: proprietary.clone(), + unknown: unknown.clone(), + ..Default::default() + } + ], + outputs: vec![ + Output { + bip32_derivation: keypaths, + proprietary, + unknown, + ..Default::default() + } + ], }; let encoded = serde_json::to_string(&psbt).unwrap(); let decoded: PartiallySignedTransaction = serde_json::from_str(&encoded).unwrap(); @@ -1166,17 +1174,19 @@ mod tests { unsigned_tx: Transaction { version: 2, lock_time: absolute::LockTime::from_consensus(1257139), - input: vec![TxIn { - previous_output: OutPoint { - txid: Txid::from_hex( - "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126", - ).unwrap(), - vout: 0, - }, - script_sig: ScriptBuf::new(), - sequence: Sequence::ENABLE_LOCKTIME_NO_RBF, - witness: Witness::default(), - }], + input: vec![ + TxIn { + previous_output: OutPoint { + txid: Txid::from_hex( + "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126", + ).unwrap(), + vout: 0, + }, + script_sig: ScriptBuf::new(), + sequence: Sequence::ENABLE_LOCKTIME_NO_RBF, + witness: Witness::default(), + } + ], output: vec![ TxOut { value: 99999699, @@ -1193,51 +1203,55 @@ mod tests { proprietary: BTreeMap::new(), unknown: BTreeMap::new(), - inputs: vec![Input { - non_witness_utxo: Some(Transaction { - version: 1, - lock_time: absolute::LockTime::ZERO, - input: vec![TxIn { - previous_output: OutPoint { - txid: Txid::from_hex( - "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389", - ).unwrap(), - vout: 1, - }, - script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"), - sequence: Sequence::MAX, - witness: Witness::from_slice(&[ - hex!("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01"), - hex!("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105"), - ]), - }, - TxIn { - previous_output: OutPoint { - txid: Txid::from_hex( - "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886", - ).unwrap(), - vout: 1, - }, - script_sig: hex_script!("160014fe3e9ef1a745e974d902c4355943abcb34bd5353"), - sequence: Sequence::MAX, - witness: Witness::from_slice(&[ - hex!("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01"), - hex!("0223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab3"), - ]), - }], - output: vec![ - TxOut { - value: 200000000, - script_pubkey: hex_script!("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac"), - }, - TxOut { - value: 190303501938, - script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"), - }, - ], - }), - ..Default::default() - },], + inputs: vec![ + Input { + non_witness_utxo: Some(Transaction { + version: 1, + lock_time: absolute::LockTime::ZERO, + input: vec![ + TxIn { + previous_output: OutPoint { + txid: Txid::from_hex( + "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389", + ).unwrap(), + vout: 1, + }, + script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"), + sequence: Sequence::MAX, + witness: Witness::from_slice(&[ + hex!("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01"), + hex!("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105"), + ]), + }, + TxIn { + previous_output: OutPoint { + txid: Txid::from_hex( + "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886", + ).unwrap(), + vout: 1, + }, + script_sig: hex_script!("160014fe3e9ef1a745e974d902c4355943abcb34bd5353"), + sequence: Sequence::MAX, + witness: Witness::from_slice(&[ + hex!("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01"), + hex!("0223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab3"), + ]), + } + ], + output: vec![ + TxOut { + value: 200000000, + script_pubkey: hex_script!("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac"), + }, + TxOut { + value: 190303501938, + script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"), + }, + ], + }), + ..Default::default() + }, + ], outputs: vec![ Output { ..Default::default() @@ -1486,17 +1500,19 @@ mod tests { unsigned_tx: Transaction { version: 2, lock_time: absolute::LockTime::from_consensus(1257139), - input: vec![TxIn { - previous_output: OutPoint { - txid: Txid::from_hex( - "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126", - ).unwrap(), - vout: 0, - }, - script_sig: ScriptBuf::new(), - sequence: Sequence::ENABLE_LOCKTIME_NO_RBF, - witness: Witness::default(), - }], + input: vec![ + TxIn { + previous_output: OutPoint { + txid: Txid::from_hex( + "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126", + ).unwrap(), + vout: 0, + }, + script_sig: ScriptBuf::new(), + sequence: Sequence::ENABLE_LOCKTIME_NO_RBF, + witness: Witness::default(), + } + ], output: vec![ TxOut { value: 99999699, @@ -1513,51 +1529,55 @@ mod tests { proprietary: Default::default(), unknown: BTreeMap::new(), - inputs: vec![Input { - non_witness_utxo: Some(Transaction { - version: 1, - lock_time: absolute::LockTime::ZERO, - input: vec![TxIn { - previous_output: OutPoint { - txid: Txid::from_hex( - "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389", - ).unwrap(), - vout: 1, - }, - script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"), - sequence: Sequence::MAX, - witness: Witness::from_slice(&[ - hex!("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01"), - hex!("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105"), - ]), - }, - TxIn { - previous_output: OutPoint { - txid: Txid::from_hex( - "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886", - ).unwrap(), - vout: 1, - }, - script_sig: hex_script!("160014fe3e9ef1a745e974d902c4355943abcb34bd5353"), - sequence: Sequence::MAX, - witness: Witness::from_slice(&[ - hex!("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01"), - hex!("0223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab3"), - ]), - }], - output: vec![ - TxOut { - value: 200000000, - script_pubkey: hex_script!("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac"), - }, - TxOut { - value: 190303501938, - script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"), - }, - ], - }), - ..Default::default() - },], + inputs: vec![ + Input { + non_witness_utxo: Some(Transaction { + version: 1, + lock_time: absolute::LockTime::ZERO, + input: vec![ + TxIn { + previous_output: OutPoint { + txid: Txid::from_hex( + "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389", + ).unwrap(), + vout: 1, + }, + script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"), + sequence: Sequence::MAX, + witness: Witness::from_slice(&[ + hex!("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01"), + hex!("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105"), + ]), + }, + TxIn { + previous_output: OutPoint { + txid: Txid::from_hex( + "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886", + ).unwrap(), + vout: 1, + }, + script_sig: hex_script!("160014fe3e9ef1a745e974d902c4355943abcb34bd5353"), + sequence: Sequence::MAX, + witness: Witness::from_slice(&[ + hex!("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01"), + hex!("0223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab3"), + ]), + } + ], + output: vec![ + TxOut { + value: 200000000, + script_pubkey: hex_script!("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac"), + }, + TxOut { + value: 190303501938, + script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"), + }, + ], + }), + ..Default::default() + }, + ], outputs: vec![ Output { ..Default::default() @@ -1656,16 +1676,18 @@ mod tests { unsigned_tx: Transaction { version: 2, lock_time: absolute::LockTime::from_consensus(1257139), - input: vec![TxIn { - previous_output: OutPoint { - txid: Txid::from_hex( - "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126", - ).unwrap(), - vout: 0, - }, - sequence: Sequence::ENABLE_LOCKTIME_NO_RBF, - ..Default::default() - }], + input: vec![ + TxIn { + previous_output: OutPoint { + txid: Txid::from_hex( + "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126", + ).unwrap(), + vout: 0, + }, + sequence: Sequence::ENABLE_LOCKTIME_NO_RBF, + ..Default::default() + } + ], output: vec![ TxOut { value: output_0_val, @@ -1682,43 +1704,47 @@ mod tests { proprietary: BTreeMap::new(), unknown: BTreeMap::new(), - inputs: vec![Input { - non_witness_utxo: Some(Transaction { - version: 1, - lock_time: absolute::LockTime::ZERO, - input: vec![TxIn { - previous_output: OutPoint { - txid: Txid::from_hex( - "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389", - ).unwrap(), - vout: 1, - }, - sequence: Sequence::MAX, - ..Default::default() - }, - TxIn { - previous_output: OutPoint { - txid: Txid::from_hex( - "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886", - ).unwrap(), - vout: 1, - }, - sequence: Sequence::MAX, - ..Default::default() - }], - output: vec![ - TxOut { - value: prev_output_val, - ..Default::default() - }, - TxOut { - value: 190303501938, - ..Default::default() - }, - ], - }), - ..Default::default() - },], + inputs: vec![ + Input { + non_witness_utxo: Some(Transaction { + version: 1, + lock_time: absolute::LockTime::ZERO, + input: vec![ + TxIn { + previous_output: OutPoint { + txid: Txid::from_hex( + "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389", + ).unwrap(), + vout: 1, + }, + sequence: Sequence::MAX, + ..Default::default() + }, + TxIn { + previous_output: OutPoint { + txid: Txid::from_hex( + "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886", + ).unwrap(), + vout: 1, + }, + sequence: Sequence::MAX, + ..Default::default() + } + ], + output: vec![ + TxOut { + value: prev_output_val, + ..Default::default() + }, + TxOut { + value: 190303501938, + ..Default::default() + }, + ], + }), + ..Default::default() + }, + ], outputs: vec![ Output { ..Default::default() From a308e1e2ea5c6ae419d961b8da71cc8a35a92715 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Fri, 20 Jan 2023 11:24:48 +1100 Subject: [PATCH 7/8] Remove FromHex for all types except Vec and array Remove `FromHex` from hash and script types - Remove the `FromHex` implementation from hash types and `ScriptBuf` - Remove the `FromStr` implementation from `ScriptBuf` because it does not roundtrip with `Display`. - Implement a method `from_hex` on `ScriptBuf`. - Implement `FromStr` on hash types using a fixed size array. This leaves `FromHex` implementations only on `Vec` and fixed size arrays. --- bitcoin/examples/ecdsa-psbt.rs | 5 +- bitcoin/examples/taproot-psbt.rs | 7 +- bitcoin/src/address.rs | 42 +++++----- bitcoin/src/bip158.rs | 7 +- bitcoin/src/blockdata/script.rs | 110 ++++++++++++------------- bitcoin/src/blockdata/transaction.rs | 13 ++- bitcoin/src/internal_macros.rs | 21 ----- bitcoin/src/merkle_tree/block.rs | 17 ++-- bitcoin/src/network/message_network.rs | 7 +- bitcoin/src/psbt/mod.rs | 105 +++++++++-------------- bitcoin/src/psbt/serialize.rs | 1 - bitcoin/src/sighash.rs | 8 +- bitcoin/src/taproot.rs | 4 +- bitcoin/tests/psbt.rs | 12 +-- bitcoin/tests/serde.rs | 11 +-- hashes/src/error.rs | 6 +- hashes/src/hash160.rs | 3 +- hashes/src/hex.rs | 15 ---- hashes/src/internal_macros.rs | 10 ++- hashes/src/ripemd160.rs | 3 +- hashes/src/sha1.rs | 3 +- hashes/src/sha256.rs | 4 +- hashes/src/sha256d.rs | 3 +- hashes/src/sha512.rs | 3 +- hashes/src/sha512_256.rs | 3 +- hashes/src/util.rs | 10 ++- 26 files changed, 180 insertions(+), 253 deletions(-) diff --git a/bitcoin/examples/ecdsa-psbt.rs b/bitcoin/examples/ecdsa-psbt.rs index 08e96859..756ac8c3 100644 --- a/bitcoin/examples/ecdsa-psbt.rs +++ b/bitcoin/examples/ecdsa-psbt.rs @@ -37,13 +37,12 @@ use bitcoin::bip32::{ ChildNumber, DerivationPath, ExtendedPrivKey, ExtendedPubKey, Fingerprint, IntoDerivationPath, }; use bitcoin::consensus::encode; -use bitcoin::hashes::hex::FromHex; use bitcoin::locktime::absolute; use bitcoin::psbt::{self, Input, Psbt, PsbtSighashType}; use bitcoin::secp256k1::{Secp256k1, Signing, Verification}; use bitcoin::{ Address, Amount, Network, OutPoint, PublicKey, ScriptBuf, Sequence, Transaction, TxIn, TxOut, - Txid, Witness, + Witness, }; type Result = std::result::Result; @@ -189,7 +188,7 @@ impl WatchOnly { lock_time: absolute::LockTime::ZERO, input: vec![TxIn { previous_output: OutPoint { - txid: Txid::from_hex(INPUT_UTXO_TXID)?, + txid: INPUT_UTXO_TXID.parse()?, vout: INPUT_UTXO_VOUT, }, script_sig: ScriptBuf::new(), diff --git a/bitcoin/examples/taproot-psbt.rs b/bitcoin/examples/taproot-psbt.rs index 5ede35f5..d68bd90d 100644 --- a/bitcoin/examples/taproot-psbt.rs +++ b/bitcoin/examples/taproot-psbt.rs @@ -81,7 +81,6 @@ use std::str::FromStr; use bitcoin::bip32::{ChildNumber, DerivationPath, ExtendedPrivKey, ExtendedPubKey, Fingerprint}; use bitcoin::consensus::encode; use bitcoin::constants::COIN_VALUE; -use bitcoin::hashes::hex::FromHex; use bitcoin::hashes::Hash; use bitcoin::key::XOnlyPublicKey; use bitcoin::opcodes::all::{OP_CHECKSIG, OP_CLTV, OP_DROP}; @@ -93,7 +92,7 @@ use bitcoin::taproot::{ LeafVersion, TapLeafHash, TapSighashHash, TaprootBuilder, TaprootSpendInfo, }; use bitcoin::{ - absolute, script, Address, Amount, Network, OutPoint, ScriptBuf, Transaction, TxIn, TxOut, Txid, Witness, + absolute, script, Address, Amount, Network, OutPoint, ScriptBuf, Transaction, TxIn, TxOut, Witness, }; fn main() -> Result<(), Box> { @@ -239,7 +238,7 @@ fn generate_bip86_key_spend_tx( lock_time: absolute::LockTime::ZERO, input: vec![TxIn { previous_output: OutPoint { - txid: Txid::from_hex(input_utxo.txid)?, + txid: input_utxo.txid.parse()?, vout: input_utxo.vout, }, script_sig: ScriptBuf::new(), @@ -290,7 +289,7 @@ fn generate_bip86_key_spend_tx( vout, &sighash::Prevouts::All(&[TxOut { value: from_amount, - script_pubkey: ScriptBuf::from_str(input_utxo.script_pubkey)?, + script_pubkey: ScriptBuf::from_hex(input_utxo.script_pubkey)?, }]), hash_ty, )?; diff --git a/bitcoin/src/address.rs b/bitcoin/src/address.rs index 0d2f13e7..5b86c7ab 100644 --- a/bitcoin/src/address.rs +++ b/bitcoin/src/address.rs @@ -1133,7 +1133,7 @@ mod tests { use super::*; use crate::crypto::key::PublicKey; - use crate::internal_macros::{hex, hex_into, hex_script}; + use crate::internal_macros::hex; use crate::network::constants::Network::{Bitcoin, Testnet}; fn roundtrips(addr: &Address) { @@ -1160,11 +1160,11 @@ mod tests { #[test] fn test_p2pkh_address_58() { - let addr = Address::new(Bitcoin, Payload::PubkeyHash(hex_into!("162c5ea71c0b23f5b9022ef047c4a86470a5b070"))); + let addr = Address::new(Bitcoin, Payload::PubkeyHash("162c5ea71c0b23f5b9022ef047c4a86470a5b070".parse().unwrap())); assert_eq!( addr.script_pubkey(), - hex_script!("76a914162c5ea71c0b23f5b9022ef047c4a86470a5b07088ac") + ScriptBuf::from_hex("76a914162c5ea71c0b23f5b9022ef047c4a86470a5b07088ac").unwrap() ); assert_eq!(&addr.to_string(), "132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM"); assert_eq!(addr.address_type(), Some(AddressType::P2pkh)); @@ -1173,11 +1173,11 @@ mod tests { #[test] fn test_p2pkh_from_key() { - let key = hex_into!("048d5141948c1702e8c95f438815794b87f706a8d4cd2bffad1dc1570971032c9b6042a0431ded2478b5c9cf2d81c124a5e57347a3c63ef0e7716cf54d613ba183"); + let key = "048d5141948c1702e8c95f438815794b87f706a8d4cd2bffad1dc1570971032c9b6042a0431ded2478b5c9cf2d81c124a5e57347a3c63ef0e7716cf54d613ba183".parse::().unwrap(); let addr = Address::p2pkh(&key, Bitcoin); assert_eq!(&addr.to_string(), "1QJVDzdqb1VpbDK7uDeyVXy9mR27CJiyhY"); - let key = hex_into!("03df154ebfcf29d29cc10d5c2565018bce2d9edbab267c31d2caf44a63056cf99f"); + let key = "03df154ebfcf29d29cc10d5c2565018bce2d9edbab267c31d2caf44a63056cf99f".parse::().unwrap(); let addr = Address::p2pkh(&key, Testnet); assert_eq!(&addr.to_string(), "mqkhEMH6NCeYjFybv7pvFC22MFeaNT9AQC"); assert_eq!(addr.address_type(), Some(AddressType::P2pkh)); @@ -1186,11 +1186,11 @@ mod tests { #[test] fn test_p2sh_address_58() { - let addr = Address::new(Bitcoin, Payload::ScriptHash(hex_into!("162c5ea71c0b23f5b9022ef047c4a86470a5b070"))); + let addr = Address::new(Bitcoin, Payload::ScriptHash("162c5ea71c0b23f5b9022ef047c4a86470a5b070".parse().unwrap())); assert_eq!( addr.script_pubkey(), - hex_script!("a914162c5ea71c0b23f5b9022ef047c4a86470a5b07087") + ScriptBuf::from_hex("a914162c5ea71c0b23f5b9022ef047c4a86470a5b07087").unwrap(), ); assert_eq!(&addr.to_string(), "33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k"); assert_eq!(addr.address_type(), Some(AddressType::P2sh)); @@ -1199,7 +1199,7 @@ mod tests { #[test] fn test_p2sh_parse() { - let script = hex_script!("552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae"); + let script = ScriptBuf::from_hex("552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae").unwrap(); let addr = Address::p2sh(&script, Testnet).unwrap(); assert_eq!(&addr.to_string(), "2N3zXjbwdTcPsJiy8sUK9FhWJhqQCxA8Jjr"); assert_eq!(addr.address_type(), Some(AddressType::P2sh)); @@ -1208,15 +1208,14 @@ mod tests { #[test] fn test_p2sh_parse_for_large_script() { - let script = hex_script!("552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123"); + let script = ScriptBuf::from_hex("552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123").unwrap(); assert_eq!(Address::p2sh(&script, Testnet), Err(Error::ExcessiveScriptSize)); } #[test] fn test_p2wpkh() { // stolen from Bitcoin transaction: b3c8c2b6cfc335abbcb2c7823a8453f55d64b2b5125a9a61e8737230cdb8ce20 - let mut key = - hex_into!("033bc8c83c52df5712229a2f72206d90192366c36428cb0c12b6af98324d97bfbc"); + let mut key = "033bc8c83c52df5712229a2f72206d90192366c36428cb0c12b6af98324d97bfbc".parse::().unwrap(); let addr = Address::p2wpkh(&key, Bitcoin).unwrap(); assert_eq!(&addr.to_string(), "bc1qvzvkjn4q3nszqxrv3nraga2r822xjty3ykvkuw"); assert_eq!(addr.address_type(), Some(AddressType::P2wpkh)); @@ -1230,7 +1229,7 @@ mod tests { #[test] fn test_p2wsh() { // stolen from Bitcoin transaction 5df912fda4becb1c29e928bec8d64d93e9ba8efa9b5b405bd683c86fd2c65667 - let script = hex_script!("52210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae"); + let script = ScriptBuf::from_hex("52210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae").unwrap(); let addr = Address::p2wsh(&script, Bitcoin); assert_eq!( &addr.to_string(), @@ -1243,8 +1242,7 @@ mod tests { #[test] fn test_p2shwpkh() { // stolen from Bitcoin transaction: ad3fd9c6b52e752ba21425435ff3dd361d6ac271531fc1d2144843a9f550ad01 - let mut key = - hex_into!("026c468be64d22761c30cd2f12cbc7de255d592d7904b1bab07236897cc4c2e766"); + let mut key = "026c468be64d22761c30cd2f12cbc7de255d592d7904b1bab07236897cc4c2e766".parse::().unwrap(); let addr = Address::p2shwpkh(&key, Bitcoin).unwrap(); assert_eq!(&addr.to_string(), "3QBRmWNqqBGme9er7fMkGqtZtp4gjMFxhE"); assert_eq!(addr.address_type(), Some(AddressType::P2sh)); @@ -1258,7 +1256,7 @@ mod tests { #[test] fn test_p2shwsh() { // stolen from Bitcoin transaction f9ee2be4df05041d0e0a35d7caa3157495ca4f93b233234c9967b6901dacf7a9 - let script = hex_script!("522103e5529d8eaa3d559903adb2e881eb06c86ac2574ffa503c45f4e942e2a693b33e2102e5f10fcdcdbab211e0af6a481f5532536ec61a5fdbf7183770cf8680fe729d8152ae"); + let script = ScriptBuf::from_hex("522103e5529d8eaa3d559903adb2e881eb06c86ac2574ffa503c45f4e942e2a693b33e2102e5f10fcdcdbab211e0af6a481f5532536ec61a5fdbf7183770cf8680fe729d8152ae").unwrap(); let addr = Address::p2shwsh(&script, Bitcoin); assert_eq!(&addr.to_string(), "36EqgNnsWW94SreZgBWc1ANC6wpFZwirHr"); assert_eq!(addr.address_type(), Some(AddressType::P2sh)); @@ -1417,7 +1415,7 @@ mod tests { assert_eq!(addr.to_string(), into.to_string()); assert_eq!( into.script_pubkey(), - hex_script!("76a914162c5ea71c0b23f5b9022ef047c4a86470a5b07088ac") + ScriptBuf::from_hex("76a914162c5ea71c0b23f5b9022ef047c4a86470a5b07088ac").unwrap() ); let addr = Address::from_str("33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k").unwrap().assume_checked(); @@ -1430,7 +1428,7 @@ mod tests { assert_eq!(addr.to_string(), into.to_string()); assert_eq!( into.script_pubkey(), - hex_script!("a914162c5ea71c0b23f5b9022ef047c4a86470a5b07087") + ScriptBuf::from_hex("a914162c5ea71c0b23f5b9022ef047c4a86470a5b07087").unwrap() ); let addr: Address = @@ -1458,7 +1456,7 @@ mod tests { assert_eq!(addr.to_string(), into.to_string()); assert_eq!( into.script_pubkey(), - hex_script!("00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262") + ScriptBuf::from_hex("00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262").unwrap() ); let addr = Address::from_str("bcrt1q2nfxmhd4n3c8834pj72xagvyr9gl57n5r94fsl").unwrap().assume_checked(); @@ -1471,7 +1469,7 @@ mod tests { assert_eq!(addr.to_string(), into.to_string()); assert_eq!( into.script_pubkey(), - hex_script!("001454d26dddb59c7073c6a197946ea1841951fa7a74") + ScriptBuf::from_hex("001454d26dddb59c7073c6a197946ea1841951fa7a74").unwrap() ); } @@ -1690,10 +1688,10 @@ mod tests { #[test] fn test_fail_address_from_script() { - let bad_p2wpkh = hex_script!("0014dbc5b0a8f9d4353b4b54c3db48846bb15abfec"); + let bad_p2wpkh = ScriptBuf::from_hex("0014dbc5b0a8f9d4353b4b54c3db48846bb15abfec").unwrap(); let bad_p2wsh = - hex_script!("00202d4fa2eb233d008cc83206fa2f4f2e60199000f5b857a835e3172323385623"); - let invalid_segwitv0_script = hex_script!("001161458e330389cd0437ee9fe3641d70cc18"); + ScriptBuf::from_hex("00202d4fa2eb233d008cc83206fa2f4f2e60199000f5b857a835e3172323385623").unwrap(); + let invalid_segwitv0_script = ScriptBuf::from_hex("001161458e330389cd0437ee9fe3641d70cc18").unwrap(); let expected = Err(Error::UnrecognizedScript); assert_eq!(Address::from_script(&bad_p2wpkh, Network::Bitcoin), expected); diff --git a/bitcoin/src/bip158.rs b/bitcoin/src/bip158.rs index b6309d69..8a1e4351 100644 --- a/bitcoin/src/bip158.rs +++ b/bitcoin/src/bip158.rs @@ -561,7 +561,6 @@ mod test { use super::*; use crate::consensus::encode::deserialize; use crate::hash_types::BlockHash; - use crate::hashes::hex::FromHex; use crate::ScriptBuf; use crate::internal_macros::hex; @@ -572,16 +571,16 @@ mod test { let testdata = serde_json::from_str::(data).unwrap().as_array().unwrap().clone(); for t in testdata.iter().skip(1) { - let block_hash = BlockHash::from_hex(t.get(1).unwrap().as_str().unwrap()).unwrap(); + let block_hash = t.get(1).unwrap().as_str().unwrap().parse::().unwrap(); let block: Block = deserialize(&hex!(t.get(2).unwrap().as_str().unwrap())).unwrap(); assert_eq!(block.block_hash(), block_hash); let scripts = t.get(3).unwrap().as_array().unwrap(); let previous_filter_header = - FilterHeader::from_hex(t.get(4).unwrap().as_str().unwrap()).unwrap(); + t.get(4).unwrap().as_str().unwrap().parse::().unwrap(); let filter_content = hex!(t.get(5).unwrap().as_str().unwrap()); let filter_header = - FilterHeader::from_hex(t.get(6).unwrap().as_str().unwrap()).unwrap(); + t.get(6).unwrap().as_str().unwrap().parse::().unwrap(); let mut txmap = HashMap::new(); let mut si = scripts.iter(); diff --git a/bitcoin/src/blockdata/script.rs b/bitcoin/src/blockdata/script.rs index 910082b1..ee496c0f 100644 --- a/bitcoin/src/blockdata/script.rs +++ b/bitcoin/src/blockdata/script.rs @@ -673,21 +673,11 @@ impl fmt::UpperHex for Script { } } -impl hex::FromHex for ScriptBuf { - #[inline] - fn from_byte_iter(iter: I) -> Result - where - I: Iterator> + ExactSizeIterator + DoubleEndedIterator, - { - Vec::from_byte_iter(iter).map(ScriptBuf) - } -} - impl core::str::FromStr for ScriptBuf { type Err = hex::Error; #[inline] fn from_str(s: &str) -> Result { - hex::FromHex::from_hex(s) + ScriptBuf::from_hex(s) } } @@ -1198,7 +1188,15 @@ impl ScriptBuf { .into_script() } - /// Converts byte vector into script. + /// Creates a [`ScriptBuf`] from a hex string. + pub fn from_hex(s: &str) -> Result { + use crate::hashes::hex::FromHex; + + let v = Vec::from_hex(s)?; + Ok(ScriptBuf::from_bytes(v)) + } + + /// Creates a [`ScriptBuf`] from a byte vector. /// /// This method doesn't (re)allocate. pub fn from_bytes(bytes: Vec) -> Self { @@ -2057,7 +2055,7 @@ mod test { use crate::blockdata::opcodes; use crate::crypto::key::PublicKey; use crate::psbt::serialize::Serialize; - use crate::internal_macros::{hex, hex_script}; + use crate::internal_macros::hex; #[test] fn script() { @@ -2401,11 +2399,11 @@ mod test { #[test] fn script_hashes() { - let script = hex_script!("410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac"); + let script = ScriptBuf::from_hex("410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac").unwrap(); assert_eq!(script.script_hash().to_string(), "8292bcfbef1884f73c813dfe9c82fd7e814291ea"); assert_eq!(script.wscript_hash().to_string(), "3e1525eb183ad4f9b3c5fa3175bdca2a52e947b135bbb90383bf9f6408e2c324"); assert_eq!( - hex_script!("20d85a959b0290bf19bb89ed43c916be835475d013da4b362117393e25a48229b8ac").tapscript_leaf_hash().to_string(), + ScriptBuf::from_hex("20d85a959b0290bf19bb89ed43c916be835475d013da4b362117393e25a48229b8ac").unwrap().tapscript_leaf_hash().to_string(), "5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21" ); } @@ -2413,18 +2411,18 @@ mod test { #[test] fn provably_unspendable_test() { // p2pk - assert!(!hex_script!("410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac").is_provably_unspendable()); - assert!(!hex_script!("4104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac").is_provably_unspendable()); + assert!(!ScriptBuf::from_hex("410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac").unwrap().is_provably_unspendable()); + assert!(!ScriptBuf::from_hex("4104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac").unwrap().is_provably_unspendable()); // p2pkhash - assert!(!hex_script!("76a914ee61d57ab51b9d212335b1dba62794ac20d2bcf988ac").is_provably_unspendable()); - assert!(hex_script!("6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87").is_provably_unspendable()); + assert!(!ScriptBuf::from_hex("76a914ee61d57ab51b9d212335b1dba62794ac20d2bcf988ac").unwrap().is_provably_unspendable()); + assert!(ScriptBuf::from_hex("6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87").unwrap().is_provably_unspendable()); } #[test] fn op_return_test() { - assert!(hex_script!("6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87").is_op_return()); - assert!(!hex_script!("76a914ee61d57ab51b9d212335b1dba62794ac20d2bcf988ac").is_op_return()); - assert!(!hex_script!("").is_op_return()); + assert!(ScriptBuf::from_hex("6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87").unwrap().is_op_return()); + assert!(!ScriptBuf::from_hex("76a914ee61d57ab51b9d212335b1dba62794ac20d2bcf988ac").unwrap().is_op_return()); + assert!(!ScriptBuf::from_hex("").unwrap().is_op_return()); } #[test] @@ -2432,7 +2430,7 @@ mod test { fn script_json_serialize() { use serde_json; - let original = hex_script!("827651a0698faaa9a8a7a687"); + let original = ScriptBuf::from_hex("827651a0698faaa9a8a7a687").unwrap(); let json = serde_json::to_value(&original).unwrap(); assert_eq!(json, serde_json::Value::String("827651a0698faaa9a8a7a687".to_owned())); let des = serde_json::from_value::(json).unwrap(); @@ -2441,77 +2439,77 @@ mod test { #[test] fn script_asm() { - assert_eq!(hex_script!("6363636363686868686800").to_asm_string(), + assert_eq!(ScriptBuf::from_hex("6363636363686868686800").unwrap().to_asm_string(), "OP_IF OP_IF OP_IF OP_IF OP_IF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_0"); - assert_eq!(hex_script!("6363636363686868686800").to_asm_string(), + assert_eq!(ScriptBuf::from_hex("6363636363686868686800").unwrap().to_asm_string(), "OP_IF OP_IF OP_IF OP_IF OP_IF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_0"); - assert_eq!(hex_script!("2102715e91d37d239dea832f1460e91e368115d8ca6cc23a7da966795abad9e3b699ac").to_asm_string(), + assert_eq!(ScriptBuf::from_hex("2102715e91d37d239dea832f1460e91e368115d8ca6cc23a7da966795abad9e3b699ac").unwrap().to_asm_string(), "OP_PUSHBYTES_33 02715e91d37d239dea832f1460e91e368115d8ca6cc23a7da966795abad9e3b699 OP_CHECKSIG"); // Elements Alpha peg-out transaction with some signatures removed for brevity. Mainly to test PUSHDATA1 - assert_eq!(hex_script!("0047304402202457e78cc1b7f50d0543863c27de75d07982bde8359b9e3316adec0aec165f2f02200203fd331c4e4a4a02f48cf1c291e2c0d6b2f7078a784b5b3649fca41f8794d401004cf1552103244e602b46755f24327142a0517288cebd159eccb6ccf41ea6edf1f601e9af952103bbbacc302d19d29dbfa62d23f37944ae19853cf260c745c2bea739c95328fcb721039227e83246bd51140fe93538b2301c9048be82ef2fb3c7fc5d78426ed6f609ad210229bf310c379b90033e2ecb07f77ecf9b8d59acb623ab7be25a0caed539e2e6472103703e2ed676936f10b3ce9149fa2d4a32060fb86fa9a70a4efe3f21d7ab90611921031e9b7c6022400a6bb0424bbcde14cff6c016b91ee3803926f3440abf5c146d05210334667f975f55a8455d515a2ef1c94fdfa3315f12319a14515d2a13d82831f62f57ae").to_asm_string(), + assert_eq!(ScriptBuf::from_hex("0047304402202457e78cc1b7f50d0543863c27de75d07982bde8359b9e3316adec0aec165f2f02200203fd331c4e4a4a02f48cf1c291e2c0d6b2f7078a784b5b3649fca41f8794d401004cf1552103244e602b46755f24327142a0517288cebd159eccb6ccf41ea6edf1f601e9af952103bbbacc302d19d29dbfa62d23f37944ae19853cf260c745c2bea739c95328fcb721039227e83246bd51140fe93538b2301c9048be82ef2fb3c7fc5d78426ed6f609ad210229bf310c379b90033e2ecb07f77ecf9b8d59acb623ab7be25a0caed539e2e6472103703e2ed676936f10b3ce9149fa2d4a32060fb86fa9a70a4efe3f21d7ab90611921031e9b7c6022400a6bb0424bbcde14cff6c016b91ee3803926f3440abf5c146d05210334667f975f55a8455d515a2ef1c94fdfa3315f12319a14515d2a13d82831f62f57ae").unwrap().to_asm_string(), "OP_0 OP_PUSHBYTES_71 304402202457e78cc1b7f50d0543863c27de75d07982bde8359b9e3316adec0aec165f2f02200203fd331c4e4a4a02f48cf1c291e2c0d6b2f7078a784b5b3649fca41f8794d401 OP_0 OP_PUSHDATA1 552103244e602b46755f24327142a0517288cebd159eccb6ccf41ea6edf1f601e9af952103bbbacc302d19d29dbfa62d23f37944ae19853cf260c745c2bea739c95328fcb721039227e83246bd51140fe93538b2301c9048be82ef2fb3c7fc5d78426ed6f609ad210229bf310c379b90033e2ecb07f77ecf9b8d59acb623ab7be25a0caed539e2e6472103703e2ed676936f10b3ce9149fa2d4a32060fb86fa9a70a4efe3f21d7ab90611921031e9b7c6022400a6bb0424bbcde14cff6c016b91ee3803926f3440abf5c146d05210334667f975f55a8455d515a2ef1c94fdfa3315f12319a14515d2a13d82831f62f57ae"); // Various weird scripts found in transaction 6d7ed9914625c73c0288694a6819196a27ef6c08f98e1270d975a8e65a3dc09a // which triggerred overflow bugs on 32-bit machines in script formatting in the past. - assert_eq!(hex_script!("01").to_asm_string(), + assert_eq!(ScriptBuf::from_hex("01").unwrap().to_asm_string(), "OP_PUSHBYTES_1 "); - assert_eq!(hex_script!("0201").to_asm_string(), + assert_eq!(ScriptBuf::from_hex("0201").unwrap().to_asm_string(), "OP_PUSHBYTES_2 "); - assert_eq!(hex_script!("4c").to_asm_string(), + assert_eq!(ScriptBuf::from_hex("4c").unwrap().to_asm_string(), ""); - assert_eq!(hex_script!("4c0201").to_asm_string(), + assert_eq!(ScriptBuf::from_hex("4c0201").unwrap().to_asm_string(), "OP_PUSHDATA1 "); - assert_eq!(hex_script!("4d").to_asm_string(), + assert_eq!(ScriptBuf::from_hex("4d").unwrap().to_asm_string(), ""); - assert_eq!(hex_script!("4dffff01").to_asm_string(), + assert_eq!(ScriptBuf::from_hex("4dffff01").unwrap().to_asm_string(), "OP_PUSHDATA2 "); - assert_eq!(hex_script!("4effffffff01").to_asm_string(), + assert_eq!(ScriptBuf::from_hex("4effffffff01").unwrap().to_asm_string(), "OP_PUSHDATA4 "); } #[test] fn script_buf_collect() { assert_eq!(&core::iter::empty::>().collect::(), Script::empty()); - let script = hex_script!("0047304402202457e78cc1b7f50d0543863c27de75d07982bde8359b9e3316adec0aec165f2f02200203fd331c4e4a4a02f48cf1c291e2c0d6b2f7078a784b5b3649fca41f8794d401004cf1552103244e602b46755f24327142a0517288cebd159eccb6ccf41ea6edf1f601e9af952103bbbacc302d19d29dbfa62d23f37944ae19853cf260c745c2bea739c95328fcb721039227e83246bd51140fe93538b2301c9048be82ef2fb3c7fc5d78426ed6f609ad210229bf310c379b90033e2ecb07f77ecf9b8d59acb623ab7be25a0caed539e2e6472103703e2ed676936f10b3ce9149fa2d4a32060fb86fa9a70a4efe3f21d7ab90611921031e9b7c6022400a6bb0424bbcde14cff6c016b91ee3803926f3440abf5c146d05210334667f975f55a8455d515a2ef1c94fdfa3315f12319a14515d2a13d82831f62f57ae"); + let script = ScriptBuf::from_hex("0047304402202457e78cc1b7f50d0543863c27de75d07982bde8359b9e3316adec0aec165f2f02200203fd331c4e4a4a02f48cf1c291e2c0d6b2f7078a784b5b3649fca41f8794d401004cf1552103244e602b46755f24327142a0517288cebd159eccb6ccf41ea6edf1f601e9af952103bbbacc302d19d29dbfa62d23f37944ae19853cf260c745c2bea739c95328fcb721039227e83246bd51140fe93538b2301c9048be82ef2fb3c7fc5d78426ed6f609ad210229bf310c379b90033e2ecb07f77ecf9b8d59acb623ab7be25a0caed539e2e6472103703e2ed676936f10b3ce9149fa2d4a32060fb86fa9a70a4efe3f21d7ab90611921031e9b7c6022400a6bb0424bbcde14cff6c016b91ee3803926f3440abf5c146d05210334667f975f55a8455d515a2ef1c94fdfa3315f12319a14515d2a13d82831f62f57ae").unwrap(); assert_eq!(script.instructions().collect::>().unwrap(), script); } #[test] fn script_p2sh_p2p2k_template() { // random outputs I picked out of the mempool - assert!(hex_script!("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").is_p2pkh()); - assert!(!hex_script!("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").is_p2sh()); - assert!(!hex_script!("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ad").is_p2pkh()); - assert!(!hex_script!("").is_p2pkh()); - assert!(hex_script!("a914acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87").is_p2sh()); - assert!(!hex_script!("a914acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87").is_p2pkh()); - assert!(!hex_script!("a314acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87").is_p2sh()); + assert!(ScriptBuf::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap().is_p2pkh()); + assert!(!ScriptBuf::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap().is_p2sh()); + assert!(!ScriptBuf::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ad").unwrap().is_p2pkh()); + assert!(!ScriptBuf::from_hex("").unwrap().is_p2pkh()); + assert!(ScriptBuf::from_hex("a914acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87").unwrap().is_p2sh()); + assert!(!ScriptBuf::from_hex("a914acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87").unwrap().is_p2pkh()); + assert!(!ScriptBuf::from_hex("a314acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87").unwrap().is_p2sh()); } #[test] fn script_p2pk() { - assert!(hex_script!("21021aeaf2f8638a129a3156fbe7e5ef635226b0bafd495ff03afe2c843d7e3a4b51ac").is_p2pk()); - assert!(hex_script!("410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac").is_p2pk()); + assert!(ScriptBuf::from_hex("21021aeaf2f8638a129a3156fbe7e5ef635226b0bafd495ff03afe2c843d7e3a4b51ac").unwrap().is_p2pk()); + assert!(ScriptBuf::from_hex("410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac").unwrap().is_p2pk()); } #[test] fn p2sh_p2wsh_conversion() { // Test vectors taken from Core tests/data/script_tests.json // bare p2wsh - let redeem_script = hex_script!("410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac"); - let expected_witout = hex_script!("0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64"); + let redeem_script = ScriptBuf::from_hex("410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac").unwrap(); + let expected_witout = ScriptBuf::from_hex("0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64").unwrap(); assert!(redeem_script.to_v0_p2wsh().is_v0_p2wsh()); assert_eq!(redeem_script.to_v0_p2wsh(), expected_witout); // p2sh - let redeem_script = hex_script!("0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"); - let expected_p2shout = hex_script!("a91491b24bf9f5288532960ac687abb035127b1d28a587"); + let redeem_script = ScriptBuf::from_hex("0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8").unwrap(); + let expected_p2shout = ScriptBuf::from_hex("a91491b24bf9f5288532960ac687abb035127b1d28a587").unwrap(); assert!(redeem_script.to_p2sh().is_p2sh()); assert_eq!(redeem_script.to_p2sh(), expected_p2shout); // p2sh-p2wsh - let redeem_script = hex_script!("410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac"); - let expected_witout = hex_script!("0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64"); - let expected_out = hex_script!("a914f386c2ba255cc56d20cfa6ea8b062f8b5994551887"); + let redeem_script = ScriptBuf::from_hex("410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac").unwrap(); + let expected_witout = ScriptBuf::from_hex("0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64").unwrap(); + let expected_out = ScriptBuf::from_hex("a914f386c2ba255cc56d20cfa6ea8b062f8b5994551887").unwrap(); assert!(redeem_script.to_p2sh().is_p2sh()); assert!(redeem_script.to_p2sh().to_v0_p2wsh().is_v0_p2wsh()); assert_eq!(redeem_script.to_v0_p2wsh(), expected_witout); @@ -2528,12 +2526,12 @@ mod test { #[test] fn test_iterator() { - let zero = hex_script!("00"); - let zeropush = hex_script!("0100"); + let zero = ScriptBuf::from_hex("00").unwrap(); + let zeropush = ScriptBuf::from_hex("0100").unwrap(); - let nonminimal = hex_script!("4c0169b2"); // PUSHDATA1 for no reason - let minimal = hex_script!("0169b2"); // minimal - let nonminimal_alt = hex_script!("026900b2"); // non-minimal number but minimal push (should be OK) + let nonminimal = ScriptBuf::from_hex("4c0169b2").unwrap(); // PUSHDATA1 for no reason + let minimal = ScriptBuf::from_hex("0169b2").unwrap(); // minimal + let nonminimal_alt = ScriptBuf::from_hex("026900b2").unwrap(); // non-minimal number but minimal push (should be OK) let v_zero: Result, Error> = zero.instruction_indices_minimal().collect(); let v_zeropush: Result, Error> = zeropush.instruction_indices_minimal().collect(); diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs index ba12104b..6a9bb334 100644 --- a/bitcoin/src/blockdata/transaction.rs +++ b/bitcoin/src/blockdata/transaction.rs @@ -22,7 +22,6 @@ use core::convert::TryFrom; use bitcoin_internals::write_err; use crate::hashes::{self, Hash, sha256d}; -use crate::hashes::hex::FromHex; use crate::blockdata::constants::WITNESS_SCALE_FACTOR; #[cfg(feature="bitcoinconsensus")] use crate::blockdata::script; @@ -175,7 +174,7 @@ impl core::str::FromStr for OutPoint { return Err(ParseOutPointError::Format); } Ok(OutPoint { - txid: Txid::from_hex(&s[..colon]).map_err(ParseOutPointError::Txid)?, + txid: s[..colon].parse().map_err(ParseOutPointError::Txid)?, vout: parse_vout(&s[colon+1..])?, }) } @@ -1163,8 +1162,6 @@ mod tests { use crate::hashes::hex::FromHex; use crate::internal_macros::hex; - use crate::hash_types::*; - const SOME_TX: &str = "0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000"; #[test] @@ -1193,20 +1190,20 @@ mod tests { assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:+42"), Err(ParseOutPointError::VoutNotCanonical)); assert_eq!(OutPoint::from_str("i don't care:1"), - Err(ParseOutPointError::Txid(Txid::from_hex("i don't care").unwrap_err()))); + Err(ParseOutPointError::Txid("i don't care".parse::().unwrap_err()))); assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c945X:1"), - Err(ParseOutPointError::Txid(Txid::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c945X").unwrap_err()))); + Err(ParseOutPointError::Txid("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c945X".parse::().unwrap_err()))); assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:lol"), Err(ParseOutPointError::Vout(crate::parse::int::("lol").unwrap_err()))); assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:42"), Ok(OutPoint{ - txid: Txid::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456").unwrap(), + txid: "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456".parse().unwrap(), vout: 42, })); assert_eq!(OutPoint::from_str("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:0"), Ok(OutPoint{ - txid: Txid::from_hex("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456").unwrap(), + txid: "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456".parse().unwrap(), vout: 0, })); } diff --git a/bitcoin/src/internal_macros.rs b/bitcoin/src/internal_macros.rs index 0afc9198..4a838472 100644 --- a/bitcoin/src/internal_macros.rs +++ b/bitcoin/src/internal_macros.rs @@ -52,7 +52,6 @@ pub(crate) use test_macros::*; #[cfg(test)] mod test_macros { use crate::hashes::hex::FromHex; - use crate::PublicKey; /// Trait used to create a value from hex string for testing purposes. pub(crate) trait TestFromHex { @@ -68,29 +67,9 @@ mod test_macros { fn test_from_hex(hex: &str) -> Self { Self::from_hex(hex).unwrap() } } - impl TestFromHex for PublicKey { - fn test_from_hex(hex: &str) -> Self { - PublicKey::from_slice(&Vec::from_hex(hex).unwrap()).unwrap() - } - } - macro_rules! hex (($hex:expr) => ( as hashes::hex::FromHex>::from_hex($hex).unwrap())); pub(crate) use hex; - macro_rules! hex_into { - ($hex:expr) => { - $crate::internal_macros::hex_into!(_, $hex) - }; - ($type:ty, $hex:expr) => { - <$type as $crate::internal_macros::TestFromHex>::test_from_hex($hex) - }; - } - pub(crate) use hex_into; - - // Script is commonly used in places where inference may fail - macro_rules! hex_script (($hex:expr) => ($crate::internal_macros::hex_into!($crate::ScriptBuf, $hex))); - pub(crate) use hex_script; - // For types that can't use TestFromHex due to coherence rules or reversed hex macro_rules! hex_from_slice { ($hex:expr) => { diff --git a/bitcoin/src/merkle_tree/block.rs b/bitcoin/src/merkle_tree/block.rs index d2b74483..8b9727c7 100644 --- a/bitcoin/src/merkle_tree/block.rs +++ b/bitcoin/src/merkle_tree/block.rs @@ -32,8 +32,7 @@ //! assert!(mb.extract_matches(&mut matches, &mut index).is_ok()); //! assert_eq!(1, matches.len()); //! assert_eq!( -//! Txid::from_hex( -//! "5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2").unwrap(), +//! "5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2".parse::().unwrap(), //! matches[0] //! ); //! assert_eq!(1, index.len()); @@ -163,7 +162,7 @@ impl PartialMerkleTree { /// "5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2", /// ] /// .iter() - /// .map(|hex| Txid::from_hex(hex).unwrap()) + /// .map(|hex| hex.parse::().unwrap()) /// .collect(); /// /// // Select the second transaction @@ -426,8 +425,7 @@ impl MerkleBlock { /// let block: Block = bitcoin::consensus::deserialize(&block_bytes).unwrap(); /// /// // Create a merkle block containing a single transaction - /// let txid = Txid::from_hex( - /// "5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2").unwrap(); + /// let txid = "5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2".parse::().unwrap(); /// let match_txids: Vec = vec![txid].into_iter().collect(); /// let mb = MerkleBlock::from_block_with_predicate(&block, |t| match_txids.contains(t)); /// @@ -506,7 +504,6 @@ mod tests { use crate::consensus::encode::{deserialize, serialize}; #[cfg(feature = "rand-std")] use crate::hash_types::TxMerkleNode; - use crate::hashes::hex::FromHex; #[cfg(feature = "rand-std")] use crate::hashes::Hash; use crate::internal_macros::hex; @@ -551,7 +548,7 @@ mod tests { let mut rng = thread_rng(); // Create some fake tx ids let tx_ids = (1..=tx_count) - .map(|i| Txid::from_hex(&format!("{:064x}", i)).unwrap()) + .map(|i| format!("{:064x}", i).parse::().unwrap()) .collect::>(); // Calculate the merkle root and height @@ -625,7 +622,7 @@ mod tests { // Create some fake tx ids with the last 2 hashes repeating let txids: Vec = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 10] .iter() - .map(|i| Txid::from_hex(&format!("{:064x}", i)).unwrap()) + .map(|i| format!("{:064x}", i).parse::().unwrap()) .collect(); let matches = @@ -670,7 +667,7 @@ mod tests { "f9fc751cb7dc372406a9f8d738d5e6f8f63bab71986a39cf36ee70ee17036d07", ] .iter() - .map(|hex| Txid::from_hex(hex).unwrap()) + .map(|hex| hex.parse::().unwrap()) .collect(); let txid1 = txids[0]; @@ -704,7 +701,7 @@ mod tests { let block = get_block_13b8a(); let txids: Vec = ["c0ffee00003bafa802c8aa084379aa98d9fcd632ddc2ed9782b586ec87451f20"] .iter() - .map(|hex| Txid::from_hex(hex).unwrap()) + .map(|hex| hex.parse::().unwrap()) .collect(); let merkle_block = MerkleBlock::from_block_with_predicate(&block, |t| txids.contains(t)); diff --git a/bitcoin/src/network/message_network.rs b/bitcoin/src/network/message_network.rs index 904dc1de..e12257b9 100644 --- a/bitcoin/src/network/message_network.rs +++ b/bitcoin/src/network/message_network.rs @@ -143,8 +143,7 @@ impl_consensus_encoding!(Reject, message, ccode, reason, hash); mod tests { use super::{Reject, RejectReason, VersionMessage}; use crate::consensus::encode::{deserialize, serialize}; - use crate::hashes::hex::FromHex; - use crate::hashes::sha256d::Hash; + use crate::hashes::sha256d; use crate::internal_macros::hex; use crate::network::constants::ServiceFlags; @@ -184,7 +183,7 @@ mod tests { assert_eq!(RejectReason::Duplicate, conflict.ccode); assert_eq!("txn-mempool-conflict", conflict.reason); assert_eq!( - Hash::from_hex("0470f4f2dc4191221b59884bcffaaf00932748ab46356a80413c0b86d354df05") + "0470f4f2dc4191221b59884bcffaaf00932748ab46356a80413c0b86d354df05".parse::() .unwrap(), conflict.hash ); @@ -194,7 +193,7 @@ mod tests { assert_eq!(RejectReason::NonStandard, nonfinal.ccode); assert_eq!("non-final", nonfinal.reason); assert_eq!( - Hash::from_hex("0b46a539138b5fde4e341b37f2d945c23d41193b30caa7fcbd8bdb836cbe9b25") + "0b46a539138b5fde4e341b37f2d945c23d41193b30caa7fcbd8bdb836cbe9b25".parse::() .unwrap(), nonfinal.hash ); diff --git a/bitcoin/src/psbt/mod.rs b/bitcoin/src/psbt/mod.rs index 622a6e2e..f493f0b0 100644 --- a/bitcoin/src/psbt/mod.rs +++ b/bitcoin/src/psbt/mod.rs @@ -812,9 +812,7 @@ mod tests { use super::*; use crate::blockdata::locktime::absolute; - 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}; @@ -827,7 +825,7 @@ mod tests { use crate::bip32::{ChildNumber, ExtendedPrivKey, ExtendedPubKey, KeySource}; use crate::psbt::map::{Output, Input}; use crate::psbt::raw; - use crate::internal_macros::{hex, hex_script}; + use crate::internal_macros::hex; use std::collections::BTreeMap; use crate::blockdata::witness::Witness; @@ -891,8 +889,8 @@ mod tests { hd_keypaths.insert(pk.public_key, (fprint, dpath.into())); let expected: Output = Output { - redeem_script: Some(hex_script!("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac")), - witness_script: Some(hex_script!("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787")), + redeem_script: Some(ScriptBuf::from_hex("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap()), + witness_script: Some(ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap()), bip32_derivation: hd_keypaths, ..Default::default() }; @@ -911,9 +909,7 @@ mod tests { input: vec![ TxIn { previous_output: OutPoint { - txid: Txid::from_hex( - "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126", - ).unwrap(), + txid: "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126".parse().unwrap(), vout: 0, }, script_sig: ScriptBuf::new(), @@ -924,15 +920,11 @@ mod tests { output: vec![ TxOut { value: 99999699, - script_pubkey: hex_script!( - "76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac" - ), + script_pubkey: ScriptBuf::from_hex("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap(), }, TxOut { value: 100000000, - script_pubkey: hex_script!( - "a9143545e6e33b832c47050f24d3eeb93c9c03948bc787" - ), + script_pubkey: ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(), }, ], }, @@ -976,7 +968,6 @@ mod tests { //! Create a full PSBT value with various fields filled and make sure it can be JSONized. use crate::hashes::sha256d; use crate::psbt::map::Input; - use crate::sighash::EcdsaSighashType; // create some values to use in the PSBT let tx = Transaction { @@ -985,10 +976,10 @@ mod tests { input: vec![ TxIn { previous_output: OutPoint { - txid: Txid::from_hex("e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389").unwrap(), + txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389".parse().unwrap(), vout: 1, }, - script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"), + script_sig: ScriptBuf::from_hex("160014be18d152a9b012039daf3da7de4f53349eecb985").unwrap(), sequence: Sequence::MAX, witness: Witness::from_slice(&[hex!("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105")]), } @@ -996,7 +987,7 @@ mod tests { output: vec![ TxOut { value: 190303501938, - script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"), + script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(), }, ], }; @@ -1041,9 +1032,9 @@ mod tests { non_witness_utxo: Some(tx), witness_utxo: Some(TxOut { value: 190303501938, - script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"), + script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(), }), - sighash_type: Some("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY".parse::().unwrap().into()), + sighash_type: Some("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY".parse::().unwrap()), redeem_script: Some(vec![0x51].into()), witness_script: None, partial_sigs: vec![( @@ -1076,12 +1067,11 @@ mod tests { } mod bip_vectors { + use super::*; + #[cfg(feature = "base64")] use std::str::FromStr; - use crate::hashes::hex::FromHex; - use crate::hash_types::Txid; - use crate::blockdata::script::ScriptBuf; use crate::blockdata::transaction::{Transaction, TxIn, TxOut, OutPoint, Sequence}; use crate::blockdata::locktime::absolute; @@ -1090,7 +1080,6 @@ mod tests { use crate::sighash::EcdsaSighashType; use std::collections::BTreeMap; use crate::blockdata::witness::Witness; - use crate::internal_macros::{hex, hex_script}; #[test] #[should_panic(expected = "InvalidMagic")] @@ -1177,9 +1166,7 @@ mod tests { input: vec![ TxIn { previous_output: OutPoint { - txid: Txid::from_hex( - "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126", - ).unwrap(), + txid: "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126".parse().unwrap(), vout: 0, }, script_sig: ScriptBuf::new(), @@ -1190,11 +1177,11 @@ mod tests { output: vec![ TxOut { value: 99999699, - script_pubkey: hex_script!("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac"), + script_pubkey: ScriptBuf::from_hex("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap(), }, TxOut { value: 100000000, - script_pubkey: hex_script!("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787"), + script_pubkey: ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(), }, ], }, @@ -1211,12 +1198,10 @@ mod tests { input: vec![ TxIn { previous_output: OutPoint { - txid: Txid::from_hex( - "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389", - ).unwrap(), + txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389".parse().unwrap(), vout: 1, }, - script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"), + script_sig: ScriptBuf::from_hex("160014be18d152a9b012039daf3da7de4f53349eecb985").unwrap(), sequence: Sequence::MAX, witness: Witness::from_slice(&[ hex!("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01"), @@ -1225,12 +1210,10 @@ mod tests { }, TxIn { previous_output: OutPoint { - txid: Txid::from_hex( - "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886", - ).unwrap(), + txid: "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886".parse().unwrap(), vout: 1, }, - script_sig: hex_script!("160014fe3e9ef1a745e974d902c4355943abcb34bd5353"), + script_sig: ScriptBuf::from_hex("160014fe3e9ef1a745e974d902c4355943abcb34bd5353").unwrap(), sequence: Sequence::MAX, witness: Witness::from_slice(&[ hex!("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01"), @@ -1241,11 +1224,11 @@ mod tests { output: vec![ TxOut { value: 200000000, - script_pubkey: hex_script!("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac"), + script_pubkey: ScriptBuf::from_hex("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac").unwrap(), }, TxOut { value: 190303501938, - script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"), + script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(), }, ], }), @@ -1285,7 +1268,7 @@ mod tests { assert!(&psbt.inputs[0].final_script_sig.is_some()); let redeem_script = psbt.inputs[1].redeem_script.as_ref().unwrap(); - let expected_out = hex_script!("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787"); + let expected_out = ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(); assert!(redeem_script.is_v0_p2wpkh()); assert_eq!( @@ -1331,7 +1314,7 @@ mod tests { assert!(&psbt.inputs[1].final_script_sig.is_none()); let redeem_script = psbt.inputs[1].redeem_script.as_ref().unwrap(); - let expected_out = hex_script!("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787"); + let expected_out = ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(); assert!(redeem_script.is_v0_p2wpkh()); assert_eq!( @@ -1355,7 +1338,7 @@ mod tests { assert!(&psbt.inputs[0].final_script_sig.is_none()); let redeem_script = psbt.inputs[0].redeem_script.as_ref().unwrap(); - let expected_out = hex_script!("a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87"); + let expected_out = ScriptBuf::from_hex("a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87").unwrap(); assert!(redeem_script.is_v0_p2wsh()); assert_eq!( @@ -1376,7 +1359,7 @@ mod tests { let tx = &psbt.unsigned_tx; assert_eq!( tx.txid(), - Txid::from_hex("75c5c9665a570569ad77dd1279e6fd4628a093c4dcbf8d41532614044c14c115").unwrap(), + "75c5c9665a570569ad77dd1279e6fd4628a093c4dcbf8d41532614044c14c115".parse().unwrap(), ); let mut unknown: BTreeMap> = BTreeMap::new(); @@ -1503,9 +1486,7 @@ mod tests { input: vec![ TxIn { previous_output: OutPoint { - txid: Txid::from_hex( - "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126", - ).unwrap(), + txid: "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126".parse().unwrap(), vout: 0, }, script_sig: ScriptBuf::new(), @@ -1516,11 +1497,11 @@ mod tests { output: vec![ TxOut { value: 99999699, - script_pubkey: hex_script!("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac"), + script_pubkey: ScriptBuf::from_hex("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap(), }, TxOut { value: 100000000, - script_pubkey: hex_script!("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787"), + script_pubkey: ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(), }, ], }, @@ -1537,12 +1518,10 @@ mod tests { input: vec![ TxIn { previous_output: OutPoint { - txid: Txid::from_hex( - "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389", - ).unwrap(), + txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389".parse().unwrap(), vout: 1, }, - script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"), + script_sig: ScriptBuf::from_hex("160014be18d152a9b012039daf3da7de4f53349eecb985").unwrap(), sequence: Sequence::MAX, witness: Witness::from_slice(&[ hex!("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01"), @@ -1551,12 +1530,10 @@ mod tests { }, TxIn { previous_output: OutPoint { - txid: Txid::from_hex( - "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886", - ).unwrap(), + txid: "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886".parse().unwrap(), vout: 1, }, - script_sig: hex_script!("160014fe3e9ef1a745e974d902c4355943abcb34bd5353"), + script_sig: ScriptBuf::from_hex("160014fe3e9ef1a745e974d902c4355943abcb34bd5353").unwrap(), sequence: Sequence::MAX, witness: Witness::from_slice(&[ hex!("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01"), @@ -1567,11 +1544,11 @@ mod tests { output: vec![ TxOut { value: 200000000, - script_pubkey: hex_script!("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac"), + script_pubkey: ScriptBuf::from_hex("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac").unwrap(), }, TxOut { value: 190303501938, - script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"), + script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(), }, ], }), @@ -1679,9 +1656,7 @@ mod tests { input: vec![ TxIn { previous_output: OutPoint { - txid: Txid::from_hex( - "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126", - ).unwrap(), + txid: "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126".parse().unwrap(), vout: 0, }, sequence: Sequence::ENABLE_LOCKTIME_NO_RBF, @@ -1712,9 +1687,7 @@ mod tests { input: vec![ TxIn { previous_output: OutPoint { - txid: Txid::from_hex( - "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389", - ).unwrap(), + txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389".parse().unwrap(), vout: 1, }, sequence: Sequence::MAX, @@ -1722,9 +1695,7 @@ mod tests { }, TxIn { previous_output: OutPoint { - txid: Txid::from_hex( - "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886", - ).unwrap(), + txid: "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886".parse().unwrap(), vout: 1, }, sequence: Sequence::MAX, diff --git a/bitcoin/src/psbt/serialize.rs b/bitcoin/src/psbt/serialize.rs index e31bce6a..47a60a64 100644 --- a/bitcoin/src/psbt/serialize.rs +++ b/bitcoin/src/psbt/serialize.rs @@ -436,7 +436,6 @@ fn key_source_len(key_source: &KeySource) -> usize { mod tests { use core::convert::TryFrom; - use crate::hashes::hex::FromHex; use super::*; // Composes tree matching a given depth map, filled with dumb script leafs, diff --git a/bitcoin/src/sighash.rs b/bitcoin/src/sighash.rs index 961ba497..226df4e7 100644 --- a/bitcoin/src/sighash.rs +++ b/bitcoin/src/sighash.rs @@ -1057,7 +1057,7 @@ mod tests { use crate::hash_types::Sighash; use crate::hashes::hex::FromHex; use crate::hashes::{Hash, HashEngine}; - use crate::internal_macros::{hex, hex_from_slice, hex_script}; + use crate::internal_macros::{hex, hex_from_slice}; use crate::network::constants::Network; use crate::taproot::{TapLeafHash, TapSighashHash}; @@ -1347,7 +1347,7 @@ mod tests { let script_inner = ScriptBuf::from_hex(script_hex).unwrap(); Some(ScriptPath::with_defaults(&script_inner).leaf_hash()) } - (_, Some(script_leaf_hash)) => Some(TapLeafHash::from_hex(script_leaf_hash).unwrap()), + (_, Some(script_leaf_hash)) => Some(script_leaf_hash.parse::().unwrap()), _ => None, }; // All our tests use the default `0xFFFFFFFF` codeseparator value @@ -1689,14 +1689,14 @@ mod tests { 05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac00000000"), ).unwrap(); - let witness_script = hex_script!( + let witness_script = ScriptBuf::from_hex( "56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28\ bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b\ 9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58\ c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b1486\ 2c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b\ 56ae" - ); + ).unwrap(); let value = 987654321; let mut cache = SighashCache::new(&tx); diff --git a/bitcoin/src/taproot.rs b/bitcoin/src/taproot.rs index 1c7dd323..0a7d536e 100644 --- a/bitcoin/src/taproot.rs +++ b/bitcoin/src/taproot.rs @@ -1394,7 +1394,7 @@ mod test { builder = process_script_trees(leaf, builder, leaves, depth + 1); } } else { - let script = ScriptBuf::from_str(v["script"].as_str().unwrap()).unwrap(); + let script = ScriptBuf::from_hex(v["script"].as_str().unwrap()).unwrap(); let ver = LeafVersion::from_consensus(v["leafVersion"].as_u64().unwrap() as u8).unwrap(); leaves.push((script.clone(), ver)); @@ -1446,7 +1446,7 @@ mod test { let expected_tweak = TapTweakHash::from_str(arr["intermediary"]["tweak"].as_str().unwrap()).unwrap(); let expected_spk = - ScriptBuf::from_str(arr["expected"]["scriptPubKey"].as_str().unwrap()).unwrap(); + ScriptBuf::from_hex(arr["expected"]["scriptPubKey"].as_str().unwrap()).unwrap(); let expected_addr = Address::from_str(arr["expected"]["bip350Address"].as_str().unwrap()).unwrap().assume_checked(); diff --git a/bitcoin/tests/psbt.rs b/bitcoin/tests/psbt.rs index e78b0b54..354a6a30 100644 --- a/bitcoin/tests/psbt.rs +++ b/bitcoin/tests/psbt.rs @@ -13,14 +13,14 @@ use bitcoin::psbt::{Psbt, PsbtSighashType}; use bitcoin::secp256k1::{self, Secp256k1}; use bitcoin::{ absolute, Amount, Denomination, Network, OutPoint, PrivateKey, PublicKey, ScriptBuf, Sequence, - Transaction, TxIn, TxOut, Txid, Witness, + Transaction, TxIn, TxOut, Witness, }; const NETWORK: Network = Network::Testnet; macro_rules! hex_script { ($s:expr) => { - ::from_str($s).unwrap() + ::from_hex($s).unwrap() }; } @@ -166,7 +166,7 @@ fn create_transaction() -> Transaction { input: vec![ TxIn { previous_output: OutPoint { - txid: Txid::from_hex(input_0.txid).expect("failed to parse txid"), + txid: input_0.txid.parse().expect("failed to parse txid"), vout: input_0.index, }, script_sig: ScriptBuf::new(), @@ -175,7 +175,7 @@ fn create_transaction() -> Transaction { }, TxIn { previous_output: OutPoint { - txid: Txid::from_hex(input_1.txid).expect("failed to parse txid"), + txid: input_1.txid.parse().expect("failed to parse txid"), vout: input_1.index, }, script_sig: ScriptBuf::new(), @@ -188,14 +188,14 @@ fn create_transaction() -> Transaction { value: Amount::from_str_in(output_0.amount, Denomination::Bitcoin) .expect("failed to parse amount") .to_sat(), - script_pubkey: ScriptBuf::from_str(output_0.script_pubkey) + script_pubkey: ScriptBuf::from_hex(output_0.script_pubkey) .expect("failed to parse script"), }, TxOut { value: Amount::from_str_in(output_1.amount, Denomination::Bitcoin) .expect("failed to parse amount") .to_sat(), - script_pubkey: ScriptBuf::from_str(output_1.script_pubkey) + script_pubkey: ScriptBuf::from_hex(output_1.script_pubkey) .expect("failed to parse script"), }, ], diff --git a/bitcoin/tests/serde.rs b/bitcoin/tests/serde.rs index cb0ab6d5..47fccf67 100644 --- a/bitcoin/tests/serde.rs +++ b/bitcoin/tests/serde.rs @@ -226,13 +226,10 @@ fn serde_regression_psbt() { lock_time: absolute::LockTime::ZERO, input: vec![TxIn { previous_output: OutPoint { - txid: Txid::from_hex( - "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389", - ) - .unwrap(), + txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389".parse::().unwrap(), vout: 1, }, - script_sig: ScriptBuf::from_str("160014be18d152a9b012039daf3da7de4f53349eecb985").unwrap(), + script_sig: ScriptBuf::from_hex("160014be18d152a9b012039daf3da7de4f53349eecb985").unwrap(), sequence: Sequence::from_consensus(4294967295), witness: Witness::from_slice(&[Vec::from_hex( "03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105", @@ -241,7 +238,7 @@ fn serde_regression_psbt() { }], output: vec![TxOut { value: 190303501938, - script_pubkey: ScriptBuf::from_str("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587") + script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587") .unwrap(), }], }; @@ -286,7 +283,7 @@ fn serde_regression_psbt() { non_witness_utxo: Some(tx), witness_utxo: Some(TxOut { value: 190303501938, - script_pubkey: ScriptBuf::from_str("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(), + script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(), }), sighash_type: Some(PsbtSighashType::from(EcdsaSighashType::from_str("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY").unwrap())), redeem_script: Some(vec![0x51].into()), diff --git a/hashes/src/error.rs b/hashes/src/error.rs index 790def1d..636edb32 100644 --- a/hashes/src/error.rs +++ b/hashes/src/error.rs @@ -26,8 +26,10 @@ pub enum Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Error::InvalidLength(ell, ell2) => write!(f, "bad slice length {} (expected {})", ell2, ell), + use self::Error::*; + + match self { + InvalidLength(ref ell, ref ell2) => write!(f, "invalid slice length {} (expected {})", ell2, ell), } } } diff --git a/hashes/src/hash160.rs b/hashes/src/hash160.rs index 4181c69c..a6b54b53 100644 --- a/hashes/src/hash160.rs +++ b/hashes/src/hash160.rs @@ -52,7 +52,6 @@ mod tests { #[cfg(any(feature = "std", feature = "alloc"))] fn test() { use crate::{hash160, Hash, HashEngine}; - use crate::hex::FromHex; #[derive(Clone)] #[cfg(any(feature = "std", feature = "alloc"))] @@ -87,7 +86,7 @@ mod tests { for test in tests { // Hash through high-level API, check hex encoding/decoding let hash = hash160::Hash::hash(&test.input[..]); - assert_eq!(hash, hash160::Hash::from_hex(test.output_str).expect("parse hex")); + assert_eq!(hash, test.output_str.parse::().expect("parse hex")); assert_eq!(&hash[..], &test.output[..]); assert_eq!(&hash.to_string(), &test.output_str); diff --git a/hashes/src/hex.rs b/hashes/src/hex.rs index 8df507c3..c7167192 100644 --- a/hashes/src/hex.rs +++ b/hashes/src/hex.rs @@ -24,7 +24,6 @@ use std::io; use core2::io; use core::{fmt, str}; -use crate::Hash; /// Hex decoding error. #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -72,20 +71,6 @@ pub trait FromHex: Sized { } } -impl FromHex for T { - fn from_byte_iter(iter: I) -> Result - where - I: Iterator> + ExactSizeIterator + DoubleEndedIterator, - { - let inner = if Self::DISPLAY_BACKWARD { - T::Inner::from_byte_iter(iter.rev())? - } else { - T::Inner::from_byte_iter(iter)? - }; - Ok(Hash::from_inner(inner)) - } -} - /// Iterator over a hex-encoded string slice which decodes hex and yields bytes. pub struct HexIterator<'a> { /// The `Bytes` iterator whose next two bytes will be decoded to yield diff --git a/hashes/src/internal_macros.rs b/hashes/src/internal_macros.rs index 4f0ff284..1d08743d 100644 --- a/hashes/src/internal_macros.rs +++ b/hashes/src/internal_macros.rs @@ -89,7 +89,15 @@ macro_rules! hash_trait_impls { impl<$($gen: $gent),*> str::FromStr for Hash<$($gen),*> { type Err = $crate::hex::Error; fn from_str(s: &str) -> Result { - $crate::hex::FromHex::from_hex(s) + use $crate::hex::{FromHex, HexIterator}; + use $crate::Hash; + + let inner: [u8; $bits / 8] = if $reverse { + FromHex::from_byte_iter(HexIterator::new(s)?.rev())? + } else { + FromHex::from_byte_iter(HexIterator::new(s)?)? + }; + Ok(Self::from_inner(inner)) } } diff --git a/hashes/src/ripemd160.rs b/hashes/src/ripemd160.rs index 7e75243c..afc2aa83 100644 --- a/hashes/src/ripemd160.rs +++ b/hashes/src/ripemd160.rs @@ -408,7 +408,6 @@ mod tests { #[cfg(any(feature = "std", feature = "alloc"))] fn test() { use crate::{Hash, HashEngine, ripemd160}; - use crate::hex::FromHex; #[derive(Clone)] struct Test { @@ -470,7 +469,7 @@ mod tests { for test in tests { // Hash through high-level API, check hex encoding/decoding let hash = ripemd160::Hash::hash(test.input.as_bytes()); - assert_eq!(hash, ripemd160::Hash::from_hex(test.output_str).expect("parse hex")); + assert_eq!(hash, test.output_str.parse::().expect("parse hex")); assert_eq!(&hash[..], &test.output[..]); assert_eq!(&hash.to_string(), &test.output_str); diff --git a/hashes/src/sha1.rs b/hashes/src/sha1.rs index 44538439..221508fa 100644 --- a/hashes/src/sha1.rs +++ b/hashes/src/sha1.rs @@ -146,7 +146,6 @@ mod tests { #[cfg(any(feature = "std", feature = "alloc"))] fn test() { use crate::{sha1, Hash, HashEngine}; - use crate::hex::FromHex; #[derive(Clone)] struct Test { @@ -196,7 +195,7 @@ mod tests { for test in tests { // Hash through high-level API, check hex encoding/decoding let hash = sha1::Hash::hash(test.input.as_bytes()); - assert_eq!(hash, sha1::Hash::from_hex(test.output_str).expect("parse hex")); + assert_eq!(hash, test.output_str.parse::().expect("parse hex")); assert_eq!(&hash[..], &test.output[..]); assert_eq!(&hash.to_string(), &test.output_str); diff --git a/hashes/src/sha256.rs b/hashes/src/sha256.rs index eafff7b7..ee53b8b8 100644 --- a/hashes/src/sha256.rs +++ b/hashes/src/sha256.rs @@ -326,8 +326,6 @@ mod tests { #[test] #[cfg(any(feature = "std", feature = "alloc"))] fn test() { - use crate::hex::FromHex; - #[derive(Clone)] struct Test { input: &'static str, @@ -372,7 +370,7 @@ mod tests { for test in tests { // Hash through high-level API, check hex encoding/decoding let hash = sha256::Hash::hash(test.input.as_bytes()); - assert_eq!(hash, sha256::Hash::from_hex(test.output_str).expect("parse hex")); + assert_eq!(hash, test.output_str.parse::().expect("parse hex")); assert_eq!(&hash[..], &test.output[..]); assert_eq!(&hash.to_string(), &test.output_str); diff --git a/hashes/src/sha256d.rs b/hashes/src/sha256d.rs index d55aaf37..2e34a759 100644 --- a/hashes/src/sha256d.rs +++ b/hashes/src/sha256d.rs @@ -47,7 +47,6 @@ mod tests { #[cfg(any(feature = "std", feature = "alloc"))] fn test() { use crate::{sha256, sha256d, Hash, HashEngine}; - use crate::hex::FromHex; #[derive(Clone)] struct Test { @@ -73,7 +72,7 @@ mod tests { for test in tests { // Hash through high-level API, check hex encoding/decoding let hash = sha256d::Hash::hash(test.input.as_bytes()); - assert_eq!(hash, sha256d::Hash::from_hex(test.output_str).expect("parse hex")); + assert_eq!(hash, test.output_str.parse::().expect("parse hex")); assert_eq!(&hash[..], &test.output[..]); assert_eq!(&hash.to_string(), &test.output_str); diff --git a/hashes/src/sha512.rs b/hashes/src/sha512.rs index ffc84805..2bd71838 100644 --- a/hashes/src/sha512.rs +++ b/hashes/src/sha512.rs @@ -311,7 +311,6 @@ mod tests { #[cfg(any(feature = "std", feature = "alloc"))] fn test() { use crate::{sha512, Hash, HashEngine}; - use crate::hex::FromHex; #[derive(Clone)] struct Test { @@ -369,7 +368,7 @@ mod tests { for test in tests { // Hash through high-level API, check hex encoding/decoding let hash = sha512::Hash::hash(test.input.as_bytes()); - assert_eq!(hash, sha512::Hash::from_hex(test.output_str).expect("parse hex")); + assert_eq!(hash, test.output_str.parse::().expect("parse hex")); assert_eq!(&hash[..], &test.output[..]); assert_eq!(&hash.to_string(), &test.output_str); diff --git a/hashes/src/sha512_256.rs b/hashes/src/sha512_256.rs index 4ba40b04..753e16e0 100644 --- a/hashes/src/sha512_256.rs +++ b/hashes/src/sha512_256.rs @@ -89,7 +89,6 @@ mod tests { #[cfg(any(feature = "std", feature = "alloc"))] fn test() { use crate::{sha512_256, Hash, HashEngine}; - use crate::hex::FromHex; #[derive(Clone)] struct Test { @@ -155,7 +154,7 @@ mod tests { for test in tests { // Hash through high-level API, check hex encoding/decoding let hash = sha512_256::Hash::hash(test.input.as_bytes()); - assert_eq!(hash, sha512_256::Hash::from_hex(test.output_str).expect("parse hex")); + assert_eq!(hash, test.output_str.parse::().expect("parse hex")); assert_eq!(&hash[..], &test.output[..]); assert_eq!(&hash.to_string(), &test.output_str); diff --git a/hashes/src/util.rs b/hashes/src/util.rs index 1a083279..9d18f357 100644 --- a/hashes/src/util.rs +++ b/hashes/src/util.rs @@ -196,7 +196,15 @@ macro_rules! hash_newtype { impl $crate::_export::_core::str::FromStr for $newtype { type Err = $crate::hex::Error; fn from_str(s: &str) -> $crate::_export::_core::result::Result<$newtype, Self::Err> { - $crate::hex::FromHex::from_hex(s) + use $crate::hex::{HexIterator, FromHex}; + use $crate::Hash; + + let inner: <$hash as Hash>::Inner = if $reverse { + FromHex::from_byte_iter(HexIterator::new(s)?.rev())? + } else { + FromHex::from_byte_iter(HexIterator::new(s)?)? + }; + Ok($newtype(<$hash>::from_inner(inner))) } } From 32ca6cc3200beaaf5eab48e08a715d4e53a1313b Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Fri, 20 Jan 2023 14:44:13 +1100 Subject: [PATCH 8/8] Remove hex_from_slice and display Sighash forwards `Sighash` should be displayed forwards according to BIP143. Currently we are displaying it backwards (as we do for double SHA256). This is working because parse using `Vec::from_hex`. We have the means to parse hex strings directly for hashes, we no longer need `hex_from_slice`. BIP143 test vectors display double SHA256 forwards but we display backwards, this is acceptable because there is no fixed display in the ecosystem for double SHA256 hashes. In order to overcome this we parse test vector hex strings with into `Vec` when needed. --- bitcoin/src/hash_types.rs | 2 +- bitcoin/src/internal_macros.rs | 30 ------------------ bitcoin/src/psbt/mod.rs | 2 +- bitcoin/src/sighash.rs | 56 +++++++++++++++------------------- 4 files changed, 27 insertions(+), 63 deletions(-) diff --git a/bitcoin/src/hash_types.rs b/bitcoin/src/hash_types.rs index edcbd98a..c7a32e41 100644 --- a/bitcoin/src/hash_types.rs +++ b/bitcoin/src/hash_types.rs @@ -45,7 +45,7 @@ See [`hashes::Hash::DISPLAY_BACKWARD`] for more details. "); hash_newtype!(Wtxid, sha256d::Hash, 32, doc="A bitcoin witness transaction ID."); hash_newtype!(BlockHash, sha256d::Hash, 32, doc="A bitcoin block hash."); - hash_newtype!(Sighash, sha256d::Hash, 32, doc="Hash of the transaction according to the signature algorithm"); + hash_newtype!(Sighash, sha256d::Hash, 32, doc="Hash of the transaction according to the signature algorithm", false); impl secp256k1::ThirtyTwoByteHash for Sighash { fn into_32(self) -> [u8; 32] { use hashes::Hash; diff --git a/bitcoin/src/internal_macros.rs b/bitcoin/src/internal_macros.rs index 4a838472..1c657938 100644 --- a/bitcoin/src/internal_macros.rs +++ b/bitcoin/src/internal_macros.rs @@ -51,39 +51,9 @@ pub(crate) use test_macros::*; #[cfg(test)] mod test_macros { - use crate::hashes::hex::FromHex; - - /// Trait used to create a value from hex string for testing purposes. - pub(crate) trait TestFromHex { - /// Produces the value from hex. - /// - /// ## Panics - /// - /// The function panics if the hex or the value is invalid. - fn test_from_hex(hex: &str) -> Self; - } - - impl TestFromHex for T { - fn test_from_hex(hex: &str) -> Self { Self::from_hex(hex).unwrap() } - } macro_rules! hex (($hex:expr) => ( as hashes::hex::FromHex>::from_hex($hex).unwrap())); pub(crate) use hex; - - // For types that can't use TestFromHex due to coherence rules or reversed hex - macro_rules! hex_from_slice { - ($hex:expr) => { - $crate::internal_macros::hex_from_slice!(_, $hex) - }; - ($type:ty, $hex:expr) => { - <$type>::from_slice( - &<$crate::prelude::Vec as $crate::hashes::hex::FromHex>::from_hex($hex) - .unwrap(), - ) - .unwrap() - }; - } - pub(crate) use hex_from_slice; } /// Implements several traits for byte-based newtypes. diff --git a/bitcoin/src/psbt/mod.rs b/bitcoin/src/psbt/mod.rs index f493f0b0..9d83ca90 100644 --- a/bitcoin/src/psbt/mod.rs +++ b/bitcoin/src/psbt/mod.rs @@ -1397,7 +1397,7 @@ mod tests { #[cfg(feature = "std")] assert_eq!(err.to_string(), "hash parse error"); #[cfg(not(feature = "std"))] - assert_eq!(err.to_string(), "hash parse error: bad slice length 33 (expected 32)"); + assert_eq!(err.to_string(), "hash parse error: invalid slice length 33 (expected 32)"); let err = hex_psbt!("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b69241142cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b094289756aa3739ccc689ec0fcf3a360be32cc0b59b16e93a1e8bb4605726b2ca7a3ff706c4176649632b2cc68e1f912b8a578e3719ce7710885c7a966f49bcd43cb01010000").unwrap_err(); #[cfg(feature = "std")] assert_eq!(err.to_string(), "invalid Schnorr signature"); diff --git a/bitcoin/src/sighash.rs b/bitcoin/src/sighash.rs index 226df4e7..39e4a1a3 100644 --- a/bitcoin/src/sighash.rs +++ b/bitcoin/src/sighash.rs @@ -1057,7 +1057,7 @@ mod tests { use crate::hash_types::Sighash; use crate::hashes::hex::FromHex; use crate::hashes::{Hash, HashEngine}; - use crate::internal_macros::{hex, hex_from_slice}; + use crate::internal_macros::hex; use crate::network::constants::Network; use crate::taproot::{TapLeafHash, TapSighashHash}; @@ -1621,24 +1621,22 @@ mod tests { let mut cache = SighashCache::new(&tx); assert_eq!( cache.segwit_signature_hash(1, &witness_script, value, EcdsaSighashType::All).unwrap(), - hex_from_slice!( - Sighash, - "c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670" - ) + "c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670".parse::().unwrap(), ); let cache = cache.segwit_cache(); + // Parse hex into Vec because BIP143 test vector displays forwards but our sha256d::Hash displays backwards. assert_eq!( - cache.prevouts, - hex_from_slice!("96b827c8483d4e9b96712b6713a7b68d6e8003a781feba36c31143470b4efd37") + cache.prevouts.into_inner().as_ref(), + &Vec::from_hex("96b827c8483d4e9b96712b6713a7b68d6e8003a781feba36c31143470b4efd37").unwrap()[..], ); assert_eq!( - cache.sequences, - hex_from_slice!("52b0a642eea2fb7ae638c36f6252b6750293dbe574a806984b8e4d8548339a3b") + cache.sequences.into_inner().as_ref(), + &Vec::from_hex("52b0a642eea2fb7ae638c36f6252b6750293dbe574a806984b8e4d8548339a3b").unwrap()[..], ); assert_eq!( - cache.outputs, - hex_from_slice!("863ef3e1a92afbfdb97f31ad0fc7683ee943e9abcf2501590ff8f6551f47e5e5") + cache.outputs.into_inner().as_ref(), + &Vec::from_hex("863ef3e1a92afbfdb97f31ad0fc7683ee943e9abcf2501590ff8f6551f47e5e5").unwrap()[..], ); } @@ -1659,24 +1657,22 @@ mod tests { let mut cache = SighashCache::new(&tx); assert_eq!( cache.segwit_signature_hash(0, &witness_script, value, EcdsaSighashType::All).unwrap(), - hex_from_slice!( - Sighash, - "64f3b0f4dd2bb3aa1ce8566d220cc74dda9df97d8490cc81d89d735c92e59fb6" - ) + "64f3b0f4dd2bb3aa1ce8566d220cc74dda9df97d8490cc81d89d735c92e59fb6".parse::().unwrap(), ); let cache = cache.segwit_cache(); + // Parse hex into Vec because BIP143 test vector displays forwards but our sha256d::Hash displays backwards. assert_eq!( - cache.prevouts, - hex_from_slice!("b0287b4a252ac05af83d2dcef00ba313af78a3e9c329afa216eb3aa2a7b4613a") + cache.prevouts.into_inner().as_ref(), + &Vec::from_hex("b0287b4a252ac05af83d2dcef00ba313af78a3e9c329afa216eb3aa2a7b4613a").unwrap()[..], ); assert_eq!( - cache.sequences, - hex_from_slice!("18606b350cd8bf565266bc352f0caddcf01e8fa789dd8a15386327cf8cabe198") + cache.sequences.into_inner().as_ref(), + &Vec::from_hex("18606b350cd8bf565266bc352f0caddcf01e8fa789dd8a15386327cf8cabe198").unwrap()[..], ); assert_eq!( - cache.outputs, - hex_from_slice!("de984f44532e2173ca0d64314fcefe6d30da6f8cf27bafa706da61df8a226c83") + cache.outputs.into_inner().as_ref(), + &Vec::from_hex("de984f44532e2173ca0d64314fcefe6d30da6f8cf27bafa706da61df8a226c83").unwrap()[..], ); } @@ -1702,24 +1698,22 @@ mod tests { let mut cache = SighashCache::new(&tx); assert_eq!( cache.segwit_signature_hash(0, &witness_script, value, EcdsaSighashType::All).unwrap(), - hex_from_slice!( - Sighash, - "185c0be5263dce5b4bb50a047973c1b6272bfbd0103a89444597dc40b248ee7c" - ) + "185c0be5263dce5b4bb50a047973c1b6272bfbd0103a89444597dc40b248ee7c".parse::().unwrap(), ); let cache = cache.segwit_cache(); + // Parse hex into Vec because BIP143 test vector displays forwards but our sha256d::Hash displays backwards. assert_eq!( - cache.prevouts, - hex_from_slice!("74afdc312af5183c4198a40ca3c1a275b485496dd3929bca388c4b5e31f7aaa0") + cache.prevouts.into_inner().as_ref(), + &Vec::from_hex("74afdc312af5183c4198a40ca3c1a275b485496dd3929bca388c4b5e31f7aaa0").unwrap()[..], ); assert_eq!( - cache.sequences, - hex_from_slice!("3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044") + cache.sequences.into_inner().as_ref(), + &Vec::from_hex("3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044").unwrap()[..], ); assert_eq!( - cache.outputs, - hex_from_slice!("bc4d309071414bed932f98832b27b4d76dad7e6c1346f487a8fdbb8eb90307cc") + cache.outputs.into_inner().as_ref(), + &Vec::from_hex("bc4d309071414bed932f98832b27b4d76dad7e6c1346f487a8fdbb8eb90307cc").unwrap()[..], ); } }