diff --git a/src/tree.rs b/src/tree.rs index c44da7c..d2451ea 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -19,7 +19,7 @@ impl From for DBKey { } } -/// Merkle Tree implementation +/// The Merkle Tree structure pub struct MerkleTree where D: Database, @@ -32,6 +32,10 @@ where cache: Vec, } +/// The Merkle proof structure +#[derive(Clone, PartialEq, Eq)] +pub struct MerkleProof(pub Vec<(H::Fr, u8)>); + impl MerkleTree where D: Database, @@ -189,3 +193,44 @@ where self.depth } } + +impl MerkleProof { + /// Computes the Merkle root by iteratively hashing specified Merkle proof with specified leaf + pub fn compute_root_from(&self, leaf: &H::Fr) -> H::Fr { + let mut acc = *leaf; + for w in self.0.iter() { + if w.1 == 0 { + acc = H::hash(&[acc, w.0]); + } else { + acc = H::hash(&[w.0, acc]); + } + } + + acc + } + + /// Computes the leaf index corresponding to a Merkle proof + pub fn leaf_index(&self) -> usize { + let binary_repr = self.get_path_index(); + + binary_repr + .into_iter() + .rev() + .fold(0, |acc, digit| (acc << 1) + usize::from(digit)) + } + + /// Returns the path indexes forming a Merkle Proof + pub fn get_path_index(&self) -> Vec { + self.0.iter().map(|x| x.1).collect() + } + + /// Returns the path elements forming a Merkle proof + pub fn get_path_elements(&self) -> Vec { + self.0.iter().map(|x| x.0).collect() + } + + /// Returns the length of a Merkle proof + pub fn length(&self) -> usize { + self.0.len() + } +}