From 2268b449110cc673c13e2ad9c1f889701fc9e33c Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Fri, 21 Jul 2023 10:38:34 +1000 Subject: [PATCH] Depend on hex-conservative We have just released the `hex-conservative` crate, we can now use it. Do the following: - Depend on `hex-conservative` in `bitcoin` and `hashes` - Re-export `hex-conservative` as `hex` from both crate roots. - Remove all the old hex code from `hashes` - Fix all the import statements (makes up the bulk of the lines changed in this patch) --- Cargo-minimal.lock | 11 ++ Cargo-recent.lock | 11 ++ bitcoin/Cargo.toml | 5 +- bitcoin/examples/bip32.rs | 2 +- bitcoin/src/bip152.rs | 2 +- bitcoin/src/bip32.rs | 4 +- bitcoin/src/blockdata/block.rs | 2 +- bitcoin/src/blockdata/script/mod.rs | 2 +- bitcoin/src/blockdata/script/owned.rs | 5 +- bitcoin/src/blockdata/transaction.rs | 4 +- bitcoin/src/blockdata/witness.rs | 8 +- bitcoin/src/consensus/serde.rs | 26 +-- bitcoin/src/crypto/ecdsa.rs | 15 +- bitcoin/src/crypto/key.rs | 12 +- bitcoin/src/crypto/sighash.rs | 2 +- bitcoin/src/internal_macros.rs | 36 ++--- bitcoin/src/lib.rs | 8 +- bitcoin/src/merkle_tree/block.rs | 8 +- bitcoin/src/network/address.rs | 2 +- bitcoin/src/network/constants.rs | 10 +- bitcoin/src/pow.rs | 8 +- bitcoin/src/psbt/macros.rs | 2 +- bitcoin/src/psbt/serialize.rs | 4 +- bitcoin/src/serde_utils.rs | 6 +- bitcoin/src/taproot.rs | 2 +- bitcoin/tests/psbt.rs | 2 +- bitcoin/tests/serde.rs | 2 +- hashes/Cargo.toml | 11 +- hashes/src/hex.rs | 225 -------------------------- hashes/src/impls.rs | 8 +- hashes/src/internal_macros.rs | 24 +-- hashes/src/lib.rs | 15 +- hashes/src/sha256.rs | 9 +- hashes/src/util.rs | 8 +- 34 files changed, 149 insertions(+), 352 deletions(-) delete mode 100644 hashes/src/hex.rs diff --git a/Cargo-minimal.lock b/Cargo-minimal.lock index 2a6ea499..ea1e7cee 100644 --- a/Cargo-minimal.lock +++ b/Cargo-minimal.lock @@ -41,6 +41,7 @@ dependencies = [ "bitcoin_hashes", "bitcoinconsensus", "core2", + "hex-conservative", "hex_lit", "mutagen", "secp256k1", @@ -74,6 +75,7 @@ version = "0.12.0" dependencies = [ "bitcoin-internals", "core2", + "hex-conservative", "schemars", "serde", "serde_json", @@ -163,6 +165,15 @@ version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3" +[[package]] +name = "hex-conservative" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ed443af458ccb6d81c1e7e661545f94d3176752fb1df2f543b902a1e0f51e2" +dependencies = [ + "core2", +] + [[package]] name = "hex_lit" version = "0.1.1" diff --git a/Cargo-recent.lock b/Cargo-recent.lock index 9f8f80e7..31b69aaa 100644 --- a/Cargo-recent.lock +++ b/Cargo-recent.lock @@ -40,6 +40,7 @@ dependencies = [ "bitcoin_hashes", "bitcoinconsensus", "core2", + "hex-conservative", "hex_lit", "mutagen", "secp256k1", @@ -73,6 +74,7 @@ version = "0.12.0" dependencies = [ "bitcoin-internals", "core2", + "hex-conservative", "schemars", "serde", "serde_json", @@ -156,6 +158,15 @@ version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3" +[[package]] +name = "hex-conservative" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ed443af458ccb6d81c1e7e661545f94d3176752fb1df2f543b902a1e0f51e2" +dependencies = [ + "core2", +] + [[package]] name = "hex_lit" version = "0.1.1" diff --git a/bitcoin/Cargo.toml b/bitcoin/Cargo.toml index ceb793c9..2c33b1b3 100644 --- a/bitcoin/Cargo.toml +++ b/bitcoin/Cargo.toml @@ -26,8 +26,8 @@ bitcoinconsensus-std = ["bitcoinconsensus/std", "std"] # The no-std feature doesn't disable std - you need to turn off the std feature for that by disabling default. # Instead no-std enables additional features required for this crate to be usable without std. # As a result, both can be enabled without conflict. -std = ["secp256k1/std", "hashes/std", "bech32/std", "internals/std"] -no-std = ["core2", "hashes/alloc", "hashes/core2", "secp256k1/alloc"] +std = ["secp256k1/std", "hashes/std", "bech32/std", "internals/std", "hex/std"] +no-std = ["core2", "hashes/alloc", "hashes/core2", "secp256k1/alloc", "hex/alloc", "hex/core2"] [package.metadata.docs.rs] all-features = true @@ -35,6 +35,7 @@ rustdoc-args = ["--cfg", "docsrs"] [dependencies] internals = { package = "bitcoin-internals", version = "0.2.0" } +hex = { package = "hex-conservative", version = "0.1.1", default-features = false } bech32 = { version = "0.9.0", default-features = false } hashes = { package = "bitcoin_hashes", version = "0.12.0", default-features = false } secp256k1 = { version = "0.27.0", default-features = false, features = ["bitcoin_hashes"] } diff --git a/bitcoin/examples/bip32.rs b/bitcoin/examples/bip32.rs index 7904c5f6..f9c81343 100644 --- a/bitcoin/examples/bip32.rs +++ b/bitcoin/examples/bip32.rs @@ -5,7 +5,7 @@ use std::{env, process}; use bitcoin::address::Address; use bitcoin::bip32::{ChildNumber, DerivationPath, ExtendedPrivKey, ExtendedPubKey}; -use bitcoin::hashes::hex::FromHex; +use bitcoin::hex::FromHex; use bitcoin::secp256k1::ffi::types::AlignedType; use bitcoin::secp256k1::Secp256k1; use bitcoin::PublicKey; diff --git a/bitcoin/src/bip152.rs b/bitcoin/src/bip152.rs index 380a8402..b04f352e 100644 --- a/bitcoin/src/bip152.rs +++ b/bitcoin/src/bip152.rs @@ -371,7 +371,7 @@ impl BlockTransactions { #[cfg(test)] mod test { - use hashes::hex::FromHex; + use hex::FromHex; use super::*; use crate::blockdata::locktime::absolute; diff --git a/bitcoin/src/bip32.rs b/bitcoin/src/bip32.rs index dc381dc0..036b56af 100644 --- a/bitcoin/src/bip32.rs +++ b/bitcoin/src/bip32.rs @@ -12,7 +12,7 @@ use core::ops::Index; use core::str::FromStr; use core::{fmt, slice}; -use hashes::{hex, sha512, Hash, HashEngine, Hmac, HmacEngine}; +use hashes::{sha512, Hash, HashEngine, Hmac, HmacEngine}; use internals::{impl_array_newtype, write_err}; use secp256k1::{self, Secp256k1, XOnlyPublicKey}; #[cfg(feature = "serde")] @@ -468,7 +468,7 @@ pub enum Error { /// Base58 encoding error Base58(base58::Error), /// Hexadecimal decoding error - Hex(hex::Error), + Hex(hex::HexToArrayError), /// `PublicKey` hex should be 66 or 130 digits long. InvalidPublicKeyHexLength(usize), } diff --git a/bitcoin/src/blockdata/block.rs b/bitcoin/src/blockdata/block.rs index dcacffec..921565e6 100644 --- a/bitcoin/src/blockdata/block.rs +++ b/bitcoin/src/blockdata/block.rs @@ -423,7 +423,7 @@ impl std::error::Error for ValidationError { #[cfg(test)] mod tests { - use hashes::hex::FromHex; + use hex::FromHex; use super::*; use crate::consensus::encode::{deserialize, serialize}; diff --git a/bitcoin/src/blockdata/script/mod.rs b/bitcoin/src/blockdata/script/mod.rs index bc4c41a6..acb94039 100644 --- a/bitcoin/src/blockdata/script/mod.rs +++ b/bitcoin/src/blockdata/script/mod.rs @@ -513,7 +513,7 @@ impl<'de> serde::Deserialize<'de> for ScriptBuf { { use core::fmt::Formatter; - use hashes::hex::FromHex; + use hex::FromHex; if deserializer.is_human_readable() { struct Visitor; diff --git a/bitcoin/src/blockdata/script/owned.rs b/bitcoin/src/blockdata/script/owned.rs index eb6190ca..db917225 100644 --- a/bitcoin/src/blockdata/script/owned.rs +++ b/bitcoin/src/blockdata/script/owned.rs @@ -3,7 +3,6 @@ #[cfg(doc)] use core::ops::Deref; -use hashes::hex; use secp256k1::{Secp256k1, Verification}; use crate::blockdata::opcodes::all::*; @@ -156,8 +155,8 @@ impl ScriptBuf { } /// Creates a [`ScriptBuf`] from a hex string. - pub fn from_hex(s: &str) -> Result { - use hashes::hex::FromHex; + pub fn from_hex(s: &str) -> Result { + use hex::FromHex; let v = Vec::from_hex(s)?; Ok(ScriptBuf::from_bytes(v)) diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs index 8418fbe6..fd95813a 100644 --- a/bitcoin/src/blockdata/transaction.rs +++ b/bitcoin/src/blockdata/transaction.rs @@ -95,7 +95,7 @@ impl fmt::Display for OutPoint { #[non_exhaustive] pub enum ParseOutPointError { /// Error in TXID part. - Txid(hashes::hex::Error), + Txid(hex::HexToArrayError), /// Error in vout part. Vout(crate::error::ParseIntError), /// Error in general format. @@ -1420,7 +1420,7 @@ impl InputWeightPrediction { mod tests { use core::str::FromStr; - use hashes::hex::FromHex; + use hex::FromHex; use super::*; use crate::blockdata::constants::WITNESS_SCALE_FACTOR; diff --git a/bitcoin/src/blockdata/witness.rs b/bitcoin/src/blockdata/witness.rs index d0b7408c..892de5fa 100644 --- a/bitcoin/src/blockdata/witness.rs +++ b/bitcoin/src/blockdata/witness.rs @@ -462,8 +462,8 @@ impl<'de> serde::Deserialize<'de> for Witness { self, mut a: A, ) -> Result { - use hashes::hex::Error::*; - use hashes::hex::FromHex; + use hex::FromHex; + use hex::HexToBytesError::*; use serde::de::{self, Unexpected}; let mut ret = match a.size_hint() { @@ -485,10 +485,6 @@ impl<'de> serde::Deserialize<'de> for Witness { }, OddLengthString(len) => de::Error::invalid_length(len, &"an even length string"), - InvalidLength(expected, got) => { - let exp = format!("expected length: {}", expected); - de::Error::invalid_length(got, &exp.as_str()) - } })?; ret.push(vec); } diff --git a/bitcoin/src/consensus/serde.rs b/bitcoin/src/consensus/serde.rs index c2393635..2b857547 100644 --- a/bitcoin/src/consensus/serde.rs +++ b/bitcoin/src/consensus/serde.rs @@ -38,7 +38,7 @@ pub mod hex { use core::fmt; use core::marker::PhantomData; - use internals::hex::BufEncoder; + use hex::buf_encoder::BufEncoder; /// Marker for upper/lower case type-level flags ("type-level enum"). /// @@ -54,15 +54,15 @@ pub mod hex { mod sealed { pub trait Case { /// Internal detail, don't depend on it!!! - const INTERNAL_CASE: internals::hex::Case; + const INTERNAL_CASE: hex::Case; } impl Case for super::Lower { - const INTERNAL_CASE: internals::hex::Case = internals::hex::Case::Lower; + const INTERNAL_CASE: hex::Case = hex::Case::Lower; } impl Case for super::Upper { - const INTERNAL_CASE: internals::hex::Case = internals::hex::Case::Upper; + const INTERNAL_CASE: hex::Case = hex::Case::Upper; } } @@ -102,18 +102,18 @@ pub mod hex { /// Error returned when a hex string decoder can't be created. #[derive(Debug)] - pub struct DecodeInitError(hashes::hex::Error); + pub struct DecodeInitError(hex::HexToBytesError); /// Error returned when a hex string contains invalid characters. #[derive(Debug)] - pub struct DecodeError(hashes::hex::Error); + pub struct DecodeError(hex::HexToBytesError); /// Hex decoder state. - pub struct Decoder<'a>(hashes::hex::HexIterator<'a>); + pub struct Decoder<'a>(hex::HexToBytesIter<'a>); impl<'a> Decoder<'a> { fn new(s: &'a str) -> Result { - match hashes::hex::HexIterator::new(s) { + match hex::HexToBytesIter::new(s) { Ok(iter) => Ok(Decoder(iter)), Err(error) => Err(DecodeInitError(error)), } @@ -138,10 +138,10 @@ pub mod hex { impl super::IntoDeError for DecodeInitError { fn into_de_error(self) -> E { - use hashes::hex::Error; + use hex::HexToBytesError; match self.0 { - Error::OddLengthString(len) => + HexToBytesError::OddLengthString(len) => E::invalid_length(len, &"an even number of ASCII-encoded hex digits"), error => panic!("unexpected error: {:?}", error), } @@ -150,15 +150,15 @@ pub mod hex { impl super::IntoDeError for DecodeError { fn into_de_error(self) -> E { - use hashes::hex::Error; + use hex::HexToBytesError; use serde::de::Unexpected; const EXPECTED_CHAR: &str = "an ASCII-encoded hex digit"; match self.0 { - Error::InvalidChar(c) if c.is_ascii() => + HexToBytesError::InvalidChar(c) if c.is_ascii() => E::invalid_value(Unexpected::Char(c as _), &EXPECTED_CHAR), - Error::InvalidChar(c) => + HexToBytesError::InvalidChar(c) => E::invalid_value(Unexpected::Unsigned(c.into()), &EXPECTED_CHAR), error => panic!("unexpected error: {:?}", error), } diff --git a/bitcoin/src/crypto/ecdsa.rs b/bitcoin/src/crypto/ecdsa.rs index 65f94446..7f0e6d15 100644 --- a/bitcoin/src/crypto/ecdsa.rs +++ b/bitcoin/src/crypto/ecdsa.rs @@ -7,8 +7,7 @@ use core::str::FromStr; use core::{fmt, iter}; -use hashes::hex::{self, FromHex}; -use internals::hex::display::DisplayHex; +use hex::FromHex; use internals::write_err; use secp256k1; @@ -188,8 +187,8 @@ impl<'a> IntoIterator for &'a SerializedSignature { #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[non_exhaustive] pub enum Error { - /// Hex encoding error - HexEncoding(hex::Error), + /// Hex decoding error + Hex(hex::HexToBytesError), /// Base58 encoding error NonStandardSighashType(u32), /// Empty Signature @@ -201,7 +200,7 @@ pub enum Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Error::HexEncoding(ref e) => write_err!(f, "Signature hex encoding error"; e), + Error::Hex(ref e) => write_err!(f, "Signature hex decoding error"; e), Error::NonStandardSighashType(hash_ty) => write!(f, "Non standard signature hash type {}", hash_ty), Error::EmptySignature => write!(f, "Empty ECDSA signature"), @@ -216,7 +215,7 @@ impl std::error::Error for Error { use self::Error::*; match self { - HexEncoding(e) => Some(e), + Hex(e) => Some(e), Secp256k1(e) => Some(e), NonStandardSighashType(_) | EmptySignature => None, } @@ -231,6 +230,6 @@ impl From for Error { fn from(err: NonStandardSighashType) -> Self { Error::NonStandardSighashType(err.0) } } -impl From for Error { - fn from(err: hex::Error) -> Self { Error::HexEncoding(err) } +impl From for Error { + fn from(err: hex::HexToBytesError) -> Self { Error::Hex(err) } } diff --git a/bitcoin/src/crypto/key.rs b/bitcoin/src/crypto/key.rs index 5108940e..216bff51 100644 --- a/bitcoin/src/crypto/key.rs +++ b/bitcoin/src/crypto/key.rs @@ -9,8 +9,8 @@ use core::fmt::{self, Write}; use core::ops; use core::str::FromStr; -use hashes::hex::FromHex; -use hashes::{hash160, hex, Hash}; +use hashes::{hash160, Hash}; +use hex::FromHex; use internals::write_err; #[cfg(feature = "rand-std")] pub use secp256k1::rand; @@ -34,7 +34,7 @@ pub enum Error { /// Invalid key prefix error InvalidKeyPrefix(u8), /// Hex decoding error - Hex(hex::Error), + Hex(hex::HexToArrayError), /// `PublicKey` hex should be 66 or 130 digits long. InvalidHexLength(usize), } @@ -74,8 +74,8 @@ impl From for Error { fn from(e: secp256k1::Error) -> Error { Error::Secp256k1(e) } } -impl From for Error { - fn from(e: hex::Error) -> Self { Error::Hex(e) } +impl From for Error { + fn from(e: hex::HexToArrayError) -> Self { Error::Hex(e) } } /// A Bitcoin ECDSA public key @@ -731,7 +731,7 @@ impl From for TweakedPublicKey { mod tests { use std::str::FromStr; - use hashes::hex::FromHex; + use hex::FromHex; use secp256k1::Secp256k1; use super::*; diff --git a/bitcoin/src/crypto/sighash.rs b/bitcoin/src/crypto/sighash.rs index fe4f757d..93c00da9 100644 --- a/bitcoin/src/crypto/sighash.rs +++ b/bitcoin/src/crypto/sighash.rs @@ -1110,8 +1110,8 @@ fn is_invalid_use_of_sighash_single(sighash: u32, input_index: usize, output_len mod tests { use std::str::FromStr; - use hashes::hex::FromHex; use hashes::HashEngine; + use hex::FromHex; use super::*; use crate::address::Address; diff --git a/bitcoin/src/internal_macros.rs b/bitcoin/src/internal_macros.rs index ae0e54f6..52c446f8 100644 --- a/bitcoin/src/internal_macros.rs +++ b/bitcoin/src/internal_macros.rs @@ -51,7 +51,7 @@ pub(crate) use test_macros::*; #[cfg(test)] mod test_macros { - macro_rules! hex (($hex:expr) => ( as hashes::hex::FromHex>::from_hex($hex).unwrap())); + macro_rules! hex (($hex:expr) => ( as $crate::hex::FromHex>::from_hex($hex).unwrap())); pub(crate) use hex; } @@ -61,7 +61,7 @@ mod test_macros { /// - core::fmt::UpperHex /// - core::fmt::Display /// - core::str::FromStr -/// - hashes::hex::FromHex +/// - hex::FromHex macro_rules! impl_bytes_newtype { ($t:ident, $len:literal) => { impl $t { @@ -83,14 +83,14 @@ macro_rules! impl_bytes_newtype { impl core::fmt::LowerHex for $t { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - use internals::hex::{display, Case}; + use $crate::hex::{display, Case}; display::fmt_hex_exact!(f, $len, &self.0, Case::Lower) } } impl core::fmt::UpperHex for $t { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - use internals::hex::{display, Case}; + use $crate::hex::{display, Case}; display::fmt_hex_exact!(f, $len, &self.0, Case::Upper) } } @@ -107,30 +107,22 @@ macro_rules! impl_bytes_newtype { } } - impl $crate::hashes::hex::FromHex for $t { - fn from_byte_iter(iter: I) -> Result + impl $crate::hex::FromHex for $t { + type Err = $crate::hex::HexToArrayError; + + fn from_byte_iter(iter: I) -> Result where - I: core::iter::Iterator> + I: core::iter::Iterator> + core::iter::ExactSizeIterator + core::iter::DoubleEndedIterator, { - if iter.len() == $len { - let mut ret = [0; $len]; - for (n, byte) in iter.enumerate() { - ret[n] = byte?; - } - Ok($t(ret)) - } else { - Err($crate::hashes::hex::Error::InvalidLength(2 * $len, 2 * iter.len())) - } + Ok($t($crate::hex::FromHex::from_byte_iter(iter)?)) } } impl core::str::FromStr for $t { - type Err = $crate::hashes::hex::Error; - fn from_str(s: &str) -> Result { - $crate::hashes::hex::FromHex::from_hex(s) - } + type Err = $crate::hex::HexToArrayError; + fn from_str(s: &str) -> Result { $crate::hex::FromHex::from_hex(s) } } #[cfg(feature = "serde")] @@ -164,7 +156,7 @@ macro_rules! impl_bytes_newtype { use $crate::serde::de::Unexpected; if let Ok(hex) = core::str::from_utf8(v) { - $crate::hashes::hex::FromHex::from_hex(hex).map_err(E::custom) + $crate::hex::FromHex::from_hex(hex).map_err(E::custom) } else { return Err(E::invalid_value(Unexpected::Bytes(v), &self)); } @@ -174,7 +166,7 @@ macro_rules! impl_bytes_newtype { where E: $crate::serde::de::Error, { - $crate::hashes::hex::FromHex::from_hex(v).map_err(E::custom) + $crate::hex::FromHex::from_hex(v).map_err(E::custom) } } diff --git a/bitcoin/src/lib.rs b/bitcoin/src/lib.rs index 5b3ef180..af6e9ed2 100644 --- a/bitcoin/src/lib.rs +++ b/bitcoin/src/lib.rs @@ -66,9 +66,15 @@ pub extern crate bech32; /// Bitcoin's libbitcoinconsensus with Rust binding. pub extern crate bitcoinconsensus; +#[cfg(not(feature = "std"))] +extern crate core2; + /// Rust implementation of cryptographic hash function algorithems. pub extern crate hashes; +/// Re-export the `hex-conservative` crate. +pub extern crate hex; + /// Rust wrapper library for Pieter Wuille's libsecp256k1. Implements ECDSA and BIP 340 signatures /// for the SECG elliptic curve group secp256k1 and related utilities. pub extern crate secp256k1; @@ -186,7 +192,7 @@ mod prelude { #[cfg(not(feature = "std"))] pub use crate::io_extras::sink; - pub use internals::hex::display::DisplayHex; + pub use hex::DisplayHex; } #[cfg(bench)] diff --git a/bitcoin/src/merkle_tree/block.rs b/bitcoin/src/merkle_tree/block.rs index 8d031ef8..1a45eb1e 100644 --- a/bitcoin/src/merkle_tree/block.rs +++ b/bitcoin/src/merkle_tree/block.rs @@ -13,7 +13,7 @@ //! //! ```rust //! use bitcoin::hash_types::Txid; -//! use bitcoin::hashes::hex::FromHex; +//! use bitcoin::hex::FromHex; //! use bitcoin::{Block, MerkleBlock}; //! //! // Get the proof from a bitcoind by running in the terminal: @@ -73,7 +73,7 @@ impl MerkleBlock { /// /// ```rust /// use bitcoin::hash_types::Txid; - /// use bitcoin::hashes::hex::FromHex; + /// use bitcoin::hex::FromHex; /// use bitcoin::{Block, MerkleBlock}; /// /// // Block 80000 @@ -223,7 +223,7 @@ impl PartialMerkleTree { /// /// ```rust /// use bitcoin::hash_types::Txid; - /// use bitcoin::hashes::hex::FromHex; + /// use bitcoin::hex::FromHex; /// use bitcoin::merkle_tree::{MerkleBlock, PartialMerkleTree}; /// /// // Block 80000 @@ -751,7 +751,7 @@ mod tests { /// Returns a real block (0000000000013b8ab2cd513b0261a14096412195a72a0c4827d229dcc7e0f7af) /// with 9 txs. fn get_block_13b8a() -> Block { - use hashes::hex::FromHex; + use hex::FromHex; let block_hex = include_str!("../../tests/data/block_13b8a.hex"); deserialize(&Vec::from_hex(block_hex).unwrap()).unwrap() } diff --git a/bitcoin/src/network/address.rs b/bitcoin/src/network/address.rs index 3dec4f14..f20907c3 100644 --- a/bitcoin/src/network/address.rs +++ b/bitcoin/src/network/address.rs @@ -306,7 +306,7 @@ mod test { use core::str::FromStr; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; - use hashes::hex::FromHex; + use hex::FromHex; use super::{AddrV2, AddrV2Message, Address}; use crate::consensus::encode::{deserialize, serialize}; diff --git a/bitcoin/src/network/constants.rs b/bitcoin/src/network/constants.rs index 202c2d69..882592a2 100644 --- a/bitcoin/src/network/constants.rs +++ b/bitcoin/src/network/constants.rs @@ -31,7 +31,7 @@ use core::fmt::Display; use core::str::FromStr; use core::{fmt, ops}; -use hashes::hex::{Error, FromHex}; +use hex::FromHex; use internals::{debug_from_display, write_err}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -313,7 +313,7 @@ impl Magic { #[derive(Debug, PartialEq, Eq, Clone)] pub struct ParseMagicError { /// The error that occurred when parsing the string. - error: Error, + error: hex::HexToArrayError, /// The byte string that failed to parse. magic: String, } @@ -362,7 +362,7 @@ impl TryFrom for Network { impl fmt::Display for Magic { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - internals::fmt_hex_exact!(f, 4, &self.0, internals::hex::Case::Lower)?; + hex::fmt_hex_exact!(f, 4, &self.0, hex::Case::Lower)?; Ok(()) } } @@ -370,14 +370,14 @@ debug_from_display!(Magic); impl fmt::LowerHex for Magic { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - internals::fmt_hex_exact!(f, 4, &self.0, internals::hex::Case::Lower)?; + hex::fmt_hex_exact!(f, 4, &self.0, hex::Case::Lower)?; Ok(()) } } impl fmt::UpperHex for Magic { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - internals::fmt_hex_exact!(f, 4, &self.0, internals::hex::Case::Upper)?; + hex::fmt_hex_exact!(f, 4, &self.0, hex::Case::Upper)?; Ok(()) } } diff --git a/bitcoin/src/pow.rs b/bitcoin/src/pow.rs index d190bda8..2e647909 100644 --- a/bitcoin/src/pow.rs +++ b/bitcoin/src/pow.rs @@ -790,13 +790,13 @@ macro_rules! impl_hex { ($hex:ident, $case:expr) => { impl $hex for U256 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - internals::hex::display::fmt_hex_exact!(f, 32, &self.to_be_bytes(), $case) + hex::fmt_hex_exact!(f, 32, &self.to_be_bytes(), $case) } } }; } -impl_hex!(LowerHex, internals::hex::Case::Lower); -impl_hex!(UpperHex, internals::hex::Case::Upper); +impl_hex!(LowerHex, hex::Case::Lower); +impl_hex!(UpperHex, hex::Case::Upper); #[cfg(feature = "serde")] impl crate::serde::Serialize for U256 { @@ -825,7 +825,7 @@ impl<'de> crate::serde::Deserialize<'de> for U256 { fn deserialize>(d: D) -> Result { use core::convert::TryInto; - use hashes::hex::FromHex; + use hex::FromHex; use crate::serde::de; diff --git a/bitcoin/src/psbt/macros.rs b/bitcoin/src/psbt/macros.rs index 02bbd8bf..328bdb4d 100644 --- a/bitcoin/src/psbt/macros.rs +++ b/bitcoin/src/psbt/macros.rs @@ -4,7 +4,7 @@ macro_rules! hex_psbt { ($s:expr) => { <$crate::psbt::Psbt>::deserialize( - &<$crate::prelude::Vec as $crate::hashes::hex::FromHex>::from_hex($s).unwrap(), + &<$crate::prelude::Vec as $crate::hex::FromHex>::from_hex($s).unwrap(), ) }; } diff --git a/bitcoin/src/psbt/serialize.rs b/bitcoin/src/psbt/serialize.rs index 28ac1d85..dfca1b6c 100644 --- a/bitcoin/src/psbt/serialize.rs +++ b/bitcoin/src/psbt/serialize.rs @@ -178,9 +178,7 @@ impl Deserialize for ecdsa::Signature { ecdsa::Error::EmptySignature => Error::InvalidEcdsaSignature(e), ecdsa::Error::NonStandardSighashType(flag) => Error::NonStandardSighashType(flag), ecdsa::Error::Secp256k1(..) => Error::InvalidEcdsaSignature(e), - ecdsa::Error::HexEncoding(..) => { - unreachable!("Decoding from slice, not hex") - } + ecdsa::Error::Hex(..) => unreachable!("Decoding from slice, not hex"), }) } } diff --git a/bitcoin/src/serde_utils.rs b/bitcoin/src/serde_utils.rs index e3cdee7a..c0789e0c 100644 --- a/bitcoin/src/serde_utils.rs +++ b/bitcoin/src/serde_utils.rs @@ -12,7 +12,7 @@ impl<'a> serde::Serialize for SerializeBytesAsHex<'a> { where S: serde::Serializer, { - use internals::hex::display::DisplayHex; + use hex::DisplayHex; serializer.collect_str(&format_args!("{:x}", self.0.as_hex())) } @@ -24,7 +24,7 @@ pub mod btreemap_byte_values { // NOTE: This module can be exactly copied to use with HashMap. - use hashes::hex::FromHex; + use hex::FromHex; use serde; use crate::prelude::*; @@ -248,7 +248,7 @@ pub mod hex_bytes { //! Module for serialization of byte arrays as hex strings. #![allow(missing_docs)] - use hashes::hex::FromHex; + use hex::FromHex; use serde; pub fn serialize(bytes: &T, s: S) -> Result diff --git a/bitcoin/src/taproot.rs b/bitcoin/src/taproot.rs index ae1b3f45..9a90757f 100644 --- a/bitcoin/src/taproot.rs +++ b/bitcoin/src/taproot.rs @@ -1561,9 +1561,9 @@ impl std::error::Error for TaprootError { mod test { use core::str::FromStr; - use hashes::hex::FromHex; use hashes::sha256t::Tag; use hashes::{sha256, Hash, HashEngine}; + use hex::FromHex; use secp256k1::{VerifyOnly, XOnlyPublicKey}; use super::*; diff --git a/bitcoin/tests/psbt.rs b/bitcoin/tests/psbt.rs index 692cc9b6..5271c59f 100644 --- a/bitcoin/tests/psbt.rs +++ b/bitcoin/tests/psbt.rs @@ -9,7 +9,7 @@ use bitcoin::bip32::{ExtendedPrivKey, ExtendedPubKey, Fingerprint, IntoDerivatio use bitcoin::blockdata::opcodes::OP_0; use bitcoin::blockdata::script; use bitcoin::consensus::encode::{deserialize, serialize_hex}; -use bitcoin::hashes::hex::FromHex; +use bitcoin::hex::FromHex; use bitcoin::psbt::{Psbt, PsbtSighashType}; use bitcoin::script::PushBytes; use bitcoin::secp256k1::{self, Secp256k1}; diff --git a/bitcoin/tests/serde.rs b/bitcoin/tests/serde.rs index fc125975..e4a85060 100644 --- a/bitcoin/tests/serde.rs +++ b/bitcoin/tests/serde.rs @@ -31,8 +31,8 @@ use bitcoin::bip32::{ChildNumber, ExtendedPrivKey, ExtendedPubKey, KeySource}; use bitcoin::blockdata::locktime::{absolute, relative}; use bitcoin::blockdata::witness::Witness; use bitcoin::consensus::encode::deserialize; -use bitcoin::hashes::hex::FromHex; use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d, Hash}; +use bitcoin::hex::FromHex; use bitcoin::psbt::raw::{self, Key, Pair, ProprietaryKey}; use bitcoin::psbt::{Input, Output, Psbt, PsbtSighashType}; use bitcoin::sighash::{EcdsaSighashType, TapSighashType}; diff --git a/hashes/Cargo.toml b/hashes/Cargo.toml index 4ce146d6..30313e14 100644 --- a/hashes/Cargo.toml +++ b/hashes/Cargo.toml @@ -14,9 +14,11 @@ exclude = ["tests", "contrib"] [features] default = ["std"] -std = ["alloc", "internals/std"] -alloc = ["internals/alloc"] +std = ["alloc", "internals/std", "hex/std"] +alloc = ["internals/alloc", "hex/alloc"] serde-std = ["serde/std"] +# If you want I/O you must enable either "std" or "core2". +core2 = ["actual-core2", "hex/core2"] [package.metadata.docs.rs] all-features = true @@ -24,12 +26,15 @@ rustdoc-args = ["--cfg", "docsrs"] [dependencies] internals = { package = "bitcoin-internals", version = "0.2.0" } +hex = { package = "hex-conservative", version = "0.1.1", default-features = false } -core2 = { version = "0.3.0", default_features = false, optional = true } schemars = { version = "0.8.3", optional = true } # Only enable this if you explicitly do not want to use "std", otherwise enable "serde-std". serde = { version = "1.0", default-features = false, optional = true } +# Do NOT use this feature! Use the "core2" feature instead. +actual-core2 = { package = "core2", version = "0.3.2", default-features = false, optional = true } + [dev-dependencies] serde_test = "1.0" serde_json = "1.0" diff --git a/hashes/src/hex.rs b/hashes/src/hex.rs deleted file mode 100644 index 31845a75..00000000 --- a/hashes/src/hex.rs +++ /dev/null @@ -1,225 +0,0 @@ -// SPDX-License-Identifier: CC0-1.0 - -//! Hex encoding and decoding. -//! - -use core::{fmt, str}; -#[cfg(feature = "std")] -use std::io; - -#[cfg(all(feature = "core2", not(feature = "std")))] -use core2::io; - -#[cfg(all(feature = "alloc", not(feature = "std")))] -use crate::alloc::vec::Vec; - -/// Hex decoding error. -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub enum Error { - /// Non-hexadecimal character. - InvalidChar(u8), - /// Purported hex string had odd length. - OddLengthString(usize), - /// Tried to parse fixed-length hash from a string with the wrong type (expected, got). - InvalidLength(usize, usize), -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Error::InvalidChar(ch) => write!(f, "invalid hex character {}", ch), - Error::OddLengthString(ell) => write!(f, "odd hex string length {}", ell), - Error::InvalidLength(ell, ell2) => - write!(f, "bad hex string length {} (expected {})", ell2, ell), - } - } -} - -#[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. - fn from_byte_iter(iter: I) -> Result - where - I: Iterator> + ExactSizeIterator + DoubleEndedIterator; - - /// Produces an object from a hex string. - fn from_hex(s: &str) -> Result { Self::from_byte_iter(HexIterator::new(s)?) } -} - -/// 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 - /// the next byte. - iter: str::Bytes<'a>, -} - -impl<'a> HexIterator<'a> { - /// Constructs a new `HexIterator` from a string slice. - /// - /// # Errors - /// - /// If the input string is of odd length. - pub fn new(s: &'a str) -> Result, Error> { - if s.len() % 2 != 0 { - Err(Error::OddLengthString(s.len())) - } else { - Ok(HexIterator { iter: s.bytes() }) - } - } -} - -fn chars_to_hex(hi: u8, lo: u8) -> Result { - let hih = (hi as char).to_digit(16).ok_or(Error::InvalidChar(hi))?; - let loh = (lo as char).to_digit(16).ok_or(Error::InvalidChar(lo))?; - - let ret = (hih << 4) + loh; - Ok(ret as u8) -} - -impl<'a> Iterator for HexIterator<'a> { - type Item = Result; - - fn next(&mut self) -> Option> { - let hi = self.iter.next()?; - let lo = self.iter.next().unwrap(); - Some(chars_to_hex(hi, lo)) - } - - fn size_hint(&self) -> (usize, Option) { - let (min, max) = self.iter.size_hint(); - (min / 2, max.map(|x| x / 2)) - } -} - -#[cfg(any(feature = "std", feature = "core2"))] -impl<'a> io::Read for HexIterator<'a> { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - let mut bytes_read = 0usize; - for dst in buf { - match self.next() { - Some(Ok(src)) => { - *dst = src; - bytes_read += 1; - } - _ => break, - } - } - Ok(bytes_read) - } -} - -impl<'a> DoubleEndedIterator for HexIterator<'a> { - fn next_back(&mut self) -> Option> { - let lo = self.iter.next_back()?; - let hi = self.iter.next_back().unwrap(); - Some(chars_to_hex(hi, lo)) - } -} - -impl<'a> ExactSizeIterator for HexIterator<'a> {} - -#[cfg(any(test, feature = "std", feature = "alloc"))] -impl FromHex for Vec { - fn from_byte_iter(iter: I) -> Result - where - I: Iterator> + ExactSizeIterator + DoubleEndedIterator, - { - iter.collect() - } -} - -macro_rules! impl_fromhex_array { - ($len:expr) => { - impl FromHex for [u8; $len] { - fn from_byte_iter(iter: I) -> Result - where - I: Iterator> + ExactSizeIterator + DoubleEndedIterator, - { - if iter.len() == $len { - let mut ret = [0; $len]; - for (n, byte) in iter.enumerate() { - ret[n] = byte?; - } - Ok(ret) - } else { - Err(Error::InvalidLength(2 * $len, 2 * iter.len())) - } - } - } - }; -} - -impl_fromhex_array!(2); -impl_fromhex_array!(4); -impl_fromhex_array!(6); -impl_fromhex_array!(8); -impl_fromhex_array!(10); -impl_fromhex_array!(12); -impl_fromhex_array!(14); -impl_fromhex_array!(16); -impl_fromhex_array!(20); -impl_fromhex_array!(24); -impl_fromhex_array!(28); -impl_fromhex_array!(32); -impl_fromhex_array!(33); -impl_fromhex_array!(64); -impl_fromhex_array!(65); -impl_fromhex_array!(128); -impl_fromhex_array!(256); -impl_fromhex_array!(384); -impl_fromhex_array!(512); - -#[cfg(test)] -#[cfg(feature = "alloc")] -mod tests { - use internals::hex::exts::DisplayHex; - - use super::*; - - #[test] - fn hex_roundtrip() { - let expected = "0123456789abcdef"; - let expected_up = "0123456789ABCDEF"; - - let parse: Vec = FromHex::from_hex(expected).expect("parse lowercase string"); - assert_eq!(parse, vec![0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]); - let ser = parse.to_lower_hex_string(); - assert_eq!(ser, expected); - - let parse: Vec = FromHex::from_hex(expected_up).expect("parse uppercase string"); - assert_eq!(parse, vec![0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]); - let ser = parse.to_lower_hex_string(); - assert_eq!(ser, expected); - - let parse: [u8; 8] = FromHex::from_hex(expected_up).expect("parse uppercase string"); - assert_eq!(parse, [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]); - let ser = parse.to_lower_hex_string(); - assert_eq!(ser, expected); - } - - #[test] - fn hex_error() { - let oddlen = "0123456789abcdef0"; - let badchar1 = "Z123456789abcdef"; - let badchar2 = "012Y456789abcdeb"; - let badchar3 = "«23456789abcdef"; - - assert_eq!(Vec::::from_hex(oddlen), Err(Error::OddLengthString(17))); - assert_eq!(<[u8; 4]>::from_hex(oddlen), Err(Error::OddLengthString(17))); - assert_eq!(<[u8; 8]>::from_hex(oddlen), Err(Error::OddLengthString(17))); - assert_eq!(Vec::::from_hex(badchar1), Err(Error::InvalidChar(b'Z'))); - assert_eq!(Vec::::from_hex(badchar2), Err(Error::InvalidChar(b'Y'))); - assert_eq!(Vec::::from_hex(badchar3), Err(Error::InvalidChar(194))); - } -} diff --git a/hashes/src/impls.rs b/hashes/src/impls.rs index 5ff0179d..088a7f1f 100644 --- a/hashes/src/impls.rs +++ b/hashes/src/impls.rs @@ -5,13 +5,7 @@ //! Implementations of traits defined in `std` / `core2` and not in `core`. //! -#[cfg(feature = "std")] -use std::io; - -#[cfg(not(feature = "std"))] -use core2::io; - -use crate::{hmac, ripemd160, sha1, sha256, sha512, siphash24, HashEngine}; +use crate::{hmac, io, ripemd160, sha1, sha256, sha512, siphash24, HashEngine}; impl io::Write for sha1::HashEngine { fn flush(&mut self) -> io::Result<()> { Ok(()) } diff --git a/hashes/src/internal_macros.rs b/hashes/src/internal_macros.rs index 13ef0be1..32a52dbf 100644 --- a/hashes/src/internal_macros.rs +++ b/hashes/src/internal_macros.rs @@ -9,11 +9,11 @@ macro_rules! arr_newtype_fmt_impl { fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result { #[allow(unused)] use crate::Hash as _; - let case = internals::hex::Case::Lower; + let case = $crate::hex::Case::Lower; if <$ty<$($gen),*>>::DISPLAY_BACKWARD { - internals::hex::display::fmt_hex_exact!(f, $bytes, self.0.iter().rev(), case) + $crate::hex::fmt_hex_exact!(f, $bytes, self.0.iter().rev(), case) } else { - internals::hex::display::fmt_hex_exact!(f, $bytes, self.0.iter(), case) + $crate::hex::fmt_hex_exact!(f, $bytes, self.0.iter(), case) } } } @@ -23,11 +23,11 @@ macro_rules! arr_newtype_fmt_impl { fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result { #[allow(unused)] use crate::Hash as _; - let case = internals::hex::Case::Upper; + let case = $crate::hex::Case::Upper; if <$ty<$($gen),*>>::DISPLAY_BACKWARD { - internals::hex::display::fmt_hex_exact!(f, $bytes, self.0.iter().rev(), case) + $crate::hex::fmt_hex_exact!(f, $bytes, self.0.iter().rev(), case) } else { - internals::hex::display::fmt_hex_exact!(f, $bytes, self.0.iter(), case) + $crate::hex::fmt_hex_exact!(f, $bytes, self.0.iter(), case) } } } @@ -76,7 +76,7 @@ macro_rules! hash_trait_impls { /// This is mainly intended as an internal method and you shouldn't need it unless /// you're doing something special. pub fn forward_hex(&self) -> impl '_ + core::fmt::LowerHex + core::fmt::UpperHex { - internals::hex::display::DisplayHex::as_hex(&self.0) + $crate::hex::DisplayHex::as_hex(&self.0) } /// Displays hex backwards, regardless of how this type would display it naturally. @@ -84,7 +84,7 @@ macro_rules! hash_trait_impls { /// This is mainly intended as an internal method and you shouldn't need it unless /// you're doing something special. pub fn backward_hex(&self) -> impl '_ + core::fmt::LowerHex + core::fmt::UpperHex { - internals::hex::display::DisplayArray::<_, [u8; $bits / 8 * 2]>::new(self.0.iter().rev()) + $crate::hex::display::DisplayArray::<_, [u8; $bits / 8 * 2]>::new(self.0.iter().rev()) } /// Zero cost conversion between a fixed length byte array shared reference and @@ -103,15 +103,15 @@ macro_rules! hash_trait_impls { } impl<$($gen: $gent),*> str::FromStr for Hash<$($gen),*> { - type Err = $crate::hex::Error; + type Err = $crate::hex::HexToArrayError; fn from_str(s: &str) -> Result { - use $crate::hex::{FromHex, HexIterator}; + use $crate::hex::{FromHex, HexToBytesIter}; use $crate::Hash; let inner: [u8; $bits / 8] = if $reverse { - FromHex::from_byte_iter(HexIterator::new(s)?.rev())? + FromHex::from_byte_iter(HexToBytesIter::new(s)?.rev())? } else { - FromHex::from_byte_iter(HexIterator::new(s)?)? + FromHex::from_byte_iter(HexToBytesIter::new(s)?)? }; Ok(Self::from_byte_array(inner)) } diff --git a/hashes/src/lib.rs b/hashes/src/lib.rs index b54feb2d..fa92397a 100644 --- a/hashes/src/lib.rs +++ b/hashes/src/lib.rs @@ -79,12 +79,12 @@ // Instead of littering the codebase for non-fuzzing code just globally allow. #![cfg_attr(hashes_fuzz, allow(dead_code, unused_imports))] +#[cfg(all(not(test), not(feature = "std"), feature = "core2"))] +extern crate actual_core2 as core2; #[cfg(all(feature = "alloc", not(feature = "std")))] extern crate alloc; #[cfg(any(test, feature = "std"))] extern crate core; -#[cfg(feature = "core2")] -extern crate core2; #[cfg(feature = "serde")] /// A generic serialization/deserialization framework. @@ -95,6 +95,9 @@ extern crate serde_test; #[cfg(bench)] extern crate test; +/// Re-export the `hex-conservative` crate. +pub extern crate hex; + #[doc(hidden)] pub mod _export { /// A re-export of core::* @@ -113,9 +116,8 @@ mod util; pub mod serde_macros; pub mod cmp; pub mod hash160; -pub mod hex; pub mod hmac; -#[cfg(any(feature = "std", feature = "core2"))] +#[cfg(any(test, feature = "std", feature = "core2"))] mod impls; pub mod ripemd160; pub mod sha1; @@ -127,7 +129,12 @@ pub mod sha512_256; pub mod siphash24; use core::{borrow, fmt, hash, ops}; +// You get I/O if you enable "std" or "core2" (as well as during testing). +#[cfg(any(test, feature = "std"))] +use std::io; +#[cfg(all(not(test), not(feature = "std"), feature = "core2"))] +use core2::io; pub use hmac::{Hmac, HmacEngine}; /// A hashing engine which bytes can be serialized into. diff --git a/hashes/src/sha256.rs b/hashes/src/sha256.rs index e34e3646..5bafe883 100644 --- a/hashes/src/sha256.rs +++ b/hashes/src/sha256.rs @@ -125,7 +125,7 @@ impl> Index for Midstate { } impl str::FromStr for Midstate { - type Err = hex::Error; + type Err = hex::HexToArrayError; fn from_str(s: &str) -> Result { hex::FromHex::from_hex(s) } } @@ -174,9 +174,12 @@ impl Midstate { } impl hex::FromHex for Midstate { - fn from_byte_iter(iter: I) -> Result + type Err = hex::HexToArrayError; + fn from_byte_iter(iter: I) -> Result where - I: Iterator> + ExactSizeIterator + DoubleEndedIterator, + I: Iterator> + + ExactSizeIterator + + DoubleEndedIterator, { // DISPLAY_BACKWARD is true Ok(Midstate::from_byte_array(hex::FromHex::from_byte_iter(iter.rev())?)) diff --git a/hashes/src/util.rs b/hashes/src/util.rs index 39eb33b6..b8c23c74 100644 --- a/hashes/src/util.rs +++ b/hashes/src/util.rs @@ -268,15 +268,15 @@ macro_rules! hash_newtype { } impl $crate::_export::_core::str::FromStr for $newtype { - type Err = $crate::hex::Error; + type Err = $crate::hex::HexToArrayError; fn from_str(s: &str) -> $crate::_export::_core::result::Result<$newtype, Self::Err> { - use $crate::hex::{HexIterator, FromHex}; + use $crate::hex::{FromHex, HexToBytesIter}; use $crate::Hash; let inner: <$hash as Hash>::Bytes = if ::DISPLAY_BACKWARD { - FromHex::from_byte_iter(HexIterator::new(s)?.rev())? + FromHex::from_byte_iter(HexToBytesIter::new(s)?.rev())? } else { - FromHex::from_byte_iter(HexIterator::new(s)?)? + FromHex::from_byte_iter(HexToBytesIter::new(s)?)? }; Ok($newtype(<$hash>::from_byte_array(inner))) }