use crate::pallas_codec::minicbor;
use crate::pallas_crypto::hash::Hash;
use cryptoxide::blake2b::Blake2b;
pub struct Hasher<const BITS: usize>(Blake2b);
impl<const BITS: usize> Hasher<BITS> {
#[inline]
pub fn input(&mut self, bytes: &[u8]) {
use cryptoxide::digest::Digest as _;
self.0.input(bytes);
}
}
macro_rules! common_hasher {
($size:literal) => {
impl Hasher<$size> {
#[inline]
pub fn new() -> Self {
Self(Blake2b::new($size / 8))
}
#[inline]
pub fn hash(bytes: &[u8]) -> Hash<{ $size / 8 }> {
let mut hasher = Self::new();
hasher.input(bytes);
hasher.finalize()
}
#[inline]
pub fn hash_tagged(bytes: &[u8], tag: u8) -> Hash<{ $size / 8 }> {
let mut hasher = Self::new();
hasher.input(&[tag]);
hasher.input(bytes);
hasher.finalize()
}
#[inline]
pub fn hash_cbor(data: &impl minicbor::Encode<()>) -> Hash<{ $size / 8 }> {
let mut hasher = Self::new();
let () = minicbor::encode(data, &mut hasher).expect("Infallible");
hasher.finalize()
}
#[inline]
pub fn hash_tagged_cbor(
data: &impl minicbor::Encode<()>,
tag: u8,
) -> Hash<{ $size / 8 }> {
let mut hasher = Self::new();
hasher.input(&[tag]);
let () = minicbor::encode(data, &mut hasher).expect("Infallible");
hasher.finalize()
}
pub fn finalize(mut self) -> Hash<{ $size / 8 }> {
use cryptoxide::digest::Digest as _;
let mut hash = [0; $size / 8];
self.0.result(&mut hash);
Hash::new(hash)
}
}
impl Default for Hasher<$size> {
fn default() -> Self {
Self::new()
}
}
};
}
common_hasher!(160);
common_hasher!(224);
common_hasher!(256);
impl<'a, const BITS: usize> minicbor::encode::Write for &'a mut Hasher<BITS> {
type Error = core::convert::Infallible;
#[inline]
fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
self.input(buf);
Ok(())
}
}