From d5dd54a489a43effcd38df46e1eb7825f6cae464 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Tue, 9 Jul 2024 13:14:26 +1000 Subject: [PATCH] hashes: Strongly type the sha256d::HashEngine Currently we are using a type alias for the `sha256d::HashEngine`. Type alias' allow for potential mixing of types, a `sha256d::HashEngine` struct can better serve our users with not much additional complexity or maintenance burden. --- bitcoin/src/crypto/sighash.rs | 8 ++++---- hashes/src/impls.rs | 11 ++++++++++- hashes/src/sha256d.rs | 26 +++++++++++++++++++++++--- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/bitcoin/src/crypto/sighash.rs b/bitcoin/src/crypto/sighash.rs index cf302e5ca..0554261b0 100644 --- a/bitcoin/src/crypto/sighash.rs +++ b/bitcoin/src/crypto/sighash.rs @@ -59,12 +59,12 @@ impl_message_from_hash!(SegwitV0Sighash); // but outside of it, it should not be possible to construct these hash // types from arbitrary data (except by casting via to/from_byte_array). impl LegacySighash { - fn engine() -> sha256::HashEngine { sha256d::Hash::engine() } - fn from_engine(e: sha256::HashEngine) -> Self { Self(sha256d::Hash::from_engine(e)) } + fn engine() -> sha256d::HashEngine { sha256d::Hash::engine() } + fn from_engine(e: sha256d::HashEngine) -> Self { Self(sha256d::Hash::from_engine(e)) } } impl SegwitV0Sighash { - fn engine() -> sha256::HashEngine { sha256d::Hash::engine() } - fn from_engine(e: sha256::HashEngine) -> Self { Self(sha256d::Hash::from_engine(e)) } + fn engine() -> sha256d::HashEngine { sha256d::Hash::engine() } + fn from_engine(e: sha256d::HashEngine) -> Self { Self(sha256d::Hash::from_engine(e)) } } sha256t_hash_newtype! { diff --git a/hashes/src/impls.rs b/hashes/src/impls.rs index bf9f0b8d4..f3d753ded 100644 --- a/hashes/src/impls.rs +++ b/hashes/src/impls.rs @@ -6,7 +6,7 @@ use bitcoin_io::impl_write; -use crate::{hmac, ripemd160, sha1, sha256, sha512, siphash24, HashEngine}; +use crate::{hmac, ripemd160, sha1, sha256, sha256d, sha512, siphash24, HashEngine}; impl_write!( sha1::HashEngine, @@ -26,6 +26,15 @@ impl_write!( |_us| { Ok(()) } ); +impl_write!( + sha256d::HashEngine, + |us: &mut sha256d::HashEngine, buf| { + us.input(buf); + Ok(buf.len()) + }, + |_us| { Ok(()) } +); + impl_write!( sha512::HashEngine, |us: &mut sha512::HashEngine, buf| { diff --git a/hashes/src/sha256d.rs b/hashes/src/sha256d.rs index 87a4cde35..175f1bae9 100644 --- a/hashes/src/sha256d.rs +++ b/hashes/src/sha256d.rs @@ -13,10 +13,30 @@ crate::internal_macros::hash_type! { "Output of the SHA256d hash function." } -type HashEngine = sha256::HashEngine; +/// Engine to compute SHA256d hash function. +#[derive(Clone)] +pub struct HashEngine(sha256::HashEngine); -fn from_engine(e: sha256::HashEngine) -> Hash { - let sha2 = sha256::Hash::from_engine(e); +impl HashEngine { + /// Creates a new SHA256d hash engine. + pub const fn new() -> Self { Self(sha256::HashEngine::new()) } +} + +impl Default for HashEngine { + fn default() -> Self { Self::new() } +} + +impl crate::HashEngine for HashEngine { + type MidState = sha256::Midstate; + fn midstate(&self) -> Self::MidState { self.0.midstate() } + + const BLOCK_SIZE: usize = 64; // Same as sha256::HashEngine::BLOCK_SIZE; + fn input(&mut self, data: &[u8]) { self.0.input(data) } + fn n_bytes_hashed(&self) -> usize { self.0.n_bytes_hashed() } +} + +fn from_engine(e: HashEngine) -> Hash { + let sha2 = sha256::Hash::from_engine(e.0); let sha2d = sha256::Hash::hash(&sha2[..]); let mut ret = [0; 32];