hashes: Add hash function to modules

Add a standalone `hash` function that is a drop in replacement for
`GeneralHash::hash`. Do not add it to `hmac` - this is in parity with
the current code because `Hmac` does not implement `GeneralHash::hash`.

Use the new function in `bitcoin` removing all occurrences of
`GeneralHash` from `bitcoin`.

In `hashes` replace usage of `GeneralHash::hash` with the new `hash`
function.
This commit is contained in:
Tobin C. Harding 2025-02-20 13:20:12 +11:00
parent e1bac7da55
commit d3846895d7
No known key found for this signature in database
GPG Key ID: 40BF9E4C269D6607
6 changed files with 32 additions and 13 deletions

View File

@ -16,7 +16,7 @@
use core::mem;
use hashes::{sha256, sha256d, GeneralHash, Hash};
use hashes::{sha256, sha256d, Hash};
use hex::DisplayHex as _;
use internals::{compact_size, ToU64};
use io::{BufRead, Cursor, Read, Write};
@ -629,7 +629,7 @@ impl Decodable for Box<[u8]> {
/// Does a double-SHA256 on `data` and returns the first 4 bytes.
fn sha2_checksum(data: &[u8]) -> [u8; 4] {
let checksum = <sha256d::Hash as GeneralHash>::hash(data);
let checksum = sha256d::hash(data);
let checksum = checksum.to_byte_array();
[checksum[0], checksum[1], checksum[2], checksum[3]]
}

View File

@ -113,15 +113,15 @@ macro_rules! impl_psbt_insert_pair {
#[rustfmt::skip]
macro_rules! psbt_insert_hash_pair {
(&mut $slf:ident.$map:ident <= $raw_key:ident|$raw_value:ident|$hash:path|$hash_type_error:path) => {
(&mut $slf:ident.$map:ident <= $raw_key:ident|$raw_value:ident|$hash:ident|$hash_type_error:path) => {
if $raw_key.key_data.is_empty() {
return Err($crate::psbt::Error::InvalidKey($raw_key));
}
let key_val: $hash = Deserialize::deserialize(&$raw_key.key_data)?;
let key_val: $hash::Hash = Deserialize::deserialize(&$raw_key.key_data)?;
match $slf.$map.entry(key_val) {
btree_map::Entry::Vacant(empty_key) => {
let val: Vec<u8> = Deserialize::deserialize(&$raw_value)?;
if <$hash as hashes::GeneralHash>::hash(&val) != key_val {
if $hash::hash(&val) != key_val {
return Err($crate::psbt::Error::InvalidPreimageHashPair {
preimage: val.into_boxed_slice(),
hash: Box::from(key_val.borrow()),

View File

@ -317,22 +317,22 @@ impl Input {
}
PSBT_IN_RIPEMD160 => {
psbt_insert_hash_pair! {
&mut self.ripemd160_preimages <= raw_key|raw_value|ripemd160::Hash|error::PsbtHash::Ripemd
&mut self.ripemd160_preimages <= raw_key|raw_value|ripemd160|error::PsbtHash::Ripemd
}
}
PSBT_IN_SHA256 => {
psbt_insert_hash_pair! {
&mut self.sha256_preimages <= raw_key|raw_value|sha256::Hash|error::PsbtHash::Sha256
&mut self.sha256_preimages <= raw_key|raw_value|sha256|error::PsbtHash::Sha256
}
}
PSBT_IN_HASH160 => {
psbt_insert_hash_pair! {
&mut self.hash160_preimages <= raw_key|raw_value|hash160::Hash|error::PsbtHash::Hash160
&mut self.hash160_preimages <= raw_key|raw_value|hash160|error::PsbtHash::Hash160
}
}
PSBT_IN_HASH256 => {
psbt_insert_hash_pair! {
&mut self.hash256_preimages <= raw_key|raw_value|sha256d::Hash|error::PsbtHash::Hash256
&mut self.hash256_preimages <= raw_key|raw_value|sha256d|error::PsbtHash::Hash256
}
}
PSBT_IN_TAP_KEY_SIG => {

View File

@ -71,6 +71,15 @@ pub(crate) use hash_trait_impls;
/// [`hash_trait_impls`].
macro_rules! general_hash_type {
($bits:expr, $reverse:expr, $doc:literal) => {
/// Hashes some bytes.
pub fn hash(data: &[u8]) -> Hash {
use crate::HashEngine as _;
let mut engine = Hash::engine();
engine.input(data);
engine.finalize()
}
$crate::internal_macros::hash_type_no_default!($bits, $reverse, $doc);
impl Hash {
@ -82,7 +91,7 @@ macro_rules! general_hash_type {
/// Hashes some bytes.
#[allow(clippy::self_named_constructors)] // Hash is a noun and a verb.
pub fn hash(data: &[u8]) -> Self { <Self as $crate::GeneralHash>::hash(data) }
pub fn hash(data: &[u8]) -> Self { hash(data) }
/// Hashes all the byte slices retrieved from the iterator together.
pub fn hash_byte_chunks<B, I>(byte_slices: I) -> Self

View File

@ -140,9 +140,7 @@ impl crate::HashEngine for HashEngine {
impl Hash {
/// Iterate the sha256 algorithm to turn a sha256 hash into a sha256d hash
#[must_use]
pub fn hash_again(&self) -> sha256d::Hash {
crate::Hash::from_byte_array(<Self as crate::GeneralHash>::hash(&self.0).0)
}
pub fn hash_again(&self) -> sha256d::Hash { sha256d::Hash::from_byte_array(hash(&self.0).0) }
/// Computes hash from `bytes` in `const` context.
///

View File

@ -9,6 +9,18 @@ use core::marker::PhantomData;
use crate::sha256::Midstate;
use crate::{sha256, HashEngine as _};
/// Hashes some bytes.
pub fn hash<T>(data: &[u8]) -> Hash<T>
where
T: Tag,
{
use crate::HashEngine as _;
let mut engine = HashEngine::default();
engine.input(data);
engine.finalize()
}
/// Trait representing a tag that can be used as a context for SHA256t hashes.
pub trait Tag {
/// The [`Midstate`] after pre-tagging the hash engine.