use snarkvm_console_algorithms::{BHP, Poseidon};
use snarkvm_console_types::prelude::*;
#[cfg(not(feature = "serial"))]
use rayon::prelude::*;
pub trait PathHash: Clone + Send + Sync {
type Hash: FieldTrait;
fn hash_empty(&self) -> Result<Self::Hash> {
self.hash_children(&Self::Hash::zero(), &Self::Hash::zero())
}
fn hash_children(&self, left: &Self::Hash, right: &Self::Hash) -> Result<Self::Hash>;
fn hash_all_children(&self, child_nodes: &[(Self::Hash, Self::Hash)]) -> Result<Vec<Self::Hash>> {
match child_nodes.len() {
0 => Ok(vec![]),
1..=100 => child_nodes.iter().map(|(left, right)| self.hash_children(left, right)).collect(),
_ => cfg_iter!(child_nodes).map(|(left, right)| self.hash_children(left, right)).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, left: &Self::Hash, right: &Self::Hash) -> Result<Self::Hash> {
let mut input = Vec::with_capacity(1 + <Self::Hash as SizeInBits>::size_in_bits() * 2);
input.push(true);
left.write_bits_le(&mut input);
right.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, left: &Self::Hash, right: &Self::Hash) -> Result<Self::Hash> {
let input = &[Self::Hash::one(), *left, *right];
Hash::hash(self, input)
}
}