diff --git a/base58/src/lib.rs b/base58/src/lib.rs index 05544c436..d2ce2de5f 100644 --- a/base58/src/lib.rs +++ b/base58/src/lib.rs @@ -35,7 +35,7 @@ use core::{fmt, str}; #[cfg(feature = "std")] pub use std::{string::String, vec::Vec}; -use hashes::{sha256d, Hash}; +use hashes::sha256d; use crate::error::{IncorrectChecksumError, TooShortError}; diff --git a/bitcoin/examples/ecdsa-psbt-simple.rs b/bitcoin/examples/ecdsa-psbt-simple.rs index ac2c17f81..f9ed0feb9 100644 --- a/bitcoin/examples/ecdsa-psbt-simple.rs +++ b/bitcoin/examples/ecdsa-psbt-simple.rs @@ -26,7 +26,6 @@ use std::collections::BTreeMap; use std::str::FromStr; use bitcoin::bip32::{ChildNumber, DerivationPath, Fingerprint, IntoDerivationPath, Xpriv, Xpub}; -use bitcoin::hashes::Hash; use bitcoin::locktime::absolute; use bitcoin::psbt::Input; use bitcoin::secp256k1::{Secp256k1, Signing}; diff --git a/bitcoin/examples/sign-tx-segwit-v0.rs b/bitcoin/examples/sign-tx-segwit-v0.rs index 73507f1f7..f861ce21d 100644 --- a/bitcoin/examples/sign-tx-segwit-v0.rs +++ b/bitcoin/examples/sign-tx-segwit-v0.rs @@ -4,7 +4,6 @@ use std::str::FromStr; -use bitcoin::hashes::Hash; use bitcoin::locktime::absolute; use bitcoin::secp256k1::{rand, Message, Secp256k1, SecretKey, Signing}; use bitcoin::sighash::{EcdsaSighashType, SighashCache}; diff --git a/bitcoin/examples/sign-tx-taproot.rs b/bitcoin/examples/sign-tx-taproot.rs index 3221c560c..151bd5639 100644 --- a/bitcoin/examples/sign-tx-taproot.rs +++ b/bitcoin/examples/sign-tx-taproot.rs @@ -4,7 +4,6 @@ use std::str::FromStr; -use bitcoin::hashes::Hash; use bitcoin::key::{Keypair, TapTweak, TweakedKeypair, UntweakedPublicKey}; use bitcoin::locktime::absolute; use bitcoin::secp256k1::{rand, Message, Secp256k1, SecretKey, Signing, Verification}; diff --git a/bitcoin/examples/taproot-psbt-simple.rs b/bitcoin/examples/taproot-psbt-simple.rs index 48b9cc0a7..7ea13d443 100644 --- a/bitcoin/examples/taproot-psbt-simple.rs +++ b/bitcoin/examples/taproot-psbt-simple.rs @@ -24,7 +24,6 @@ use std::collections::BTreeMap; use std::str::FromStr; use bitcoin::bip32::{ChildNumber, DerivationPath, Fingerprint, IntoDerivationPath, Xpriv, Xpub}; -use bitcoin::hashes::Hash; use bitcoin::key::UntweakedPublicKey; use bitcoin::locktime::absolute; use bitcoin::psbt::Input; diff --git a/bitcoin/src/address/mod.rs b/bitcoin/src/address/mod.rs index 9eee27a6e..115d0d90b 100644 --- a/bitcoin/src/address/mod.rs +++ b/bitcoin/src/address/mod.rs @@ -33,7 +33,7 @@ use core::marker::PhantomData; use core::str::FromStr; use bech32::primitives::hrp::Hrp; -use hashes::{sha256, Hash, HashEngine}; +use hashes::{sha256, HashEngine}; use secp256k1::{Secp256k1, Verification, XOnlyPublicKey}; use crate::blockdata::constants::{ diff --git a/bitcoin/src/bip152.rs b/bitcoin/src/bip152.rs index b20fb8b22..766a82e0e 100644 --- a/bitcoin/src/bip152.rs +++ b/bitcoin/src/bip152.rs @@ -8,7 +8,7 @@ use core::{convert, fmt, mem}; #[cfg(feature = "std")] use std::error; -use hashes::{sha256, siphash24, Hash}; +use hashes::{sha256, siphash24}; use internals::impl_array_newtype; use io::{BufRead, Write}; diff --git a/bitcoin/src/bip158.rs b/bitcoin/src/bip158.rs index 7e54b810c..ee027d7ce 100644 --- a/bitcoin/src/bip158.rs +++ b/bitcoin/src/bip158.rs @@ -40,7 +40,7 @@ use core::cmp::{self, Ordering}; use core::fmt::{self, Display, Formatter}; -use hashes::{sha256d, siphash24, Hash}; +use hashes::{sha256d, siphash24}; use internals::write_err; use io::{BufRead, Write}; diff --git a/bitcoin/src/blockdata/block.rs b/bitcoin/src/blockdata/block.rs index 9d194d625..2e61ec0f9 100644 --- a/bitcoin/src/blockdata/block.rs +++ b/bitcoin/src/blockdata/block.rs @@ -9,7 +9,7 @@ use core::fmt; -use hashes::{sha256d, Hash, HashEngine}; +use hashes::{sha256d, HashEngine}; use io::{BufRead, Write}; use super::Weight; diff --git a/bitcoin/src/blockdata/constants.rs b/bitcoin/src/blockdata/constants.rs index c652c4bf3..8aa42d22c 100644 --- a/bitcoin/src/blockdata/constants.rs +++ b/bitcoin/src/blockdata/constants.rs @@ -6,7 +6,7 @@ //! consensus code. In particular, it defines the genesis block and its //! single transaction. -use hashes::{sha256d, Hash}; +use hashes::sha256d; use internals::impl_array_newtype; use crate::blockdata::block::{self, Block}; diff --git a/bitcoin/src/blockdata/script/borrowed.rs b/bitcoin/src/blockdata/script/borrowed.rs index f07858d21..050e0c578 100644 --- a/bitcoin/src/blockdata/script/borrowed.rs +++ b/bitcoin/src/blockdata/script/borrowed.rs @@ -5,7 +5,6 @@ use core::ops::{ Bound, Index, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive, }; -use hashes::Hash; use secp256k1::{Secp256k1, Verification}; use super::PushBytes; diff --git a/bitcoin/src/blockdata/script/tests.rs b/bitcoin/src/blockdata/script/tests.rs index 965e61890..5fb6da4d6 100644 --- a/bitcoin/src/blockdata/script/tests.rs +++ b/bitcoin/src/blockdata/script/tests.rs @@ -2,7 +2,6 @@ use core::str::FromStr; -use hashes::Hash; use hex_lit::hex; use super::*; diff --git a/bitcoin/src/blockdata/script/witness_program.rs b/bitcoin/src/blockdata/script/witness_program.rs index 9b76becc8..710753acc 100644 --- a/bitcoin/src/blockdata/script/witness_program.rs +++ b/bitcoin/src/blockdata/script/witness_program.rs @@ -9,7 +9,6 @@ use core::fmt; -use hashes::Hash as _; use internals::array_vec::ArrayVec; use secp256k1::{Secp256k1, Verification}; diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs index 26948bbe3..132d7a71d 100644 --- a/bitcoin/src/blockdata/transaction.rs +++ b/bitcoin/src/blockdata/transaction.rs @@ -12,7 +12,7 @@ use core::{cmp, fmt, str}; -use hashes::{sha256d, Hash}; +use hashes::sha256d; use internals::write_err; use io::{BufRead, Write}; use units::parse::{self, PrefixedHexError, UnprefixedHexError}; diff --git a/bitcoin/src/crypto/key.rs b/bitcoin/src/crypto/key.rs index 01a7f7f18..8e5127df3 100644 --- a/bitcoin/src/crypto/key.rs +++ b/bitcoin/src/crypto/key.rs @@ -9,7 +9,7 @@ use core::fmt::{self, Write as _}; use core::ops; use core::str::FromStr; -use hashes::{hash160, Hash}; +use hashes::hash160; use hex::{FromHex, HexToArrayError}; use internals::array_vec::ArrayVec; use internals::write_err; diff --git a/bitcoin/src/crypto/sighash.rs b/bitcoin/src/crypto/sighash.rs index a11c770de..f68fb56bc 100644 --- a/bitcoin/src/crypto/sighash.rs +++ b/bitcoin/src/crypto/sighash.rs @@ -13,7 +13,7 @@ use core::{fmt, str}; -use hashes::{hash_newtype, sha256, sha256d, sha256t_hash_newtype, Hash}; +use hashes::{hash_newtype, sha256, sha256d, sha256t_hash_newtype}; use internals::write_err; use io::Write; diff --git a/bitcoin/src/hash_types.rs b/bitcoin/src/hash_types.rs index a7014583a..58c008a7f 100644 --- a/bitcoin/src/hash_types.rs +++ b/bitcoin/src/hash_types.rs @@ -13,7 +13,6 @@ pub use crate::{ #[cfg(test)] mod tests { use super::*; - use crate::hashes::Hash; use crate::{ LegacySighash, PubkeyHash, ScriptHash, SegwitV0Sighash, TapSighash, WPubkeyHash, WScriptHash, XKeyIdentifier, diff --git a/bitcoin/src/internal_macros.rs b/bitcoin/src/internal_macros.rs index b33ac5fc5..2429009fe 100644 --- a/bitcoin/src/internal_macros.rs +++ b/bitcoin/src/internal_macros.rs @@ -185,7 +185,6 @@ macro_rules! impl_hashencode { impl $crate::consensus::Decodable for $hashtype { fn consensus_decode(r: &mut R) -> core::result::Result { - use $crate::hashes::Hash; Ok(Self::from_byte_array(<<$hashtype as $crate::hashes::Hash>::Bytes>::consensus_decode(r)?)) } } @@ -199,14 +198,12 @@ macro_rules! impl_asref_push_bytes { $( impl AsRef<$crate::blockdata::script::PushBytes> for $hashtype { fn as_ref(&self) -> &$crate::blockdata::script::PushBytes { - use $crate::hashes::Hash; self.as_byte_array().into() } } impl From<$hashtype> for $crate::blockdata::script::PushBytesBuf { fn from(hash: $hashtype) -> Self { - use $crate::hashes::Hash; hash.as_byte_array().into() } } diff --git a/bitcoin/src/merkle_tree/block.rs b/bitcoin/src/merkle_tree/block.rs index ed8f26dc7..09915eb6b 100644 --- a/bitcoin/src/merkle_tree/block.rs +++ b/bitcoin/src/merkle_tree/block.rs @@ -40,7 +40,6 @@ use core::fmt; -use hashes::Hash; use io::{BufRead, Write}; use self::MerkleBlockError::*; diff --git a/bitcoin/src/p2p/message.rs b/bitcoin/src/p2p/message.rs index 239ba91c8..829e12114 100644 --- a/bitcoin/src/p2p/message.rs +++ b/bitcoin/src/p2p/message.rs @@ -7,7 +7,7 @@ use core::{fmt, iter}; -use hashes::{sha256d, Hash}; +use hashes::sha256d; use io::{BufRead, Write}; use crate::blockdata::{block, transaction}; diff --git a/bitcoin/src/p2p/message_blockdata.rs b/bitcoin/src/p2p/message_blockdata.rs index 05c4d4e01..c61421506 100644 --- a/bitcoin/src/p2p/message_blockdata.rs +++ b/bitcoin/src/p2p/message_blockdata.rs @@ -5,7 +5,7 @@ //! This module describes network messages which are used for passing //! Bitcoin data (blocks and transactions) around. -use hashes::{sha256d, Hash as _}; +use hashes::sha256d; use io::{BufRead, Write}; use crate::blockdata::block::BlockHash; @@ -144,7 +144,6 @@ impl_consensus_encoding!(GetHeadersMessage, version, locator_hashes, stop_hash); #[cfg(test)] mod tests { - use hashes::Hash; use hex::test_hex_unwrap as hex; use super::*; diff --git a/bitcoin/src/pow.rs b/bitcoin/src/pow.rs index eab1f9e3e..b936644d3 100644 --- a/bitcoin/src/pow.rs +++ b/bitcoin/src/pow.rs @@ -217,7 +217,6 @@ impl Target { /// to the target. #[cfg_attr(all(test, mutate), mutate)] pub fn is_met_by(&self, hash: BlockHash) -> bool { - use hashes::Hash; let hash = U256::from_le_bytes(hash.to_byte_array()); hash <= self.0 } @@ -1784,8 +1783,6 @@ mod tests { #[test] fn compact_target_from_upwards_difficulty_adjustment_using_headers() { - use hashes::Hash; - use crate::block::Version; use crate::constants::genesis_block; use crate::TxMerkleNode; @@ -1809,8 +1806,6 @@ mod tests { #[test] fn compact_target_from_downwards_difficulty_adjustment_using_headers() { - use hashes::Hash; - use crate::block::Version; use crate::TxMerkleNode; let params = Params::new(crate::Network::Signet); @@ -1896,8 +1891,6 @@ mod tests { fn target_is_met_by_for_target_equals_hash() { use std::str::FromStr; - use hashes::Hash; - let hash = BlockHash::from_str("ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c") .expect("failed to parse block hash"); diff --git a/bitcoin/src/psbt/mod.rs b/bitcoin/src/psbt/mod.rs index 86f1f9b47..1f12a053e 100644 --- a/bitcoin/src/psbt/mod.rs +++ b/bitcoin/src/psbt/mod.rs @@ -1205,7 +1205,7 @@ pub use self::display_from_str::PsbtParseError; #[cfg(test)] mod tests { - use hashes::{hash160, ripemd160, sha256, Hash}; + use hashes::{hash160, ripemd160, sha256}; use hex::{test_hex_unwrap as hex, FromHex}; #[cfg(feature = "rand-std")] use secp256k1::{All, SecretKey}; diff --git a/bitcoin/src/psbt/serialize.rs b/bitcoin/src/psbt/serialize.rs index 25e7890fb..972c93a97 100644 --- a/bitcoin/src/psbt/serialize.rs +++ b/bitcoin/src/psbt/serialize.rs @@ -5,7 +5,7 @@ //! Traits to serialize PSBT values to and from raw bytes //! according to the BIP-174 specification. -use hashes::{hash160, ripemd160, sha256, sha256d, Hash}; +use hashes::{hash160, ripemd160, sha256, sha256d}; use secp256k1::XOnlyPublicKey; use super::map::{Input, Map, Output, PsbtSighashType}; diff --git a/bitcoin/src/sign_message.rs b/bitcoin/src/sign_message.rs index 9f7bb524d..3e85a7a8c 100644 --- a/bitcoin/src/sign_message.rs +++ b/bitcoin/src/sign_message.rs @@ -5,7 +5,7 @@ //! This module provides signature related functions including secp256k1 signature recovery when //! library is used with the `secp-recovery` feature. -use hashes::{sha256d, Hash, HashEngine}; +use hashes::{sha256d, HashEngine}; use crate::consensus::{encode, Encodable}; @@ -21,7 +21,7 @@ pub const BITCOIN_SIGNED_MSG_PREFIX: &[u8] = b"\x18Bitcoin Signed Message:\n"; mod message_signing { use core::fmt; - use hashes::{sha256d, Hash}; + use hashes::sha256d; use internals::write_err; use secp256k1::ecdsa::{RecoverableSignature, RecoveryId}; diff --git a/bitcoin/src/taproot/mod.rs b/bitcoin/src/taproot/mod.rs index 138c391ce..5fe0a16b1 100644 --- a/bitcoin/src/taproot/mod.rs +++ b/bitcoin/src/taproot/mod.rs @@ -11,7 +11,7 @@ use core::cmp::Reverse; use core::fmt; use core::iter::FusedIterator; -use hashes::{sha256t_hash_newtype, Hash, HashEngine}; +use hashes::{sha256t_hash_newtype, HashEngine}; use internals::write_err; use io::Write; use secp256k1::{Scalar, Secp256k1}; diff --git a/bitcoin/tests/serde.rs b/bitcoin/tests/serde.rs index 014012fd3..6bd400bcc 100644 --- a/bitcoin/tests/serde.rs +++ b/bitcoin/tests/serde.rs @@ -30,7 +30,7 @@ use bitcoin::bip32::{ChildNumber, KeySource, Xpriv, Xpub}; use bitcoin::blockdata::locktime::{absolute, relative}; use bitcoin::blockdata::witness::Witness; use bitcoin::consensus::encode::deserialize; -use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d, Hash}; +use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d}; use bitcoin::hex::FromHex; use bitcoin::psbt::raw::{self, Key, Pair, ProprietaryKey}; use bitcoin::psbt::{Input, Output, Psbt, PsbtSighashType}; diff --git a/fuzz/fuzz_targets/hashes/ripemd160.rs b/fuzz/fuzz_targets/hashes/ripemd160.rs index f311a9b5b..9b0e338ec 100644 --- a/fuzz/fuzz_targets/hashes/ripemd160.rs +++ b/fuzz/fuzz_targets/hashes/ripemd160.rs @@ -1,4 +1,4 @@ -use bitcoin::hashes::{ripemd160, Hash, HashEngine}; +use bitcoin::hashes::{ripemd160, HashEngine}; use honggfuzz::fuzz; fn do_test(data: &[u8]) { diff --git a/fuzz/fuzz_targets/hashes/sha1.rs b/fuzz/fuzz_targets/hashes/sha1.rs index 81b0a2c7f..ab72db64e 100644 --- a/fuzz/fuzz_targets/hashes/sha1.rs +++ b/fuzz/fuzz_targets/hashes/sha1.rs @@ -1,4 +1,4 @@ -use bitcoin::hashes::{sha1, Hash, HashEngine}; +use bitcoin::hashes::{sha1, HashEngine}; use honggfuzz::fuzz; fn do_test(data: &[u8]) { diff --git a/fuzz/fuzz_targets/hashes/sha256.rs b/fuzz/fuzz_targets/hashes/sha256.rs index a81a31e9e..c2397f193 100644 --- a/fuzz/fuzz_targets/hashes/sha256.rs +++ b/fuzz/fuzz_targets/hashes/sha256.rs @@ -1,4 +1,4 @@ -use bitcoin::hashes::{sha256, Hash, HashEngine}; +use bitcoin::hashes::{sha256, HashEngine}; use honggfuzz::fuzz; fn do_test(data: &[u8]) { diff --git a/fuzz/fuzz_targets/hashes/sha512.rs b/fuzz/fuzz_targets/hashes/sha512.rs index b49ef7934..32b1d879b 100644 --- a/fuzz/fuzz_targets/hashes/sha512.rs +++ b/fuzz/fuzz_targets/hashes/sha512.rs @@ -1,4 +1,4 @@ -use bitcoin::hashes::{sha512, Hash, HashEngine}; +use bitcoin::hashes::{sha512, HashEngine}; use honggfuzz::fuzz; fn do_test(data: &[u8]) { diff --git a/fuzz/fuzz_targets/hashes/sha512_256.rs b/fuzz/fuzz_targets/hashes/sha512_256.rs index 30f09302d..44c90960d 100644 --- a/fuzz/fuzz_targets/hashes/sha512_256.rs +++ b/fuzz/fuzz_targets/hashes/sha512_256.rs @@ -1,4 +1,4 @@ -use bitcoin::hashes::{sha512_256, Hash, HashEngine}; +use bitcoin::hashes::{sha512_256, HashEngine}; use honggfuzz::fuzz; fn do_test(data: &[u8]) { diff --git a/hashes/src/hash160.rs b/hashes/src/hash160.rs index df1efc922..6f2da18fd 100644 --- a/hashes/src/hash160.rs +++ b/hashes/src/hash160.rs @@ -21,8 +21,6 @@ crate::internal_macros::hash_type! { type HashEngine = sha256::HashEngine; fn from_engine(e: HashEngine) -> Hash { - use crate::Hash as _; - let sha2 = sha256::Hash::from_engine(e); let rmd = ripemd160::Hash::hash(&sha2[..]); @@ -92,7 +90,7 @@ mod tests { fn ripemd_serde() { use serde_test::{assert_tokens, Configure, Token}; - use crate::{hash160, Hash}; + use crate::hash160; #[rustfmt::skip] static HASH_BYTES: [u8; 20] = [ diff --git a/hashes/src/internal_macros.rs b/hashes/src/internal_macros.rs index bbe40c0a4..2a52157ed 100644 --- a/hashes/src/internal_macros.rs +++ b/hashes/src/internal_macros.rs @@ -63,17 +63,14 @@ pub(crate) use arr_newtype_fmt_impl; /// /// * There must be a free-standing `fn from_engine(HashEngine) -> Hash` in the scope /// * `fn internal_new([u8; $bits / 8]) -> Self` must exist on `Hash` -/// * `fn internal_engine() -> HashEngine` must exist on `Hash` /// /// `from_engine` obviously implements the finalization algorithm. -/// `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, $reverse:expr $(, $gen:ident: $gent:ident)*) => { impl<$($gen: $gent),*> $crate::_export::_core::str::FromStr for Hash<$($gen),*> { type Err = $crate::hex::HexToArrayError; fn from_str(s: &str) -> $crate::_export::_core::result::Result { - use $crate::{Hash, hex::{FromHex}}; + use $crate::{hex::{FromHex}}; let mut bytes = <[u8; $bits / 8]>::from_hex(s)?; if $reverse { @@ -109,39 +106,21 @@ macro_rules! hash_trait_impls { const LEN: usize = $bits / 8; const DISPLAY_BACKWARD: bool = $reverse; - fn engine() -> Self::Engine { - Self::internal_engine() - } + fn engine() -> HashEngine { Self::engine() } - fn from_engine(e: HashEngine) -> Hash<$($gen),*> { - from_engine(e) - } + fn from_engine(e: HashEngine) -> Hash<$($gen),*> { Self::from_engine(e) } fn from_slice(sl: &[u8]) -> $crate::_export::_core::result::Result, FromSliceError> { - if sl.len() != $bits / 8 { - Err(FromSliceError{expected: Self::LEN, got: sl.len()}) - } else { - let mut ret = [0; $bits / 8]; - ret.copy_from_slice(sl); - Ok(Self::internal_new(ret)) - } + Self::from_slice(sl) } - fn to_byte_array(self) -> Self::Bytes { - self.0 - } + fn to_byte_array(self) -> Self::Bytes { self.to_byte_array() } - fn as_byte_array(&self) -> &Self::Bytes { - &self.0 - } + fn as_byte_array(&self) -> &Self::Bytes { self.as_byte_array() } - fn from_byte_array(bytes: Self::Bytes) -> Self { - Self::internal_new(bytes) - } + fn from_byte_array(bytes: Self::Bytes) -> Self { Self::from_byte_array(bytes) } - fn all_zeros() -> Self { - Hash::internal_new([0x00; $bits / 8]) - } + fn all_zeros() -> Self { Self::all_zeros() } } } } @@ -149,8 +128,8 @@ pub(crate) use hash_trait_impls; /// Creates a type called `Hash` and implements standard interface for it. /// -/// The created type will have all standard derives, `Hash` impl and implementation of -/// `internal_engine` returning default. The created type has a single field. +/// The created type has a single field and will have all standard derives as well as an +/// implementation of [`crate::Hash`]. /// /// Arguments: /// @@ -169,9 +148,7 @@ macro_rules! hash_type { pub struct Hash([u8; $bits / 8]); impl Hash { - fn internal_new(arr: [u8; $bits / 8]) -> Self { Hash(arr) } - - fn internal_engine() -> HashEngine { Default::default() } + const fn internal_new(arr: [u8; $bits / 8]) -> Self { Hash(arr) } /// Zero cost conversion between a fixed length byte array shared reference and /// a shared reference to this Hash type. @@ -186,6 +163,68 @@ macro_rules! hash_type { // Safety: Sound because Self is #[repr(transparent)] containing [u8; $bits / 8] unsafe { &mut *(bytes as *mut _ as *mut Self) } } + + /// Constructs a new engine. + pub fn engine() -> HashEngine { Default::default() } + + /// Produces a hash from the current state of a given engine. + pub fn from_engine(e: HashEngine) -> Hash { from_engine(e) } + + /// Copies a byte slice into a hash object. + pub fn from_slice(sl: &[u8]) -> $crate::_export::_core::result::Result { + if sl.len() != $bits / 8 { + Err(FromSliceError{expected: $bits / 8, got: sl.len()}) + } else { + let mut ret = [0; $bits / 8]; + ret.copy_from_slice(sl); + Ok(Self::internal_new(ret)) + } + } + + /// Hashes some bytes. + #[allow(clippy::self_named_constructors)] // Hash is a noun and a verb. + pub fn hash(data: &[u8]) -> Self { + use $crate::HashEngine; + + let mut engine = Self::engine(); + engine.input(data); + Self::from_engine(engine) + } + + /// Hashes all the byte slices retrieved from the iterator together. + pub fn hash_byte_chunks(byte_slices: I) -> Self + where + B: AsRef<[u8]>, + I: IntoIterator, + { + use $crate::HashEngine; + + let mut engine = Self::engine(); + for slice in byte_slices { + engine.input(slice.as_ref()); + } + Self::from_engine(engine) + } + + /// Returns the underlying byte array. + pub const fn to_byte_array(self) -> [u8; $bits / 8] { self.0 } + + /// Returns a reference to the underlying byte array. + pub const fn as_byte_array(&self) -> &[u8; $bits / 8] { &self.0 } + + /// Constructs a hash from the underlying byte array. + pub const fn from_byte_array(bytes: [u8; $bits / 8]) -> Self { + Self::internal_new(bytes) + } + + /// Returns an all zero hash. + /// + /// An all zeros hash is a made up construct because there is not a known input that can create + /// it, however it is used in various places in Bitcoin e.g., the Bitcoin genesis block's + /// previous blockhash and the coinbase transaction's outpoint txid. + pub const fn all_zeros() -> Self { + Hash::internal_new([0x00; $bits / 8]) + } } #[cfg(feature = "schemars")] diff --git a/hashes/src/lib.rs b/hashes/src/lib.rs index ae7c01a1b..df3325bd1 100644 --- a/hashes/src/lib.rs +++ b/hashes/src/lib.rs @@ -249,7 +249,7 @@ impl std::error::Error for FromSliceError {} #[cfg(test)] mod tests { - use crate::{sha256d, Hash}; + use crate::sha256d; hash_newtype! { /// A test newtype diff --git a/hashes/src/ripemd160.rs b/hashes/src/ripemd160.rs index 0a2b2d7cc..4ad076090 100644 --- a/hashes/src/ripemd160.rs +++ b/hashes/src/ripemd160.rs @@ -412,7 +412,7 @@ mod tests { fn test() { use std::convert::TryFrom; - use crate::{ripemd160, Hash, HashEngine}; + use crate::{ripemd160, HashEngine}; #[derive(Clone)] struct Test { @@ -507,7 +507,7 @@ mod tests { fn ripemd_serde() { use serde_test::{assert_tokens, Configure, Token}; - use crate::{ripemd160, Hash}; + use crate::ripemd160; #[rustfmt::skip] static HASH_BYTES: [u8; 20] = [ diff --git a/hashes/src/sha1.rs b/hashes/src/sha1.rs index c2584f9ca..221666301 100644 --- a/hashes/src/sha1.rs +++ b/hashes/src/sha1.rs @@ -129,7 +129,7 @@ mod tests { #[test] #[cfg(feature = "alloc")] fn test() { - use crate::{sha1, Hash, HashEngine}; + use crate::{sha1, HashEngine}; #[derive(Clone)] struct Test { @@ -199,7 +199,7 @@ mod tests { fn sha1_serde() { use serde_test::{assert_tokens, Configure, Token}; - use crate::{sha1, Hash}; + use crate::sha1; #[rustfmt::skip] static HASH_BYTES: [u8; 20] = [ diff --git a/hashes/src/sha256.rs b/hashes/src/sha256.rs index 8c26ff9ec..37be2ff8b 100644 --- a/hashes/src/sha256.rs +++ b/hashes/src/sha256.rs @@ -154,7 +154,7 @@ impl Midstate { } /// Unwraps the [`Midstate`] and returns the underlying byte array. - pub fn to_byte_array(self) -> [u8; 32] { self.0 } + pub const fn to_byte_array(self) -> [u8; 32] { self.0 } /// Creates midstate for tagged hashes. /// @@ -815,7 +815,7 @@ impl HashEngine { #[cfg(test)] mod tests { use super::*; - use crate::{sha256, Hash as _, HashEngine}; + use crate::{sha256, HashEngine}; #[test] #[cfg(feature = "alloc")] diff --git a/hashes/src/sha256d.rs b/hashes/src/sha256d.rs index 3d3ad5b9b..87a4cde35 100644 --- a/hashes/src/sha256d.rs +++ b/hashes/src/sha256d.rs @@ -16,8 +16,6 @@ crate::internal_macros::hash_type! { type HashEngine = sha256::HashEngine; fn from_engine(e: sha256::HashEngine) -> Hash { - use crate::Hash as _; - let sha2 = sha256::Hash::from_engine(e); let sha2d = sha256::Hash::hash(&sha2[..]); @@ -28,7 +26,7 @@ fn from_engine(e: sha256::HashEngine) -> Hash { #[cfg(test)] mod tests { - use crate::{sha256d, Hash as _}; + use crate::sha256d; #[test] #[cfg(feature = "alloc")] diff --git a/hashes/src/sha256t.rs b/hashes/src/sha256t.rs index b4be1db90..0678f3dab 100644 --- a/hashes/src/sha256t.rs +++ b/hashes/src/sha256t.rs @@ -7,7 +7,7 @@ use core::marker::PhantomData; use core::ops::Index; use core::slice::SliceIndex; -use crate::{sha256, FromSliceError}; +use crate::{sha256, FromSliceError, HashEngine as _}; type HashEngine = sha256::HashEngine; @@ -39,8 +39,6 @@ impl schemars::JsonSchema for Hash { impl Hash { fn internal_new(arr: [u8; 32]) -> Self { Hash(arr, Default::default()) } - fn internal_engine() -> HashEngine { T::engine() } - /// Zero cost conversion between a fixed length byte array shared reference and /// a shared reference to this Hash type. pub fn from_bytes_ref(bytes: &[u8; 32]) -> &Self { @@ -54,6 +52,68 @@ impl Hash { // Safety: Sound because Self is #[repr(transparent)] containing [u8; 32] unsafe { &mut *(bytes as *mut _ as *mut Self) } } + + /// Constructs a new engine. + pub fn engine() -> HashEngine { T::engine() } + + /// Produces a hash from the current state of a given engine. + pub fn from_engine(e: HashEngine) -> Hash { + from_engine(e) + } + + /// Copies a byte slice into a hash object. + pub fn from_slice(sl: &[u8]) -> Result, FromSliceError> { + if sl.len() != 32 { + Err(FromSliceError{expected: 32, got: sl.len()}) + } else { + let mut ret = [0; 32]; + ret.copy_from_slice(sl); + Ok(Self::internal_new(ret)) + } + } + + /// Hashes some bytes. + #[allow(clippy::self_named_constructors)] // Hash is a noun and a verb. + pub fn hash(data: &[u8]) -> Self { + use crate::HashEngine; + + let mut engine = Self::engine(); + engine.input(data); + Self::from_engine(engine) + } + + /// Hashes all the byte slices retrieved from the iterator together. + pub fn hash_byte_chunks(byte_slices: I) -> Self + where + B: AsRef<[u8]>, + I: IntoIterator, + { + let mut engine = Self::engine(); + for slice in byte_slices { + engine.input(slice.as_ref()); + } + Self::from_engine(engine) + } + + /// Returns the underlying byte array. + pub fn to_byte_array(self) -> [u8; 32] { self.0 } + + /// Returns a reference to the underlying byte array. + pub fn as_byte_array(&self) -> &[u8; 32] { &self.0 } + + /// Constructs a hash from the underlying byte array. + pub fn from_byte_array(bytes: [u8; 32]) -> Self { + Self::internal_new(bytes) + } + + /// Returns an all zero hash. + /// + /// An all zeros hash is a made up construct because there is not a known input that can create + /// it, however it is used in various places in Bitcoin e.g., the Bitcoin genesis block's + /// previous blockhash and the coinbase transaction's outpoint txid. + pub fn all_zeros() -> Self { + Hash::internal_new([0x00; 32]) + } } impl Copy for Hash {} @@ -82,8 +142,6 @@ impl core::hash::Hash for Hash { crate::internal_macros::hash_trait_impls!(256, false, T: Tag); fn from_engine(e: sha256::HashEngine) -> Hash { - use crate::Hash as _; - Hash::from_byte_array(sha256::Hash::from_engine(e).to_byte_array()) } @@ -176,8 +234,6 @@ macro_rules! sha256t_hash_newtype_tag_constructor { #[cfg(test)] mod tests { - #[cfg(feature = "alloc")] - use crate::Hash; use crate::{sha256, sha256t}; const TEST_MIDSTATE: [u8; 32] = [ diff --git a/hashes/src/sha384.rs b/hashes/src/sha384.rs index ce23c3118..ed675ce78 100644 --- a/hashes/src/sha384.rs +++ b/hashes/src/sha384.rs @@ -47,7 +47,7 @@ mod tests { #[test] #[cfg(feature = "alloc")] fn test() { - use crate::{sha384, Hash, HashEngine}; + use crate::{sha384, HashEngine}; #[derive(Clone)] struct Test { diff --git a/hashes/src/sha512.rs b/hashes/src/sha512.rs index 904bb4d65..fb3ab5433 100644 --- a/hashes/src/sha512.rs +++ b/hashes/src/sha512.rs @@ -307,7 +307,7 @@ mod tests { #[test] #[cfg(feature = "alloc")] fn test() { - use crate::{sha512, Hash, HashEngine}; + use crate::{sha512, HashEngine}; #[derive(Clone)] struct Test { @@ -386,7 +386,7 @@ mod tests { fn sha512_serde() { use serde_test::{assert_tokens, Configure, Token}; - use crate::{sha512, Hash}; + use crate::sha512; #[rustfmt::skip] static HASH_BYTES: [u8; 64] = [ diff --git a/hashes/src/sha512_256.rs b/hashes/src/sha512_256.rs index bcaee9216..73d871621 100644 --- a/hashes/src/sha512_256.rs +++ b/hashes/src/sha512_256.rs @@ -57,7 +57,7 @@ mod tests { #[test] #[cfg(feature = "alloc")] fn test() { - use crate::{sha512_256, Hash, HashEngine}; + use crate::{sha512_256, HashEngine}; #[derive(Clone)] struct Test { diff --git a/hashes/src/siphash24.rs b/hashes/src/siphash24.rs index 048ab94ff..ce45cbb37 100644 --- a/hashes/src/siphash24.rs +++ b/hashes/src/siphash24.rs @@ -6,7 +6,7 @@ use core::ops::Index; use core::slice::SliceIndex; use core::{cmp, mem, ptr}; -use crate::{FromSliceError, Hash as _, HashEngine as _}; +use crate::{FromSliceError, HashEngine as _}; crate::internal_macros::hash_type! { 64, diff --git a/hashes/src/util.rs b/hashes/src/util.rs index 79ac4d052..f778f098f 100644 --- a/hashes/src/util.rs +++ b/hashes/src/util.rs @@ -192,24 +192,88 @@ macro_rules! hash_newtype { $crate::serde_impl!($newtype, <$newtype as $crate::Hash>::LEN); $crate::borrow_slice_impl!($newtype); + #[allow(unused)] // Private wrapper types may not need all functions. impl $newtype { /// Creates this wrapper type from the inner hash type. - #[allow(unused)] // the user of macro may not need this pub fn from_raw_hash(inner: $hash) -> $newtype { $newtype(inner) } /// Returns the inner hash (sha256, sh256d etc.). - #[allow(unused)] // the user of macro may not need this pub fn to_raw_hash(self) -> $hash { self.0 } /// Returns a reference to the inner hash (sha256, sh256d etc.). - #[allow(unused)] // the user of macro may not need this pub fn as_raw_hash(&self) -> &$hash { &self.0 } + + /// Constructs a new engine. + pub fn engine() -> <$hash as $crate::Hash>::Engine { + <$hash as $crate::Hash>::engine() + } + + /// Produces a hash from the current state of a given engine. + pub fn from_engine(e: <$hash as $crate::Hash>::Engine) -> Self { + Self::from(<$hash as $crate::Hash>::from_engine(e)) + } + + /// Copies a byte slice into a hash object. + pub fn from_slice(sl: &[u8]) -> $crate::_export::_core::result::Result<$newtype, $crate::FromSliceError> { + Ok($newtype(<$hash as $crate::Hash>::from_slice(sl)?)) + } + + /// Hashes some bytes. + #[allow(unused)] // the user of macro may not need this + pub fn hash(data: &[u8]) -> Self { + use $crate::HashEngine; + + let mut engine = Self::engine(); + engine.input(data); + Self::from_engine(engine) + } + + /// Hashes all the byte slices retrieved from the iterator together. + pub fn hash_byte_chunks(byte_slices: I) -> Self + where + B: AsRef<[u8]>, + I: IntoIterator, + { + use $crate::HashEngine; + + let mut engine = Self::engine(); + for slice in byte_slices { + engine.input(slice.as_ref()); + } + Self::from_engine(engine) + } + + /// Returns the underlying byte array. + pub fn to_byte_array(self) -> <$hash as $crate::Hash>::Bytes { + self.0.to_byte_array() + } + + /// Returns a reference to the underlying byte array. + pub fn as_byte_array(&self) -> &<$hash as $crate::Hash>::Bytes { + self.0.as_byte_array() + } + + /// Constructs a hash from the underlying byte array. + pub fn from_byte_array(bytes: <$hash as $crate::Hash>::Bytes) -> Self { + $newtype(<$hash as $crate::Hash>::from_byte_array(bytes)) + } + + /// Returns an all zero hash. + /// + /// An all zeros hash is a made up construct because there is not a known input that can create + /// it, however it is used in various places in Bitcoin e.g., the Bitcoin genesis block's + /// previous blockhash and the coinbase transaction's outpoint txid. + pub fn all_zeros() -> Self { + let zeros = <$hash>::all_zeros(); + $newtype(zeros) + } + } impl $crate::_export::_core::convert::From<$hash> for $newtype { @@ -232,45 +296,27 @@ macro_rules! hash_newtype { const LEN: usize = <$hash as $crate::Hash>::LEN; const DISPLAY_BACKWARD: bool = $crate::hash_newtype_get_direction!($hash, $(#[$($type_attrs)*])*); - fn engine() -> Self::Engine { - <$hash as $crate::Hash>::engine() - } + fn engine() -> <$hash as $crate::Hash>::Engine { Self::engine() } - fn from_engine(e: Self::Engine) -> Self { - Self::from(<$hash as $crate::Hash>::from_engine(e)) - } + fn from_engine(e: <$hash as $crate::Hash>::Engine) -> $newtype { Self::from_engine(e) } - #[inline] fn from_slice(sl: &[u8]) -> $crate::_export::_core::result::Result<$newtype, $crate::FromSliceError> { - Ok($newtype(<$hash as $crate::Hash>::from_slice(sl)?)) + Self::from_slice(sl) } - #[inline] - fn from_byte_array(bytes: Self::Bytes) -> Self { - $newtype(<$hash as $crate::Hash>::from_byte_array(bytes)) - } + fn to_byte_array(self) -> Self::Bytes { self.to_byte_array() } - #[inline] - fn to_byte_array(self) -> Self::Bytes { - self.0.to_byte_array() - } + fn as_byte_array(&self) -> &Self::Bytes { self.as_byte_array() } - #[inline] - fn as_byte_array(&self) -> &Self::Bytes { - self.0.as_byte_array() - } + fn from_byte_array(bytes: Self::Bytes) -> Self { Self::from_byte_array(bytes) } - #[inline] - fn all_zeros() -> Self { - let zeros = <$hash>::all_zeros(); - $newtype(zeros) - } + fn all_zeros() -> Self { Self::all_zeros() } } impl $crate::_export::_core::str::FromStr for $newtype { type Err = $crate::hex::HexToArrayError; fn from_str(s: &str) -> $crate::_export::_core::result::Result<$newtype, Self::Err> { - use $crate::{Hash, hex::FromHex}; + use $crate::{hex::FromHex}; let mut bytes = <[u8; ::LEN]>::from_hex(s)?; if ::DISPLAY_BACKWARD { @@ -386,7 +432,7 @@ macro_rules! hash_newtype_known_attrs { #[cfg(test)] mod test { - use crate::{sha256, Hash}; + use crate::sha256; #[test] fn hash_as_ref_array() {