Merge rust-bitcoin/rust-bitcoin#2988: Add additional `HashEngine` types

51010777bf hashes: Strongly type the hash160::HashEngine (Tobin C. Harding)
d5dd54a489 hashes: Strongly type the sha256d::HashEngine (Tobin C. Harding)
a7422a779c hashes: Add const hash engine constructors (Tobin C. Harding)

Pull request description:

  Currently we are using a type alias for a few of the hash engines.

  Type alias' allow for potential mixing of types, a struct can better serve our users with not much additional complexity or maintenance burden.

  - As preparation add const constructors where possible to hash engines (excl. `HmacEngine`).
  - Add a `sha256d::HashEngine` struct
  - Add a `hash160::HashEngine` struct

  If this goes in we can improve the `sha256t::HashEngine` in a similar manner.

ACKs for top commit:
  Kixunil:
    ACK 51010777bf
  apoelstra:
    ACK 51010777bf but will hold off on merging until tcharding indicates whether he wants to address the midstate thing

Tree-SHA512: 810db3a8cd66e4d135b04a65d5b4c926cf2e5e8ac531619bbd884db69df17b29b64daeb6fb31b8b1fb32bffbf81cf84e55cd46945c743451c73f1b7f63489f63
This commit is contained in:
merge-script 2024-07-10 17:46:33 +00:00
commit 66b0b52870
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
11 changed files with 120 additions and 38 deletions

View File

