use super::BooleanHash;
use snarkvm_console_algorithms::{Keccak, Poseidon, BHP};
use snarkvm_console_types::prelude::*;
#[cfg(not(feature = "serial"))]
use rayon::prelude::*;
pub trait PathHash: Clone + Send + Sync {
type Hash: Copy + Clone + Debug + Default + PartialEq + Eq + FromBytes + ToBytes + Send + Sync;
fn hash_children(&self, children: &[Self::Hash]) -> Result<Self::Hash>;
fn hash_empty<const ARITY: u8>(&self) -> Result<Self::Hash> {
let children = vec![Self::Hash::default(); ARITY as usize];
self.hash_children(&children)
}
fn hash_all_children(&self, child_nodes: &[Vec<Self::Hash>]) -> Result<Vec<Self::Hash>> {
match child_nodes.len() {
0 => Ok(vec![]),
1..=100 => child_nodes.iter().map(|children| self.hash_children(children)).collect(),
_ => cfg_iter!(child_nodes).map(|children| self.hash_children(children)).collect(),
}
}
}
impl<E: Environment, const NUM_WINDOWS: u8, const WINDOW_SIZE: u8> PathHash for BHP<E, NUM_WINDOWS, WINDOW_SIZE> {
type Hash = Field<E>;
fn hash_children(&self, children: &[Self::Hash]) -> Result<Self::Hash> {
let mut input = Vec::new();
input.push(true);
for child in children {
child.write_bits_le(&mut input);
}
Hash::hash(self, &input)
}
}
impl<E: Environment, const RATE: usize> PathHash for Poseidon<E, RATE> {
type Hash = Field<E>;
fn hash_children(&self, children: &[Self::Hash]) -> Result<Self::Hash> {
let mut input = Vec::with_capacity(1 + children.len());
input.push(Self::Hash::one());
for child in children {
input.push(*child);
}
Hash::hash(self, &input)
}
}
impl<const TYPE: u8, const VARIANT: usize> PathHash for Keccak<TYPE, VARIANT> {
type Hash = BooleanHash<VARIANT>;
fn hash_children(&self, children: &[Self::Hash]) -> Result<Self::Hash> {
let mut input = Vec::new();
input.push(true);
for child in children {
input.extend_from_slice(child.as_slice());
}
let output = Hash::hash(self, &input)?;
let mut result = BooleanHash::new();
result.0.copy_from_slice(&output[..VARIANT]);
Ok(result)
}
}