From aef2cd9287b03cfcafee9e8d9ddf8f57b9c1cc3e Mon Sep 17 00:00:00 2001 From: intx4 Date: Mon, 15 Jan 2024 17:13:34 +0100 Subject: [PATCH 01/36] implemented multipath --- src/merkle_tree/mod.rs | 217 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 214 insertions(+), 3 deletions(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index 2b624903..7c30221c 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -7,6 +7,7 @@ use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_std::borrow::Borrow; use ark_std::hash::Hash; use ark_std::vec::Vec; +use std::collections::HashMap; #[cfg(test)] mod tests; @@ -159,8 +160,11 @@ impl Path

{ P::TwoToOneHash::evaluate(&two_to_one_params, left_child, right_child)?; // we will use `index` variable to track the position of path - let mut index = self.leaf_index; - index >>= 1; + //let mut index = self.leaf_index; + //index >>= 1; + let tree_height = self.auth_path.len() + 2; + let mut index = convert_index_to_last_level(index, tree_height); + index = parent(index); // Check levels between leaf level and root for level in (0..self.auth_path.len()).rev() { @@ -169,7 +173,8 @@ impl Path

{ select_left_right_child(index, &curr_path_node, &self.auth_path[level])?; // update curr_path_node curr_path_node = P::TwoToOneHash::compress(&two_to_one_params, &left, &right)?; - index >>= 1; + //index >>= 1; + index = parent(index); } // check if final hash is root @@ -181,6 +186,190 @@ impl Path

{ } } +/// Optimized data structure to store multiple nodes proofs. +/// For example: +/// ```tree_diagram +/// [A] +/// / \ +/// [B] C +/// / \ / \ +/// D [E] F H +/// .. / \ .... +/// [I] J +/// ``` +/// Suppose we want to prove I and J, then: +/// `leaf_indexes` is: [2,3] (indexes in Merkle Tree leaves vector) +/// `leaf_siblings_hashes`: [J,I] +/// `auth_paths_prefix_lenghts`: [0,2] +/// `auth_paths_suffixes`: [ [C,D], []] +/// We can reconstruct the paths incrementally: +/// First, we reconstruct the first path. The prefix length is 0, hence we do not have any prefix encoding. +/// The path is thus [C,D]. +/// Once the first path is verified, we can reconstruct the second path. +/// The prefix length of 2 means that the path prefix will be `previous_path[:2] -> [C,D]`. +/// Since the Merkle Tree branch is the same, the authentication path is the same (which means in this case that there is no suffix). +/// The second path is hence `[C,D] + []` (i.e., plus the empty suffix). We can verify the second path as the first one. + +#[derive(Derivative, CanonicalSerialize, CanonicalDeserialize)] +#[derivative( + Clone(bound = "P: Config"), + Debug(bound = "P: Config"), + Default(bound = "P: Config") +)] +pub struct MultiPath { + /// For node i, stores the hash of node i's sibling + pub leaf_siblings_hashes: Vec, + /// For node i path, stores at index i the prefix length of the path, for Incremental encoding + pub auth_paths_prefix_lenghts: Vec, + /// For node i path, stores at index i the suffix of the path for Incremental Encoding (as vector of symbols to be resolved with self.lut). Order is from higher layer to lower layer (does not include root node). + pub auth_paths_suffixes: Vec>, + /// stores the leaf indexes of the nodes to prove + pub leaf_indexes: Vec, +} + +impl MultiPath

{ + /// Returns a compressed MultiPath containing multiple encoded authentication paths for `indexes` + fn compress(&mut self, indexes: Vec, leaf_sibling_hashes: Vec, auth_paths: Vec>)->Result{ + + // use multipath for more than 1 leaf + assert!(indexes.len() > 1, format!("Expected more than one leaf to verify for MultiPath, got {}", indexes.len())); + + let mut auth_paths_prefix_lenghts = Vec::new(); + let mut auth_paths_suffixes = Vec::new(); + let mut prev_path = Path::default(); + + // Encode paths with Incremental Encoding (Front compression) + for path in auth_paths{ + if prev_path == Path::default(){ + // no previous prefix + auth_paths_prefix_lenghts.append(0); + auth_paths_suffixes.append(path.auth_path); + } else{ + // there is a previous prefix + let mut prefix_len = 0; + while prev_path.auth_path[prefix_len] == path[prefix_len]{ + prefix_len++; + } + auth_paths_prefix_lenghts.append(prefix_len); + auth_paths_suffixes.append({Vec::new()} if prefix_len == prev_path.auth_path.len() else {path[prefix_len..]}) + } + prev_path = path; + } + + // check that the first path is complete + assert_eq!(self.auth_paths_prefix_lenghts[0],0, format!("Expected first prefix length of MultiPath to be 0, got {}",self.auth_paths_prefix_lenghts[0])); + assert_ne!(self.auth_paths_suffixes[0].len(),0, "Expected first suffix length of MultiPath not to be 0"); + + // check consistent lengths + assert_eq!(self.auth_paths_prefix_lenghts.len(), self.auth_paths_suffixes.len(), format!("Vector of prefix lenghts and suffixes of MultiPath do not have equal length: {} and {}", self.auth_paths_prefix_lenghts.len(), self.auth_paths_suffixes.len())); + assert_eq!(self.auth_paths_suffixes.len(), self.indexes.len(), format!("Vector of suffixes and indexes of MultiPath do not have equal length: {} and {}",self.auth_paths_suffixes.len(), self.indexes.len())); + + + Ok( + MultiPath{ + leaf_indexes: indexes, + auth_paths_prefix_lenghts: auth_paths_prefix_lenghts, + auth_paths_suffixes: auth_paths_suffixes, + leaf_siblings_hashes + } + ) + } + + /// Returns the decompressed authentication paths for every leaf index + fn decompress(&'_ self) -> Result>,crate::Error> { + + // check that the first path is complete + assert_eq!(self.auth_paths_prefix_lenghts[0],0, format!("Expected first prefix length of MultiPath to be 0, got {}",self.auth_paths_prefix_lenghts[0])); + assert_ne!(self.auth_paths_suffixes[0].len(),0, "Expected first suffix length of MultiPath not to be 0"); + + // check consistent lengths + assert_eq!(self.auth_paths_prefix_lenghts.len(), self.auth_paths_suffixes.len(), format!("Vector of prefix lenghts and suffixes of MultiPath do not have equal length: {} and {}", self.auth_paths_prefix_lenghts.len(), self.auth_paths_suffixes.len())); + assert_eq!(self.auth_paths_suffixes.len(), self.indexes.len(), format!("Vector of suffixes and indexes of MultiPath do not have equal length: {} and {}",self.auth_paths_suffixes.len(), self.indexes.len())); + + // Incrementally reconstruct all the paths + let mut curr_path = self.auth_paths_suffixes[0]; + let mut auth_paths = (0..self.indexes.len()).map(|_| Vec::new()); + auth_paths[0] = self.auth_paths_suffixes[0]; + for i in (1..auth_paths.len()){ + let path = curr_path[0..self.auth_paths_prefix_lenghts[i]].extend(&self.auth_paths_suffixes[i]); + } + Ok( + auth_paths + ) + } + + /// Verify that leaves are at `self.indexes` of the merkle tree. + /// * `leaf_size`: leaf size in number of bytes + /// + /// `verify` infers the tree height by setting `tree_height = self.auth_paths_suffixes[0].len() + 2` + pub fn verify>( + &self, + leaf_hash_params: &LeafParam

, + two_to_one_params: &TwoToOneParam

, + root_hash: &P::InnerDigest, + leaves: Vec, + ) -> Result { + + let auth_paths = self.decompress()?; + let tree_height = auth_paths[0].len(); + + // LookUp table to speedup computation avoid redundant hash computations + let hash_lut: HashMap<&usize,P::InnerDigest> = HashMap::new(); + + for leaf_index, leaf, leaf_sibling_hash, path in zip(self.indexes, leaves, self.leaf_siblings_hashes, self.auth_paths){ + let claimed_leaf_hash = P::LeafHash::evaluate(&leaf_hash_params, leaf)?; + let (left_child, right_child) = + select_left_right_child(leaf_index, &claimed_leaf_hash, &leaf_sibling_hash)?; + // check hash along the path from bottom to root + + // leaf layer to inner layer conversion + let left_child = P::LeafInnerDigestConverter::convert(left_child)?; + let right_child = P::LeafInnerDigestConverter::convert(right_child)?; + + // we will use `index` variable to track the position of path + let mut index = convert_index_to_last_level(leaf_index, tree_height); + index = parent(index); + + let mut curr_path_node = *hash_lut.entry(index).or_insert( + P::TwoToOneHash::evaluate(&two_to_one_params, left_child, right_child)? + ); + + // Check levels between leaf level and root + for level in (0..self.auth_path.len()).rev() { + // check if path node at this level is left or right + let (left, right) = + select_left_right_child(index, &curr_path_node, &auth_path[level])?; + // update curr_path_node + index = parent(index); + curr_path_node = *hash_lut.entry(index).or_insert( + P::TwoToOneHash::evaluate(&two_to_one_params, left, right)? + ); + } + + // check if final hash is root + if &curr_path_node != root_hash { + return Ok(false); + } + } + Ok(true) + } + + /// The position of on_path node in `leaf_and_sibling_hash` and `non_leaf_and_sibling_hash_path`. + /// `position[i]` is 0 (false) iff `i`th on-path node from top to bottom is on the left. + /// + /// This function simply converts every index in `self.indexes` to boolean array in big endian form. + #[allow(unused)] // this function is actually used when r1cs feature is on + fn position_list(&'_ self) -> impl '_ + Iterator> { + let path_len = self.auth_paths_suffixes[0].len(); + + cfg_into_iter!(self.indexes).map(|i| { + (0..path_len + 1) + .map(move |j| ((i >> j) & 1) != 0) + .rev() + }) + } +} + /// `index` is the first `path.len()` bits of /// the position of tree. /// @@ -400,6 +589,28 @@ impl MerkleTree

{ }) } + /// Returns a MultiPath (multiple authentication paths in compressed form), from every leaf i at `indexes[i]` to root. + /// For compression efficiency, indexes should be sorted, so that leaves with similar paths are close together + + pub fn generate_multi_proof(&self, indexes: Vec) -> Result, crate::Error> { + // gather basic tree information + let tree_height = tree_height(self.leaf_nodes.len()); + + let auth_paths: Vec = cfg_into_iter!(indexes).map(|i| self.generate_proof(i)).collect::,_>>()?; + + let leaf_siblings_hashes = cfg_into_iter!(indexes).map(|i| { + if i & 1 == 0 { + // leaf is left child + self.leaf_nodes[index + 1].clone() + } else { + // leaf is right child + self.leaf_nodes[index - 1].clone() + } + }).collect(); + + MultiPath::compress(indexes, leaf_siblings_hashes, auth_paths) + } + /// Given the index and new leaf, return the hash of leaf and an updated path in order from root to bottom non-leaf level. /// This does not mutate the underlying tree. fn updated_path>( From 9e54b600482c8f1472ac18e1eddca6e8c8e1e688 Mon Sep 17 00:00:00 2001 From: intx4 Date: Mon, 15 Jan 2024 22:33:00 +0100 Subject: [PATCH 02/36] reverted index logic in verify --- src/merkle_tree/mod.rs | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index 7c30221c..0793d0e7 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -7,7 +7,7 @@ use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_std::borrow::Borrow; use ark_std::hash::Hash; use ark_std::vec::Vec; -use std::collections::HashMap; +//use std::collections::HashMap; #[cfg(test)] mod tests; @@ -160,11 +160,8 @@ impl Path

{ P::TwoToOneHash::evaluate(&two_to_one_params, left_child, right_child)?; // we will use `index` variable to track the position of path - //let mut index = self.leaf_index; - //index >>= 1; - let tree_height = self.auth_path.len() + 2; - let mut index = convert_index_to_last_level(index, tree_height); - index = parent(index); + let mut index = self.leaf_index; + index >>= 1; // Check levels between leaf level and root for level in (0..self.auth_path.len()).rev() { @@ -173,8 +170,7 @@ impl Path

{ select_left_right_child(index, &curr_path_node, &self.auth_path[level])?; // update curr_path_node curr_path_node = P::TwoToOneHash::compress(&two_to_one_params, &left, &right)?; - //index >>= 1; - index = parent(index); + index >>= 1; } // check if final hash is root @@ -209,8 +205,7 @@ impl Path

{ /// The prefix length of 2 means that the path prefix will be `previous_path[:2] -> [C,D]`. /// Since the Merkle Tree branch is the same, the authentication path is the same (which means in this case that there is no suffix). /// The second path is hence `[C,D] + []` (i.e., plus the empty suffix). We can verify the second path as the first one. - -#[derive(Derivative, CanonicalSerialize, CanonicalDeserialize)] +//#[derive(Derivative, CanonicalSerialize, CanonicalDeserialize)] #[derivative( Clone(bound = "P: Config"), Debug(bound = "P: Config"), @@ -229,7 +224,7 @@ pub struct MultiPath { impl MultiPath

{ /// Returns a compressed MultiPath containing multiple encoded authentication paths for `indexes` - fn compress(&mut self, indexes: Vec, leaf_sibling_hashes: Vec, auth_paths: Vec>)->Result{ + fn compress(&mut self, indexes: Vec, leaf_sibling_hashes: Vec, auth_paths: &mut Vec>)->Result{ // use multipath for more than 1 leaf assert!(indexes.len() > 1, format!("Expected more than one leaf to verify for MultiPath, got {}", indexes.len())); @@ -248,10 +243,14 @@ impl MultiPath

{ // there is a previous prefix let mut prefix_len = 0; while prev_path.auth_path[prefix_len] == path[prefix_len]{ - prefix_len++; + prefix_len += 1; } auth_paths_prefix_lenghts.append(prefix_len); - auth_paths_suffixes.append({Vec::new()} if prefix_len == prev_path.auth_path.len() else {path[prefix_len..]}) + if prefix_len == prev_path.auth_path.len() { + auth_paths_suffixes.append(Vec::new()); + } else { + auth_paths_suffixes.append(path[prefix_len..]); + } } prev_path = path; } @@ -316,7 +315,7 @@ impl MultiPath

{ // LookUp table to speedup computation avoid redundant hash computations let hash_lut: HashMap<&usize,P::InnerDigest> = HashMap::new(); - for leaf_index, leaf, leaf_sibling_hash, path in zip(self.indexes, leaves, self.leaf_siblings_hashes, self.auth_paths){ + for (leaf_index, leaf, leaf_sibling_hash, path) in zip(self.indexes, leaves, self.leaf_siblings_hashes, self.auth_paths){ let claimed_leaf_hash = P::LeafHash::evaluate(&leaf_hash_params, leaf)?; let (left_child, right_child) = select_left_right_child(leaf_index, &claimed_leaf_hash, &leaf_sibling_hash)?; @@ -327,10 +326,12 @@ impl MultiPath

{ let right_child = P::LeafInnerDigestConverter::convert(right_child)?; // we will use `index` variable to track the position of path - let mut index = convert_index_to_last_level(leaf_index, tree_height); - index = parent(index); + let mut index = leaf_index; + let mut index_in_tree = convert_index_to_last_level(leaf_index, tree_height); + index >>= 1; + index_in_tree = parent(index_in_tree).unwrap(); - let mut curr_path_node = *hash_lut.entry(index).or_insert( + let mut curr_path_node = *hash_lut.entry(index_in_tree).or_insert( P::TwoToOneHash::evaluate(&two_to_one_params, left_child, right_child)? ); @@ -340,8 +341,9 @@ impl MultiPath

{ let (left, right) = select_left_right_child(index, &curr_path_node, &auth_path[level])?; // update curr_path_node - index = parent(index); - curr_path_node = *hash_lut.entry(index).or_insert( + index >>= 1; + index_in_tree = parent(index).unwrap(); + curr_path_node = *hash_lut.entry(index_in_tree).or_insert( P::TwoToOneHash::evaluate(&two_to_one_params, left, right)? ); } @@ -591,7 +593,6 @@ impl MerkleTree

{ /// Returns a MultiPath (multiple authentication paths in compressed form), from every leaf i at `indexes[i]` to root. /// For compression efficiency, indexes should be sorted, so that leaves with similar paths are close together - pub fn generate_multi_proof(&self, indexes: Vec) -> Result, crate::Error> { // gather basic tree information let tree_height = tree_height(self.leaf_nodes.len()); From bd8a30dd7bbfff2ec0905a3a0eb17659336343ff Mon Sep 17 00:00:00 2001 From: intx4 Date: Wed, 17 Jan 2024 11:40:47 +0100 Subject: [PATCH 03/36] fixed compile errors --- src/merkle_tree/mod.rs | 113 +++++++++++++++++++++++------------------ 1 file changed, 63 insertions(+), 50 deletions(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index 0793d0e7..7296edad 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -7,7 +7,7 @@ use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_std::borrow::Borrow; use ark_std::hash::Hash; use ark_std::vec::Vec; -//use std::collections::HashMap; +use std::collections::HashMap; #[cfg(test)] mod tests; @@ -107,7 +107,7 @@ pub type LeafParam

= <

::LeafHash as CRHScheme>::Parameters; /// [I] J /// ``` /// Suppose we want to prove I, then `leaf_sibling_hash` is J, `auth_path` is `[C,D]` -#[derive(Derivative, CanonicalSerialize, CanonicalDeserialize)] +#[derive(PartialEq, Derivative, CanonicalSerialize, CanonicalDeserialize)] #[derivative( Clone(bound = "P: Config"), Debug(bound = "P: Config"), @@ -205,7 +205,8 @@ impl Path

{ /// The prefix length of 2 means that the path prefix will be `previous_path[:2] -> [C,D]`. /// Since the Merkle Tree branch is the same, the authentication path is the same (which means in this case that there is no suffix). /// The second path is hence `[C,D] + []` (i.e., plus the empty suffix). We can verify the second path as the first one. -//#[derive(Derivative, CanonicalSerialize, CanonicalDeserialize)] + +#[derive(Derivative, CanonicalSerialize, CanonicalDeserialize)] #[derivative( Clone(bound = "P: Config"), Debug(bound = "P: Config"), @@ -224,44 +225,46 @@ pub struct MultiPath { impl MultiPath

{ /// Returns a compressed MultiPath containing multiple encoded authentication paths for `indexes` - fn compress(&mut self, indexes: Vec, leaf_sibling_hashes: Vec, auth_paths: &mut Vec>)->Result{ + fn compress(indexes: Vec, leaf_siblings_hashes: Vec, auth_paths: Vec>)->Result{ // use multipath for more than 1 leaf - assert!(indexes.len() > 1, format!("Expected more than one leaf to verify for MultiPath, got {}", indexes.len())); + assert!(indexes.len() > 1, "Expected more than one leaf to verify for MultiPath, got {}", indexes.len()); - let mut auth_paths_prefix_lenghts = Vec::new(); - let mut auth_paths_suffixes = Vec::new(); + let mut auth_paths_prefix_lenghts:Vec = Vec::with_capacity(indexes.len()); + let mut auth_paths_suffixes:Vec> = Vec::with_capacity(indexes.len()); + // init to empty path let mut prev_path = Path::default(); + prev_path.auth_path = Vec::new(); // Encode paths with Incremental Encoding (Front compression) for path in auth_paths{ - if prev_path == Path::default(){ + if prev_path.auth_path.len() == 0{ // no previous prefix - auth_paths_prefix_lenghts.append(0); - auth_paths_suffixes.append(path.auth_path); + auth_paths_prefix_lenghts.push(0); + auth_paths_suffixes.push(path.auth_path.clone()); } else{ // there is a previous prefix let mut prefix_len = 0; - while prev_path.auth_path[prefix_len] == path[prefix_len]{ + while prev_path.auth_path[prefix_len] == path.auth_path[prefix_len]{ prefix_len += 1; } - auth_paths_prefix_lenghts.append(prefix_len); + auth_paths_prefix_lenghts.push(prefix_len); if prefix_len == prev_path.auth_path.len() { - auth_paths_suffixes.append(Vec::new()); + auth_paths_suffixes.push(Vec::new()); } else { - auth_paths_suffixes.append(path[prefix_len..]); + auth_paths_suffixes.push(path.auth_path[prefix_len..].to_vec().clone()); } } prev_path = path; } // check that the first path is complete - assert_eq!(self.auth_paths_prefix_lenghts[0],0, format!("Expected first prefix length of MultiPath to be 0, got {}",self.auth_paths_prefix_lenghts[0])); - assert_ne!(self.auth_paths_suffixes[0].len(),0, "Expected first suffix length of MultiPath not to be 0"); + assert_eq!(auth_paths_prefix_lenghts[0], 0, "Expected first prefix length of MultiPath to be 0, got {}",auth_paths_prefix_lenghts[0]); + assert_ne!(auth_paths_suffixes[0].len(), 0, "Expected first suffix length of MultiPath not to be 0"); // check consistent lengths - assert_eq!(self.auth_paths_prefix_lenghts.len(), self.auth_paths_suffixes.len(), format!("Vector of prefix lenghts and suffixes of MultiPath do not have equal length: {} and {}", self.auth_paths_prefix_lenghts.len(), self.auth_paths_suffixes.len())); - assert_eq!(self.auth_paths_suffixes.len(), self.indexes.len(), format!("Vector of suffixes and indexes of MultiPath do not have equal length: {} and {}",self.auth_paths_suffixes.len(), self.indexes.len())); + assert_eq!(auth_paths_prefix_lenghts.len(), auth_paths_suffixes.len(), "Vector of prefix lenghts and suffixes of MultiPath do not have equal length: {} and {}", auth_paths_prefix_lenghts.len(), auth_paths_suffixes.len()); + assert_eq!(auth_paths_suffixes.len(), indexes.len(), "Vector of suffixes and indexes of MultiPath do not have equal length: {} and {}", auth_paths_suffixes.len(), indexes.len()); Ok( @@ -269,7 +272,7 @@ impl MultiPath

{ leaf_indexes: indexes, auth_paths_prefix_lenghts: auth_paths_prefix_lenghts, auth_paths_suffixes: auth_paths_suffixes, - leaf_siblings_hashes + leaf_siblings_hashes: leaf_siblings_hashes } ) } @@ -278,30 +281,33 @@ impl MultiPath

{ fn decompress(&'_ self) -> Result>,crate::Error> { // check that the first path is complete - assert_eq!(self.auth_paths_prefix_lenghts[0],0, format!("Expected first prefix length of MultiPath to be 0, got {}",self.auth_paths_prefix_lenghts[0])); - assert_ne!(self.auth_paths_suffixes[0].len(),0, "Expected first suffix length of MultiPath not to be 0"); + assert_eq!(self.auth_paths_prefix_lenghts[0], 0, "Expected first prefix length of MultiPath to be 0, got {}",self.auth_paths_prefix_lenghts[0]); + assert_ne!(self.auth_paths_suffixes[0].len(), 0, "Expected first suffix length of MultiPath not to be 0"); // check consistent lengths - assert_eq!(self.auth_paths_prefix_lenghts.len(), self.auth_paths_suffixes.len(), format!("Vector of prefix lenghts and suffixes of MultiPath do not have equal length: {} and {}", self.auth_paths_prefix_lenghts.len(), self.auth_paths_suffixes.len())); - assert_eq!(self.auth_paths_suffixes.len(), self.indexes.len(), format!("Vector of suffixes and indexes of MultiPath do not have equal length: {} and {}",self.auth_paths_suffixes.len(), self.indexes.len())); + assert_eq!(self.auth_paths_prefix_lenghts.len(), self.auth_paths_suffixes.len(), "Vector of prefix lenghts and suffixes of MultiPath do not have equal length: {} and {}", self.auth_paths_prefix_lenghts.len(), self.auth_paths_suffixes.len()); + assert_eq!(self.auth_paths_suffixes.len(), self.leaf_indexes.len(), "Vector of suffixes and indexes of MultiPath do not have equal length: {} and {}",self.auth_paths_suffixes.len(), self.leaf_indexes.len()); // Incrementally reconstruct all the paths - let mut curr_path = self.auth_paths_suffixes[0]; - let mut auth_paths = (0..self.indexes.len()).map(|_| Vec::new()); - auth_paths[0] = self.auth_paths_suffixes[0]; - for i in (1..auth_paths.len()){ - let path = curr_path[0..self.auth_paths_prefix_lenghts[i]].extend(&self.auth_paths_suffixes[i]); + let mut curr_path = self.auth_paths_suffixes[0].clone(); + let mut auth_paths = (0..self.leaf_indexes.len()).map(|_| Vec::new()).collect::>>(); + auth_paths[0] = self.auth_paths_suffixes[0].clone(); + + for i in 1..auth_paths.len(){ + auth_paths[i].extend_from_slice(&curr_path[0..self.auth_paths_prefix_lenghts[i]]); + auth_paths[i].extend(self.auth_paths_suffixes[i].clone()); + curr_path = auth_paths[i].clone(); } Ok( - auth_paths + auth_paths.into_iter() ) } - /// Verify that leaves are at `self.indexes` of the merkle tree. + /// Verify that leaves are at `self.leaf_indexes` of the merkle tree. /// * `leaf_size`: leaf size in number of bytes /// /// `verify` infers the tree height by setting `tree_height = self.auth_paths_suffixes[0].len() + 2` - pub fn verify>( + pub fn verify + Clone>( &self, leaf_hash_params: &LeafParam

, two_to_one_params: &TwoToOneParam

, @@ -309,14 +315,20 @@ impl MultiPath

{ leaves: Vec, ) -> Result { - let auth_paths = self.decompress()?; + // array of auth paths as arrays of InnerDigests + let auth_paths:Vec> = self.decompress()?.collect(); let tree_height = auth_paths[0].len(); // LookUp table to speedup computation avoid redundant hash computations - let hash_lut: HashMap<&usize,P::InnerDigest> = HashMap::new(); + let mut hash_lut: HashMap = HashMap::new(); - for (leaf_index, leaf, leaf_sibling_hash, path) in zip(self.indexes, leaves, self.leaf_siblings_hashes, self.auth_paths){ - let claimed_leaf_hash = P::LeafHash::evaluate(&leaf_hash_params, leaf)?; + for i in 0..self.leaf_indexes.len(){ + let leaf_index = self.leaf_indexes[i]; + let leaf = &leaves[i]; + let leaf_sibling_hash = &self.leaf_siblings_hashes[i]; + let auth_path = &auth_paths[i]; + + let claimed_leaf_hash = P::LeafHash::evaluate(&leaf_hash_params, leaf.clone())?; let (left_child, right_child) = select_left_right_child(leaf_index, &claimed_leaf_hash, &leaf_sibling_hash)?; // check hash along the path from bottom to root @@ -331,25 +343,25 @@ impl MultiPath

{ index >>= 1; index_in_tree = parent(index_in_tree).unwrap(); - let mut curr_path_node = *hash_lut.entry(index_in_tree).or_insert( + let mut curr_path_node = hash_lut.entry(index_in_tree).or_insert( P::TwoToOneHash::evaluate(&two_to_one_params, left_child, right_child)? ); // Check levels between leaf level and root - for level in (0..self.auth_path.len()).rev() { + for level in (0..auth_path.len()).rev() { // check if path node at this level is left or right let (left, right) = - select_left_right_child(index, &curr_path_node, &auth_path[level])?; + select_left_right_child(index, curr_path_node, &auth_path[level])?; // update curr_path_node index >>= 1; index_in_tree = parent(index).unwrap(); - curr_path_node = *hash_lut.entry(index_in_tree).or_insert( - P::TwoToOneHash::evaluate(&two_to_one_params, left, right)? + curr_path_node = hash_lut.entry(index_in_tree).or_insert( + P::TwoToOneHash::compress(&two_to_one_params, left, right)? ); } // check if final hash is root - if &curr_path_node != root_hash { + if curr_path_node != root_hash { return Ok(false); } } @@ -359,15 +371,16 @@ impl MultiPath

{ /// The position of on_path node in `leaf_and_sibling_hash` and `non_leaf_and_sibling_hash_path`. /// `position[i]` is 0 (false) iff `i`th on-path node from top to bottom is on the left. /// - /// This function simply converts every index in `self.indexes` to boolean array in big endian form. + /// This function simply converts every index in `self.leaf_indexes` to boolean array in big endian form. #[allow(unused)] // this function is actually used when r1cs feature is on fn position_list(&'_ self) -> impl '_ + Iterator> { let path_len = self.auth_paths_suffixes[0].len(); - cfg_into_iter!(self.indexes).map(|i| { + cfg_into_iter!(self.leaf_indexes.clone()).map(move |i| { (0..path_len + 1) .map(move |j| ((i >> j) & 1) != 0) .rev() + .collect() }) } } @@ -594,18 +607,18 @@ impl MerkleTree

{ /// Returns a MultiPath (multiple authentication paths in compressed form), from every leaf i at `indexes[i]` to root. /// For compression efficiency, indexes should be sorted, so that leaves with similar paths are close together pub fn generate_multi_proof(&self, indexes: Vec) -> Result, crate::Error> { - // gather basic tree information - let tree_height = tree_height(self.leaf_nodes.len()); - - let auth_paths: Vec = cfg_into_iter!(indexes).map(|i| self.generate_proof(i)).collect::,_>>()?; + + let auth_paths: Vec> = cfg_into_iter!(indexes.clone()) + .map(|i| self.generate_proof(i)) + .collect::>,crate::Error>>()?; - let leaf_siblings_hashes = cfg_into_iter!(indexes).map(|i| { + let leaf_siblings_hashes = cfg_into_iter!(indexes.clone()).map(|i| { if i & 1 == 0 { // leaf is left child - self.leaf_nodes[index + 1].clone() + self.leaf_nodes[i + 1].clone() } else { // leaf is right child - self.leaf_nodes[index - 1].clone() + self.leaf_nodes[i - 1].clone() } }).collect(); From 97deaf8e3badae08fa6aeef971ee76023af72bb9 Mon Sep 17 00:00:00 2001 From: intx4 Date: Wed, 17 Jan 2024 15:37:22 +0100 Subject: [PATCH 04/36] unittests passing --- src/merkle_tree/mod.rs | 71 +++++++++++++++++++----------------- src/merkle_tree/tests/mod.rs | 38 ++++++++++++++++++- 2 files changed, 74 insertions(+), 35 deletions(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index 7296edad..1b6bf15a 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -232,39 +232,40 @@ impl MultiPath

{ let mut auth_paths_prefix_lenghts:Vec = Vec::with_capacity(indexes.len()); let mut auth_paths_suffixes:Vec> = Vec::with_capacity(indexes.len()); - // init to empty path - let mut prev_path = Path::default(); - prev_path.auth_path = Vec::new(); + + + auth_paths_prefix_lenghts.push(0); + auth_paths_suffixes.push(auth_paths[0].auth_path.clone()); + + let mut prev_path = auth_paths[0].clone(); // Encode paths with Incremental Encoding (Front compression) - for path in auth_paths{ - if prev_path.auth_path.len() == 0{ - // no previous prefix - auth_paths_prefix_lenghts.push(0); - auth_paths_suffixes.push(path.auth_path.clone()); - } else{ - // there is a previous prefix - let mut prefix_len = 0; + for path in auth_paths[1..].to_vec(){ + let mut prefix_len = 0; + if prev_path.auth_path.len() != 0 && path.auth_path.len() != 0{ while prev_path.auth_path[prefix_len] == path.auth_path[prefix_len]{ prefix_len += 1; + if prefix_len == prev_path.auth_path.len() || prefix_len == path.auth_path.len(){ + break; + } } - auth_paths_prefix_lenghts.push(prefix_len); - if prefix_len == prev_path.auth_path.len() { - auth_paths_suffixes.push(Vec::new()); - } else { - auth_paths_suffixes.push(path.auth_path[prefix_len..].to_vec().clone()); - } + } + auth_paths_prefix_lenghts.push(prefix_len); + if prefix_len == prev_path.auth_path.len() { + auth_paths_suffixes.push(vec![]); + } else { + auth_paths_suffixes.push(path.auth_path[prefix_len..].to_vec().clone()); } prev_path = path; } // check that the first path is complete - assert_eq!(auth_paths_prefix_lenghts[0], 0, "Expected first prefix length of MultiPath to be 0, got {}",auth_paths_prefix_lenghts[0]); - assert_ne!(auth_paths_suffixes[0].len(), 0, "Expected first suffix length of MultiPath not to be 0"); - - // check consistent lengths - assert_eq!(auth_paths_prefix_lenghts.len(), auth_paths_suffixes.len(), "Vector of prefix lenghts and suffixes of MultiPath do not have equal length: {} and {}", auth_paths_prefix_lenghts.len(), auth_paths_suffixes.len()); - assert_eq!(auth_paths_suffixes.len(), indexes.len(), "Vector of suffixes and indexes of MultiPath do not have equal length: {} and {}", auth_paths_suffixes.len(), indexes.len()); + //assert_eq!(auth_paths_prefix_lenghts[0], 0, "Expected first prefix length of MultiPath to be 0, got {}",auth_paths_prefix_lenghts[0]); + //assert_ne!(auth_paths_suffixes[0].len(), 0, "Expected first suffix length of MultiPath not to be 0"); + // + //// check consistent lengths + //assert_eq!(auth_paths_prefix_lenghts.len(), auth_paths_suffixes.len(), "Vector of prefix lenghts and suffixes of MultiPath do not have equal length: {} and {}", auth_paths_prefix_lenghts.len(), auth_paths_suffixes.len()); + //assert_eq!(auth_paths_suffixes.len(), indexes.len(), "Vector of suffixes and indexes of MultiPath do not have equal length: {} and {}", auth_paths_suffixes.len(), indexes.len()); Ok( @@ -280,13 +281,13 @@ impl MultiPath

{ /// Returns the decompressed authentication paths for every leaf index fn decompress(&'_ self) -> Result>,crate::Error> { - // check that the first path is complete - assert_eq!(self.auth_paths_prefix_lenghts[0], 0, "Expected first prefix length of MultiPath to be 0, got {}",self.auth_paths_prefix_lenghts[0]); - assert_ne!(self.auth_paths_suffixes[0].len(), 0, "Expected first suffix length of MultiPath not to be 0"); - - // check consistent lengths - assert_eq!(self.auth_paths_prefix_lenghts.len(), self.auth_paths_suffixes.len(), "Vector of prefix lenghts and suffixes of MultiPath do not have equal length: {} and {}", self.auth_paths_prefix_lenghts.len(), self.auth_paths_suffixes.len()); - assert_eq!(self.auth_paths_suffixes.len(), self.leaf_indexes.len(), "Vector of suffixes and indexes of MultiPath do not have equal length: {} and {}",self.auth_paths_suffixes.len(), self.leaf_indexes.len()); + //// check that the first path is complete + //assert_eq!(self.auth_paths_prefix_lenghts[0], 0, "Expected first prefix length of MultiPath to be 0, got {}",self.auth_paths_prefix_lenghts[0]); + //assert_ne!(self.auth_paths_suffixes[0].len(), 0, "Expected first suffix length of MultiPath not to be 0"); + // + //// check consistent lengths + //assert_eq!(self.auth_paths_prefix_lenghts.len(), self.auth_paths_suffixes.len(), "Vector of prefix lenghts and suffixes of MultiPath do not have equal length: {} and {}", self.auth_paths_prefix_lenghts.len(), self.auth_paths_suffixes.len()); + //assert_eq!(self.auth_paths_suffixes.len(), self.leaf_indexes.len(), "Vector of suffixes and indexes of MultiPath do not have equal length: {} and {}",self.auth_paths_suffixes.len(), self.leaf_indexes.len()); // Incrementally reconstruct all the paths let mut curr_path = self.auth_paths_suffixes[0].clone(); @@ -312,12 +313,13 @@ impl MultiPath

{ leaf_hash_params: &LeafParam

, two_to_one_params: &TwoToOneParam

, root_hash: &P::InnerDigest, - leaves: Vec, + leaves: &Vec, ) -> Result { // array of auth paths as arrays of InnerDigests - let auth_paths:Vec> = self.decompress()?.collect(); - let tree_height = auth_paths[0].len(); + let auth_paths:Vec> = self.decompress()?.collect(); + + let tree_height = auth_paths[0].len() + 2; // LookUp table to speedup computation avoid redundant hash computations let mut hash_lut: HashMap = HashMap::new(); @@ -354,7 +356,7 @@ impl MultiPath

{ select_left_right_child(index, curr_path_node, &auth_path[level])?; // update curr_path_node index >>= 1; - index_in_tree = parent(index).unwrap(); + index_in_tree = parent(index_in_tree).unwrap(); curr_path_node = hash_lut.entry(index_in_tree).or_insert( P::TwoToOneHash::compress(&two_to_one_params, left, right)? ); @@ -608,6 +610,7 @@ impl MerkleTree

{ /// For compression efficiency, indexes should be sorted, so that leaves with similar paths are close together pub fn generate_multi_proof(&self, indexes: Vec) -> Result, crate::Error> { + let auth_paths: Vec> = cfg_into_iter!(indexes.clone()) .map(|i| self.generate_proof(i)) .collect::>,crate::Error>>()?; diff --git a/src/merkle_tree/tests/mod.rs b/src/merkle_tree/tests/mod.rs index a4968917..8ceb8f9c 100644 --- a/src/merkle_tree/tests/mod.rs +++ b/src/merkle_tree/tests/mod.rs @@ -55,11 +55,20 @@ mod bytes_mt_tests { // test merkle tree functionality without update for (i, leaf) in leaves.iter().enumerate() { let proof = tree.generate_proof(i).unwrap(); + println!("{}", proof.auth_path.len()); assert!(proof .verify(&leaf_crh_params, &two_to_one_params, &root, leaf.as_slice()) .unwrap()); } + // test the merkle tree multi-proof functionality + let mut multi_proof = tree.generate_multi_proof((0..leaves.len()).collect()).unwrap(); + + assert!(multi_proof + .verify(&leaf_crh_params, &two_to_one_params, &root, &leaves) + .unwrap()); + + // test merkle tree update functionality for (i, v) in update_query { let v = crate::to_uncompressed_bytes!(v).unwrap(); @@ -75,6 +84,13 @@ mod bytes_mt_tests { .verify(&leaf_crh_params, &two_to_one_params, &root, leaf.as_slice()) .unwrap()); } + + // test the merkle tree multi-proof functionality again + multi_proof = tree.generate_multi_proof((0..leaves.len()).collect()).unwrap(); + + assert!(multi_proof + .verify(&leaf_crh_params, &two_to_one_params, &root, &leaves) + .unwrap()); } #[test] @@ -155,6 +171,13 @@ mod field_mt_tests { .unwrap()); } + // test the merkle tree multi-proof functionality + let mut multi_proof = tree.generate_multi_proof((0..leaves.len()).collect()).unwrap(); + + assert!(multi_proof + .verify(&leaf_crh_params, &two_to_one_params, &root, &leaves) + .unwrap()); + { // wrong root should lead to error but do not panic let wrong_root = root + F::one(); @@ -166,7 +189,14 @@ mod field_mt_tests { &wrong_root, leaves[0].as_slice() ) - .unwrap()) + .unwrap()); + + // test the merkle tree multi-proof functionality + let multi_proof = tree.generate_multi_proof((0..leaves.len()).collect()).unwrap(); + + assert!(!multi_proof + .verify(&leaf_crh_params, &two_to_one_params, &wrong_root, &leaves) + .unwrap()); } // test merkle tree update functionality @@ -185,6 +215,12 @@ mod field_mt_tests { .verify(&leaf_crh_params, &two_to_one_params, &root, leaf.as_slice()) .unwrap()); } + + multi_proof = tree.generate_multi_proof((0..leaves.len()).collect()).unwrap(); + + assert!(multi_proof + .verify(&leaf_crh_params, &two_to_one_params, &root, &leaves) + .unwrap()); } #[test] From 156d43c508f7cab54a561bc769899d8a028fd4ca Mon Sep 17 00:00:00 2001 From: intx4 Date: Wed, 17 Jan 2024 15:55:28 +0100 Subject: [PATCH 05/36] changed signature of generate_multi_proof to sort indexes --- src/merkle_tree/mod.rs | 16 ++++++++-------- src/merkle_tree/tests/mod.rs | 10 +++++----- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index 1b6bf15a..f8c6b8a2 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -225,7 +225,7 @@ pub struct MultiPath { impl MultiPath

{ /// Returns a compressed MultiPath containing multiple encoded authentication paths for `indexes` - fn compress(indexes: Vec, leaf_siblings_hashes: Vec, auth_paths: Vec>)->Result{ + fn compress(indexes: &mut Vec, leaf_siblings_hashes: Vec, auth_paths: Vec>)->Result{ // use multipath for more than 1 leaf assert!(indexes.len() > 1, "Expected more than one leaf to verify for MultiPath, got {}", indexes.len()); @@ -270,7 +270,7 @@ impl MultiPath

{ Ok( MultiPath{ - leaf_indexes: indexes, + leaf_indexes: indexes.clone(), auth_paths_prefix_lenghts: auth_paths_prefix_lenghts, auth_paths_suffixes: auth_paths_suffixes, leaf_siblings_hashes: leaf_siblings_hashes @@ -383,7 +383,7 @@ impl MultiPath

{ .map(move |j| ((i >> j) & 1) != 0) .rev() .collect() - }) + }).collect::>().into_iter() } } @@ -607,12 +607,12 @@ impl MerkleTree

{ } /// Returns a MultiPath (multiple authentication paths in compressed form), from every leaf i at `indexes[i]` to root. - /// For compression efficiency, indexes should be sorted, so that leaves with similar paths are close together - pub fn generate_multi_proof(&self, indexes: Vec) -> Result, crate::Error> { + pub fn generate_multi_proof(&self, indexes: &mut Vec) -> Result, crate::Error> { - - let auth_paths: Vec> = cfg_into_iter!(indexes.clone()) - .map(|i| self.generate_proof(i)) + // sort for encoding efficiency + indexes.sort(); + let auth_paths: Vec> = cfg_into_iter!(indexes) + .map(|i| self.generate_proof(*i)) .collect::>,crate::Error>>()?; let leaf_siblings_hashes = cfg_into_iter!(indexes.clone()).map(|i| { diff --git a/src/merkle_tree/tests/mod.rs b/src/merkle_tree/tests/mod.rs index 8ceb8f9c..9e7f84ad 100644 --- a/src/merkle_tree/tests/mod.rs +++ b/src/merkle_tree/tests/mod.rs @@ -62,7 +62,7 @@ mod bytes_mt_tests { } // test the merkle tree multi-proof functionality - let mut multi_proof = tree.generate_multi_proof((0..leaves.len()).collect()).unwrap(); + let mut multi_proof = tree.generate_multi_proof(&mut (0..leaves.len()).collect()).unwrap(); assert!(multi_proof .verify(&leaf_crh_params, &two_to_one_params, &root, &leaves) @@ -86,7 +86,7 @@ mod bytes_mt_tests { } // test the merkle tree multi-proof functionality again - multi_proof = tree.generate_multi_proof((0..leaves.len()).collect()).unwrap(); + multi_proof = tree.generate_multi_proof(&mut (0..leaves.len()).collect()).unwrap(); assert!(multi_proof .verify(&leaf_crh_params, &two_to_one_params, &root, &leaves) @@ -172,7 +172,7 @@ mod field_mt_tests { } // test the merkle tree multi-proof functionality - let mut multi_proof = tree.generate_multi_proof((0..leaves.len()).collect()).unwrap(); + let mut multi_proof = tree.generate_multi_proof(&mut (0..leaves.len()).collect()).unwrap(); assert!(multi_proof .verify(&leaf_crh_params, &two_to_one_params, &root, &leaves) @@ -192,7 +192,7 @@ mod field_mt_tests { .unwrap()); // test the merkle tree multi-proof functionality - let multi_proof = tree.generate_multi_proof((0..leaves.len()).collect()).unwrap(); + let multi_proof = tree.generate_multi_proof(&mut (0..leaves.len()).collect()).unwrap(); assert!(!multi_proof .verify(&leaf_crh_params, &two_to_one_params, &wrong_root, &leaves) @@ -216,7 +216,7 @@ mod field_mt_tests { .unwrap()); } - multi_proof = tree.generate_multi_proof((0..leaves.len()).collect()).unwrap(); + multi_proof = tree.generate_multi_proof(&mut (0..leaves.len()).collect()).unwrap(); assert!(multi_proof .verify(&leaf_crh_params, &two_to_one_params, &root, &leaves) From 43809076cb97986b3d385321915853081d4273c4 Mon Sep 17 00:00:00 2001 From: intx4 Date: Wed, 17 Jan 2024 16:04:02 +0100 Subject: [PATCH 06/36] cargo fmt --- src/merkle_tree/mod.rs | 2 +- src/merkle_tree/tests/mod.rs | 30 +++++++++++++++++++----------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index f8c6b8a2..ea927645 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -8,6 +8,7 @@ use ark_std::borrow::Borrow; use ark_std::hash::Hash; use ark_std::vec::Vec; use std::collections::HashMap; +use std::iter::zip; #[cfg(test)] mod tests; @@ -267,7 +268,6 @@ impl MultiPath

{ //assert_eq!(auth_paths_prefix_lenghts.len(), auth_paths_suffixes.len(), "Vector of prefix lenghts and suffixes of MultiPath do not have equal length: {} and {}", auth_paths_prefix_lenghts.len(), auth_paths_suffixes.len()); //assert_eq!(auth_paths_suffixes.len(), indexes.len(), "Vector of suffixes and indexes of MultiPath do not have equal length: {} and {}", auth_paths_suffixes.len(), indexes.len()); - Ok( MultiPath{ leaf_indexes: indexes.clone(), diff --git a/src/merkle_tree/tests/mod.rs b/src/merkle_tree/tests/mod.rs index 9e7f84ad..cbcc7758 100644 --- a/src/merkle_tree/tests/mod.rs +++ b/src/merkle_tree/tests/mod.rs @@ -55,20 +55,20 @@ mod bytes_mt_tests { // test merkle tree functionality without update for (i, leaf) in leaves.iter().enumerate() { let proof = tree.generate_proof(i).unwrap(); - println!("{}", proof.auth_path.len()); assert!(proof .verify(&leaf_crh_params, &two_to_one_params, &root, leaf.as_slice()) .unwrap()); } // test the merkle tree multi-proof functionality - let mut multi_proof = tree.generate_multi_proof(&mut (0..leaves.len()).collect()).unwrap(); - + let mut multi_proof = tree + .generate_multi_proof(&mut (0..leaves.len()).collect()) + .unwrap(); + assert!(multi_proof .verify(&leaf_crh_params, &two_to_one_params, &root, &leaves) .unwrap()); - // test merkle tree update functionality for (i, v) in update_query { let v = crate::to_uncompressed_bytes!(v).unwrap(); @@ -86,7 +86,9 @@ mod bytes_mt_tests { } // test the merkle tree multi-proof functionality again - multi_proof = tree.generate_multi_proof(&mut (0..leaves.len()).collect()).unwrap(); + multi_proof = tree + .generate_multi_proof(&mut (0..leaves.len()).collect()) + .unwrap(); assert!(multi_proof .verify(&leaf_crh_params, &two_to_one_params, &root, &leaves) @@ -172,8 +174,10 @@ mod field_mt_tests { } // test the merkle tree multi-proof functionality - let mut multi_proof = tree.generate_multi_proof(&mut (0..leaves.len()).collect()).unwrap(); - + let mut multi_proof = tree + .generate_multi_proof(&mut (0..leaves.len()).collect()) + .unwrap(); + assert!(multi_proof .verify(&leaf_crh_params, &two_to_one_params, &root, &leaves) .unwrap()); @@ -192,8 +196,10 @@ mod field_mt_tests { .unwrap()); // test the merkle tree multi-proof functionality - let multi_proof = tree.generate_multi_proof(&mut (0..leaves.len()).collect()).unwrap(); - + let multi_proof = tree + .generate_multi_proof(&mut (0..leaves.len()).collect()) + .unwrap(); + assert!(!multi_proof .verify(&leaf_crh_params, &two_to_one_params, &wrong_root, &leaves) .unwrap()); @@ -216,8 +222,10 @@ mod field_mt_tests { .unwrap()); } - multi_proof = tree.generate_multi_proof(&mut (0..leaves.len()).collect()).unwrap(); - + multi_proof = tree + .generate_multi_proof(&mut (0..leaves.len()).collect()) + .unwrap(); + assert!(multi_proof .verify(&leaf_crh_params, &two_to_one_params, &root, &leaves) .unwrap()); From 1bfb0253e6d20687a2954c963e8f99d9c73b39b8 Mon Sep 17 00:00:00 2001 From: intx4 Date: Wed, 17 Jan 2024 16:51:31 +0100 Subject: [PATCH 07/36] implemented unit test for multi_proof internals --- src/merkle_tree/mod.rs | 26 ++++------------- src/merkle_tree/tests/mod.rs | 54 ++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 20 deletions(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index ea927645..ffd4ee0e 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -260,14 +260,7 @@ impl MultiPath

{ prev_path = path; } - // check that the first path is complete - //assert_eq!(auth_paths_prefix_lenghts[0], 0, "Expected first prefix length of MultiPath to be 0, got {}",auth_paths_prefix_lenghts[0]); - //assert_ne!(auth_paths_suffixes[0].len(), 0, "Expected first suffix length of MultiPath not to be 0"); - // - //// check consistent lengths - //assert_eq!(auth_paths_prefix_lenghts.len(), auth_paths_suffixes.len(), "Vector of prefix lenghts and suffixes of MultiPath do not have equal length: {} and {}", auth_paths_prefix_lenghts.len(), auth_paths_suffixes.len()); - //assert_eq!(auth_paths_suffixes.len(), indexes.len(), "Vector of suffixes and indexes of MultiPath do not have equal length: {} and {}", auth_paths_suffixes.len(), indexes.len()); - + Ok( MultiPath{ leaf_indexes: indexes.clone(), @@ -281,14 +274,7 @@ impl MultiPath

{ /// Returns the decompressed authentication paths for every leaf index fn decompress(&'_ self) -> Result>,crate::Error> { - //// check that the first path is complete - //assert_eq!(self.auth_paths_prefix_lenghts[0], 0, "Expected first prefix length of MultiPath to be 0, got {}",self.auth_paths_prefix_lenghts[0]); - //assert_ne!(self.auth_paths_suffixes[0].len(), 0, "Expected first suffix length of MultiPath not to be 0"); - // - //// check consistent lengths - //assert_eq!(self.auth_paths_prefix_lenghts.len(), self.auth_paths_suffixes.len(), "Vector of prefix lenghts and suffixes of MultiPath do not have equal length: {} and {}", self.auth_paths_prefix_lenghts.len(), self.auth_paths_suffixes.len()); - //assert_eq!(self.auth_paths_suffixes.len(), self.leaf_indexes.len(), "Vector of suffixes and indexes of MultiPath do not have equal length: {} and {}",self.auth_paths_suffixes.len(), self.leaf_indexes.len()); - + // Incrementally reconstruct all the paths let mut curr_path = self.auth_paths_suffixes[0].clone(); let mut auth_paths = (0..self.leaf_indexes.len()).map(|_| Vec::new()).collect::>>(); @@ -499,8 +485,8 @@ impl MerkleTree

{ // leaf in the whole tree (represented as a list in level order). We need to shift it // by `-upper_bound` to get the index in `leaf_nodes` list. - //similarly, we need to rescale i by start_index - //to get the index outside the slice and in the level-ordered list of nodes + // similarly, we need to rescale i by start_index + // to get the index outside the slice and in the level-ordered list of nodes let current_index = i + start_index; let left_leaf_index = left_child(current_index) - upper_bound; @@ -535,8 +521,8 @@ impl MerkleTree

{ // leaf in the whole tree (represented as a list in level order). We need to shift it // by `-upper_bound` to get the index in `leaf_nodes` list. - //similarly, we need to rescale i by start_index - //to get the index outside the slice and in the level-ordered list of nodes + // similarly, we need to rescale i by start_index + // to get the index outside the slice and in the level-ordered list of nodes let current_index = i + start_index; let left_leaf_index = left_child(current_index) - upper_bound; let right_leaf_index = right_child(current_index) - upper_bound; diff --git a/src/merkle_tree/tests/mod.rs b/src/merkle_tree/tests/mod.rs index cbcc7758..6895759a 100644 --- a/src/merkle_tree/tests/mod.rs +++ b/src/merkle_tree/tests/mod.rs @@ -132,6 +132,60 @@ mod bytes_mt_tests { ], ); } + + #[test] + fn multi_proof_test(){ + let mut rng = test_rng(); + + let mut leaves = Vec::new(); + for _ in 0..8u8 { + leaves.push(BigInteger256::rand(&mut rng)); + } + assert_eq!(leaves.len(),8); + + let serialized_leaves: Vec<_> = leaves + .iter() + .map(|leaf| crate::to_uncompressed_bytes!(leaf).unwrap()) + .collect(); + + let leaf_crh_params = ::setup(&mut rng).unwrap(); + let two_to_one_params = ::setup(&mut rng).unwrap(); + + let tree = + JubJubMerkleTree::new(&leaf_crh_params, &two_to_one_params, &serialized_leaves).unwrap(); + + let mut proofs=Vec::with_capacity(leaves.len()); + + for (i, _) in leaves.iter().enumerate() { + proofs.push(tree.generate_proof(i).unwrap()); + } + + let multi_proof = tree + .generate_multi_proof(&mut (0..leaves.len()).collect()) + .unwrap(); + + // test compression theretical lengths for size 8 Tree + let theoretical_prefix_lengths = vec![0, 2, 1, 2, 0, 2, 1, 2]; + + for (comp_len, exp_len) in zip(&multi_proof.auth_paths_prefix_lenghts, &theoretical_prefix_lengths){ + assert_eq!(comp_len, exp_len); + } + + // test that the compressed paths can expand to expected len + for (prefix_len, suffix) in zip(&multi_proof.auth_paths_prefix_lenghts, &multi_proof.auth_paths_suffixes){ + assert_eq!(prefix_len + suffix.len(), proofs[0].auth_path.len()); + } + + let comp_proofs:Vec<_> = multi_proof.decompress().unwrap().collect(); + + // test decompressed paths are as expected + for (comp_path, exp_path) in zip(&comp_proofs, &proofs){ + for (comp_hash, exp_hash) in zip(comp_path, &exp_path.auth_path){ + assert_eq!(*comp_hash, *exp_hash); + } + } + + } } mod field_mt_tests { From 561228a6a3dccf0621ad3c39c5fbe847d01759e1 Mon Sep 17 00:00:00 2001 From: intx4 Date: Wed, 17 Jan 2024 16:52:02 +0100 Subject: [PATCH 08/36] renamed multi_proof specific test --- src/merkle_tree/tests/mod.rs | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/merkle_tree/tests/mod.rs b/src/merkle_tree/tests/mod.rs index 6895759a..b9d039b6 100644 --- a/src/merkle_tree/tests/mod.rs +++ b/src/merkle_tree/tests/mod.rs @@ -134,14 +134,14 @@ mod bytes_mt_tests { } #[test] - fn multi_proof_test(){ + fn multi_proof_dissection_test() { let mut rng = test_rng(); let mut leaves = Vec::new(); for _ in 0..8u8 { leaves.push(BigInteger256::rand(&mut rng)); } - assert_eq!(leaves.len(),8); + assert_eq!(leaves.len(), 8); let serialized_leaves: Vec<_> = leaves .iter() @@ -151,10 +151,10 @@ mod bytes_mt_tests { let leaf_crh_params = ::setup(&mut rng).unwrap(); let two_to_one_params = ::setup(&mut rng).unwrap(); - let tree = - JubJubMerkleTree::new(&leaf_crh_params, &two_to_one_params, &serialized_leaves).unwrap(); + let tree = JubJubMerkleTree::new(&leaf_crh_params, &two_to_one_params, &serialized_leaves) + .unwrap(); - let mut proofs=Vec::with_capacity(leaves.len()); + let mut proofs = Vec::with_capacity(leaves.len()); for (i, _) in leaves.iter().enumerate() { proofs.push(tree.generate_proof(i).unwrap()); @@ -167,24 +167,29 @@ mod bytes_mt_tests { // test compression theretical lengths for size 8 Tree let theoretical_prefix_lengths = vec![0, 2, 1, 2, 0, 2, 1, 2]; - for (comp_len, exp_len) in zip(&multi_proof.auth_paths_prefix_lenghts, &theoretical_prefix_lengths){ + for (comp_len, exp_len) in zip( + &multi_proof.auth_paths_prefix_lenghts, + &theoretical_prefix_lengths, + ) { assert_eq!(comp_len, exp_len); } // test that the compressed paths can expand to expected len - for (prefix_len, suffix) in zip(&multi_proof.auth_paths_prefix_lenghts, &multi_proof.auth_paths_suffixes){ + for (prefix_len, suffix) in zip( + &multi_proof.auth_paths_prefix_lenghts, + &multi_proof.auth_paths_suffixes, + ) { assert_eq!(prefix_len + suffix.len(), proofs[0].auth_path.len()); } - let comp_proofs:Vec<_> = multi_proof.decompress().unwrap().collect(); - + let comp_proofs: Vec<_> = multi_proof.decompress().unwrap().collect(); + // test decompressed paths are as expected - for (comp_path, exp_path) in zip(&comp_proofs, &proofs){ - for (comp_hash, exp_hash) in zip(comp_path, &exp_path.auth_path){ + for (comp_path, exp_path) in zip(&comp_proofs, &proofs) { + for (comp_hash, exp_hash) in zip(comp_path, &exp_path.auth_path) { assert_eq!(*comp_hash, *exp_hash); } } - } } From 6a247692f76649d0c5d35bdd44aa5bfca934753a Mon Sep 17 00:00:00 2001 From: intx4 Date: Wed, 17 Jan 2024 16:52:12 +0100 Subject: [PATCH 09/36] cargo fmt --- src/merkle_tree/mod.rs | 149 +++++++++++++++++++++++------------------ 1 file changed, 82 insertions(+), 67 deletions(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index ffd4ee0e..3cbaa7ed 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -194,7 +194,7 @@ impl Path

{ /// .. / \ .... /// [I] J /// ``` -/// Suppose we want to prove I and J, then: +/// Suppose we want to prove I and J, then: /// `leaf_indexes` is: [2,3] (indexes in Merkle Tree leaves vector) /// `leaf_siblings_hashes`: [J,I] /// `auth_paths_prefix_lenghts`: [0,2] @@ -202,7 +202,7 @@ impl Path

{ /// We can reconstruct the paths incrementally: /// First, we reconstruct the first path. The prefix length is 0, hence we do not have any prefix encoding. /// The path is thus [C,D]. -/// Once the first path is verified, we can reconstruct the second path. +/// Once the first path is verified, we can reconstruct the second path. /// The prefix length of 2 means that the path prefix will be `previous_path[:2] -> [C,D]`. /// Since the Merkle Tree branch is the same, the authentication path is the same (which means in this case that there is no suffix). /// The second path is hence `[C,D] + []` (i.e., plus the empty suffix). We can verify the second path as the first one. @@ -226,27 +226,34 @@ pub struct MultiPath { impl MultiPath

{ /// Returns a compressed MultiPath containing multiple encoded authentication paths for `indexes` - fn compress(indexes: &mut Vec, leaf_siblings_hashes: Vec, auth_paths: Vec>)->Result{ - + fn compress( + indexes: &mut Vec, + leaf_siblings_hashes: Vec, + auth_paths: Vec>, + ) -> Result { // use multipath for more than 1 leaf - assert!(indexes.len() > 1, "Expected more than one leaf to verify for MultiPath, got {}", indexes.len()); + assert!( + indexes.len() > 1, + "Expected more than one leaf to verify for MultiPath, got {}", + indexes.len() + ); - let mut auth_paths_prefix_lenghts:Vec = Vec::with_capacity(indexes.len()); - let mut auth_paths_suffixes:Vec> = Vec::with_capacity(indexes.len()); - + let mut auth_paths_prefix_lenghts: Vec = Vec::with_capacity(indexes.len()); + let mut auth_paths_suffixes: Vec> = Vec::with_capacity(indexes.len()); auth_paths_prefix_lenghts.push(0); auth_paths_suffixes.push(auth_paths[0].auth_path.clone()); - + let mut prev_path = auth_paths[0].clone(); // Encode paths with Incremental Encoding (Front compression) - for path in auth_paths[1..].to_vec(){ + for path in auth_paths[1..].to_vec() { let mut prefix_len = 0; - if prev_path.auth_path.len() != 0 && path.auth_path.len() != 0{ - while prev_path.auth_path[prefix_len] == path.auth_path[prefix_len]{ + if prev_path.auth_path.len() != 0 && path.auth_path.len() != 0 { + while prev_path.auth_path[prefix_len] == path.auth_path[prefix_len] { prefix_len += 1; - if prefix_len == prev_path.auth_path.len() || prefix_len == path.auth_path.len(){ + if prefix_len == prev_path.auth_path.len() || prefix_len == path.auth_path.len() + { break; } } @@ -260,34 +267,31 @@ impl MultiPath

{ prev_path = path; } - - Ok( - MultiPath{ - leaf_indexes: indexes.clone(), - auth_paths_prefix_lenghts: auth_paths_prefix_lenghts, - auth_paths_suffixes: auth_paths_suffixes, - leaf_siblings_hashes: leaf_siblings_hashes - } - ) + Ok(MultiPath { + leaf_indexes: indexes.clone(), + auth_paths_prefix_lenghts: auth_paths_prefix_lenghts, + auth_paths_suffixes: auth_paths_suffixes, + leaf_siblings_hashes: leaf_siblings_hashes, + }) } /// Returns the decompressed authentication paths for every leaf index - fn decompress(&'_ self) -> Result>,crate::Error> { - - + fn decompress( + &'_ self, + ) -> Result>, crate::Error> { // Incrementally reconstruct all the paths let mut curr_path = self.auth_paths_suffixes[0].clone(); - let mut auth_paths = (0..self.leaf_indexes.len()).map(|_| Vec::new()).collect::>>(); + let mut auth_paths = (0..self.leaf_indexes.len()) + .map(|_| Vec::new()) + .collect::>>(); auth_paths[0] = self.auth_paths_suffixes[0].clone(); - - for i in 1..auth_paths.len(){ + + for i in 1..auth_paths.len() { auth_paths[i].extend_from_slice(&curr_path[0..self.auth_paths_prefix_lenghts[i]]); auth_paths[i].extend(self.auth_paths_suffixes[i].clone()); curr_path = auth_paths[i].clone(); } - Ok( - auth_paths.into_iter() - ) + Ok(auth_paths.into_iter()) } /// Verify that leaves are at `self.leaf_indexes` of the merkle tree. @@ -301,16 +305,15 @@ impl MultiPath

{ root_hash: &P::InnerDigest, leaves: &Vec, ) -> Result { - // array of auth paths as arrays of InnerDigests - let auth_paths:Vec> = self.decompress()?.collect(); - + let auth_paths: Vec> = self.decompress()?.collect(); + let tree_height = auth_paths[0].len() + 2; // LookUp table to speedup computation avoid redundant hash computations - let mut hash_lut: HashMap = HashMap::new(); - - for i in 0..self.leaf_indexes.len(){ + let mut hash_lut: HashMap = HashMap::new(); + + for i in 0..self.leaf_indexes.len() { let leaf_index = self.leaf_indexes[i]; let leaf = &leaves[i]; let leaf_sibling_hash = &self.leaf_siblings_hashes[i]; @@ -324,17 +327,22 @@ impl MultiPath

{ // leaf layer to inner layer conversion let left_child = P::LeafInnerDigestConverter::convert(left_child)?; let right_child = P::LeafInnerDigestConverter::convert(right_child)?; - + // we will use `index` variable to track the position of path let mut index = leaf_index; let mut index_in_tree = convert_index_to_last_level(leaf_index, tree_height); index >>= 1; index_in_tree = parent(index_in_tree).unwrap(); - - let mut curr_path_node = hash_lut.entry(index_in_tree).or_insert( - P::TwoToOneHash::evaluate(&two_to_one_params, left_child, right_child)? - ); - + + let mut curr_path_node = + hash_lut + .entry(index_in_tree) + .or_insert(P::TwoToOneHash::evaluate( + &two_to_one_params, + left_child, + right_child, + )?); + // Check levels between leaf level and root for level in (0..auth_path.len()).rev() { // check if path node at this level is left or right @@ -343,11 +351,11 @@ impl MultiPath

{ // update curr_path_node index >>= 1; index_in_tree = parent(index_in_tree).unwrap(); - curr_path_node = hash_lut.entry(index_in_tree).or_insert( - P::TwoToOneHash::compress(&two_to_one_params, left, right)? - ); + curr_path_node = hash_lut + .entry(index_in_tree) + .or_insert(P::TwoToOneHash::compress(&two_to_one_params, left, right)?); } - + // check if final hash is root if curr_path_node != root_hash { return Ok(false); @@ -363,13 +371,16 @@ impl MultiPath

{ #[allow(unused)] // this function is actually used when r1cs feature is on fn position_list(&'_ self) -> impl '_ + Iterator> { let path_len = self.auth_paths_suffixes[0].len(); - - cfg_into_iter!(self.leaf_indexes.clone()).map(move |i| { - (0..path_len + 1) - .map(move |j| ((i >> j) & 1) != 0) - .rev() - .collect() - }).collect::>().into_iter() + + cfg_into_iter!(self.leaf_indexes.clone()) + .map(move |i| { + (0..path_len + 1) + .map(move |j| ((i >> j) & 1) != 0) + .rev() + .collect() + }) + .collect::>() + .into_iter() } } @@ -593,23 +604,27 @@ impl MerkleTree

{ } /// Returns a MultiPath (multiple authentication paths in compressed form), from every leaf i at `indexes[i]` to root. - pub fn generate_multi_proof(&self, indexes: &mut Vec) -> Result, crate::Error> { - + pub fn generate_multi_proof( + &self, + indexes: &mut Vec, + ) -> Result, crate::Error> { // sort for encoding efficiency indexes.sort(); let auth_paths: Vec> = cfg_into_iter!(indexes) .map(|i| self.generate_proof(*i)) - .collect::>,crate::Error>>()?; - - let leaf_siblings_hashes = cfg_into_iter!(indexes.clone()).map(|i| { - if i & 1 == 0 { - // leaf is left child - self.leaf_nodes[i + 1].clone() - } else { - // leaf is right child - self.leaf_nodes[i - 1].clone() - } - }).collect(); + .collect::>, crate::Error>>()?; + + let leaf_siblings_hashes = cfg_into_iter!(indexes.clone()) + .map(|i| { + if i & 1 == 0 { + // leaf is left child + self.leaf_nodes[i + 1].clone() + } else { + // leaf is right child + self.leaf_nodes[i - 1].clone() + } + }) + .collect(); MultiPath::compress(indexes, leaf_siblings_hashes, auth_paths) } From 804aa033b0f131e3feda1d18b50987c391d9b41d Mon Sep 17 00:00:00 2001 From: intx4 Date: Wed, 17 Jan 2024 16:54:37 +0100 Subject: [PATCH 10/36] commnts in unittest --- src/merkle_tree/tests/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/merkle_tree/tests/mod.rs b/src/merkle_tree/tests/mod.rs index b9d039b6..e234e15f 100644 --- a/src/merkle_tree/tests/mod.rs +++ b/src/merkle_tree/tests/mod.rs @@ -164,7 +164,8 @@ mod bytes_mt_tests { .generate_multi_proof(&mut (0..leaves.len()).collect()) .unwrap(); - // test compression theretical lengths for size 8 Tree + // test compression theretical prefix lengths for size 8 Tree: + // we should send 6 hashes instead of 2*8 = 16 let theoretical_prefix_lengths = vec![0, 2, 1, 2, 0, 2, 1, 2]; for (comp_len, exp_len) in zip( From 376644097c9a161a51b01066c72ae13a775fdd72 Mon Sep 17 00:00:00 2001 From: intx4 Date: Wed, 17 Jan 2024 18:20:04 +0100 Subject: [PATCH 11/36] changed function signatures --- src/merkle_tree/mod.rs | 36 +++++++++++++++++++++++------------- src/merkle_tree/tests/mod.rs | 23 ++++++++++++----------- 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index 3cbaa7ed..dc5f8977 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -7,8 +7,7 @@ use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_std::borrow::Borrow; use ark_std::hash::Hash; use ark_std::vec::Vec; -use std::collections::HashMap; -use std::iter::zip; +use std::collections::{HashMap, BTreeSet}; #[cfg(test)] mod tests; @@ -191,8 +190,8 @@ impl Path

{ /// [B] C /// / \ / \ /// D [E] F H -/// .. / \ .... -/// [I] J +/// / \ / \ .... +/// [I]J L M /// ``` /// Suppose we want to prove I and J, then: /// `leaf_indexes` is: [2,3] (indexes in Merkle Tree leaves vector) @@ -227,10 +226,12 @@ pub struct MultiPath { impl MultiPath

{ /// Returns a compressed MultiPath containing multiple encoded authentication paths for `indexes` fn compress( - indexes: &mut Vec, + indexes: impl IntoIterator, leaf_siblings_hashes: Vec, auth_paths: Vec>, ) -> Result { + + let indexes = Vec::from_iter(indexes); // use multipath for more than 1 leaf assert!( indexes.len() > 1, @@ -268,7 +269,7 @@ impl MultiPath

{ } Ok(MultiPath { - leaf_indexes: indexes.clone(), + leaf_indexes: indexes, auth_paths_prefix_lenghts: auth_paths_prefix_lenghts, auth_paths_suffixes: auth_paths_suffixes, leaf_siblings_hashes: leaf_siblings_hashes, @@ -295,6 +296,7 @@ impl MultiPath

{ } /// Verify that leaves are at `self.leaf_indexes` of the merkle tree. + /// Note that the order of the leaves hashes should match the leaves respective indexes /// * `leaf_size`: leaf size in number of bytes /// /// `verify` infers the tree height by setting `tree_height = self.auth_paths_suffixes[0].len() + 2` @@ -303,9 +305,12 @@ impl MultiPath

{ leaf_hash_params: &LeafParam

, two_to_one_params: &TwoToOneParam

, root_hash: &P::InnerDigest, - leaves: &Vec, + leaves: impl IntoIterator, ) -> Result { // array of auth paths as arrays of InnerDigests + + let leaves: Vec = leaves.into_iter().collect(); + let auth_paths: Vec> = self.decompress()?.collect(); let tree_height = auth_paths[0].len() + 2; @@ -603,15 +608,20 @@ impl MerkleTree

{ }) } - /// Returns a MultiPath (multiple authentication paths in compressed form), from every leaf i at `indexes[i]` to root. + /// Returns a MultiPath (multiple authentication paths in compressed form, with Front Incremental Encoding), + /// from every leaf to root. + /// Note that for compression efficiency, the indexes are internally sorted. + /// When verifying the proof, leaves hashes should be supplied in order, that is: + /// let ordered_leaves: Vec<_> = self.leaf_indexes.into_iter().map(|i| leaves[i]).collect(); pub fn generate_multi_proof( &self, - indexes: &mut Vec, + indexes: impl IntoIterator, ) -> Result, crate::Error> { - // sort for encoding efficiency - indexes.sort(); - let auth_paths: Vec> = cfg_into_iter!(indexes) - .map(|i| self.generate_proof(*i)) + // pruned and sorted for encoding efficiency + let indexes: BTreeSet = indexes.into_iter().collect(); + + let auth_paths: Vec> = cfg_into_iter!(indexes.clone()) + .map(|i| self.generate_proof(i)) .collect::>, crate::Error>>()?; let leaf_siblings_hashes = cfg_into_iter!(indexes.clone()) diff --git a/src/merkle_tree/tests/mod.rs b/src/merkle_tree/tests/mod.rs index e234e15f..bfa29b08 100644 --- a/src/merkle_tree/tests/mod.rs +++ b/src/merkle_tree/tests/mod.rs @@ -11,6 +11,7 @@ mod bytes_mt_tests { use ark_ed_on_bls12_381::EdwardsProjective as JubJub; use ark_ff::BigInteger256; use ark_std::{test_rng, UniformRand}; + use std::iter::zip; #[derive(Clone)] pub(super) struct Window4x256; @@ -62,11 +63,11 @@ mod bytes_mt_tests { // test the merkle tree multi-proof functionality let mut multi_proof = tree - .generate_multi_proof(&mut (0..leaves.len()).collect()) + .generate_multi_proof((0..leaves.len()).collect::>()) .unwrap(); assert!(multi_proof - .verify(&leaf_crh_params, &two_to_one_params, &root, &leaves) + .verify(&leaf_crh_params, &two_to_one_params, &root, leaves.clone()) .unwrap()); // test merkle tree update functionality @@ -87,11 +88,11 @@ mod bytes_mt_tests { // test the merkle tree multi-proof functionality again multi_proof = tree - .generate_multi_proof(&mut (0..leaves.len()).collect()) + .generate_multi_proof((0..leaves.len()).collect::>()) .unwrap(); assert!(multi_proof - .verify(&leaf_crh_params, &two_to_one_params, &root, &leaves) + .verify(&leaf_crh_params, &two_to_one_params, &root, leaves.clone()) .unwrap()); } @@ -161,7 +162,7 @@ mod bytes_mt_tests { } let multi_proof = tree - .generate_multi_proof(&mut (0..leaves.len()).collect()) + .generate_multi_proof((0..leaves.len()).collect::>()) .unwrap(); // test compression theretical prefix lengths for size 8 Tree: @@ -235,11 +236,11 @@ mod field_mt_tests { // test the merkle tree multi-proof functionality let mut multi_proof = tree - .generate_multi_proof(&mut (0..leaves.len()).collect()) + .generate_multi_proof((0..leaves.len()).collect::>()) .unwrap(); assert!(multi_proof - .verify(&leaf_crh_params, &two_to_one_params, &root, &leaves) + .verify(&leaf_crh_params, &two_to_one_params, &root, leaves.clone()) .unwrap()); { @@ -257,11 +258,11 @@ mod field_mt_tests { // test the merkle tree multi-proof functionality let multi_proof = tree - .generate_multi_proof(&mut (0..leaves.len()).collect()) + .generate_multi_proof((0..leaves.len()).collect::>()) .unwrap(); assert!(!multi_proof - .verify(&leaf_crh_params, &two_to_one_params, &wrong_root, &leaves) + .verify(&leaf_crh_params, &two_to_one_params, &wrong_root, leaves.clone()) .unwrap()); } @@ -283,11 +284,11 @@ mod field_mt_tests { } multi_proof = tree - .generate_multi_proof(&mut (0..leaves.len()).collect()) + .generate_multi_proof((0..leaves.len()).collect::>()) .unwrap(); assert!(multi_proof - .verify(&leaf_crh_params, &two_to_one_params, &root, &leaves) + .verify(&leaf_crh_params, &two_to_one_params, &root, leaves.clone()) .unwrap()); } From ff2de465f63fe7b7dfa793124e2c4c530c153227 Mon Sep 17 00:00:00 2001 From: intx4 Date: Wed, 17 Jan 2024 19:09:29 +0100 Subject: [PATCH 12/36] cargo fmt --- src/merkle_tree/mod.rs | 5 ++--- src/merkle_tree/tests/mod.rs | 7 ++++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index dc5f8977..b2bf7122 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -7,7 +7,7 @@ use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_std::borrow::Borrow; use ark_std::hash::Hash; use ark_std::vec::Vec; -use std::collections::{HashMap, BTreeSet}; +use std::collections::{BTreeSet, HashMap}; #[cfg(test)] mod tests; @@ -226,11 +226,10 @@ pub struct MultiPath { impl MultiPath

{ /// Returns a compressed MultiPath containing multiple encoded authentication paths for `indexes` fn compress( - indexes: impl IntoIterator, + indexes: impl IntoIterator, leaf_siblings_hashes: Vec, auth_paths: Vec>, ) -> Result { - let indexes = Vec::from_iter(indexes); // use multipath for more than 1 leaf assert!( diff --git a/src/merkle_tree/tests/mod.rs b/src/merkle_tree/tests/mod.rs index bfa29b08..aae0dcff 100644 --- a/src/merkle_tree/tests/mod.rs +++ b/src/merkle_tree/tests/mod.rs @@ -262,7 +262,12 @@ mod field_mt_tests { .unwrap(); assert!(!multi_proof - .verify(&leaf_crh_params, &two_to_one_params, &wrong_root, leaves.clone()) + .verify( + &leaf_crh_params, + &two_to_one_params, + &wrong_root, + leaves.clone() + ) .unwrap()); } From 5548bd70483aaab5906b8c7ca81d1c02752760d7 Mon Sep 17 00:00:00 2001 From: intx4 <65897068+intx4@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:40:59 +0100 Subject: [PATCH 13/36] modified use of BtreeSet and HashMap from ark_std crate Co-authored-by: Pratyush Mishra --- src/merkle_tree/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index b2bf7122..4272e9ba 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -7,7 +7,7 @@ use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_std::borrow::Borrow; use ark_std::hash::Hash; use ark_std::vec::Vec; -use std::collections::{BTreeSet, HashMap}; +use ark_std::collections::{BTreeSet, HashMap}; #[cfg(test)] mod tests; From d849e80d6c7e1a2e80ffb371f782a4f2604bf8a8 Mon Sep 17 00:00:00 2001 From: intx4 <65897068+intx4@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:41:57 +0100 Subject: [PATCH 14/36] modified multipath to derivative(PartialEq...) Co-authored-by: Pratyush Mishra --- src/merkle_tree/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index 4272e9ba..8916fa0f 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -107,8 +107,9 @@ pub type LeafParam

= <

::LeafHash as CRHScheme>::Parameters; /// [I] J /// ``` /// Suppose we want to prove I, then `leaf_sibling_hash` is J, `auth_path` is `[C,D]` -#[derive(PartialEq, Derivative, CanonicalSerialize, CanonicalDeserialize)] +#[derive(Derivative, CanonicalSerialize, CanonicalDeserialize)] #[derivative( + PartialEq(bound = "P: Config"), Clone(bound = "P: Config"), Debug(bound = "P: Config"), Default(bound = "P: Config") From 42a2f45e2a5831a1eca05fd70aa4eb097d522be6 Mon Sep 17 00:00:00 2001 From: intx4 <65897068+intx4@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:42:44 +0100 Subject: [PATCH 15/36] keep leaves as iterator in multipath verify Co-authored-by: Marcin --- src/merkle_tree/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index 8916fa0f..f88b4c0a 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -309,7 +309,7 @@ impl MultiPath

{ ) -> Result { // array of auth paths as arrays of InnerDigests - let leaves: Vec = leaves.into_iter().collect(); + let mut leaves = leaves.into_iter(); let auth_paths: Vec> = self.decompress()?.collect(); From 46a537763e58446591995dfccc478f32d675a867 Mon Sep 17 00:00:00 2001 From: intx4 <65897068+intx4@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:43:08 +0100 Subject: [PATCH 16/36] auth_paths to peekable in multipath.verify Co-authored-by: Marcin --- src/merkle_tree/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index f88b4c0a..04a717cd 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -311,7 +311,7 @@ impl MultiPath

{ let mut leaves = leaves.into_iter(); - let auth_paths: Vec> = self.decompress()?.collect(); + let mut auth_paths: Vec> = self.decompress()?.peekable(); let tree_height = auth_paths[0].len() + 2; From 2eb01dba5cd37291c5ac8d5c2e604f2c365cd5ae Mon Sep 17 00:00:00 2001 From: intx4 <65897068+intx4@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:43:37 +0100 Subject: [PATCH 17/36] updated syntax for iterators in multipath.verify Co-authored-by: Marcin --- src/merkle_tree/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index 04a717cd..ace56b0f 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -313,7 +313,7 @@ impl MultiPath

{ let mut auth_paths: Vec> = self.decompress()?.peekable(); - let tree_height = auth_paths[0].len() + 2; + let tree_height = auth_paths.peek().unwrap().len() + 2; // LookUp table to speedup computation avoid redundant hash computations let mut hash_lut: HashMap = HashMap::new(); From 7f5ac1d97b6a6a0e22fd56c26da904de04018401 Mon Sep 17 00:00:00 2001 From: intx4 <65897068+intx4@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:43:49 +0100 Subject: [PATCH 18/36] updated syntax for iterators in multipath.verify Co-authored-by: Marcin --- src/merkle_tree/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index ace56b0f..cd6a1f3c 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -320,7 +320,7 @@ impl MultiPath

{ for i in 0..self.leaf_indexes.len() { let leaf_index = self.leaf_indexes[i]; - let leaf = &leaves[i]; + let leaf = leaves.next().unwrap(); let leaf_sibling_hash = &self.leaf_siblings_hashes[i]; let auth_path = &auth_paths[i]; From 387e018f69c72637efcfae3ac834d16b43792aee Mon Sep 17 00:00:00 2001 From: intx4 <65897068+intx4@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:43:57 +0100 Subject: [PATCH 19/36] updated syntax for iterators in multipath.verify Co-authored-by: Marcin --- src/merkle_tree/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index cd6a1f3c..657350c4 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -322,7 +322,7 @@ impl MultiPath

{ let leaf_index = self.leaf_indexes[i]; let leaf = leaves.next().unwrap(); let leaf_sibling_hash = &self.leaf_siblings_hashes[i]; - let auth_path = &auth_paths[i]; + let auth_path = auth_paths.next().unwrap(); let claimed_leaf_hash = P::LeafHash::evaluate(&leaf_hash_params, leaf.clone())?; let (left_child, right_child) = From decf749bb3cc683b214d74978dfa4cc07e9115be Mon Sep 17 00:00:00 2001 From: intx4 Date: Thu, 18 Jan 2024 12:48:48 +0100 Subject: [PATCH 20/36] shortend init for multipath --- src/merkle_tree/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index 657350c4..ac3d20de 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -269,10 +269,10 @@ impl MultiPath

{ } Ok(MultiPath { - leaf_indexes: indexes, - auth_paths_prefix_lenghts: auth_paths_prefix_lenghts, - auth_paths_suffixes: auth_paths_suffixes, - leaf_siblings_hashes: leaf_siblings_hashes, + indexes, + auth_paths_prefix_lenghts, + auth_paths_suffixes, + leaf_siblings_hashes, }) } From d08af2a48725a166e733642a2ec606070f7727e6 Mon Sep 17 00:00:00 2001 From: intx4 Date: Thu, 18 Jan 2024 15:00:06 +0100 Subject: [PATCH 21/36] fixed build issues and implementing benches --- benches/merkle_tree.rs | 134 ++++++++++++++++++++++++++++++++++++++++- src/merkle_tree/mod.rs | 6 +- 2 files changed, 134 insertions(+), 6 deletions(-) diff --git a/benches/merkle_tree.rs b/benches/merkle_tree.rs index b32168e8..d3f0d5b9 100644 --- a/benches/merkle_tree.rs +++ b/benches/merkle_tree.rs @@ -12,6 +12,7 @@ mod bytes_mt_benches { use ark_std::{test_rng, UniformRand}; use criterion::Criterion; use std::borrow::Borrow; + use std::iter::zip; use crate::NUM_LEAVES; @@ -56,11 +57,138 @@ mod bytes_mt_benches { }); } + pub fn merkle_tree_generate_proof(c: &mut Criterion) { + let mut rng = test_rng(); + let leaves: Vec<_> = (0..NUM_LEAVES) + .map(|_| { + let rnd = BigInteger256::rand(&mut rng); + to_uncompressed_bytes!(rnd).unwrap() + }) + .collect(); + let leaf_crh_params = ::setup(&mut rng).unwrap(); + let two_to_one_params = ::setup(&mut rng) + .unwrap() + .clone(); + + let tree = Sha256MerkleTree::new( + &leaf_crh_params.clone(), + &two_to_one_params.clone(), + &leaves, + ) + .unwrap(); + c.bench_function("Merkle Tree Generate Proof (Leaves as [u8])", move |b| { + b.iter(|| { + for (i, _) in leaves.iter().enumerate() { + tree.generate_proof(i).unwrap(); + } + }) + }); + } + + pub fn merkle_tree_verify_proof(c: &mut Criterion) { + let mut rng = test_rng(); + let leaves: Vec<_> = (0..NUM_LEAVES) + .map(|_| { + let rnd = BigInteger256::rand(&mut rng); + to_uncompressed_bytes!(rnd).unwrap() + }) + .collect(); + let leaf_crh_params = ::setup(&mut rng).unwrap(); + let two_to_one_params = ::setup(&mut rng) + .unwrap() + .clone(); + + let tree = Sha256MerkleTree::new( + &leaf_crh_params.clone(), + &two_to_one_params.clone(), + &leaves, + ) + .unwrap(); + + let root = tree.root(); + + let proofs: Vec<_> = leaves + .iter() + .enumerate() + .map(|(i, _)| tree.generate_proof(i).unwrap()) + .collect(); + + c.bench_function("Merkle Tree Verify Proof (Leaves as [u8])", move |b| { + b.iter(move || { + for (proof, leaf) in zip(proofs.clone(), leaves.clone()) { + proof + .verify(&leaf_crh_params, &two_to_one_params, &root, leaf.as_slice()) + .unwrap(); + } + }) + }); + } + + pub fn merkle_tree_generate_multi_proof(c: &mut Criterion) { + let mut rng = test_rng(); + let leaves: Vec<_> = (0..NUM_LEAVES) + .map(|_| { + let rnd = BigInteger256::rand(&mut rng); + to_uncompressed_bytes!(rnd).unwrap() + }) + .collect(); + let leaf_crh_params = ::setup(&mut rng).unwrap(); + let two_to_one_params = ::setup(&mut rng) + .unwrap() + .clone(); + + let tree = Sha256MerkleTree::new( + &leaf_crh_params.clone(), + &two_to_one_params.clone(), + &leaves, + ) + .unwrap(); + c.bench_function("Merkle Tree Generate Multi Proof (Leaves as [u8])", move |b| { + b.iter(|| { + tree.generate_multi_proof((0..leaves.len()).collect::>()) + .unwrap(); + }) + }); + } + + pub fn merkle_tree_verify_multi_proof(c: &mut Criterion) { + let mut rng = test_rng(); + let leaves: Vec<_> = (0..NUM_LEAVES) + .map(|_| { + let rnd = BigInteger256::rand(&mut rng); + to_uncompressed_bytes!(rnd).unwrap() + }) + .collect(); + let leaf_crh_params = ::setup(&mut rng).unwrap(); + let two_to_one_params = ::setup(&mut rng) + .unwrap() + .clone(); + + let tree = Sha256MerkleTree::new( + &leaf_crh_params.clone(), + &two_to_one_params.clone(), + &leaves, + ) + .unwrap(); + + let root = tree.root(); + + let multi_proof = tree + .generate_multi_proof((0..leaves.len()).collect::>()) + .unwrap(); + + c.bench_function("Merkle Tree Verify Multi Proof (Leaves as [u8])", move |b| { + b.iter(|| { + multi_proof.verify(&leaf_crh_params, &two_to_one_params, &root, leaves.clone()) + }) + }); + } + criterion_group! { - name = mt_create; + name = mt_benches; config = Criterion::default().sample_size(10); - targets = merkle_tree_create + targets = merkle_tree_create, merkle_tree_generate_proof, merkle_tree_verify_proof, merkle_tree_generate_multi_proof, merkle_tree_verify_multi_proof } } -criterion_main!(crate::bytes_mt_benches::mt_create,); +criterion_main!(crate::bytes_mt_benches::mt_benches); diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index ac3d20de..0926ea87 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -5,9 +5,9 @@ use crate::crh::TwoToOneCRHScheme; use crate::{crh::CRHScheme, Error}; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_std::borrow::Borrow; +use ark_std::collections::{BTreeSet, HashMap}; use ark_std::hash::Hash; use ark_std::vec::Vec; -use ark_std::collections::{BTreeSet, HashMap}; #[cfg(test)] mod tests; @@ -269,7 +269,7 @@ impl MultiPath

{ } Ok(MultiPath { - indexes, + leaf_indexes: indexes, auth_paths_prefix_lenghts, auth_paths_suffixes, leaf_siblings_hashes, @@ -311,7 +311,7 @@ impl MultiPath

{ let mut leaves = leaves.into_iter(); - let mut auth_paths: Vec> = self.decompress()?.peekable(); + let mut auth_paths = self.decompress()?.peekable(); let tree_height = auth_paths.peek().unwrap().len() + 2; From e93e622aa8c4c15ff6e82122a747aa049fce3b05 Mon Sep 17 00:00:00 2001 From: intx4 Date: Thu, 18 Jan 2024 19:26:01 +0100 Subject: [PATCH 22/36] implemented benches for proof and multiproof --- benches/merkle_tree.rs | 30 ++++++++++++++++++------------ src/merkle_tree/mod.rs | 6 +++++- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/benches/merkle_tree.rs b/benches/merkle_tree.rs index d3f0d5b9..3b375b88 100644 --- a/benches/merkle_tree.rs +++ b/benches/merkle_tree.rs @@ -114,7 +114,7 @@ mod bytes_mt_benches { .collect(); c.bench_function("Merkle Tree Verify Proof (Leaves as [u8])", move |b| { - b.iter(move || { + b.iter(|| { for (proof, leaf) in zip(proofs.clone(), leaves.clone()) { proof .verify(&leaf_crh_params, &two_to_one_params, &root, leaf.as_slice()) @@ -143,12 +143,15 @@ mod bytes_mt_benches { &leaves, ) .unwrap(); - c.bench_function("Merkle Tree Generate Multi Proof (Leaves as [u8])", move |b| { - b.iter(|| { - tree.generate_multi_proof((0..leaves.len()).collect::>()) - .unwrap(); - }) - }); + c.bench_function( + "Merkle Tree Generate Multi Proof (Leaves as [u8])", + move |b| { + b.iter(|| { + tree.generate_multi_proof((0..leaves.len()).collect::>()) + .unwrap(); + }) + }, + ); } pub fn merkle_tree_verify_multi_proof(c: &mut Criterion) { @@ -177,11 +180,14 @@ mod bytes_mt_benches { .generate_multi_proof((0..leaves.len()).collect::>()) .unwrap(); - c.bench_function("Merkle Tree Verify Multi Proof (Leaves as [u8])", move |b| { - b.iter(|| { - multi_proof.verify(&leaf_crh_params, &two_to_one_params, &root, leaves.clone()) - }) - }); + c.bench_function( + "Merkle Tree Verify Multi Proof (Leaves as [u8])", + move |b| { + b.iter(|| { + multi_proof.verify(&leaf_crh_params, &two_to_one_params, &root, leaves.clone()) + }) + }, + ); } criterion_group! { diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index 0926ea87..8a2b207d 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -283,7 +283,7 @@ impl MultiPath

{ // Incrementally reconstruct all the paths let mut curr_path = self.auth_paths_suffixes[0].clone(); let mut auth_paths = (0..self.leaf_indexes.len()) - .map(|_| Vec::new()) + .map(|_| Vec::with_capacity(curr_path.len())) .collect::>>(); auth_paths[0] = self.auth_paths_suffixes[0].clone(); @@ -611,6 +611,10 @@ impl MerkleTree

{ /// Returns a MultiPath (multiple authentication paths in compressed form, with Front Incremental Encoding), /// from every leaf to root. /// Note that for compression efficiency, the indexes are internally sorted. + /// For sorted indexes, MultiPath contains: + /// `2*( (num_leaves.log2()-1).pow(2) - (num_leaves.log2()-2) )` + /// instead of + /// `num_leaves*(num_leaves.log2()-1)` /// When verifying the proof, leaves hashes should be supplied in order, that is: /// let ordered_leaves: Vec<_> = self.leaf_indexes.into_iter().map(|i| leaves[i]).collect(); pub fn generate_multi_proof( From 8ab9692c5fc5c4630d4a8dc5a625ee36fa0e1138 Mon Sep 17 00:00:00 2001 From: intx4 Date: Thu, 18 Jan 2024 22:22:30 +0100 Subject: [PATCH 23/36] removed extra loop in decompress --- src/merkle_tree/mod.rs | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index 8a2b207d..f4970058 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -281,17 +281,23 @@ impl MultiPath

{ &'_ self, ) -> Result>, crate::Error> { // Incrementally reconstruct all the paths - let mut curr_path = self.auth_paths_suffixes[0].clone(); - let mut auth_paths = (0..self.leaf_indexes.len()) - .map(|_| Vec::with_capacity(curr_path.len())) - .collect::>>(); - auth_paths[0] = self.auth_paths_suffixes[0].clone(); - - for i in 1..auth_paths.len() { - auth_paths[i].extend_from_slice(&curr_path[0..self.auth_paths_prefix_lenghts[i]]); - auth_paths[i].extend(self.auth_paths_suffixes[i].clone()); - curr_path = auth_paths[i].clone(); + + let mut auth_paths = Vec::with_capacity(self.leaf_indexes.len()); + let mut curr_path = &self.auth_paths_suffixes[0]; + + for i in 0..self.leaf_indexes.len(){ + if self.auth_paths_prefix_lenghts[i] == 0{ + auth_paths.push(self.auth_paths_suffixes[i].clone()); + } else { + auth_paths.push( + vec![ + curr_path[0..self.auth_paths_prefix_lenghts[i]].to_vec(), + self.auth_paths_suffixes[i].clone() + ].concat()); + } + curr_path = &auth_paths[i]; } + Ok(auth_paths.into_iter()) } From 0719d3628441bdde615d69b2f38788e21ebe7f4a Mon Sep 17 00:00:00 2001 From: intx4 Date: Thu, 18 Jan 2024 22:42:56 +0100 Subject: [PATCH 24/36] removed explicit decompress and merged decompression into multipath verification --- src/merkle_tree/mod.rs | 70 ++++++++++++++++++++---------------- src/merkle_tree/tests/mod.rs | 16 ++++----- 2 files changed, 48 insertions(+), 38 deletions(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index f4970058..93865190 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -277,29 +277,29 @@ impl MultiPath

{ } /// Returns the decompressed authentication paths for every leaf index - fn decompress( - &'_ self, - ) -> Result>, crate::Error> { - // Incrementally reconstruct all the paths - - let mut auth_paths = Vec::with_capacity(self.leaf_indexes.len()); - let mut curr_path = &self.auth_paths_suffixes[0]; - - for i in 0..self.leaf_indexes.len(){ - if self.auth_paths_prefix_lenghts[i] == 0{ - auth_paths.push(self.auth_paths_suffixes[i].clone()); - } else { - auth_paths.push( - vec![ - curr_path[0..self.auth_paths_prefix_lenghts[i]].to_vec(), - self.auth_paths_suffixes[i].clone() - ].concat()); - } - curr_path = &auth_paths[i]; - } - - Ok(auth_paths.into_iter()) - } + //fn decompress( + // &'_ self, + //) -> Result>, crate::Error> { + // // Incrementally reconstruct all the paths + // + // let mut auth_paths = Vec::with_capacity(self.leaf_indexes.len()); + // let mut curr_path = &self.auth_paths_suffixes[0]; + // + // for i in 0..self.leaf_indexes.len(){ + // if self.auth_paths_prefix_lenghts[i] == 0{ + // auth_paths.push(self.auth_paths_suffixes[i].clone()); + // } else { + // auth_paths.push( + // vec![ + // curr_path[0..self.auth_paths_prefix_lenghts[i]].to_vec(), + // self.auth_paths_suffixes[i].clone() + // ].concat()); + // } + // curr_path = &auth_paths[i]; + // } + // + // Ok(auth_paths.into_iter()) + //} /// Verify that leaves are at `self.leaf_indexes` of the merkle tree. /// Note that the order of the leaves hashes should match the leaves respective indexes @@ -313,22 +313,32 @@ impl MultiPath

{ root_hash: &P::InnerDigest, leaves: impl IntoIterator, ) -> Result { - // array of auth paths as arrays of InnerDigests - + let tree_height = self.auth_paths_suffixes[0].len() + 2; let mut leaves = leaves.into_iter(); - let mut auth_paths = self.decompress()?.peekable(); - - let tree_height = auth_paths.peek().unwrap().len() + 2; - // LookUp table to speedup computation avoid redundant hash computations let mut hash_lut: HashMap = HashMap::new(); + // init curr path for decoding + let mut curr_path: Vec<_> = self.auth_paths_suffixes[0].clone(); + for i in 0..self.leaf_indexes.len() { let leaf_index = self.leaf_indexes[i]; let leaf = leaves.next().unwrap(); let leaf_sibling_hash = &self.leaf_siblings_hashes[i]; - let auth_path = auth_paths.next().unwrap(); + + // decode i-th auth path + let auth_path: Vec<_> = if self.auth_paths_prefix_lenghts[i] == 0 { + self.auth_paths_suffixes[i].clone() + } else { + vec![ + curr_path[0..self.auth_paths_prefix_lenghts[i]].to_vec(), + self.auth_paths_suffixes[i].clone(), + ] + .concat() + }; + // update current path for decoding next one + curr_path = auth_path.clone(); let claimed_leaf_hash = P::LeafHash::evaluate(&leaf_hash_params, leaf.clone())?; let (left_child, right_child) = diff --git a/src/merkle_tree/tests/mod.rs b/src/merkle_tree/tests/mod.rs index aae0dcff..7a0f1eb8 100644 --- a/src/merkle_tree/tests/mod.rs +++ b/src/merkle_tree/tests/mod.rs @@ -184,14 +184,14 @@ mod bytes_mt_tests { assert_eq!(prefix_len + suffix.len(), proofs[0].auth_path.len()); } - let comp_proofs: Vec<_> = multi_proof.decompress().unwrap().collect(); - - // test decompressed paths are as expected - for (comp_path, exp_path) in zip(&comp_proofs, &proofs) { - for (comp_hash, exp_hash) in zip(comp_path, &exp_path.auth_path) { - assert_eq!(*comp_hash, *exp_hash); - } - } + //let comp_proofs: Vec<_> = multi_proof.decompress().unwrap().collect(); + // + //// test decompressed paths are as expected + //for (comp_path, exp_path) in zip(&comp_proofs, &proofs) { + // for (comp_hash, exp_hash) in zip(comp_path, &exp_path.auth_path) { + // assert_eq!(*comp_hash, *exp_hash); + // } + //} } } From e3030283dbeba79ab09e890476e5574ec74bf1ff Mon Sep 17 00:00:00 2001 From: intx4 Date: Fri, 19 Jan 2024 14:48:05 +0100 Subject: [PATCH 25/36] removed multi_path.compress and merged compression step in generate_multi_proof --- src/merkle_tree/mod.rs | 210 ++++++++++++++++++++++++++++------------- 1 file changed, 145 insertions(+), 65 deletions(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index 93865190..902afe37 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -226,55 +226,55 @@ pub struct MultiPath { impl MultiPath

{ /// Returns a compressed MultiPath containing multiple encoded authentication paths for `indexes` - fn compress( - indexes: impl IntoIterator, - leaf_siblings_hashes: Vec, - auth_paths: Vec>, - ) -> Result { - let indexes = Vec::from_iter(indexes); - // use multipath for more than 1 leaf - assert!( - indexes.len() > 1, - "Expected more than one leaf to verify for MultiPath, got {}", - indexes.len() - ); - - let mut auth_paths_prefix_lenghts: Vec = Vec::with_capacity(indexes.len()); - let mut auth_paths_suffixes: Vec> = Vec::with_capacity(indexes.len()); - - auth_paths_prefix_lenghts.push(0); - auth_paths_suffixes.push(auth_paths[0].auth_path.clone()); - - let mut prev_path = auth_paths[0].clone(); - - // Encode paths with Incremental Encoding (Front compression) - for path in auth_paths[1..].to_vec() { - let mut prefix_len = 0; - if prev_path.auth_path.len() != 0 && path.auth_path.len() != 0 { - while prev_path.auth_path[prefix_len] == path.auth_path[prefix_len] { - prefix_len += 1; - if prefix_len == prev_path.auth_path.len() || prefix_len == path.auth_path.len() - { - break; - } - } - } - auth_paths_prefix_lenghts.push(prefix_len); - if prefix_len == prev_path.auth_path.len() { - auth_paths_suffixes.push(vec![]); - } else { - auth_paths_suffixes.push(path.auth_path[prefix_len..].to_vec().clone()); - } - prev_path = path; - } - - Ok(MultiPath { - leaf_indexes: indexes, - auth_paths_prefix_lenghts, - auth_paths_suffixes, - leaf_siblings_hashes, - }) - } + //fn compress( + // indexes: impl IntoIterator, + // leaf_siblings_hashes: Vec, + // auth_paths: Vec>, + //) -> Result { + // let indexes = Vec::from_iter(indexes); + // // use multipath for more than 1 leaf + // assert!( + // indexes.len() > 1, + // "Expected more than one leaf to verify for MultiPath, got {}", + // indexes.len() + // ); +// + // let mut auth_paths_prefix_lenghts: Vec = Vec::with_capacity(indexes.len()); + // let mut auth_paths_suffixes: Vec> = Vec::with_capacity(indexes.len()); +// + // auth_paths_prefix_lenghts.push(0); + // auth_paths_suffixes.push(auth_paths[0].auth_path.clone()); +// + // let mut prev_path = auth_paths[0].clone(); +// + // // Encode paths with Incremental Encoding (Front compression) + // for path in auth_paths[1..].to_vec() { + // let mut prefix_len = 0; + // if prev_path.auth_path.len() != 0 && path.auth_path.len() != 0 { + // while prev_path.auth_path[prefix_len] == path.auth_path[prefix_len] { + // prefix_len += 1; + // if prefix_len == prev_path.auth_path.len() || prefix_len == path.auth_path.len() + // { + // break; + // } + // } + // } + // auth_paths_prefix_lenghts.push(prefix_len); + // if prefix_len == prev_path.auth_path.len() { + // auth_paths_suffixes.push(vec![]); + // } else { + // auth_paths_suffixes.push(path.auth_path[prefix_len..].to_vec().clone()); + // } + // prev_path = path; + // } +// + // Ok(MultiPath { + // leaf_indexes: indexes, + // auth_paths_prefix_lenghts, + // auth_paths_suffixes, + // leaf_siblings_hashes, + // }) + //} /// Returns the decompressed authentication paths for every leaf index //fn decompress( @@ -637,26 +637,75 @@ impl MerkleTree

{ &self, indexes: impl IntoIterator, ) -> Result, crate::Error> { + // pruned and sorted for encoding efficiency let indexes: BTreeSet = indexes.into_iter().collect(); + // gather basic tree information + let tree_height = tree_height(self.leaf_nodes.len()); + + //let auth_paths = Vec::with_capacity(indexes.len()); + let mut auth_paths_prefix_lenghts: Vec = Vec::with_capacity(indexes.len()); + let mut auth_paths_suffixes: Vec> = Vec::with_capacity(indexes.len()); - let auth_paths: Vec> = cfg_into_iter!(indexes.clone()) - .map(|i| self.generate_proof(i)) - .collect::>, crate::Error>>()?; - - let leaf_siblings_hashes = cfg_into_iter!(indexes.clone()) - .map(|i| { - if i & 1 == 0 { - // leaf is left child - self.leaf_nodes[i + 1].clone() - } else { - // leaf is right child - self.leaf_nodes[i - 1].clone() - } - }) - .collect(); + let mut leaf_siblings_hashes = Vec::with_capacity(indexes.len()); + + let mut prev_path = Vec::new(); + + for index in &indexes{ + let leaf_index_in_tree = convert_index_to_last_level(*index, tree_height); + + let leaf_sibling_hash = if index & 1 == 0 { + // leaf is left child + self.leaf_nodes[index + 1].clone() + } else { + // leaf is right child + self.leaf_nodes[index - 1].clone() + }; + leaf_siblings_hashes.push(leaf_sibling_hash); + + // path.len() = `tree height - 2`, the two missing elements being the leaf sibling hash and the root + let mut path = Vec::with_capacity(tree_height - 2); + + // Iterate from the bottom layer after the leaves, to the top, storing all sibling node's hash values. + let mut current_node = parent(leaf_index_in_tree).unwrap(); + while !is_root(current_node) { + let sibling_node = sibling(current_node).unwrap(); + path.push(self.non_leaf_nodes[sibling_node].clone()); + current_node = parent(current_node).unwrap(); + } - MultiPath::compress(indexes, leaf_siblings_hashes, auth_paths) + debug_assert_eq!(path.len(), tree_height - 2); + + // we want to make path from root to bottom + path.reverse(); + + //let mut prefix_len = 0; + //if prev_path.len() != 0 && path.len() != 0 { + // while prev_path[prefix_len] == path[prefix_len]{ + // prefix_len += 1; + // } + // if prefix_len == prev_path.len() || prefix_len == path.len() { + // break; + // } + //} + //auth_paths_prefix_lenghts.push(prefix_len); + //if prefix_len == prev_path.len(){ + // auth_paths_suffixes.push(vec![]); + //} else { + // auth_paths_suffixes.push(path[prefix_len..].to_vec().clone()); + //} + let (prefix_len, suffix) = prefix_encode_path(&prev_path, &path); + auth_paths_prefix_lenghts.push(prefix_len); + auth_paths_suffixes.push(suffix); + prev_path = path; + } + + Ok(MultiPath { + leaf_indexes: Vec::from_iter(indexes), + auth_paths_prefix_lenghts, + auth_paths_suffixes, + leaf_siblings_hashes, + }) } /// Given the index and new leaf, return the hash of leaf and an updated path in order from root to bottom non-leaf level. @@ -819,3 +868,34 @@ fn parent(index: usize) -> Option { fn convert_index_to_last_level(index: usize, tree_height: usize) -> usize { index + (1 << (tree_height - 1)) - 1 } + + + +/// Encodes path with Incremental Encoding by comparing with prev_path +/// Returns the prefix length and the suffix to append during decoding +/// Example: +/// If `prev_path` is vec![C,D] and `path` is vec![C,E] (where C,D,E are hashes) +/// `prefix_encode_path` returns 1,vec![E] +#[inline] +fn prefix_encode_path( + prev_path: &Vec, + path: &Vec +) -> (usize, Vec) +where +T: Eq + Clone{ + let mut prefix_len = 0; + if prev_path.len() != 0 && path.len() != 0 { + while prev_path[prefix_len] == path[prefix_len]{ + prefix_len += 1; + if prefix_len == prev_path.len() || prefix_len == path.len() { + break; + } + } + } + if prefix_len != 0 && prefix_len == prev_path.len(){ + return (prefix_len, Vec::new()); + } else { + return (prefix_len, path[prefix_len..].to_vec()); + } +} + From 3d6f9bef157e7f727531818d0dec9465a322861f Mon Sep 17 00:00:00 2001 From: intx4 Date: Fri, 19 Jan 2024 15:05:03 +0100 Subject: [PATCH 26/36] implemented prefix_decode_path --- src/merkle_tree/mod.rs | 155 ++++++++--------------------------- src/merkle_tree/tests/mod.rs | 9 -- 2 files changed, 33 insertions(+), 131 deletions(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index 902afe37..551b15de 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -225,82 +225,6 @@ pub struct MultiPath { } impl MultiPath

{ - /// Returns a compressed MultiPath containing multiple encoded authentication paths for `indexes` - //fn compress( - // indexes: impl IntoIterator, - // leaf_siblings_hashes: Vec, - // auth_paths: Vec>, - //) -> Result { - // let indexes = Vec::from_iter(indexes); - // // use multipath for more than 1 leaf - // assert!( - // indexes.len() > 1, - // "Expected more than one leaf to verify for MultiPath, got {}", - // indexes.len() - // ); -// - // let mut auth_paths_prefix_lenghts: Vec = Vec::with_capacity(indexes.len()); - // let mut auth_paths_suffixes: Vec> = Vec::with_capacity(indexes.len()); -// - // auth_paths_prefix_lenghts.push(0); - // auth_paths_suffixes.push(auth_paths[0].auth_path.clone()); -// - // let mut prev_path = auth_paths[0].clone(); -// - // // Encode paths with Incremental Encoding (Front compression) - // for path in auth_paths[1..].to_vec() { - // let mut prefix_len = 0; - // if prev_path.auth_path.len() != 0 && path.auth_path.len() != 0 { - // while prev_path.auth_path[prefix_len] == path.auth_path[prefix_len] { - // prefix_len += 1; - // if prefix_len == prev_path.auth_path.len() || prefix_len == path.auth_path.len() - // { - // break; - // } - // } - // } - // auth_paths_prefix_lenghts.push(prefix_len); - // if prefix_len == prev_path.auth_path.len() { - // auth_paths_suffixes.push(vec![]); - // } else { - // auth_paths_suffixes.push(path.auth_path[prefix_len..].to_vec().clone()); - // } - // prev_path = path; - // } -// - // Ok(MultiPath { - // leaf_indexes: indexes, - // auth_paths_prefix_lenghts, - // auth_paths_suffixes, - // leaf_siblings_hashes, - // }) - //} - - /// Returns the decompressed authentication paths for every leaf index - //fn decompress( - // &'_ self, - //) -> Result>, crate::Error> { - // // Incrementally reconstruct all the paths - // - // let mut auth_paths = Vec::with_capacity(self.leaf_indexes.len()); - // let mut curr_path = &self.auth_paths_suffixes[0]; - // - // for i in 0..self.leaf_indexes.len(){ - // if self.auth_paths_prefix_lenghts[i] == 0{ - // auth_paths.push(self.auth_paths_suffixes[i].clone()); - // } else { - // auth_paths.push( - // vec![ - // curr_path[0..self.auth_paths_prefix_lenghts[i]].to_vec(), - // self.auth_paths_suffixes[i].clone() - // ].concat()); - // } - // curr_path = &auth_paths[i]; - // } - // - // Ok(auth_paths.into_iter()) - //} - /// Verify that leaves are at `self.leaf_indexes` of the merkle tree. /// Note that the order of the leaves hashes should match the leaves respective indexes /// * `leaf_size`: leaf size in number of bytes @@ -319,8 +243,8 @@ impl MultiPath

{ // LookUp table to speedup computation avoid redundant hash computations let mut hash_lut: HashMap = HashMap::new(); - // init curr path for decoding - let mut curr_path: Vec<_> = self.auth_paths_suffixes[0].clone(); + // init prev path for decoding + let mut prev_path: Vec<_> = self.auth_paths_suffixes[0].clone(); for i in 0..self.leaf_indexes.len() { let leaf_index = self.leaf_indexes[i]; @@ -328,17 +252,13 @@ impl MultiPath

{ let leaf_sibling_hash = &self.leaf_siblings_hashes[i]; // decode i-th auth path - let auth_path: Vec<_> = if self.auth_paths_prefix_lenghts[i] == 0 { - self.auth_paths_suffixes[i].clone() - } else { - vec![ - curr_path[0..self.auth_paths_prefix_lenghts[i]].to_vec(), - self.auth_paths_suffixes[i].clone(), - ] - .concat() - }; - // update current path for decoding next one - curr_path = auth_path.clone(); + let auth_path = prefix_decode_path( + &prev_path, + self.auth_paths_prefix_lenghts[i], + &self.auth_paths_suffixes[i], + ); + // update prev path for decoding next one + prev_path = auth_path.clone(); let claimed_leaf_hash = P::LeafHash::evaluate(&leaf_hash_params, leaf.clone())?; let (left_child, right_child) = @@ -637,23 +557,22 @@ impl MerkleTree

{ &self, indexes: impl IntoIterator, ) -> Result, crate::Error> { - // pruned and sorted for encoding efficiency let indexes: BTreeSet = indexes.into_iter().collect(); // gather basic tree information let tree_height = tree_height(self.leaf_nodes.len()); - + //let auth_paths = Vec::with_capacity(indexes.len()); let mut auth_paths_prefix_lenghts: Vec = Vec::with_capacity(indexes.len()); let mut auth_paths_suffixes: Vec> = Vec::with_capacity(indexes.len()); let mut leaf_siblings_hashes = Vec::with_capacity(indexes.len()); - let mut prev_path = Vec::new(); - - for index in &indexes{ + let mut prev_path = Vec::new(); + + for index in &indexes { let leaf_index_in_tree = convert_index_to_last_level(*index, tree_height); - + let leaf_sibling_hash = if index & 1 == 0 { // leaf is left child self.leaf_nodes[index + 1].clone() @@ -665,7 +584,7 @@ impl MerkleTree

{ // path.len() = `tree height - 2`, the two missing elements being the leaf sibling hash and the root let mut path = Vec::with_capacity(tree_height - 2); - + // Iterate from the bottom layer after the leaves, to the top, storing all sibling node's hash values. let mut current_node = parent(leaf_index_in_tree).unwrap(); while !is_root(current_node) { @@ -678,28 +597,14 @@ impl MerkleTree

{ // we want to make path from root to bottom path.reverse(); - - //let mut prefix_len = 0; - //if prev_path.len() != 0 && path.len() != 0 { - // while prev_path[prefix_len] == path[prefix_len]{ - // prefix_len += 1; - // } - // if prefix_len == prev_path.len() || prefix_len == path.len() { - // break; - // } - //} - //auth_paths_prefix_lenghts.push(prefix_len); - //if prefix_len == prev_path.len(){ - // auth_paths_suffixes.push(vec![]); - //} else { - // auth_paths_suffixes.push(path[prefix_len..].to_vec().clone()); - //} + + // incremental encoding let (prefix_len, suffix) = prefix_encode_path(&prev_path, &path); auth_paths_prefix_lenghts.push(prefix_len); auth_paths_suffixes.push(suffix); prev_path = path; } - + Ok(MultiPath { leaf_indexes: Vec::from_iter(indexes), auth_paths_prefix_lenghts, @@ -869,33 +774,39 @@ fn convert_index_to_last_level(index: usize, tree_height: usize) -> usize { index + (1 << (tree_height - 1)) - 1 } - - /// Encodes path with Incremental Encoding by comparing with prev_path /// Returns the prefix length and the suffix to append during decoding /// Example: /// If `prev_path` is vec![C,D] and `path` is vec![C,E] (where C,D,E are hashes) /// `prefix_encode_path` returns 1,vec![E] #[inline] -fn prefix_encode_path( - prev_path: &Vec, - path: &Vec -) -> (usize, Vec) +fn prefix_encode_path(prev_path: &Vec, path: &Vec) -> (usize, Vec) where -T: Eq + Clone{ + T: Eq + Clone, +{ let mut prefix_len = 0; if prev_path.len() != 0 && path.len() != 0 { - while prev_path[prefix_len] == path[prefix_len]{ + while prev_path[prefix_len] == path[prefix_len] { prefix_len += 1; if prefix_len == prev_path.len() || prefix_len == path.len() { break; } } } - if prefix_len != 0 && prefix_len == prev_path.len(){ + if prefix_len != 0 && prefix_len == prev_path.len() { return (prefix_len, Vec::new()); } else { return (prefix_len, path[prefix_len..].to_vec()); } } +fn prefix_decode_path(prev_path: &Vec, prefix_len: usize, suffix: &Vec) -> Vec +where + T: Eq + Clone, +{ + if prefix_len == 0 { + suffix.clone() + } else { + vec![prev_path[0..prefix_len].to_vec(), suffix.clone()].concat() + } +} diff --git a/src/merkle_tree/tests/mod.rs b/src/merkle_tree/tests/mod.rs index 7a0f1eb8..0eae7aad 100644 --- a/src/merkle_tree/tests/mod.rs +++ b/src/merkle_tree/tests/mod.rs @@ -183,15 +183,6 @@ mod bytes_mt_tests { ) { assert_eq!(prefix_len + suffix.len(), proofs[0].auth_path.len()); } - - //let comp_proofs: Vec<_> = multi_proof.decompress().unwrap().collect(); - // - //// test decompressed paths are as expected - //for (comp_path, exp_path) in zip(&comp_proofs, &proofs) { - // for (comp_hash, exp_hash) in zip(comp_path, &exp_path.auth_path) { - // assert_eq!(*comp_hash, *exp_hash); - // } - //} } } From fe685f85681ce071ef4b541b756bff9fb3f3b076 Mon Sep 17 00:00:00 2001 From: intx4 Date: Fri, 19 Jan 2024 17:18:31 +0100 Subject: [PATCH 27/36] removed redundant code with new helper functions --- src/merkle_tree/mod.rs | 56 +++++++++++++++--------------------------- 1 file changed, 20 insertions(+), 36 deletions(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index 551b15de..60053831 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -507,20 +507,23 @@ impl MerkleTree

{ self.height } - /// Returns the authentication path from leaf at `index` to root. - pub fn generate_proof(&self, index: usize) -> Result, crate::Error> { - // gather basic tree information - let tree_height = tree_height(self.leaf_nodes.len()); - - // Get Leaf hash, and leaf sibling hash, - let leaf_index_in_tree = convert_index_to_last_level(index, tree_height); - let leaf_sibling_hash = if index & 1 == 0 { + fn get_leaf_sibling_hash(&self, index: usize) -> P::LeafDigest{ + if index & 1 == 0 { // leaf is left child self.leaf_nodes[index + 1].clone() } else { // leaf is right child self.leaf_nodes[index - 1].clone() - }; + } + } + + /// Returns the authentication path from leaf at `index` to root, as a Vec of digests + fn compute_path(&self, index: usize) -> Vec { + // gather basic tree information + let tree_height = tree_height(self.leaf_nodes.len()); + + // Get Leaf hash, and leaf sibling hash, + let leaf_index_in_tree = convert_index_to_last_level(index, tree_height); // path.len() = `tree height - 2`, the two missing elements being the leaf sibling hash and the root let mut path = Vec::with_capacity(tree_height - 2); @@ -536,11 +539,16 @@ impl MerkleTree

{ // we want to make path from root to bottom path.reverse(); + path + } + /// Returns the authentication path from leaf at `index` to root. + pub fn generate_proof(&self, index: usize) -> Result, crate::Error> { + let path = self.compute_path(index); Ok(Path { leaf_index: index, auth_path: path, - leaf_sibling_hash, + leaf_sibling_hash: self.get_leaf_sibling_hash(index), }) } @@ -559,8 +567,6 @@ impl MerkleTree

{ ) -> Result, crate::Error> { // pruned and sorted for encoding efficiency let indexes: BTreeSet = indexes.into_iter().collect(); - // gather basic tree information - let tree_height = tree_height(self.leaf_nodes.len()); //let auth_paths = Vec::with_capacity(indexes.len()); let mut auth_paths_prefix_lenghts: Vec = Vec::with_capacity(indexes.len()); @@ -571,32 +577,10 @@ impl MerkleTree

{ let mut prev_path = Vec::new(); for index in &indexes { - let leaf_index_in_tree = convert_index_to_last_level(*index, tree_height); - - let leaf_sibling_hash = if index & 1 == 0 { - // leaf is left child - self.leaf_nodes[index + 1].clone() - } else { - // leaf is right child - self.leaf_nodes[index - 1].clone() - }; - leaf_siblings_hashes.push(leaf_sibling_hash); - - // path.len() = `tree height - 2`, the two missing elements being the leaf sibling hash and the root - let mut path = Vec::with_capacity(tree_height - 2); - - // Iterate from the bottom layer after the leaves, to the top, storing all sibling node's hash values. - let mut current_node = parent(leaf_index_in_tree).unwrap(); - while !is_root(current_node) { - let sibling_node = sibling(current_node).unwrap(); - path.push(self.non_leaf_nodes[sibling_node].clone()); - current_node = parent(current_node).unwrap(); - } - debug_assert_eq!(path.len(), tree_height - 2); + leaf_siblings_hashes.push(self.get_leaf_sibling_hash(*index)); - // we want to make path from root to bottom - path.reverse(); + let path = self.compute_path(*index); // incremental encoding let (prefix_len, suffix) = prefix_encode_path(&prev_path, &path); From aad27850a26db0a8cb8cfba2ce62419b1d641196 Mon Sep 17 00:00:00 2001 From: intx4 Date: Fri, 19 Jan 2024 17:20:48 +0100 Subject: [PATCH 28/36] added doc for get_leaf_sibling_hash and made it pub. Renamed compute_path to compute_auth_path --- src/merkle_tree/mod.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index 60053831..e94fde14 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -507,7 +507,8 @@ impl MerkleTree

{ self.height } - fn get_leaf_sibling_hash(&self, index: usize) -> P::LeafDigest{ + /// Given the `index` of a leaf, returns the digest of its leaf sibling + pub fn get_leaf_sibling_hash(&self, index: usize) -> P::LeafDigest{ if index & 1 == 0 { // leaf is left child self.leaf_nodes[index + 1].clone() @@ -518,7 +519,7 @@ impl MerkleTree

{ } /// Returns the authentication path from leaf at `index` to root, as a Vec of digests - fn compute_path(&self, index: usize) -> Vec { + fn compute_auth_path(&self, index: usize) -> Vec { // gather basic tree information let tree_height = tree_height(self.leaf_nodes.len()); @@ -544,7 +545,7 @@ impl MerkleTree

{ /// Returns the authentication path from leaf at `index` to root. pub fn generate_proof(&self, index: usize) -> Result, crate::Error> { - let path = self.compute_path(index); + let path = self.compute_auth_path(index); Ok(Path { leaf_index: index, auth_path: path, @@ -580,7 +581,7 @@ impl MerkleTree

{ leaf_siblings_hashes.push(self.get_leaf_sibling_hash(*index)); - let path = self.compute_path(*index); + let path = self.compute_auth_path(*index); // incremental encoding let (prefix_len, suffix) = prefix_encode_path(&prev_path, &path); From 76846e1ef58a3610726f5369bdca39bb39895e67 Mon Sep 17 00:00:00 2001 From: intx4 Date: Mon, 22 Jan 2024 18:12:16 +0100 Subject: [PATCH 29/36] cargo fmt --- src/merkle_tree/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index e94fde14..50653b63 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -508,7 +508,7 @@ impl MerkleTree

{ } /// Given the `index` of a leaf, returns the digest of its leaf sibling - pub fn get_leaf_sibling_hash(&self, index: usize) -> P::LeafDigest{ + pub fn get_leaf_sibling_hash(&self, index: usize) -> P::LeafDigest { if index & 1 == 0 { // leaf is left child self.leaf_nodes[index + 1].clone() @@ -578,7 +578,6 @@ impl MerkleTree

{ let mut prev_path = Vec::new(); for index in &indexes { - leaf_siblings_hashes.push(self.get_leaf_sibling_hash(*index)); let path = self.compute_auth_path(*index); From 13b259375f15c76a84af42f4d598afbb1260f0f9 Mon Sep 17 00:00:00 2001 From: intx4 Date: Wed, 24 Jan 2024 11:19:25 +0100 Subject: [PATCH 30/36] changed multiproof.verify to use "insert_with" instead of "insert" (this solves a bug where hashes were computed no matter what). This makes the lut optimization effective --- src/merkle_tree/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index 50653b63..898fd223 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -278,11 +278,11 @@ impl MultiPath

{ let mut curr_path_node = hash_lut .entry(index_in_tree) - .or_insert(P::TwoToOneHash::evaluate( + .or_insert_with(|| P::TwoToOneHash::evaluate( &two_to_one_params, left_child, right_child, - )?); + ).unwrap()); // Check levels between leaf level and root for level in (0..auth_path.len()).rev() { @@ -294,7 +294,7 @@ impl MultiPath

{ index_in_tree = parent(index_in_tree).unwrap(); curr_path_node = hash_lut .entry(index_in_tree) - .or_insert(P::TwoToOneHash::compress(&two_to_one_params, left, right)?); + .or_insert_with(|| P::TwoToOneHash::compress(&two_to_one_params, left, right).unwrap()); } // check if final hash is root From c4cd0af2bcd0f16e880d94e783ca98cf165813c2 Mon Sep 17 00:00:00 2001 From: intx4 Date: Wed, 24 Jan 2024 11:22:45 +0100 Subject: [PATCH 31/36] cargo fmt --- src/merkle_tree/mod.rs | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index 898fd223..cea8f242 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -275,14 +275,9 @@ impl MultiPath

{ index >>= 1; index_in_tree = parent(index_in_tree).unwrap(); - let mut curr_path_node = - hash_lut - .entry(index_in_tree) - .or_insert_with(|| P::TwoToOneHash::evaluate( - &two_to_one_params, - left_child, - right_child, - ).unwrap()); + let mut curr_path_node = hash_lut.entry(index_in_tree).or_insert_with(|| { + P::TwoToOneHash::evaluate(&two_to_one_params, left_child, right_child).unwrap() + }); // Check levels between leaf level and root for level in (0..auth_path.len()).rev() { @@ -292,9 +287,9 @@ impl MultiPath

{ // update curr_path_node index >>= 1; index_in_tree = parent(index_in_tree).unwrap(); - curr_path_node = hash_lut - .entry(index_in_tree) - .or_insert_with(|| P::TwoToOneHash::compress(&two_to_one_params, left, right).unwrap()); + curr_path_node = hash_lut.entry(index_in_tree).or_insert_with(|| { + P::TwoToOneHash::compress(&two_to_one_params, left, right).unwrap() + }); } // check if final hash is root From 1537337370089dc392589384e4b939a6de008b26 Mon Sep 17 00:00:00 2001 From: Cesar199999 Date: Sat, 23 Mar 2024 16:24:19 +0100 Subject: [PATCH 32/36] Use iterators in prefix_encode_path --- crypto-primitives/src/merkle_tree/mod.rs | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/crypto-primitives/src/merkle_tree/mod.rs b/crypto-primitives/src/merkle_tree/mod.rs index 96253dd5..a20f08ae 100644 --- a/crypto-primitives/src/merkle_tree/mod.rs +++ b/crypto-primitives/src/merkle_tree/mod.rs @@ -760,25 +760,19 @@ fn convert_index_to_last_level(index: usize, tree_height: usize) -> usize { /// Example: /// If `prev_path` is vec![C,D] and `path` is vec![C,E] (where C,D,E are hashes) /// `prefix_encode_path` returns 1,vec![E] + #[inline] fn prefix_encode_path(prev_path: &Vec, path: &Vec) -> (usize, Vec) where T: Eq + Clone, { - let mut prefix_len = 0; - if prev_path.len() != 0 && path.len() != 0 { - while prev_path[prefix_len] == path[prefix_len] { - prefix_len += 1; - if prefix_len == prev_path.len() || prefix_len == path.len() { - break; - } - } - } - if prefix_len != 0 && prefix_len == prev_path.len() { - return (prefix_len, Vec::new()); - } else { - return (prefix_len, path[prefix_len..].to_vec()); - } + let prefix_length = prev_path + .iter() + .zip(path.iter()) + .take_while(|(a, b)| a == b) + .count(); + + (prefix_length, path[prefix_length..].to_vec()) } fn prefix_decode_path(prev_path: &Vec, prefix_len: usize, suffix: &Vec) -> Vec From b400a405752167637ce1433916ba97835817a923 Mon Sep 17 00:00:00 2001 From: Cesar199999 Date: Sat, 23 Mar 2024 16:39:47 +0100 Subject: [PATCH 33/36] Allow function-specific sample size in merkle tree benches --- crypto-primitives/benches/merkle_tree.rs | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/crypto-primitives/benches/merkle_tree.rs b/crypto-primitives/benches/merkle_tree.rs index 3b375b88..405cbbc5 100644 --- a/crypto-primitives/benches/merkle_tree.rs +++ b/crypto-primitives/benches/merkle_tree.rs @@ -191,10 +191,26 @@ mod bytes_mt_benches { } criterion_group! { - name = mt_benches; + name = mt_create; + config = Criterion::default().sample_size(100); + targets = merkle_tree_create + } + + criterion_group! { + name = mt_proof; + config = Criterion::default().sample_size(100); + targets = merkle_tree_generate_proof, merkle_tree_generate_multi_proof + } + + criterion_group! { + name = mt_verify; config = Criterion::default().sample_size(10); - targets = merkle_tree_create, merkle_tree_generate_proof, merkle_tree_verify_proof, merkle_tree_generate_multi_proof, merkle_tree_verify_multi_proof + targets = merkle_tree_verify_proof, merkle_tree_verify_multi_proof } } -criterion_main!(crate::bytes_mt_benches::mt_benches); +criterion_main!( + bytes_mt_benches::mt_create, + bytes_mt_benches::mt_proof, + bytes_mt_benches::mt_verify +); From 6fdca79e895008924e82e5f31098c873edf5f59b Mon Sep 17 00:00:00 2001 From: intx4 Date: Mon, 25 Mar 2024 21:50:27 +0100 Subject: [PATCH 34/36] removed redundant imports (nightly build tests) --- .../src/commitment/blake2s/constraints.rs | 1 - .../src/commitment/pedersen/constraints.rs | 1 - .../src/commitment/pedersen/mod.rs | 2 +- .../src/crh/bowe_hopwood/constraints.rs | 16 +++++--------- crypto-primitives/src/crh/bowe_hopwood/mod.rs | 2 +- .../src/crh/injective_map/constraints.rs | 4 +--- .../src/crh/pedersen/constraints.rs | 9 +++----- crypto-primitives/src/crh/pedersen/mod.rs | 2 +- .../src/crh/poseidon/constraints.rs | 1 + .../src/crh/sha256/constraints.rs | 12 ++-------- crypto-primitives/src/crh/sha256/mod.rs | 2 +- .../src/encryption/elgamal/constraints.rs | 2 +- .../src/merkle_tree/constraints.rs | 1 - crypto-primitives/src/merkle_tree/mod.rs | 1 - .../src/merkle_tree/tests/mod.rs | 9 +++----- .../src/prf/blake2s/constraints.rs | 2 +- crypto-primitives/src/prf/blake2s/mod.rs | 1 - crypto-primitives/src/prf/constraints.rs | 2 +- crypto-primitives/src/signature/mod.rs | 4 ++-- .../src/signature/schnorr/constraints.rs | 1 - .../src/signature/schnorr/mod.rs | 2 +- crypto-primitives/src/snark/constraints.rs | 22 ++++++------------- crypto-primitives/src/sponge/absorb.rs | 5 ++--- .../src/sponge/constraints/absorb.rs | 3 +-- .../src/sponge/constraints/mod.rs | 3 +-- crypto-primitives/src/sponge/mod.rs | 1 - .../src/sponge/poseidon/constraints.rs | 2 -- .../src/sponge/poseidon/grain_lfsr.rs | 2 +- crypto-primitives/src/sponge/poseidon/mod.rs | 3 +-- .../src/sponge/poseidon/traits.rs | 3 +-- 30 files changed, 39 insertions(+), 82 deletions(-) diff --git a/crypto-primitives/src/commitment/blake2s/constraints.rs b/crypto-primitives/src/commitment/blake2s/constraints.rs index f38b7378..07f28ca8 100644 --- a/crypto-primitives/src/commitment/blake2s/constraints.rs +++ b/crypto-primitives/src/commitment/blake2s/constraints.rs @@ -3,7 +3,6 @@ use ark_relations::r1cs::{Namespace, SynthesisError}; use crate::{ commitment::{blake2s, CommitmentGadget}, prf::blake2s::constraints::{evaluate_blake2s, OutputVar}, - Vec, }; use ark_ff::{Field, PrimeField}; use ark_r1cs_std::prelude::*; diff --git a/crypto-primitives/src/commitment/pedersen/constraints.rs b/crypto-primitives/src/commitment/pedersen/constraints.rs index f077e295..8386815d 100644 --- a/crypto-primitives/src/commitment/pedersen/constraints.rs +++ b/crypto-primitives/src/commitment/pedersen/constraints.rs @@ -1,7 +1,6 @@ use crate::{ commitment::pedersen::{Commitment, Parameters, Randomness}, crh::pedersen::Window, - Vec, }; use ark_ec::CurveGroup; use ark_ff::{ diff --git a/crypto-primitives/src/commitment/pedersen/mod.rs b/crypto-primitives/src/commitment/pedersen/mod.rs index 6782e9c6..cfcdab74 100644 --- a/crypto-primitives/src/commitment/pedersen/mod.rs +++ b/crypto-primitives/src/commitment/pedersen/mod.rs @@ -1,4 +1,4 @@ -use crate::{crh::CRHScheme, Error, Vec}; +use crate::{crh::CRHScheme, Error}; use ark_ec::CurveGroup; use ark_ff::{BitIteratorLE, Field, PrimeField, ToConstraintField}; use ark_serialize::CanonicalSerialize; diff --git a/crypto-primitives/src/crh/bowe_hopwood/constraints.rs b/crypto-primitives/src/crh/bowe_hopwood/constraints.rs index e1f6f487..e5eef789 100644 --- a/crypto-primitives/src/crh/bowe_hopwood/constraints.rs +++ b/crypto-primitives/src/crh/bowe_hopwood/constraints.rs @@ -2,22 +2,16 @@ use ark_ec::twisted_edwards::{Projective as TEProjective, TECurveConfig}; use ark_ec::CurveConfig; use core::{borrow::Borrow, iter, marker::PhantomData}; -use crate::{ - crh::{ - bowe_hopwood::{Parameters, CHUNK_SIZE}, - pedersen::{self, Window}, - CRHSchemeGadget, TwoToOneCRHSchemeGadget, - }, - Vec, +use crate::crh::{ + bowe_hopwood::{Parameters, CHUNK_SIZE}, + pedersen::{self, Window}, + CRHSchemeGadget, TwoToOneCRHSchemeGadget, }; use ark_ff::Field; -use ark_r1cs_std::{ - alloc::AllocVar, groups::curves::twisted_edwards::AffineVar, prelude::*, uint8::UInt8, -}; +use ark_r1cs_std::{groups::curves::twisted_edwards::AffineVar, prelude::*}; use ark_relations::r1cs::{Namespace, SynthesisError}; use crate::crh::bowe_hopwood::{TwoToOneCRH, CRH}; -use ark_r1cs_std::boolean::Boolean; type ConstraintF

= <

::BaseField as Field>::BasePrimeField; diff --git a/crypto-primitives/src/crh/bowe_hopwood/mod.rs b/crypto-primitives/src/crh/bowe_hopwood/mod.rs index 820727a0..fb2bf0ac 100644 --- a/crypto-primitives/src/crh/bowe_hopwood/mod.rs +++ b/crypto-primitives/src/crh/bowe_hopwood/mod.rs @@ -2,7 +2,7 @@ //! specific Twisted Edwards (TE) curves. See [Section 5.4.17 of the Zcash protocol specification](https://raw.githubusercontent.com/zcash/zips/master/protocol/protocol.pdf#concretepedersenhash) for a formal description of this hash function, specialized for the Jubjub curve. //! The implementation in this repository is generic across choice of TE curves. -use crate::{Error, Vec}; +use crate::Error; use ark_std::rand::Rng; use ark_std::{ fmt::{Debug, Formatter, Result as FmtResult}, diff --git a/crypto-primitives/src/crh/injective_map/constraints.rs b/crypto-primitives/src/crh/injective_map/constraints.rs index 8e9cd703..1a60c842 100644 --- a/crypto-primitives/src/crh/injective_map/constraints.rs +++ b/crypto-primitives/src/crh/injective_map/constraints.rs @@ -14,9 +14,7 @@ use ark_ec::{ }; use ark_ff::fields::{Field, PrimeField}; use ark_r1cs_std::{ - fields::fp::FpVar, - groups::{curves::twisted_edwards::AffineVar as TEVar, CurveVar}, - prelude::*, + fields::fp::FpVar, groups::curves::twisted_edwards::AffineVar as TEVar, prelude::*, }; use ark_relations::r1cs::SynthesisError; diff --git a/crypto-primitives/src/crh/pedersen/constraints.rs b/crypto-primitives/src/crh/pedersen/constraints.rs index fdf2340a..3f64e755 100644 --- a/crypto-primitives/src/crh/pedersen/constraints.rs +++ b/crypto-primitives/src/crh/pedersen/constraints.rs @@ -1,9 +1,6 @@ -use crate::{ - crh::{ - pedersen::{Parameters, Window}, - CRHSchemeGadget as CRHGadgetTrait, - }, - Vec, +use crate::crh::{ + pedersen::{Parameters, Window}, + CRHSchemeGadget as CRHGadgetTrait, }; use ark_ec::CurveGroup; use ark_ff::Field; diff --git a/crypto-primitives/src/crh/pedersen/mod.rs b/crypto-primitives/src/crh/pedersen/mod.rs index eec86e36..97850b86 100644 --- a/crypto-primitives/src/crh/pedersen/mod.rs +++ b/crypto-primitives/src/crh/pedersen/mod.rs @@ -1,4 +1,4 @@ -use crate::{Error, Vec}; +use crate::Error; use ark_std::rand::Rng; use ark_std::{ fmt::{Debug, Formatter, Result as FmtResult}, diff --git a/crypto-primitives/src/crh/poseidon/constraints.rs b/crypto-primitives/src/crh/poseidon/constraints.rs index 9684624c..4e152e7f 100644 --- a/crypto-primitives/src/crh/poseidon/constraints.rs +++ b/crypto-primitives/src/crh/poseidon/constraints.rs @@ -1,4 +1,5 @@ use crate::crh::poseidon::{TwoToOneCRH, CRH}; +use crate::crh::CRHScheme; use crate::crh::{ CRHSchemeGadget as CRHGadgetTrait, TwoToOneCRHSchemeGadget as TwoToOneCRHGadgetTrait, }; diff --git a/crypto-primitives/src/crh/sha256/constraints.rs b/crypto-primitives/src/crh/sha256/constraints.rs index c7080809..bf40c945 100644 --- a/crypto-primitives/src/crh/sha256/constraints.rs +++ b/crypto-primitives/src/crh/sha256/constraints.rs @@ -19,7 +19,6 @@ use ark_r1cs_std::{ R1CSVar, }; use ark_relations::r1cs::{ConstraintSystemRef, Namespace, SynthesisError}; -use ark_std::{vec, vec::Vec}; const STATE_LEN: usize = 8; @@ -383,17 +382,10 @@ where #[cfg(test)] mod test { use super::*; - use crate::crh::{ - sha256::{digest::Digest, Sha256}, - CRHScheme, CRHSchemeGadget, TwoToOneCRHScheme, TwoToOneCRHSchemeGadget, - }; + use crate::crh::{sha256::digest::Digest, CRHScheme, TwoToOneCRHScheme}; use ark_bls12_377::Fr; - use ark_r1cs_std::R1CSVar; - use ark_relations::{ - ns, - r1cs::{ConstraintSystem, Namespace}, - }; + use ark_relations::{ns, r1cs::ConstraintSystem}; use ark_std::rand::RngCore; const TEST_LENGTHS: &[usize] = &[ diff --git a/crypto-primitives/src/crh/sha256/mod.rs b/crypto-primitives/src/crh/sha256/mod.rs index 6010be32..8a2cb1d4 100644 --- a/crypto-primitives/src/crh/sha256/mod.rs +++ b/crypto-primitives/src/crh/sha256/mod.rs @@ -1,5 +1,5 @@ use crate::crh::{CRHScheme, TwoToOneCRHScheme}; -use crate::{Error, Vec}; +use crate::Error; use ark_std::rand::Rng; diff --git a/crypto-primitives/src/encryption/elgamal/constraints.rs b/crypto-primitives/src/encryption/elgamal/constraints.rs index 7527352a..290492d2 100644 --- a/crypto-primitives/src/encryption/elgamal/constraints.rs +++ b/crypto-primitives/src/encryption/elgamal/constraints.rs @@ -11,7 +11,7 @@ use ark_ff::{ Zero, }; use ark_serialize::CanonicalSerialize; -use ark_std::{borrow::Borrow, marker::PhantomData, vec::Vec}; +use ark_std::{borrow::Borrow, marker::PhantomData}; pub type ConstraintF = <::BaseField as Field>::BasePrimeField; diff --git a/crypto-primitives/src/merkle_tree/constraints.rs b/crypto-primitives/src/merkle_tree/constraints.rs index e243079c..4cb764a3 100644 --- a/crypto-primitives/src/merkle_tree/constraints.rs +++ b/crypto-primitives/src/merkle_tree/constraints.rs @@ -6,7 +6,6 @@ use ark_r1cs_std::prelude::*; use ark_relations::r1cs::{Namespace, SynthesisError}; use ark_std::borrow::Borrow; use ark_std::fmt::Debug; -use ark_std::vec::Vec; pub trait DigestVarConverter { type TargetType: Borrow; diff --git a/crypto-primitives/src/merkle_tree/mod.rs b/crypto-primitives/src/merkle_tree/mod.rs index a20f08ae..a5fd30b0 100644 --- a/crypto-primitives/src/merkle_tree/mod.rs +++ b/crypto-primitives/src/merkle_tree/mod.rs @@ -8,7 +8,6 @@ use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_std::borrow::Borrow; use ark_std::collections::{BTreeSet, HashMap}; use ark_std::hash::Hash; -use ark_std::vec::Vec; #[cfg(test)] mod tests; diff --git a/crypto-primitives/src/merkle_tree/tests/mod.rs b/crypto-primitives/src/merkle_tree/tests/mod.rs index 0eae7aad..bd03f443 100644 --- a/crypto-primitives/src/merkle_tree/tests/mod.rs +++ b/crypto-primitives/src/merkle_tree/tests/mod.rs @@ -4,10 +4,7 @@ mod test_utils; mod bytes_mt_tests { - use crate::{ - crh::{pedersen, *}, - merkle_tree::*, - }; + use crate::{crh::*, merkle_tree::*}; use ark_ed_on_bls12_381::EdwardsProjective as JubJub; use ark_ff::BigInteger256; use ark_std::{test_rng, UniformRand}; @@ -190,8 +187,8 @@ mod field_mt_tests { use crate::crh::poseidon; use crate::merkle_tree::tests::test_utils::poseidon_parameters; use crate::merkle_tree::{Config, IdentityDigestConverter, MerkleTree}; - use ark_std::{test_rng, vec::Vec, One, UniformRand}; - + use ark_std::{test_rng, One, UniformRand}; + type F = ark_ed_on_bls12_381::Fr; type H = poseidon::CRH; type TwoToOneH = poseidon::TwoToOneCRH; diff --git a/crypto-primitives/src/prf/blake2s/constraints.rs b/crypto-primitives/src/prf/blake2s/constraints.rs index cd52cf69..fdfd99d7 100644 --- a/crypto-primitives/src/prf/blake2s/constraints.rs +++ b/crypto-primitives/src/prf/blake2s/constraints.rs @@ -1,7 +1,7 @@ use ark_ff::PrimeField; use ark_relations::r1cs::{ConstraintSystemRef, Namespace, SynthesisError}; -use crate::{prf::PRFGadget, Vec}; +use crate::prf::PRFGadget; use ark_r1cs_std::prelude::*; use core::borrow::Borrow; diff --git a/crypto-primitives/src/prf/blake2s/mod.rs b/crypto-primitives/src/prf/blake2s/mod.rs index 7455e18a..b2696c19 100644 --- a/crypto-primitives/src/prf/blake2s/mod.rs +++ b/crypto-primitives/src/prf/blake2s/mod.rs @@ -1,4 +1,3 @@ -use crate::Vec; use blake2::{Blake2s256 as B2s, Blake2sMac}; use digest::Digest; diff --git a/crypto-primitives/src/prf/constraints.rs b/crypto-primitives/src/prf/constraints.rs index bbca88c7..1e09571d 100644 --- a/crypto-primitives/src/prf/constraints.rs +++ b/crypto-primitives/src/prf/constraints.rs @@ -1,7 +1,7 @@ use ark_ff::Field; use core::fmt::Debug; -use crate::{prf::PRF, Vec}; +use crate::prf::PRF; use ark_relations::r1cs::{Namespace, SynthesisError}; use ark_r1cs_std::prelude::*; diff --git a/crypto-primitives/src/signature/mod.rs b/crypto-primitives/src/signature/mod.rs index c7cbddca..1f7cf219 100644 --- a/crypto-primitives/src/signature/mod.rs +++ b/crypto-primitives/src/signature/mod.rs @@ -52,10 +52,10 @@ pub trait SignatureScheme { #[cfg(test)] mod test { - use crate::signature::{schnorr, *}; + use crate::signature::*; use ark_ec::AdditiveGroup; use ark_ed_on_bls12_381::EdwardsProjective as JubJub; - use ark_std::{test_rng, vec::Vec, UniformRand}; + use ark_std::{test_rng, UniformRand}; use blake2::Blake2s256 as Blake2s; fn sign_and_verify(message: &[u8]) { diff --git a/crypto-primitives/src/signature/schnorr/constraints.rs b/crypto-primitives/src/signature/schnorr/constraints.rs index 0f663825..7d19ecc1 100644 --- a/crypto-primitives/src/signature/schnorr/constraints.rs +++ b/crypto-primitives/src/signature/schnorr/constraints.rs @@ -1,4 +1,3 @@ -use crate::Vec; use ark_ec::CurveGroup; use ark_ff::Field; use ark_r1cs_std::prelude::*; diff --git a/crypto-primitives/src/signature/schnorr/mod.rs b/crypto-primitives/src/signature/schnorr/mod.rs index e0584c44..c8c3cf75 100644 --- a/crypto-primitives/src/signature/schnorr/mod.rs +++ b/crypto-primitives/src/signature/schnorr/mod.rs @@ -1,4 +1,4 @@ -use crate::{signature::SignatureScheme, Error, Vec}; +use crate::{signature::SignatureScheme, Error}; use ark_ec::{AffineRepr, CurveGroup}; use ark_ff::{ fields::{Field, PrimeField}, diff --git a/crypto-primitives/src/snark/constraints.rs b/crypto-primitives/src/snark/constraints.rs index 66419198..ba1ef909 100644 --- a/crypto-primitives/src/snark/constraints.rs +++ b/crypto-primitives/src/snark/constraints.rs @@ -1,15 +1,12 @@ use ark_ff::{BigInteger, PrimeField}; -use ark_r1cs_std::prelude::*; -use ark_r1cs_std::{ - fields::{ - emulated_fp::{ - params::{get_params, OptimizationType}, - AllocatedEmulatedFpVar, EmulatedFpVar, - }, - fp::{AllocatedFp, FpVar}, +use ark_r1cs_std::fields::{ + emulated_fp::{ + params::{get_params, OptimizationType}, + AllocatedEmulatedFpVar, EmulatedFpVar, }, - R1CSVar, + fp::{AllocatedFp, FpVar}, }; +use ark_r1cs_std::prelude::*; use ark_relations::r1cs::OptimizationGoal; use ark_relations::{ lc, ns, @@ -18,12 +15,7 @@ use ark_relations::{ }, }; use ark_snark::{CircuitSpecificSetupSNARK, UniversalSetupSNARK, SNARK}; -use ark_std::{ - borrow::Borrow, - fmt, - marker::PhantomData, - vec::{IntoIter, Vec}, -}; +use ark_std::{borrow::Borrow, fmt, marker::PhantomData, vec::IntoIter}; /// This implements constraints for SNARK verifiers. pub trait SNARKGadget> { diff --git a/crypto-primitives/src/sponge/absorb.rs b/crypto-primitives/src/sponge/absorb.rs index ed98bf1d..85241d9f 100644 --- a/crypto-primitives/src/sponge/absorb.rs +++ b/crypto-primitives/src/sponge/absorb.rs @@ -7,8 +7,7 @@ use ark_ec::{ use ark_ff::models::{Fp, FpConfig}; use ark_ff::{BigInteger, Field, PrimeField, ToConstraintField}; use ark_serialize::CanonicalSerialize; -use ark_std::string::String; -use ark_std::vec::Vec; + pub use ark_crypto_primitives_macros::*; @@ -389,7 +388,7 @@ mod tests { use crate::sponge::Absorb; use crate::sponge::{field_cast, CryptographicSponge}; use ark_ff::PrimeField; - use ark_std::{test_rng, vec::Vec, UniformRand}; + use ark_std::{test_rng, UniformRand}; #[test] fn test_cast() { diff --git a/crypto-primitives/src/sponge/constraints/absorb.rs b/crypto-primitives/src/sponge/constraints/absorb.rs index 58779a02..fa943cdf 100644 --- a/crypto-primitives/src/sponge/constraints/absorb.rs +++ b/crypto-primitives/src/sponge/constraints/absorb.rs @@ -13,8 +13,7 @@ use ark_r1cs_std::groups::curves::short_weierstrass::{ use ark_r1cs_std::groups::curves::twisted_edwards::AffineVar as TEAffineVar; use ark_r1cs_std::uint8::UInt8; use ark_relations::r1cs::SynthesisError; -use ark_std::vec; -use ark_std::vec::Vec; + /// An interface for objects that can be absorbed by a `CryptographicSpongeVar` whose constraint field /// is `CF`. pub trait AbsorbGadget { diff --git a/crypto-primitives/src/sponge/constraints/mod.rs b/crypto-primitives/src/sponge/constraints/mod.rs index 0d29efe9..ea4311d0 100644 --- a/crypto-primitives/src/sponge/constraints/mod.rs +++ b/crypto-primitives/src/sponge/constraints/mod.rs @@ -9,8 +9,7 @@ use ark_r1cs_std::uint8::UInt8; use ark_r1cs_std::R1CSVar; use ark_relations::lc; use ark_relations::r1cs::{ConstraintSystemRef, LinearCombination, SynthesisError}; -use ark_std::vec; -use ark_std::vec::Vec; + mod absorb; pub use absorb::*; diff --git a/crypto-primitives/src/sponge/mod.rs b/crypto-primitives/src/sponge/mod.rs index bd8a1d92..e0c84744 100644 --- a/crypto-primitives/src/sponge/mod.rs +++ b/crypto-primitives/src/sponge/mod.rs @@ -1,6 +1,5 @@ use ark_ff::PrimeField; use ark_std::vec; -use ark_std::vec::Vec; /// Infrastructure for the constraints counterparts. #[cfg(feature = "r1cs")] diff --git a/crypto-primitives/src/sponge/poseidon/constraints.rs b/crypto-primitives/src/sponge/poseidon/constraints.rs index 8cbec6d2..276ed0e0 100644 --- a/crypto-primitives/src/sponge/poseidon/constraints.rs +++ b/crypto-primitives/src/sponge/poseidon/constraints.rs @@ -7,8 +7,6 @@ use ark_ff::PrimeField; use ark_r1cs_std::fields::fp::FpVar; use ark_r1cs_std::prelude::*; use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError}; -use ark_std::vec; -use ark_std::vec::Vec; #[derive(Clone)] /// the gadget for Poseidon sponge diff --git a/crypto-primitives/src/sponge/poseidon/grain_lfsr.rs b/crypto-primitives/src/sponge/poseidon/grain_lfsr.rs index 41b83c65..ee9dff06 100644 --- a/crypto-primitives/src/sponge/poseidon/grain_lfsr.rs +++ b/crypto-primitives/src/sponge/poseidon/grain_lfsr.rs @@ -1,7 +1,7 @@ #![allow(dead_code)] use ark_ff::{BigInteger, PrimeField}; -use ark_std::vec::Vec; + pub struct PoseidonGrainLFSR { pub prime_num_bits: u64, diff --git a/crypto-primitives/src/sponge/poseidon/mod.rs b/crypto-primitives/src/sponge/poseidon/mod.rs index 69dd01ff..11c2cb80 100644 --- a/crypto-primitives/src/sponge/poseidon/mod.rs +++ b/crypto-primitives/src/sponge/poseidon/mod.rs @@ -5,8 +5,7 @@ use crate::sponge::{ use ark_ff::{BigInteger, PrimeField}; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_std::any::TypeId; -use ark_std::vec; -use ark_std::vec::Vec; + /// constraints for Poseidon #[cfg(feature = "r1cs")] diff --git a/crypto-primitives/src/sponge/poseidon/traits.rs b/crypto-primitives/src/sponge/poseidon/traits.rs index 1e85214c..237f8732 100644 --- a/crypto-primitives/src/sponge/poseidon/traits.rs +++ b/crypto-primitives/src/sponge/poseidon/traits.rs @@ -1,7 +1,6 @@ use crate::sponge::poseidon::grain_lfsr::PoseidonGrainLFSR; use crate::sponge::poseidon::PoseidonConfig; -use ark_ff::{fields::models::*, FpConfig, PrimeField}; -use ark_std::{vec, vec::Vec}; +use ark_ff::{fields::models::*, PrimeField}; /// An entry in the default Poseidon parameters pub struct PoseidonDefaultConfigEntry { From 98efb10789e2da6d5f832be4cd08014b566f4191 Mon Sep 17 00:00:00 2001 From: intx4 Date: Mon, 25 Mar 2024 21:51:51 +0100 Subject: [PATCH 35/36] cargo fmt --- crypto-primitives/src/merkle_tree/tests/mod.rs | 2 +- crypto-primitives/src/sponge/absorb.rs | 1 - crypto-primitives/src/sponge/constraints/mod.rs | 1 - crypto-primitives/src/sponge/poseidon/grain_lfsr.rs | 1 - crypto-primitives/src/sponge/poseidon/mod.rs | 1 - 5 files changed, 1 insertion(+), 5 deletions(-) diff --git a/crypto-primitives/src/merkle_tree/tests/mod.rs b/crypto-primitives/src/merkle_tree/tests/mod.rs index bd03f443..a2815f57 100644 --- a/crypto-primitives/src/merkle_tree/tests/mod.rs +++ b/crypto-primitives/src/merkle_tree/tests/mod.rs @@ -188,7 +188,7 @@ mod field_mt_tests { use crate::merkle_tree::tests::test_utils::poseidon_parameters; use crate::merkle_tree::{Config, IdentityDigestConverter, MerkleTree}; use ark_std::{test_rng, One, UniformRand}; - + type F = ark_ed_on_bls12_381::Fr; type H = poseidon::CRH; type TwoToOneH = poseidon::TwoToOneCRH; diff --git a/crypto-primitives/src/sponge/absorb.rs b/crypto-primitives/src/sponge/absorb.rs index 85241d9f..eb154515 100644 --- a/crypto-primitives/src/sponge/absorb.rs +++ b/crypto-primitives/src/sponge/absorb.rs @@ -8,7 +8,6 @@ use ark_ff::models::{Fp, FpConfig}; use ark_ff::{BigInteger, Field, PrimeField, ToConstraintField}; use ark_serialize::CanonicalSerialize; - pub use ark_crypto_primitives_macros::*; /// An interface for objects that can be absorbed by a `CryptographicSponge`. diff --git a/crypto-primitives/src/sponge/constraints/mod.rs b/crypto-primitives/src/sponge/constraints/mod.rs index ea4311d0..889f733f 100644 --- a/crypto-primitives/src/sponge/constraints/mod.rs +++ b/crypto-primitives/src/sponge/constraints/mod.rs @@ -10,7 +10,6 @@ use ark_r1cs_std::R1CSVar; use ark_relations::lc; use ark_relations::r1cs::{ConstraintSystemRef, LinearCombination, SynthesisError}; - mod absorb; pub use absorb::*; diff --git a/crypto-primitives/src/sponge/poseidon/grain_lfsr.rs b/crypto-primitives/src/sponge/poseidon/grain_lfsr.rs index ee9dff06..1cda4f71 100644 --- a/crypto-primitives/src/sponge/poseidon/grain_lfsr.rs +++ b/crypto-primitives/src/sponge/poseidon/grain_lfsr.rs @@ -2,7 +2,6 @@ use ark_ff::{BigInteger, PrimeField}; - pub struct PoseidonGrainLFSR { pub prime_num_bits: u64, diff --git a/crypto-primitives/src/sponge/poseidon/mod.rs b/crypto-primitives/src/sponge/poseidon/mod.rs index 11c2cb80..26349b0b 100644 --- a/crypto-primitives/src/sponge/poseidon/mod.rs +++ b/crypto-primitives/src/sponge/poseidon/mod.rs @@ -6,7 +6,6 @@ use ark_ff::{BigInteger, PrimeField}; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_std::any::TypeId; - /// constraints for Poseidon #[cfg(feature = "r1cs")] pub mod constraints; From d6059c6fc2c46a936115ed9c907b6743b55e51ce Mon Sep 17 00:00:00 2001 From: intx4 Date: Mon, 25 Mar 2024 21:55:39 +0100 Subject: [PATCH 36/36] nightly build fix --- crypto-primitives/src/crh/injective_map/mod.rs | 1 - crypto-primitives/src/crh/poseidon/constraints.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/crypto-primitives/src/crh/injective_map/mod.rs b/crypto-primitives/src/crh/injective_map/mod.rs index fbd99fd1..4927852a 100644 --- a/crypto-primitives/src/crh/injective_map/mod.rs +++ b/crypto-primitives/src/crh/injective_map/mod.rs @@ -9,7 +9,6 @@ use ark_ec::{ }; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_std::borrow::Borrow; -use ark_std::vec::Vec; #[cfg(feature = "r1cs")] pub mod constraints; diff --git a/crypto-primitives/src/crh/poseidon/constraints.rs b/crypto-primitives/src/crh/poseidon/constraints.rs index 4e152e7f..a0ad5001 100644 --- a/crypto-primitives/src/crh/poseidon/constraints.rs +++ b/crypto-primitives/src/crh/poseidon/constraints.rs @@ -6,7 +6,6 @@ use crate::crh::{ use crate::sponge::constraints::CryptographicSpongeVar; use crate::sponge::poseidon::constraints::PoseidonSpongeVar; use crate::sponge::poseidon::PoseidonConfig; -use crate::{crh::CRHScheme, Vec}; use crate::sponge::Absorb; use ark_ff::PrimeField;