use std::{
cmp::max,
fmt::Debug,
iter::{once, repeat_n},
str::FromStr,
};
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use super::{
error::{FromConfigError, ZerokitMerkleTreeError},
merkle_tree::{FrOf, Hasher, ZerokitMerkleProof, ZerokitMerkleTree, MIN_PARALLEL_NODES},
override_range_validation::{validate_override_range_inputs, EmptyIndicesPolicy},
};
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct FullMerkleTree<H>
where
H: Hasher,
{
depth: usize,
nodes: Vec<H::Fr>,
cached_leaves_indices: Vec<u8>,
next_index: usize,
metadata: Vec<u8>,
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub(crate) enum FullMerkleBranch<H: Hasher> {
Left(H::Fr),
Right(H::Fr),
}
#[derive(Clone, PartialEq, Eq)]
pub struct FullMerkleProof<H: Hasher>(Vec<FullMerkleBranch<H>>);
#[derive(Default)]
pub struct FullMerkleConfig(());
impl FromStr for FullMerkleConfig {
type Err = FromConfigError;
fn from_str(_s: &str) -> Result<Self, Self::Err> {
Ok(FullMerkleConfig::default())
}
}
impl<H: Hasher> ZerokitMerkleTree for FullMerkleTree<H>
where
H: Hasher,
{
type Proof = FullMerkleProof<H>;
type Hasher = H;
type Config = FullMerkleConfig;
fn default(depth: usize) -> Result<Self, ZerokitMerkleTreeError> {
FullMerkleTree::<H>::new(depth, Self::Hasher::default_leaf(), Self::Config::default())
}
fn new(
depth: usize,
default_leaf: FrOf<Self::Hasher>,
_config: Self::Config,
) -> Result<Self, ZerokitMerkleTreeError> {
if depth >= usize::BITS as usize {
return Err(ZerokitMerkleTreeError::InvalidDepth);
}
let mut cached_nodes: Vec<H::Fr> = Vec::with_capacity(depth + 1);
cached_nodes.push(default_leaf);
for i in 0..depth {
cached_nodes.push(H::hash_pair(cached_nodes[i], cached_nodes[i]));
}
cached_nodes.reverse();
let nodes = cached_nodes
.iter()
.enumerate()
.flat_map(|(levels, hash)| repeat_n(hash, 1 << levels))
.cloned()
.collect::<Vec<_>>();
debug_assert!(nodes.len() == (1 << (depth + 1)) - 1);
Ok(Self {
depth,
nodes,
cached_leaves_indices: vec![0; 1 << depth],
next_index: 0,
metadata: Vec::new(),
})
}
fn close_db_connection(&mut self) -> Result<(), ZerokitMerkleTreeError> {
Ok(())
}
fn depth(&self) -> usize {
self.depth
}
fn capacity(&self) -> usize {
1 << self.depth
}
fn leaves_set(&self) -> usize {
self.next_index
}
fn root(&self) -> FrOf<Self::Hasher> {
self.nodes[0]
}
fn set(&mut self, leaf: usize, hash: FrOf<Self::Hasher>) -> Result<(), ZerokitMerkleTreeError> {
self.set_range(leaf, once(hash))?;
self.next_index = max(self.next_index, leaf + 1);
Ok(())
}
fn get(&self, leaf: usize) -> Result<FrOf<Self::Hasher>, ZerokitMerkleTreeError> {
if leaf >= self.capacity() {
return Err(ZerokitMerkleTreeError::InvalidLeaf);
}
Ok(self.nodes[self.capacity() + leaf - 1])
}
fn get_subtree_root(&self, n: usize, index: usize) -> Result<H::Fr, ZerokitMerkleTreeError> {
if n > self.depth() {
return Err(ZerokitMerkleTreeError::InvalidIndex);
}
if index >= self.capacity() {
return Err(ZerokitMerkleTreeError::InvalidLeaf);
}
if n == 0 {
Ok(self.root())
} else if n == self.depth {
self.get(index)
} else {
let mut idx = self.capacity() + index - 1;
let mut nd = self.depth;
loop {
let parent = self
.parent(idx)
.ok_or(ZerokitMerkleTreeError::InvalidIndex)?;
nd -= 1;
if nd == n {
return Ok(self.nodes[parent]);
} else {
idx = parent;
}
}
}
}
fn get_empty_leaves_indices(&self) -> Vec<usize> {
self.cached_leaves_indices
.iter()
.take(self.next_index)
.enumerate()
.filter(|&(_, &v)| v == 0u8)
.map(|(idx, _)| idx)
.collect()
}
fn set_range<I: ExactSizeIterator<Item = FrOf<Self::Hasher>>>(
&mut self,
start: usize,
leaves: I,
) -> Result<(), ZerokitMerkleTreeError> {
let mut count = 0;
let leaves = leaves.into_iter().collect::<Vec<_>>();
let end = start
.checked_add(leaves.len())
.ok_or(ZerokitMerkleTreeError::TooManySet)?;
if end > self.capacity() {
return Err(ZerokitMerkleTreeError::TooManySet);
}
let index = self.capacity() + start - 1;
leaves.into_iter().for_each(|hash| {
self.nodes[index + count] = hash;
self.cached_leaves_indices[start + count] = 1;
count += 1;
});
if count != 0 {
self.update_hashes(index, index + (count - 1))?;
self.next_index = max(self.next_index, start + count);
}
Ok(())
}
fn override_range<I, J>(
&mut self,
start: usize,
leaves: I,
indices: J,
) -> Result<(), ZerokitMerkleTreeError>
where
I: ExactSizeIterator<Item = FrOf<Self::Hasher>>,
J: ExactSizeIterator<Item = usize>,
{
let leaves_vec = leaves.into_iter().collect::<Vec<_>>();
let validated = validate_override_range_inputs(
start,
leaves_vec.len(),
indices.into_iter().collect::<Vec<_>>(),
self.capacity(),
EmptyIndicesPolicy::Reject,
)?;
let indices = validated.indices;
let min_index = validated
.min_index
.ok_or(ZerokitMerkleTreeError::InvalidIndices)?;
let max_index = validated.max_index.unwrap_or(start);
let mut set_values = vec![Self::Hasher::default_leaf(); max_index - min_index];
for i in min_index..start {
if !indices.contains(&i) {
let value = self.get(i)?;
set_values[i - min_index] = value;
}
}
for i in 0..leaves_vec.len() {
set_values[start - min_index + i] = leaves_vec[i];
}
for i in indices {
self.cached_leaves_indices[i] = 0;
}
self.set_range(start, set_values.into_iter())
}
fn update_next(&mut self, leaf: FrOf<Self::Hasher>) -> Result<(), ZerokitMerkleTreeError> {
self.set(self.next_index, leaf)?;
Ok(())
}
fn delete(&mut self, index: usize) -> Result<(), ZerokitMerkleTreeError> {
if index < self.next_index {
self.set(index, H::default_leaf())?;
self.cached_leaves_indices[index] = 0;
}
Ok(())
}
fn proof(&self, leaf: usize) -> Result<FullMerkleProof<H>, ZerokitMerkleTreeError> {
if leaf >= self.capacity() {
return Err(ZerokitMerkleTreeError::InvalidLeaf);
}
let mut index = self.capacity() + leaf - 1;
let mut path = Vec::with_capacity(self.depth + 1);
while let Some(parent) = self.parent(index) {
path.push(match index & 1 {
1 => FullMerkleBranch::Left(self.nodes[index + 1]),
0 => FullMerkleBranch::Right(self.nodes[index - 1]),
_ => unreachable!(),
});
index = parent;
}
Ok(FullMerkleProof(path))
}
fn verify(
&self,
leaf: &FrOf<Self::Hasher>,
merkle_proof: &FullMerkleProof<H>,
) -> Result<bool, ZerokitMerkleTreeError> {
if merkle_proof.length() != self.depth {
return Err(ZerokitMerkleTreeError::InvalidMerkleProof);
}
let expected_root = merkle_proof.compute_root_from(leaf);
Ok(expected_root.eq(&self.root()))
}
fn set_metadata(&mut self, metadata: &[u8]) -> Result<(), ZerokitMerkleTreeError> {
self.metadata = metadata.to_vec();
Ok(())
}
fn metadata(&self) -> Result<Vec<u8>, ZerokitMerkleTreeError> {
Ok(self.metadata.to_vec())
}
}
impl<H: Hasher> FullMerkleTree<H>
where
H: Hasher,
{
fn parent(&self, index: usize) -> Option<usize> {
if index == 0 {
None
} else {
Some(((index + 1) >> 1) - 1)
}
}
fn first_child(&self, index: usize) -> usize {
(index << 1) + 1
}
fn levels(&self, index: usize) -> usize {
(index + 2).next_power_of_two().trailing_zeros() as usize - 1
}
fn update_hashes(
&mut self,
start_index: usize,
end_index: usize,
) -> Result<(), ZerokitMerkleTreeError> {
if self.levels(start_index) != self.levels(end_index) {
return Err(ZerokitMerkleTreeError::InvalidStartAndEndLevel);
}
if let (Some(start_parent), Some(end_parent)) =
(self.parent(start_index), self.parent(end_index))
{
let hash_parent = |parent: usize| {
let left = self.first_child(parent);
H::hash_pair(self.nodes[left], self.nodes[left + 1])
};
let hashes: Vec<H::Fr> = if end_parent - start_parent + 1 >= MIN_PARALLEL_NODES {
(start_parent..=end_parent)
.into_par_iter()
.map(hash_parent)
.collect()
} else {
(start_parent..=end_parent).map(hash_parent).collect()
};
self.nodes[start_parent..=end_parent].copy_from_slice(&hashes);
self.update_hashes(start_parent, end_parent)?;
}
Ok(())
}
}
impl<H: Hasher> ZerokitMerkleProof for FullMerkleProof<H> {
type Index = u8;
type Hasher = H;
fn length(&self) -> usize {
self.0.len()
}
fn leaf_index(&self) -> usize {
self.0.iter().rev().fold(0, |index, branch| match branch {
FullMerkleBranch::Left(_) => index << 1,
FullMerkleBranch::Right(_) => (index << 1) + 1,
})
}
fn get_path_elements(&self) -> Vec<FrOf<Self::Hasher>> {
self.0
.iter()
.map(|x| match x {
FullMerkleBranch::Left(value) | FullMerkleBranch::Right(value) => *value,
})
.collect()
}
fn get_path_index(&self) -> Vec<Self::Index> {
self.0
.iter()
.map(|branch| match branch {
FullMerkleBranch::Left(_) => 0,
FullMerkleBranch::Right(_) => 1,
})
.collect()
}
fn compute_root_from(&self, hash: &FrOf<Self::Hasher>) -> FrOf<Self::Hasher> {
self.0.iter().fold(*hash, |hash, branch| match branch {
FullMerkleBranch::Left(sibling) => H::hash_pair(hash, *sibling),
FullMerkleBranch::Right(sibling) => H::hash_pair(*sibling, hash),
})
}
}
impl<H> Debug for FullMerkleBranch<H>
where
H: Hasher,
H::Fr: Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Left(arg0) => f.debug_tuple("Left").field(arg0).finish(),
Self::Right(arg0) => f.debug_tuple("Right").field(arg0).finish(),
}
}
}
impl<H> Debug for FullMerkleProof<H>
where
H: Hasher,
H::Fr: Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("Proof").field(&self.0).finish()
}
}