Add a tagged sha256t hash engine
We would like it if two different pre-tagged engines were considered different types so it is not possible to mix them up. Add a new `sha256t::HashEngine<T>` where `T` is a tag the same as on `sha256t::Hash<T>`.
This commit is contained in:
parent
3e8e2e46bf
commit
6002ccdc56
|
@ -1600,7 +1600,7 @@ mod test {
|
||||||
fn empty_hash(tag_name: &str) -> [u8; 32] {
|
fn empty_hash(tag_name: &str) -> [u8; 32] {
|
||||||
let mut e = tag_engine(tag_name);
|
let mut e = tag_engine(tag_name);
|
||||||
e.input(&[]);
|
e.input(&[]);
|
||||||
Hash::<TapBranchTag>::from_engine(e).to_byte_array()
|
sha256::Hash::from_engine(e).to_byte_array()
|
||||||
}
|
}
|
||||||
assert_eq!(empty_hash("TapLeaf"), Hash::<TapLeafTag>::hash(&[]).to_byte_array());
|
assert_eq!(empty_hash("TapLeaf"), Hash::<TapLeafTag>::hash(&[]).to_byte_array());
|
||||||
assert_eq!(empty_hash("TapBranch"), Hash::<TapBranchTag>::hash(&[]).to_byte_array());
|
assert_eq!(empty_hash("TapBranch"), Hash::<TapBranchTag>::hash(&[]).to_byte_array());
|
||||||
|
|
|
@ -27,7 +27,7 @@ macro_rules! hash_trait_impls {
|
||||||
$crate::impl_debug_only!(Hash, { $bits / 8 }, $reverse $(, $gen: $gent)*);
|
$crate::impl_debug_only!(Hash, { $bits / 8 }, $reverse $(, $gen: $gent)*);
|
||||||
|
|
||||||
impl<$($gen: $gent),*> $crate::GeneralHash for Hash<$($gen),*> {
|
impl<$($gen: $gent),*> $crate::GeneralHash for Hash<$($gen),*> {
|
||||||
type Engine = HashEngine;
|
type Engine = HashEngine<$($gen),*>;
|
||||||
|
|
||||||
fn from_engine(e: Self::Engine) -> Hash<$($gen),*> { Self::from_engine(e) }
|
fn from_engine(e: Self::Engine) -> Hash<$($gen),*> { Self::from_engine(e) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
use core::cmp;
|
use core::cmp;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
|
#[cfg(doc)]
|
||||||
|
use crate::sha256::Midstate;
|
||||||
use crate::{sha256, FromSliceError, HashEngine as _};
|
use crate::{sha256, FromSliceError, HashEngine as _};
|
||||||
|
|
||||||
type HashEngine = sha256::HashEngine;
|
|
||||||
|
|
||||||
/// Trait representing a tag that can be used as a context for SHA256t hashes.
|
/// Trait representing a tag that can be used as a context for SHA256t hashes.
|
||||||
pub trait Tag {
|
pub trait Tag: Clone {
|
||||||
/// The [`Midstate`] after pre-tagging the hash engine.
|
/// The [`Midstate`] after pre-tagging the hash engine.
|
||||||
const MIDSTATE: sha256::Midstate;
|
const MIDSTATE: sha256::Midstate;
|
||||||
}
|
}
|
||||||
|
@ -57,14 +57,12 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Produces a hash from the current state of a given engine.
|
/// Produces a hash from the current state of a given engine.
|
||||||
pub fn from_engine(e: HashEngine) -> Hash<T> {
|
pub fn from_engine(e: HashEngine<T>) -> Hash<T> {
|
||||||
Hash::from_byte_array(sha256::Hash::from_engine(e).to_byte_array())
|
Hash::from_byte_array(sha256::Hash::from_engine(e.0).to_byte_array())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a new engine.
|
/// Constructs a new engine.
|
||||||
pub fn engine() -> HashEngine {
|
pub fn engine() -> HashEngine<T> { HashEngine::default() }
|
||||||
sha256::HashEngine::from_midstate(T::MIDSTATE)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Hashes some bytes.
|
/// Hashes some bytes.
|
||||||
#[allow(clippy::self_named_constructors)] // Hash is a noun and a verb.
|
#[allow(clippy::self_named_constructors)] // Hash is a noun and a verb.
|
||||||
|
@ -137,6 +135,33 @@ impl<T: Tag> core::hash::Hash for Hash<T> {
|
||||||
|
|
||||||
crate::internal_macros::hash_trait_impls!(256, false, T: Tag);
|
crate::internal_macros::hash_trait_impls!(256, false, T: Tag);
|
||||||
|
|
||||||
|
/// Engine to compute SHA256t hash function.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct HashEngine<T>(sha256::HashEngine, PhantomData<T>);
|
||||||
|
|
||||||
|
impl<T: Tag> Default for HashEngine<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
let tagged = sha256::HashEngine::from_midstate(T::MIDSTATE);
|
||||||
|
HashEngine(tagged, PhantomData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Tag> crate::HashEngine for HashEngine<T> {
|
||||||
|
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) -> u64 { self.0.n_bytes_hashed() }
|
||||||
|
}
|
||||||
|
|
||||||
|
crate::internal_macros::impl_io_write!(
|
||||||
|
HashEngine<T>,
|
||||||
|
|us: &mut HashEngine<T>, buf| {
|
||||||
|
us.input(buf);
|
||||||
|
Ok(buf.len())
|
||||||
|
},
|
||||||
|
|_us| { Ok(()) },
|
||||||
|
T: crate::sha256t::Tag
|
||||||
|
);
|
||||||
|
|
||||||
// Workaround macros being unavailable in attributes.
|
// Workaround macros being unavailable in attributes.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
|
Loading…
Reference in New Issue