@ -34,7 +34,7 @@ use core::str::FromStr;
use bech32::primitives::gf32::Fe32;
use bech32::primitives::hrp::Hrp;
use hashes::{sha256, HashEngine};
use hashes::{hash160, HashEngine};
use secp256k1::{Secp256k1, Verification, XOnlyPublicKey};
use crate::consensus::Params;
@ -878,11 +878,11 @@ impl FromStr for Address<NetworkUnchecked> {
}
/// Convert a byte array of a pubkey hash into a segwit redeem hash
fn segwit_redeem_hash(pubkey_hash: PubkeyHash) -> crate::hashes::hash160::Hash {
let mut sha_engine = sha256::Hash::engine();
fn segwit_redeem_hash(pubkey_hash: PubkeyHash) -> hash160::Hash {
let mut sha_engine = hash160::Hash::engine();
sha_engine.input(&[0, 20]);
sha_engine.input(pubkey_hash.as_ref());
crate::hashes::hash160::Hash::from_engine(sha_engine)
hash160::Hash::from_engine(sha_engine)
}
#[cfg(test)]

View File

@ -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! {

View File

@ -18,10 +18,30 @@ crate::internal_macros::hash_type! {
"Output of the Bitcoin HASH160 hash function. (RIPEMD160(SHA256))"
}
type HashEngine = sha256::HashEngine;
/// Engine to compute HASH160 hash function.
#[derive(Clone)]
pub struct HashEngine(sha256::HashEngine);
impl HashEngine {
/// Creates a new HASH160 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);
let sha2 = sha256::Hash::from_engine(e.0);
let rmd = ripemd160::Hash::hash(&sha2[..]);
let mut ret = [0; 20];

View File

@ -6,7 +6,16 @@
use bitcoin_io::impl_write;
use crate::{hmac, ripemd160, sha1, sha256, sha512, siphash24, HashEngine};
use crate::{hash160, hmac, ripemd160, sha1, sha256, sha256d, sha512, siphash24, HashEngine};
impl_write!(
hash160::HashEngine,
|us: &mut hash160::HashEngine, buf| {
us.input(buf);
Ok(buf.len())
},
|_us| { Ok(()) }
);
impl_write!(
sha1::HashEngine,
@ -26,6 +35,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| {

View File

@ -51,9 +51,10 @@ pub struct HashEngine {
length: usize,
}
impl Default for HashEngine {
fn default() -> Self {
HashEngine {
impl HashEngine {
/// Creates a new SHA256 hash engine.
pub const fn new() -> Self {
Self {
h: [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0],
length: 0,
buffer: [0; BLOCK_SIZE],
@ -61,6 +62,10 @@ impl Default for HashEngine {
}
}
impl Default for HashEngine {
fn default() -> Self { Self::new() }
}
impl crate::HashEngine for HashEngine {
type MidState = [u8; 20];

View File

@ -43,9 +43,10 @@ pub struct HashEngine {
length: usize,
}
impl Default for HashEngine {
fn default() -> Self {
HashEngine {
impl HashEngine {
/// Creates a new SHA1 hash engine.
pub const fn new() -> Self {
Self {
h: [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0],
length: 0,
buffer: [0; BLOCK_SIZE],
@ -53,6 +54,10 @@ impl Default for HashEngine {
}
}
impl Default for HashEngine {
fn default() -> Self { Self::new() }
}
impl crate::HashEngine for HashEngine {
type MidState = [u8; 20];

View File

@ -59,9 +59,10 @@ pub struct HashEngine {
length: usize,
}
impl Default for HashEngine {
fn default() -> Self {
HashEngine {
impl HashEngine {
/// Creates a new SHA256 hash engine.
pub const fn new() -> Self {
Self {
h: [
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab,
0x5be0cd19,
@ -72,6 +73,10 @@ impl Default for HashEngine {
}
}
impl Default for HashEngine {
fn default() -> Self { Self::new() }
}
impl crate::HashEngine for HashEngine {
type MidState = Midstate;

View File

@ -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];

View File

@ -23,11 +23,13 @@ fn from_engine(e: HashEngine) -> Hash {
#[derive(Clone)]
pub struct HashEngine(sha512::HashEngine);
impl HashEngine {
/// Creates a new SHA384 hash engine.
pub const fn new() -> Self { Self(sha512::HashEngine::sha384()) }
}
impl Default for HashEngine {
#[rustfmt::skip]
fn default() -> Self {
HashEngine(sha512::HashEngine::sha384())
}
fn default() -> Self { Self::new() }
}
impl crate::HashEngine for HashEngine {

View File

@ -52,10 +52,11 @@ pub struct HashEngine {
buffer: [u8; BLOCK_SIZE],
}
impl Default for HashEngine {
impl HashEngine {
/// Creates a new SHA512 hash engine.
#[rustfmt::skip]
fn default() -> Self {
HashEngine {
pub const fn new() -> Self {
Self {
h: [
0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179,
@ -66,10 +67,14 @@ impl Default for HashEngine {
}
}
impl Default for HashEngine {
fn default() -> Self { Self::new() }
}
impl HashEngine {
/// Constructs a hash engine suitable for use inside the default `sha512_256::HashEngine`.
/// Constructs a hash engine suitable for use constructing a `sha512_256::HashEngine`.
#[rustfmt::skip]
pub(crate) fn sha512_256() -> Self {
pub(crate) const fn sha512_256() -> Self {
HashEngine {
h: [
0x22312194fc2bf72c, 0x9f555fa3c84c64c2, 0x2393b86b6f53b151, 0x963877195940eabd,
@ -80,9 +85,9 @@ impl HashEngine {
}
}
/// Constructs a hash engine suitable for use inside the default `sha384::HashEngine`.
/// Constructs a hash engine suitable for constructing `sha384::HashEngine`.
#[rustfmt::skip]
pub(crate) fn sha384() -> Self {
pub(crate) const fn sha384() -> Self {
HashEngine {
h: [
0xcbbb9d5dc1059ed8, 0x629a292a367cd507, 0x9159015a3070dd17, 0x152fecd8f70e5939,

View File

@ -33,11 +33,13 @@ fn from_engine(e: HashEngine) -> Hash {
#[derive(Clone)]
pub struct HashEngine(sha512::HashEngine);
impl HashEngine {
/// Creates a new SHA512/256 hash engine.
pub const fn new() -> Self { Self(sha512::HashEngine::sha512_256()) }
}
impl Default for HashEngine {
#[rustfmt::skip]
fn default() -> Self {
HashEngine(sha512::HashEngine::sha512_256())
}
fn default() -> Self { Self::new() }
}
impl crate::HashEngine for HashEngine {