diff --git a/CHANGELOG.md b/CHANGELOG.md index 461680b..ff66e1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.4.0 (2023-04-21) + +- Exported `MmrProof` from the crate (#137). +- Allowed merging of leaves in `MerkleStore` (#138). +- [BREAKING] Refactored how existing data structures are added to `MerkleStore` (#139). + ## 0.3.0 (2023-04-08) - Added `depth` parameter to SMT constructors in `MerkleStore` (#115). diff --git a/Cargo.toml b/Cargo.toml index 13fc97f..9b1555f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "miden-crypto" -version = "0.3.0" +version = "0.4.0" description = "Miden Cryptographic primitives" authors = ["miden contributors"] readme = "README.md" license = "MIT" repository = "https://github.com/0xPolygonMiden/crypto" -documentation = "https://docs.rs/miden-crypto/0.3.0" +documentation = "https://docs.rs/miden-crypto/0.4.0" categories = ["cryptography", "no-std"] keywords = ["miden", "crypto", "hash", "merkle"] edition = "2021" diff --git a/benches/hash.rs b/benches/hash.rs index ef0680d..271c1f5 100644 --- a/benches/hash.rs +++ b/benches/hash.rs @@ -106,11 +106,5 @@ fn blake3_sequential(c: &mut Criterion) { }); } -criterion_group!( - hash_group, - rpo256_2to1, - rpo256_sequential, - blake3_2to1, - blake3_sequential -); +criterion_group!(hash_group, rpo256_2to1, rpo256_sequential, blake3_2to1, blake3_sequential); criterion_main!(hash_group); diff --git a/benches/smt.rs b/benches/smt.rs index a19c4d2..3c63c04 100644 --- a/benches/smt.rs +++ b/benches/smt.rs @@ -75,10 +75,5 @@ criterion_main!(smt_group); fn generate_word(seed: &mut [u8; 32]) -> Word { swap(seed, &mut prng_array(*seed)); let nums: [u64; 4] = prng_array(*seed); - [ - Felt::new(nums[0]), - Felt::new(nums[1]), - Felt::new(nums[2]), - Felt::new(nums[3]), - ] + [Felt::new(nums[0]), Felt::new(nums[1]), Felt::new(nums[2]), Felt::new(nums[3])] } diff --git a/benches/store.rs b/benches/store.rs index 804faa6..3ad79c4 100644 --- a/benches/store.rs +++ b/benches/store.rs @@ -34,7 +34,7 @@ fn get_empty_leaf_simplesmt(c: &mut Criterion) { // both SMT and the store are pre-populated with empty hashes, accessing these values is what is // being benchmarked here, so no values are inserted into the backends let smt = SimpleSmt::new(depth).unwrap(); - let store = MerkleStore::new(); + let store = MerkleStore::from(&smt); let root = smt.root(); group.bench_function(BenchmarkId::new("SimpleSmt", depth), |b| { @@ -66,7 +66,7 @@ fn get_leaf_merkletree(c: &mut Criterion) { let mtree_leaves: Vec = leaves.iter().map(|v| v.into()).collect(); let mtree = MerkleTree::new(mtree_leaves.clone()).unwrap(); - let store = MerkleStore::new().with_merkle_tree(mtree_leaves).unwrap(); + let store = MerkleStore::from(&mtree); let depth = mtree.depth(); let root = mtree.root(); let size_u64 = size as u64; @@ -108,9 +108,7 @@ fn get_leaf_simplesmt(c: &mut Criterion) { .unwrap() .with_leaves(smt_leaves.clone()) .unwrap(); - let store = MerkleStore::new() - .with_sparse_merkle_tree(SimpleSmt::MAX_DEPTH, smt_leaves) - .unwrap(); + let store = MerkleStore::from(&smt); let depth = smt.depth(); let root = smt.root(); let size_u64 = size as u64; @@ -143,7 +141,7 @@ fn get_node_of_empty_simplesmt(c: &mut Criterion) { // of these values is what is being benchmarked here, so no values are inserted into the // backends. let smt = SimpleSmt::new(depth).unwrap(); - let store = MerkleStore::new(); + let store = MerkleStore::from(&smt); let root = smt.root(); let half_depth = depth / 2; let half_size = 2_u64.pow(half_depth as u32); @@ -178,7 +176,7 @@ fn get_node_merkletree(c: &mut Criterion) { let mtree_leaves: Vec = leaves.iter().map(|v| v.into()).collect(); let mtree = MerkleTree::new(mtree_leaves.clone()).unwrap(); - let store = MerkleStore::new().with_merkle_tree(mtree_leaves).unwrap(); + let store = MerkleStore::from(&mtree); let root = mtree.root(); let half_depth = mtree.depth() / 2; let half_size = 2_u64.pow(half_depth as u32); @@ -221,9 +219,7 @@ fn get_node_simplesmt(c: &mut Criterion) { .unwrap() .with_leaves(smt_leaves.clone()) .unwrap(); - let store = MerkleStore::new() - .with_sparse_merkle_tree(SimpleSmt::MAX_DEPTH, smt_leaves) - .unwrap(); + let store = MerkleStore::from(&smt); let root = smt.root(); let half_depth = smt.depth() / 2; let half_size = 2_u64.pow(half_depth as u32); @@ -258,7 +254,7 @@ fn get_leaf_path_merkletree(c: &mut Criterion) { let mtree_leaves: Vec = leaves.iter().map(|v| v.into()).collect(); let mtree = MerkleTree::new(mtree_leaves.clone()).unwrap(); - let store = MerkleStore::new().with_merkle_tree(mtree_leaves).unwrap(); + let store = MerkleStore::from(&mtree); let depth = mtree.depth(); let root = mtree.root(); let size_u64 = size as u64; @@ -300,9 +296,7 @@ fn get_leaf_path_simplesmt(c: &mut Criterion) { .unwrap() .with_leaves(smt_leaves.clone()) .unwrap(); - let store = MerkleStore::new() - .with_sparse_merkle_tree(SimpleSmt::MAX_DEPTH, smt_leaves) - .unwrap(); + let store = MerkleStore::from(&smt); let depth = smt.depth(); let root = smt.root(); let size_u64 = size as u64; @@ -347,16 +341,16 @@ fn new(c: &mut Criterion) { // This could be done with `bench_with_input`, however to remove variables while comparing // with MerkleTree it is using `iter_batched` - group.bench_function( - BenchmarkId::new("MerkleStore::with_merkle_tree", size), - |b| { - b.iter_batched( - || leaves.iter().map(|v| v.into()).collect::>(), - |l| black_box(MerkleStore::new().with_merkle_tree(l)), - BatchSize::SmallInput, - ) - }, - ); + group.bench_function(BenchmarkId::new("MerkleStore::extend::MerkleTree", size), |b| { + b.iter_batched( + || leaves.iter().map(|v| v.into()).collect::>(), + |l| { + let mtree = MerkleTree::new(l).unwrap(); + black_box(MerkleStore::from(&mtree)); + }, + BatchSize::SmallInput, + ) + }); group.bench_function(BenchmarkId::new("SimpleSmt::new", size), |b| { b.iter_batched( @@ -372,26 +366,22 @@ fn new(c: &mut Criterion) { ) }); - group.bench_function( - BenchmarkId::new("MerkleStore::with_sparse_merkle_tree", size), - |b| { - b.iter_batched( - || { - leaves - .iter() - .enumerate() - .map(|(c, v)| (c.try_into().unwrap(), v.into())) - .collect::>() - }, - |l| { - black_box( - MerkleStore::new().with_sparse_merkle_tree(SimpleSmt::MAX_DEPTH, l), - ) - }, - BatchSize::SmallInput, - ) - }, - ); + group.bench_function(BenchmarkId::new("MerkleStore::extend::SimpleSmt", size), |b| { + b.iter_batched( + || { + leaves + .iter() + .enumerate() + .map(|(c, v)| (c.try_into().unwrap(), v.into())) + .collect::>() + }, + |l| { + let smt = SimpleSmt::new(SimpleSmt::MAX_DEPTH).unwrap().with_leaves(l).unwrap(); + black_box(MerkleStore::from(&smt)); + }, + BatchSize::SmallInput, + ) + }); } } @@ -407,7 +397,7 @@ fn update_leaf_merkletree(c: &mut Criterion) { let mtree_leaves: Vec = leaves.iter().map(|v| v.into()).collect(); let mut mtree = MerkleTree::new(mtree_leaves.clone()).unwrap(); - let mut store = MerkleStore::new().with_merkle_tree(mtree_leaves).unwrap(); + let mut store = MerkleStore::from(&mtree); let depth = mtree.depth(); let root = mtree.root(); let size_u64 = size as u64; @@ -456,9 +446,7 @@ fn update_leaf_simplesmt(c: &mut Criterion) { .unwrap() .with_leaves(smt_leaves.clone()) .unwrap(); - let mut store = MerkleStore::new() - .with_sparse_merkle_tree(SimpleSmt::MAX_DEPTH, smt_leaves) - .unwrap(); + let mut store = MerkleStore::from(&smt); let depth = smt.depth(); let root = smt.root(); let size_u64 = size as u64; diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..93e66a1 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,20 @@ +edition = "2021" +array_width = 80 +attr_fn_like_width = 80 +chain_width = 80 +#condense_wildcard_suffixes = true +#enum_discrim_align_threshold = 40 +fn_call_width = 80 +#fn_single_line = true +#format_code_in_doc_comments = true +#format_macro_matchers = true +#format_strings = true +#group_imports = "StdExternalCrate" +#hex_literal_case = "Lower" +#imports_granularity = "Crate" +newline_style = "Unix" +#normalize_doc_attributes = true +#reorder_impl_items = true +single_line_if_else_max_width = 60 +use_field_init_shorthand = true +use_try_shorthand = true diff --git a/src/hash/blake/mod.rs b/src/hash/blake/mod.rs index a3bcfd0..91c9bca 100644 --- a/src/hash/blake/mod.rs +++ b/src/hash/blake/mod.rs @@ -270,10 +270,7 @@ impl Blake3_160 { /// Zero-copy ref shrink to array. fn shrink_bytes(bytes: &[u8; M]) -> &[u8; N] { // compile-time assertion - assert!( - M >= N, - "N should fit in M so it can be safely transmuted into a smaller slice!" - ); + assert!(M >= N, "N should fit in M so it can be safely transmuted into a smaller slice!"); // safety: bytes len is asserted unsafe { transmute(bytes) } } diff --git a/src/hash/rpo/digest.rs b/src/hash/rpo/digest.rs index 92f2a15..2edfd27 100644 --- a/src/hash/rpo/digest.rs +++ b/src/hash/rpo/digest.rs @@ -118,14 +118,13 @@ impl Ord for RpoDigest { // finally, we use `Felt::inner` instead of `Felt::as_int` so we avoid performing a // montgomery reduction for every limb. that is safe because every inner element of the // digest is guaranteed to be in its canonical form (that is, `x in [0,p)`). - self.0 - .iter() - .map(Felt::inner) - .zip(other.0.iter().map(Felt::inner)) - .fold(Ordering::Equal, |ord, (a, b)| match ord { + self.0.iter().map(Felt::inner).zip(other.0.iter().map(Felt::inner)).fold( + Ordering::Equal, + |ord, (a, b)| match ord { Ordering::Equal => a.cmp(&b), _ => ord, - }) + }, + ) } } diff --git a/src/merkle/index.rs b/src/merkle/index.rs index b4f3bdf..b1c7389 100644 --- a/src/merkle/index.rs +++ b/src/merkle/index.rs @@ -132,10 +132,7 @@ mod tests { #[test] fn test_node_index_value_too_high() { - assert_eq!( - NodeIndex::new(0, 0).unwrap(), - NodeIndex { depth: 0, value: 0 } - ); + assert_eq!(NodeIndex::new(0, 0).unwrap(), NodeIndex { depth: 0, value: 0 }); match NodeIndex::new(0, 1) { Err(MerkleError::InvalidIndex { depth, value }) => { assert_eq!(depth, 0); diff --git a/src/merkle/merkle_tree.rs b/src/merkle/merkle_tree.rs index 3587fc6..42f289a 100644 --- a/src/merkle/merkle_tree.rs +++ b/src/merkle/merkle_tree.rs @@ -109,10 +109,7 @@ impl MerkleTree { index.move_up(); } - debug_assert!( - index.is_root(), - "the path walk must go all the way to the root" - ); + debug_assert!(index.is_root(), "the path walk must go all the way to the root"); Ok(path.into()) } @@ -153,9 +150,11 @@ impl MerkleTree { Ok(()) } - /// An iterator over every inner node in the tree. The iterator order is unspecified. - pub fn inner_nodes(&self) -> MerkleTreeNodes<'_> { - MerkleTreeNodes { + /// Returns n iterator over every inner node of this [MerkleTree]. + /// + /// The iterator order is unspecified. + pub fn inner_nodes(&self) -> InnerNodeIterator<'_> { + InnerNodeIterator { nodes: &self.nodes, index: 1, // index 0 is just padding, start at 1 } @@ -168,12 +167,12 @@ impl MerkleTree { /// An iterator over every inner node of the [MerkleTree]. /// /// Use this to extract the data of the tree, there is no guarantee on the order of the elements. -pub struct MerkleTreeNodes<'a> { +pub struct InnerNodeIterator<'a> { nodes: &'a Vec, index: usize, } -impl<'a> Iterator for MerkleTreeNodes<'a> { +impl<'a> Iterator for InnerNodeIterator<'a> { type Item = InnerNodeInfo; fn next(&mut self) -> Option { @@ -195,6 +194,9 @@ impl<'a> Iterator for MerkleTreeNodes<'a> { } } +// UTILITY FUNCTIONS +// ================================================================================================ + /// Utility to visualize a [MerkleTree] in text. pub fn tree_to_text(tree: &MerkleTree) -> Result { let indent = " "; @@ -248,12 +250,7 @@ mod tests { use core::mem::size_of; use proptest::prelude::*; - const LEAVES4: [Word; 4] = [ - int_to_node(1), - int_to_node(2), - int_to_node(3), - int_to_node(4), - ]; + const LEAVES4: [Word; 4] = [int_to_node(1), int_to_node(2), int_to_node(3), int_to_node(4)]; const LEAVES8: [Word; 8] = [ int_to_node(1), @@ -309,22 +306,10 @@ mod tests { let (_, node2, node3) = compute_internal_nodes(); // check depth 2 - assert_eq!( - vec![LEAVES4[1], node3], - *tree.get_path(NodeIndex::make(2, 0)).unwrap() - ); - assert_eq!( - vec![LEAVES4[0], node3], - *tree.get_path(NodeIndex::make(2, 1)).unwrap() - ); - assert_eq!( - vec![LEAVES4[3], node2], - *tree.get_path(NodeIndex::make(2, 2)).unwrap() - ); - assert_eq!( - vec![LEAVES4[2], node2], - *tree.get_path(NodeIndex::make(2, 3)).unwrap() - ); + assert_eq!(vec![LEAVES4[1], node3], *tree.get_path(NodeIndex::make(2, 0)).unwrap()); + assert_eq!(vec![LEAVES4[0], node3], *tree.get_path(NodeIndex::make(2, 1)).unwrap()); + assert_eq!(vec![LEAVES4[3], node2], *tree.get_path(NodeIndex::make(2, 2)).unwrap()); + assert_eq!(vec![LEAVES4[2], node2], *tree.get_path(NodeIndex::make(2, 3)).unwrap()); // check depth 1 assert_eq!(vec![node3], *tree.get_path(NodeIndex::make(1, 0)).unwrap()); diff --git a/src/merkle/mmr/accumulator.rs b/src/merkle/mmr/accumulator.rs index 2a5d522..610999a 100644 --- a/src/merkle/mmr/accumulator.rs +++ b/src/merkle/mmr/accumulator.rs @@ -54,8 +54,6 @@ impl MmrPeaks { pub fn verify(&self, value: Word, opening: MmrProof) -> bool { let root = &self.peaks[opening.peak_index()]; - opening - .merkle_path - .verify(opening.relative_pos() as u64, value, root) + opening.merkle_path.verify(opening.relative_pos() as u64, value, root) } } diff --git a/src/merkle/mmr/full.rs b/src/merkle/mmr/full.rs index d100f57..6737f7b 100644 --- a/src/merkle/mmr/full.rs +++ b/src/merkle/mmr/full.rs @@ -280,10 +280,7 @@ impl<'a> Iterator for MmrNodes<'a> { type Item = InnerNodeInfo; fn next(&mut self) -> Option { - debug_assert!( - self.last_right.count_ones() <= 1, - "last_right tracks zero or one element" - ); + debug_assert!(self.last_right.count_ones() <= 1, "last_right tracks zero or one element"); // only parent nodes are emitted, remove the single node tree from the forest let target = self.mmr.forest & (usize::MAX << 1); diff --git a/src/merkle/mmr/tests.rs b/src/merkle/mmr/tests.rs index 218a6dd..aca4ff7 100644 --- a/src/merkle/mmr/tests.rs +++ b/src/merkle/mmr/tests.rs @@ -118,9 +118,7 @@ fn test_mmr_simple() { postorder.push(LEAVES[2]); postorder.push(LEAVES[3]); postorder.push(*Rpo256::hash_elements(&[LEAVES[2], LEAVES[3]].concat())); - postorder.push(*Rpo256::hash_elements( - &[postorder[2], postorder[5]].concat(), - )); + postorder.push(*Rpo256::hash_elements(&[postorder[2], postorder[5]].concat())); postorder.push(LEAVES[4]); postorder.push(LEAVES[5]); postorder.push(*Rpo256::hash_elements(&[LEAVES[4], LEAVES[5]].concat())); @@ -201,10 +199,7 @@ fn test_mmr_open() { let h23: Word = Rpo256::hash_elements(&LEAVES[2..4].concat()).into(); // node at pos 7 is the root - assert!( - mmr.open(7).is_err(), - "Element 7 is not in the tree, result should be None" - ); + assert!(mmr.open(7).is_err(), "Element 7 is not in the tree, result should be None"); // node at pos 6 is the root let empty: MerklePath = MerklePath::new(vec![]); @@ -297,41 +292,13 @@ fn test_mmr_open() { #[test] fn test_mmr_get() { let mmr: Mmr = LEAVES.into(); - assert_eq!( - mmr.get(0).unwrap(), - LEAVES[0], - "value at pos 0 must correspond" - ); - assert_eq!( - mmr.get(1).unwrap(), - LEAVES[1], - "value at pos 1 must correspond" - ); - assert_eq!( - mmr.get(2).unwrap(), - LEAVES[2], - "value at pos 2 must correspond" - ); - assert_eq!( - mmr.get(3).unwrap(), - LEAVES[3], - "value at pos 3 must correspond" - ); - assert_eq!( - mmr.get(4).unwrap(), - LEAVES[4], - "value at pos 4 must correspond" - ); - assert_eq!( - mmr.get(5).unwrap(), - LEAVES[5], - "value at pos 5 must correspond" - ); - assert_eq!( - mmr.get(6).unwrap(), - LEAVES[6], - "value at pos 6 must correspond" - ); + assert_eq!(mmr.get(0).unwrap(), LEAVES[0], "value at pos 0 must correspond"); + assert_eq!(mmr.get(1).unwrap(), LEAVES[1], "value at pos 1 must correspond"); + assert_eq!(mmr.get(2).unwrap(), LEAVES[2], "value at pos 2 must correspond"); + assert_eq!(mmr.get(3).unwrap(), LEAVES[3], "value at pos 3 must correspond"); + assert_eq!(mmr.get(4).unwrap(), LEAVES[4], "value at pos 4 must correspond"); + assert_eq!(mmr.get(5).unwrap(), LEAVES[5], "value at pos 5 must correspond"); + assert_eq!(mmr.get(6).unwrap(), LEAVES[6], "value at pos 6 must correspond"); assert!(mmr.get(7).is_err()); } @@ -341,11 +308,7 @@ fn test_mmr_invariants() { for v in 1..=1028 { mmr.add(int_to_node(v)); let accumulator = mmr.accumulator(); - assert_eq!( - v as usize, - mmr.forest(), - "MMR leaf count must increase by one on every add" - ); + assert_eq!(v as usize, mmr.forest(), "MMR leaf count must increase by one on every add"); assert_eq!( v as usize, accumulator.num_leaves, "MMR and its accumulator must match leaves count" @@ -374,41 +337,21 @@ fn test_bit_position_iterator() { assert_eq!(TrueBitPositionIterator::new(0).count(), 0); assert_eq!(TrueBitPositionIterator::new(0).rev().count(), 0); - assert_eq!( - TrueBitPositionIterator::new(1).collect::>(), - vec![0] - ); - assert_eq!( - TrueBitPositionIterator::new(1).rev().collect::>(), - vec![0], - ); + assert_eq!(TrueBitPositionIterator::new(1).collect::>(), vec![0]); + assert_eq!(TrueBitPositionIterator::new(1).rev().collect::>(), vec![0],); - assert_eq!( - TrueBitPositionIterator::new(2).collect::>(), - vec![1] - ); - assert_eq!( - TrueBitPositionIterator::new(2).rev().collect::>(), - vec![1], - ); + assert_eq!(TrueBitPositionIterator::new(2).collect::>(), vec![1]); + assert_eq!(TrueBitPositionIterator::new(2).rev().collect::>(), vec![1],); - assert_eq!( - TrueBitPositionIterator::new(3).collect::>(), - vec![0, 1], - ); - assert_eq!( - TrueBitPositionIterator::new(3).rev().collect::>(), - vec![1, 0], - ); + assert_eq!(TrueBitPositionIterator::new(3).collect::>(), vec![0, 1],); + assert_eq!(TrueBitPositionIterator::new(3).rev().collect::>(), vec![1, 0],); assert_eq!( TrueBitPositionIterator::new(0b11010101).collect::>(), vec![0, 2, 4, 6, 7], ); assert_eq!( - TrueBitPositionIterator::new(0b11010101) - .rev() - .collect::>(), + TrueBitPositionIterator::new(0b11010101).rev().collect::>(), vec![7, 6, 4, 2, 0], ); } @@ -463,10 +406,7 @@ fn test_mmr_hash_peaks() { // minimum length is 16 let mut expected_peaks = [first_peak, second_peak, third_peak].to_vec(); expected_peaks.resize(16, [ZERO; WORD_SIZE]); - assert_eq!( - peaks.hash_peaks(), - *Rpo256::hash_elements(&expected_peaks.as_slice().concat()) - ); + assert_eq!(peaks.hash_peaks(), *Rpo256::hash_elements(&expected_peaks.as_slice().concat())); } #[test] diff --git a/src/merkle/mod.rs b/src/merkle/mod.rs index 4d36577..aca3dde 100644 --- a/src/merkle/mod.rs +++ b/src/merkle/mod.rs @@ -27,7 +27,7 @@ mod simple_smt; pub use simple_smt::SimpleSmt; mod mmr; -pub use mmr::{Mmr, MmrPeaks}; +pub use mmr::{Mmr, MmrPeaks, MmrProof}; mod store; pub use store::MerkleStore; diff --git a/src/merkle/path.rs b/src/merkle/path.rs index 964f6d0..e873d84 100644 --- a/src/merkle/path.rs +++ b/src/merkle/path.rs @@ -1,4 +1,4 @@ -use super::{vec, MerkleError, NodeIndex, Rpo256, Vec, Word}; +use super::{vec, InnerNodeInfo, MerkleError, NodeIndex, Rpo256, Vec, Word}; use core::ops::{Deref, DerefMut}; // MERKLE PATH @@ -22,6 +22,11 @@ impl MerklePath { // PROVIDERS // -------------------------------------------------------------------------------------------- + /// Returns the depth in which this Merkle path proof is valid. + pub fn depth(&self) -> u8 { + self.nodes.len() as u8 + } + /// Computes the merkle root for this opening. pub fn compute_root(&self, index: u64, node: Word) -> Result { let mut index = NodeIndex::new(self.depth(), index)?; @@ -34,11 +39,6 @@ impl MerklePath { Ok(root) } - /// Returns the depth in which this Merkle path proof is valid. - pub fn depth(&self) -> u8 { - self.nodes.len() as u8 - } - /// Verifies the Merkle opening proof towards the provided root. /// /// Returns `true` if `node` exists at `index` in a Merkle tree with `root`. @@ -48,6 +48,20 @@ impl MerklePath { Err(_) => false, } } + + /// Returns an iterator over every inner node of this [MerklePath]. + /// + /// The iteration order is unspecified. + /// + /// # Errors + /// Returns an error if the specified index is not valid for this path. + pub fn inner_nodes(&self, index: u64, node: Word) -> Result { + Ok(InnerNodeIterator { + nodes: &self.nodes, + index: NodeIndex::new(self.depth(), index)?, + value: node, + }) + } } impl From> for MerklePath { @@ -72,6 +86,9 @@ impl DerefMut for MerklePath { } } +// ITERATORS +// ================================================================================================ + impl FromIterator for MerklePath { fn from_iter>(iter: T) -> Self { Self::new(iter.into_iter().collect()) @@ -87,6 +104,39 @@ impl IntoIterator for MerklePath { } } +/// An iterator over internal nodes of a [MerklePath]. +pub struct InnerNodeIterator<'a> { + nodes: &'a Vec, + index: NodeIndex, + value: Word, +} + +impl<'a> Iterator for InnerNodeIterator<'a> { + type Item = InnerNodeInfo; + + fn next(&mut self) -> Option { + if !self.index.is_root() { + let sibling_pos = self.nodes.len() - self.index.depth() as usize; + let (left, right) = if self.index.is_value_odd() { + (self.nodes[sibling_pos], self.value) + } else { + (self.value, self.nodes[sibling_pos]) + }; + + self.value = Rpo256::merge(&[left.into(), right.into()]).into(); + self.index.move_up(); + + Some(InnerNodeInfo { + value: self.value, + left, + right, + }) + } else { + None + } + } +} + // MERKLE PATH CONTAINERS // ================================================================================================ @@ -110,3 +160,25 @@ pub struct RootPath { /// The path from `value` to `root` (exclusive). pub path: MerklePath, } + +// TESTS +// ================================================================================================ + +#[cfg(test)] +mod tests { + use crate::merkle::{int_to_node, MerklePath}; + + #[test] + fn test_inner_nodes() { + let nodes = vec![int_to_node(1), int_to_node(2), int_to_node(3), int_to_node(4)]; + let merkle_path = MerklePath::new(nodes); + + let index = 6; + let node = int_to_node(5); + let root = merkle_path.compute_root(index, node).unwrap(); + + let inner_root = merkle_path.inner_nodes(index, node).unwrap().last().unwrap().value; + + assert_eq!(root, inner_root); + } +} diff --git a/src/merkle/path_set.rs b/src/merkle/path_set.rs index ef3cc48..653fab1 100644 --- a/src/merkle/path_set.rs +++ b/src/merkle/path_set.rs @@ -34,12 +34,10 @@ impl MerklePathSet { where I: IntoIterator, { - paths - .into_iter() - .try_fold(self, |mut set, (index, value, path)| { - set.add_path(index, value, path)?; - Ok(set) - }) + paths.into_iter().try_fold(self, |mut set, (index, value, path)| { + set.add_path(index, value, path)?; + Ok(set) + }) } // PUBLIC ACCESSORS @@ -291,14 +289,9 @@ mod tests { let hash_6 = int_to_node(6); let index = 6_u64; let depth = 3_u8; - let set = MerklePathSet::new(depth) - .with_paths([(index, hash_6, path_6.into())]) - .unwrap(); + let set = MerklePathSet::new(depth).with_paths([(index, hash_6, path_6.into())]).unwrap(); - assert_eq!( - int_to_node(6u64), - set.get_node(NodeIndex::make(depth, index)).unwrap() - ); + assert_eq!(int_to_node(6u64), set.get_node(NodeIndex::make(depth, index)).unwrap()); } #[test] diff --git a/src/merkle/simple_smt/mod.rs b/src/merkle/simple_smt/mod.rs index b9eda8a..1f29fe0 100644 --- a/src/merkle/simple_smt/mod.rs +++ b/src/merkle/simple_smt/mod.rs @@ -131,12 +131,7 @@ impl SimpleSmt { Err(MerkleError::DepthTooBig(index.depth() as u64)) } else if index.depth() == self.depth() { self.get_leaf_node(index.value()) - .or_else(|| { - self.empty_hashes - .get(index.depth() as usize) - .copied() - .map(Word::from) - }) + .or_else(|| self.empty_hashes.get(index.depth() as usize).copied().map(Word::from)) .ok_or(MerkleError::NodeNotInSet(index.value())) } else { let branch_node = self.get_branch_node(&index); @@ -217,11 +212,7 @@ impl SimpleSmt { let is_right = index.is_value_odd(); index.move_up(); let BranchNode { left, right } = self.get_branch_node(&index); - let (left, right) = if is_right { - (left, value) - } else { - (value, right) - }; + let (left, right) = if is_right { (left, value) } else { (value, right) }; self.insert_branch_node(index, left, right); value = Rpo256::merge(&[left, right]); } diff --git a/src/merkle/simple_smt/tests.rs b/src/merkle/simple_smt/tests.rs index 82938d3..582e003 100644 --- a/src/merkle/simple_smt/tests.rs +++ b/src/merkle/simple_smt/tests.rs @@ -8,12 +8,7 @@ use rand_utils::prng_array; const KEYS4: [u64; 4] = [0, 1, 2, 3]; const KEYS8: [u64; 8] = [0, 1, 2, 3, 4, 5, 6, 7]; -const VALUES4: [Word; 4] = [ - int_to_node(1), - int_to_node(2), - int_to_node(3), - int_to_node(4), -]; +const VALUES4: [Word; 4] = [int_to_node(1), int_to_node(2), int_to_node(3), int_to_node(4)]; const VALUES8: [Word; 8] = [ int_to_node(1), @@ -56,8 +51,7 @@ fn build_sparse_tree() { let key = 6; let new_node = int_to_node(7); values[key as usize] = new_node; - smt.insert_leaf(key, new_node) - .expect("Failed to insert leaf"); + smt.insert_leaf(key, new_node).expect("Failed to insert leaf"); let mt2 = MerkleTree::new(values.clone()).unwrap(); assert_eq!(mt2.root(), smt.root()); assert_eq!( @@ -69,8 +63,7 @@ fn build_sparse_tree() { let key = 2; let new_node = int_to_node(3); values[key as usize] = new_node; - smt.insert_leaf(key, new_node) - .expect("Failed to insert leaf"); + smt.insert_leaf(key, new_node).expect("Failed to insert leaf"); let mt3 = MerkleTree::new(values).unwrap(); assert_eq!(mt3.root(), smt.root()); assert_eq!( @@ -116,22 +109,10 @@ fn get_path() { let (_, node2, node3) = compute_internal_nodes(); // check depth 2 - assert_eq!( - vec![VALUES4[1], node3], - *tree.get_path(NodeIndex::make(2, 0)).unwrap() - ); - assert_eq!( - vec![VALUES4[0], node3], - *tree.get_path(NodeIndex::make(2, 1)).unwrap() - ); - assert_eq!( - vec![VALUES4[3], node2], - *tree.get_path(NodeIndex::make(2, 2)).unwrap() - ); - assert_eq!( - vec![VALUES4[2], node2], - *tree.get_path(NodeIndex::make(2, 3)).unwrap() - ); + assert_eq!(vec![VALUES4[1], node3], *tree.get_path(NodeIndex::make(2, 0)).unwrap()); + assert_eq!(vec![VALUES4[0], node3], *tree.get_path(NodeIndex::make(2, 1)).unwrap()); + assert_eq!(vec![VALUES4[3], node2], *tree.get_path(NodeIndex::make(2, 2)).unwrap()); + assert_eq!(vec![VALUES4[2], node2], *tree.get_path(NodeIndex::make(2, 3)).unwrap()); // check depth 1 assert_eq!(vec![node3], *tree.get_path(NodeIndex::make(1, 0)).unwrap()); diff --git a/src/merkle/store/mod.rs b/src/merkle/store/mod.rs index a938c4f..96ca54a 100644 --- a/src/merkle/store/mod.rs +++ b/src/merkle/store/mod.rs @@ -1,7 +1,7 @@ -use super::mmr::{Mmr, MmrPeaks}; +use super::mmr::Mmr; use super::{ - BTreeMap, EmptySubtreeRoots, MerkleError, MerklePath, MerklePathSet, MerkleTree, NodeIndex, - RootPath, Rpo256, RpoDigest, SimpleSmt, ValuePath, Vec, Word, + BTreeMap, EmptySubtreeRoots, InnerNodeInfo, MerkleError, MerklePath, MerklePathSet, MerkleTree, + NodeIndex, RootPath, Rpo256, RpoDigest, SimpleSmt, ValuePath, Vec, Word, }; use crate::utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable}; @@ -47,9 +47,13 @@ pub struct Node { /// // the store is initialized with the SMT empty nodes /// assert_eq!(store.num_internal_nodes(), 255); /// +/// let tree1 = MerkleTree::new(vec![A, B, C, D, E, F, G, H0]).unwrap(); +/// let tree2 = MerkleTree::new(vec![A, B, C, D, E, F, G, H1]).unwrap(); +/// /// // populates the store with two merkle trees, common nodes are shared -/// store.add_merkle_tree([A, B, C, D, E, F, G, H0]); -/// store.add_merkle_tree([A, B, C, D, E, F, G, H1]); +/// store +/// .extend(tree1.inner_nodes()) +/// .extend(tree2.inner_nodes()); /// /// // every leaf except the last are the same /// for i in 0..7 { @@ -111,60 +115,6 @@ impl MerkleStore { MerkleStore { nodes } } - /// Appends the provided merkle tree represented by its `leaves` to the set. - pub fn with_merkle_tree(mut self, leaves: I) -> Result - where - I: IntoIterator, - { - self.add_merkle_tree(leaves)?; - Ok(self) - } - - /// Appends the provided Sparse Merkle tree represented by its `entries` to the set. - /// - /// For more information, check [MerkleStore::add_sparse_merkle_tree]. - pub fn with_sparse_merkle_tree( - mut self, - depth: u8, - entries: R, - ) -> Result - where - R: IntoIterator, - I: Iterator + ExactSizeIterator, - { - self.add_sparse_merkle_tree(depth, entries)?; - Ok(self) - } - - /// Appends the provided merkle path set. - pub fn with_merkle_path( - mut self, - index_value: u64, - node: Word, - path: MerklePath, - ) -> Result { - self.add_merkle_path(index_value, node, path)?; - Ok(self) - } - - /// Appends the provided merkle path set. - pub fn with_merkle_paths(mut self, paths: I) -> Result - where - I: IntoIterator, - { - self.add_merkle_paths(paths)?; - Ok(self) - } - - /// Appends the provided [Mmr] represented by its `leaves` to the set. - pub fn with_mmr(mut self, leaves: I) -> Result - where - I: IntoIterator, - { - self.add_mmr(leaves)?; - Ok(self) - } - // PUBLIC ACCESSORS // -------------------------------------------------------------------------------------------- @@ -184,15 +134,11 @@ impl MerkleStore { let mut hash: RpoDigest = root.into(); // corner case: check the root is in the store when called with index `NodeIndex::root()` - self.nodes - .get(&hash) - .ok_or(MerkleError::RootNotInStore(hash.into()))?; + self.nodes.get(&hash).ok_or(MerkleError::RootNotInStore(hash.into()))?; for i in (0..index.depth()).rev() { - let node = self - .nodes - .get(&hash) - .ok_or(MerkleError::NodeNotInStore(hash.into(), index))?; + let node = + self.nodes.get(&hash).ok_or(MerkleError::NodeNotInStore(hash.into(), index))?; let bit = (index.value() >> i) & 1; hash = if bit == 0 { node.left } else { node.right } @@ -215,15 +161,11 @@ impl MerkleStore { let mut path = Vec::with_capacity(index.depth().into()); // corner case: check the root is in the store when called with index `NodeIndex::root()` - self.nodes - .get(&hash) - .ok_or(MerkleError::RootNotInStore(hash.into()))?; + self.nodes.get(&hash).ok_or(MerkleError::RootNotInStore(hash.into()))?; for i in (0..index.depth()).rev() { - let node = self - .nodes - .get(&hash) - .ok_or(MerkleError::NodeNotInStore(hash.into(), index))?; + let node = + self.nodes.get(&hash).ok_or(MerkleError::NodeNotInStore(hash.into(), index))?; let bit = (index.value() >> i) & 1; hash = if bit == 0 { @@ -302,11 +244,7 @@ impl MerkleStore { }; // traverse down - hash = if path & 1 == 0 { - children.left - } else { - children.right - }; + hash = if path & 1 == 0 { children.left } else { children.right }; path >>= 1; } @@ -322,68 +260,21 @@ impl MerkleStore { // STATE MUTATORS // -------------------------------------------------------------------------------------------- - /// Adds all the nodes of a Merkle tree represented by `leaves`. - /// - /// This will instantiate a Merkle tree using `leaves` and include all the nodes into the - /// store. - /// - /// # Errors - /// - /// This method may return the following errors: - /// - `DepthTooSmall` if leaves is empty or contains only 1 element - /// - `NumLeavesNotPowerOfTwo` if the number of leaves is not a power-of-two - pub fn add_merkle_tree(&mut self, leaves: I) -> Result + /// Adds a sequence of nodes yielded by the provided iterator into the store. + pub fn extend(&mut self, iter: I) -> &mut MerkleStore where - I: IntoIterator, + I: Iterator, { - let leaves: Vec<_> = leaves.into_iter().collect(); - if leaves.len() < 2 { - return Err(MerkleError::DepthTooSmall(leaves.len() as u8)); + for node in iter { + let value: RpoDigest = node.value.into(); + let left: RpoDigest = node.left.into(); + let right: RpoDigest = node.right.into(); + + debug_assert_eq!(Rpo256::merge(&[left, right]), value); + self.nodes.insert(value, Node { left, right }); } - let tree = MerkleTree::new(leaves)?; - for node in tree.inner_nodes() { - self.nodes.insert( - node.value.into(), - Node { - left: node.left.into(), - right: node.right.into(), - }, - ); - } - - Ok(tree.root()) - } - - /// Adds a Sparse Merkle tree defined by the specified `entries` to the store, and returns the - /// root of the added tree. - /// - /// The entries are expected to contain tuples of `(index, node)` describing nodes in the tree - /// at `depth`. - /// - /// # Errors - /// Returns an error if the provided `depth` is greater than [SimpleSmt::MAX_DEPTH]. - pub fn add_sparse_merkle_tree( - &mut self, - depth: u8, - entries: R, - ) -> Result - where - R: IntoIterator, - I: Iterator + ExactSizeIterator, - { - let smt = SimpleSmt::new(depth)?.with_leaves(entries)?; - for node in smt.inner_nodes() { - self.nodes.insert( - node.value.into(), - Node { - left: node.left.into(), - right: node.right.into(), - }, - ); - } - - Ok(smt.root()) + self } /// Adds all the nodes of a Merkle path represented by `path`, opening to `node`. Returns the @@ -393,31 +284,21 @@ impl MerkleStore { /// include all the nodes into the store. pub fn add_merkle_path( &mut self, - index_value: u64, - mut node: Word, + index: u64, + node: Word, path: MerklePath, ) -> Result { - let mut index = NodeIndex::new(path.len() as u8, index_value)?; + let root = path.inner_nodes(index, node)?.fold(Word::default(), |_, node| { + let value: RpoDigest = node.value.into(); + let left: RpoDigest = node.left.into(); + let right: RpoDigest = node.right.into(); - for sibling in path { - let (left, right) = match index.is_value_odd() { - true => (sibling, node), - false => (node, sibling), - }; - let parent = Rpo256::merge(&[left.into(), right.into()]); - self.nodes.insert( - parent, - Node { - left: left.into(), - right: right.into(), - }, - ); + debug_assert_eq!(Rpo256::merge(&[left, right]), value); + self.nodes.insert(value, Node { left, right }); - index.move_up(); - node = parent.into(); - } - - Ok(node) + node.value + }); + Ok(root) } /// Adds all the nodes of multiple Merkle paths into the store. @@ -447,25 +328,6 @@ impl MerkleStore { Ok(root) } - /// Appends the provided [Mmr] into the store. - pub fn add_mmr(&mut self, leaves: I) -> Result - where - I: IntoIterator, - { - let mmr = Mmr::from(leaves); - for node in mmr.inner_nodes() { - self.nodes.insert( - node.value.into(), - Node { - left: node.left.into(), - right: node.right.into(), - }, - ); - } - - Ok(mmr.accumulator()) - } - /// Sets a node to `value`. /// /// # Errors @@ -490,26 +352,61 @@ impl MerkleStore { Ok(RootPath { root, path }) } + /// Merges two elements and adds the resulting node into the store. + /// + /// Merges arbitrary values. They may be leafs, nodes, or a mixture of both. pub fn merge_roots(&mut self, root1: Word, root2: Word) -> Result { - let root1: RpoDigest = root1.into(); - let root2: RpoDigest = root2.into(); + let left: RpoDigest = root1.into(); + let right: RpoDigest = root2.into(); - if !self.nodes.contains_key(&root1) { - Err(MerkleError::NodeNotInStore(root1.into(), NodeIndex::root())) - } else if !self.nodes.contains_key(&root1) { - Err(MerkleError::NodeNotInStore(root2.into(), NodeIndex::root())) - } else { - let parent: Word = Rpo256::merge(&[root1, root2]).into(); - self.nodes.insert( - parent.into(), - Node { - left: root1, - right: root2, - }, - ); + let parent = Rpo256::merge(&[left, right]); + self.nodes.insert(parent, Node { left, right }); - Ok(parent) - } + Ok(parent.into()) + } +} + +// CONVERSIONS +// ================================================================================================ + +impl From<&MerkleTree> for MerkleStore { + fn from(value: &MerkleTree) -> Self { + let mut store = MerkleStore::new(); + store.extend(value.inner_nodes()); + store + } +} + +impl From<&SimpleSmt> for MerkleStore { + fn from(value: &SimpleSmt) -> Self { + let mut store = MerkleStore::new(); + store.extend(value.inner_nodes()); + store + } +} + +impl From<&Mmr> for MerkleStore { + fn from(value: &Mmr) -> Self { + let mut store = MerkleStore::new(); + store.extend(value.inner_nodes()); + store + } +} + +impl FromIterator for MerkleStore { + fn from_iter>(iter: T) -> Self { + let mut store = MerkleStore::new(); + store.extend(iter.into_iter()); + store + } +} + +// ITERATORS +// ================================================================================================ + +impl Extend for MerkleStore { + fn extend>(&mut self, iter: T) { + self.extend(iter.into_iter()); } } diff --git a/src/merkle/store/tests.rs b/src/merkle/store/tests.rs index de65b1f..02e12b2 100644 --- a/src/merkle/store/tests.rs +++ b/src/merkle/store/tests.rs @@ -1,26 +1,21 @@ use super::*; use crate::{ hash::rpo::Rpo256, - merkle::{int_to_node, MerklePathSet}, + merkle::{int_to_node, MerklePathSet, MerkleTree, SimpleSmt}, Felt, Word, WORD_SIZE, ZERO, }; -#[cfg(std)] +#[cfg(feature = "std")] use std::error::Error; const KEYS4: [u64; 4] = [0, 1, 2, 3]; -const LEAVES4: [Word; 4] = [ - int_to_node(1), - int_to_node(2), - int_to_node(3), - int_to_node(4), -]; +const LEAVES4: [Word; 4] = [int_to_node(1), int_to_node(2), int_to_node(3), int_to_node(4)]; const EMPTY: Word = [ZERO; WORD_SIZE]; #[test] fn test_root_not_in_store() -> Result<(), MerkleError> { let mtree = MerkleTree::new(LEAVES4.to_vec())?; - let store = MerkleStore::default().with_merkle_tree(LEAVES4)?; + let store = MerkleStore::from(&mtree); assert_eq!( store.get_node(LEAVES4[0], NodeIndex::make(mtree.depth(), 0)), Err(MerkleError::RootNotInStore(LEAVES4[0])), @@ -37,10 +32,8 @@ fn test_root_not_in_store() -> Result<(), MerkleError> { #[test] fn test_merkle_tree() -> Result<(), MerkleError> { - let mut store = MerkleStore::default(); - let mtree = MerkleTree::new(LEAVES4.to_vec())?; - store.add_merkle_tree(LEAVES4.to_vec())?; + let store = MerkleStore::from(&mtree); // STORE LEAVES ARE CORRECT ============================================================== // checks the leaves in the store corresponds to the expected values @@ -90,9 +83,7 @@ fn test_merkle_tree() -> Result<(), MerkleError> { // STORE MERKLE PATH MATCHS ============================================================== // assert the merkle path returned by the store is the same as the one in the tree - let result = store - .get_path(mtree.root(), NodeIndex::make(mtree.depth(), 0)) - .unwrap(); + let result = store.get_path(mtree.root(), NodeIndex::make(mtree.depth(), 0)).unwrap(); assert_eq!( LEAVES4[0], result.value, "Value for merkle path at index 0 must match leaf value" @@ -103,9 +94,7 @@ fn test_merkle_tree() -> Result<(), MerkleError> { "merkle path for index 0 must be the same for the MerkleTree and MerkleStore" ); - let result = store - .get_path(mtree.root(), NodeIndex::make(mtree.depth(), 1)) - .unwrap(); + let result = store.get_path(mtree.root(), NodeIndex::make(mtree.depth(), 1)).unwrap(); assert_eq!( LEAVES4[1], result.value, "Value for merkle path at index 0 must match leaf value" @@ -116,9 +105,7 @@ fn test_merkle_tree() -> Result<(), MerkleError> { "merkle path for index 1 must be the same for the MerkleTree and MerkleStore" ); - let result = store - .get_path(mtree.root(), NodeIndex::make(mtree.depth(), 2)) - .unwrap(); + let result = store.get_path(mtree.root(), NodeIndex::make(mtree.depth(), 2)).unwrap(); assert_eq!( LEAVES4[2], result.value, "Value for merkle path at index 0 must match leaf value" @@ -129,9 +116,7 @@ fn test_merkle_tree() -> Result<(), MerkleError> { "merkle path for index 0 must be the same for the MerkleTree and MerkleStore" ); - let result = store - .get_path(mtree.root(), NodeIndex::make(mtree.depth(), 3)) - .unwrap(); + let result = store.get_path(mtree.root(), NodeIndex::make(mtree.depth(), 3)).unwrap(); assert_eq!( LEAVES4[3], result.value, "Value for merkle path at index 0 must match leaf value" @@ -172,10 +157,7 @@ fn test_leaf_paths_for_empty_trees() -> Result<(), MerkleError> { let index = NodeIndex::make(depth, 0); let store_path = store.get_path(smt.root(), index)?; let smt_path = smt.get_path(index)?; - assert_eq!( - store_path.value, EMPTY, - "the leaf of an empty tree is always ZERO" - ); + assert_eq!(store_path.value, EMPTY, "the leaf of an empty tree is always ZERO"); assert_eq!( store_path.path, smt_path, "the returned merkle path does not match the computed values" @@ -192,55 +174,41 @@ fn test_leaf_paths_for_empty_trees() -> Result<(), MerkleError> { #[test] fn test_get_invalid_node() { - let mut store = MerkleStore::default(); let mtree = MerkleTree::new(LEAVES4.to_vec()).expect("creating a merkle tree must work"); - store - .add_merkle_tree(LEAVES4.to_vec()) - .expect("adding a merkle tree to the store must work"); + let store = MerkleStore::from(&mtree); let _ = store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 3)); } #[test] fn test_add_sparse_merkle_tree_one_level() -> Result<(), MerkleError> { - let mut store = MerkleStore::default(); let keys2: [u64; 2] = [0, 1]; let leaves2: [Word; 2] = [int_to_node(1), int_to_node(2)]; - store.add_sparse_merkle_tree(48, keys2.into_iter().zip(leaves2.into_iter()))?; let smt = SimpleSmt::new(1) .unwrap() .with_leaves(keys2.into_iter().zip(leaves2.into_iter())) .unwrap(); + let store = MerkleStore::from(&smt); let idx = NodeIndex::make(1, 0); assert_eq!(smt.get_node(idx).unwrap(), leaves2[0]); - assert_eq!( - store.get_node(smt.root(), idx).unwrap(), - smt.get_node(idx).unwrap() - ); + assert_eq!(store.get_node(smt.root(), idx).unwrap(), smt.get_node(idx).unwrap()); let idx = NodeIndex::make(1, 1); assert_eq!(smt.get_node(idx).unwrap(), leaves2[1]); - assert_eq!( - store.get_node(smt.root(), idx).unwrap(), - smt.get_node(idx).unwrap() - ); + assert_eq!(store.get_node(smt.root(), idx).unwrap(), smt.get_node(idx).unwrap()); Ok(()) } #[test] fn test_sparse_merkle_tree() -> Result<(), MerkleError> { - let mut store = MerkleStore::default(); - store.add_sparse_merkle_tree( - SimpleSmt::MAX_DEPTH, - KEYS4.into_iter().zip(LEAVES4.into_iter()), - )?; - let smt = SimpleSmt::new(SimpleSmt::MAX_DEPTH) .unwrap() .with_leaves(KEYS4.into_iter().zip(LEAVES4.into_iter())) .unwrap(); + let store = MerkleStore::from(&smt); + // STORE LEAVES ARE CORRECT ============================================================== // checks the leaves in the store corresponds to the expected values assert_eq!( @@ -299,9 +267,7 @@ fn test_sparse_merkle_tree() -> Result<(), MerkleError> { // STORE MERKLE PATH MATCHS ============================================================== // assert the merkle path returned by the store is the same as the one in the tree - let result = store - .get_path(smt.root(), NodeIndex::make(smt.depth(), 0)) - .unwrap(); + let result = store.get_path(smt.root(), NodeIndex::make(smt.depth(), 0)).unwrap(); assert_eq!( LEAVES4[0], result.value, "Value for merkle path at index 0 must match leaf value" @@ -312,9 +278,7 @@ fn test_sparse_merkle_tree() -> Result<(), MerkleError> { "merkle path for index 0 must be the same for the MerkleTree and MerkleStore" ); - let result = store - .get_path(smt.root(), NodeIndex::make(smt.depth(), 1)) - .unwrap(); + let result = store.get_path(smt.root(), NodeIndex::make(smt.depth(), 1)).unwrap(); assert_eq!( LEAVES4[1], result.value, "Value for merkle path at index 1 must match leaf value" @@ -325,9 +289,7 @@ fn test_sparse_merkle_tree() -> Result<(), MerkleError> { "merkle path for index 1 must be the same for the MerkleTree and MerkleStore" ); - let result = store - .get_path(smt.root(), NodeIndex::make(smt.depth(), 2)) - .unwrap(); + let result = store.get_path(smt.root(), NodeIndex::make(smt.depth(), 2)).unwrap(); assert_eq!( LEAVES4[2], result.value, "Value for merkle path at index 2 must match leaf value" @@ -338,9 +300,7 @@ fn test_sparse_merkle_tree() -> Result<(), MerkleError> { "merkle path for index 2 must be the same for the MerkleTree and MerkleStore" ); - let result = store - .get_path(smt.root(), NodeIndex::make(smt.depth(), 3)) - .unwrap(); + let result = store.get_path(smt.root(), NodeIndex::make(smt.depth(), 3)).unwrap(); assert_eq!( LEAVES4[3], result.value, "Value for merkle path at index 3 must match leaf value" @@ -351,13 +311,8 @@ fn test_sparse_merkle_tree() -> Result<(), MerkleError> { "merkle path for index 3 must be the same for the MerkleTree and MerkleStore" ); - let result = store - .get_path(smt.root(), NodeIndex::make(smt.depth(), 4)) - .unwrap(); - assert_eq!( - EMPTY, result.value, - "Value for merkle path at index 4 must match leaf value" - ); + let result = store.get_path(smt.root(), NodeIndex::make(smt.depth(), 4)).unwrap(); + assert_eq!(EMPTY, result.value, "Value for merkle path at index 4 must match leaf value"); assert_eq!( smt.get_path(NodeIndex::make(smt.depth(), 4)), Ok(result.path), @@ -391,9 +346,7 @@ fn test_add_merkle_paths() -> Result<(), MerkleError> { ]; let mut store = MerkleStore::default(); - store - .add_merkle_paths(paths.clone()) - .expect("the valid paths must work"); + store.add_merkle_paths(paths.clone()).expect("the valid paths must work"); let depth = 2; let set = MerklePathSet::new(depth).with_paths(paths).unwrap(); @@ -446,9 +399,7 @@ fn test_add_merkle_paths() -> Result<(), MerkleError> { // STORE MERKLE PATH MATCHS ============================================================== // assert the merkle path returned by the store is the same as the one in the set - let result = store - .get_path(set.root(), NodeIndex::make(set.depth(), 0)) - .unwrap(); + let result = store.get_path(set.root(), NodeIndex::make(set.depth(), 0)).unwrap(); assert_eq!( LEAVES4[0], result.value, "Value for merkle path at index 0 must match leaf value" @@ -459,9 +410,7 @@ fn test_add_merkle_paths() -> Result<(), MerkleError> { "merkle path for index 0 must be the same for the MerkleTree and MerkleStore" ); - let result = store - .get_path(set.root(), NodeIndex::make(set.depth(), 1)) - .unwrap(); + let result = store.get_path(set.root(), NodeIndex::make(set.depth(), 1)).unwrap(); assert_eq!( LEAVES4[1], result.value, "Value for merkle path at index 0 must match leaf value" @@ -472,9 +421,7 @@ fn test_add_merkle_paths() -> Result<(), MerkleError> { "merkle path for index 1 must be the same for the MerkleTree and MerkleStore" ); - let result = store - .get_path(set.root(), NodeIndex::make(set.depth(), 2)) - .unwrap(); + let result = store.get_path(set.root(), NodeIndex::make(set.depth(), 2)).unwrap(); assert_eq!( LEAVES4[2], result.value, "Value for merkle path at index 0 must match leaf value" @@ -485,9 +432,7 @@ fn test_add_merkle_paths() -> Result<(), MerkleError> { "merkle path for index 0 must be the same for the MerkleTree and MerkleStore" ); - let result = store - .get_path(set.root(), NodeIndex::make(set.depth(), 3)) - .unwrap(); + let result = store.get_path(set.root(), NodeIndex::make(set.depth(), 3)).unwrap(); assert_eq!( LEAVES4[3], result.value, "Value for merkle path at index 0 must match leaf value" @@ -519,7 +464,8 @@ fn wont_open_to_different_depth_root() { // For this example, the depth of the Merkle tree is 1, as we have only two leaves. Here we // attempt to fetch a node on the maximum depth, and it should fail because the root shouldn't // exist for the set. - let store = MerkleStore::default().with_merkle_tree([a, b]).unwrap(); + let mtree = MerkleTree::new(vec![a, b]).unwrap(); + let store = MerkleStore::from(&mtree); let index = NodeIndex::root(); let err = store.get_node(root, index).err().unwrap(); assert_eq!(err, MerkleError::RootNotInStore(root)); @@ -546,13 +492,9 @@ fn store_path_opens_from_leaf() { let root = Rpo256::merge(&[m.into(), n.into()]); - let store = MerkleStore::default() - .with_merkle_tree([a, b, c, d, e, f, g, h]) - .unwrap(); - let path = store - .get_path(root.into(), NodeIndex::make(3, 1)) - .unwrap() - .path; + let mtree = MerkleTree::new(vec![a, b, c, d, e, f, g, h]).unwrap(); + let store = MerkleStore::from(&mtree); + let path = store.get_path(root.into(), NodeIndex::make(3, 1)).unwrap().path; let expected = MerklePath::new([a.into(), j.into(), n.into()].to_vec()); assert_eq!(path, expected); @@ -561,23 +503,19 @@ fn store_path_opens_from_leaf() { #[test] fn test_set_node() -> Result<(), MerkleError> { let mtree = MerkleTree::new(LEAVES4.to_vec())?; - let mut store = MerkleStore::default().with_merkle_tree(LEAVES4)?; + let mut store = MerkleStore::from(&mtree); let value = int_to_node(42); let index = NodeIndex::make(mtree.depth(), 0); let new_root = store.set_node(mtree.root(), index, value)?.root; - assert_eq!( - store.get_node(new_root, index), - Ok(value), - "Value must have changed" - ); + assert_eq!(store.get_node(new_root, index), Ok(value), "Value must have changed"); Ok(()) } #[test] fn test_constructors() -> Result<(), MerkleError> { - let store = MerkleStore::new().with_merkle_tree(LEAVES4)?; let mtree = MerkleTree::new(LEAVES4.to_vec())?; + let store = MerkleStore::from(&mtree); let depth = mtree.depth(); let leaves = 2u64.pow(depth.into()); @@ -588,12 +526,11 @@ fn test_constructors() -> Result<(), MerkleError> { } let depth = 32; - let store = MerkleStore::default() - .with_sparse_merkle_tree(depth, KEYS4.into_iter().zip(LEAVES4.into_iter()))?; let smt = SimpleSmt::new(depth) .unwrap() .with_leaves(KEYS4.into_iter().zip(LEAVES4.into_iter())) .unwrap(); + let store = MerkleStore::from(&smt); let depth = smt.depth(); for key in KEYS4 { @@ -604,34 +541,20 @@ fn test_constructors() -> Result<(), MerkleError> { let d = 2; let paths = [ - ( - 0, - LEAVES4[0], - mtree.get_path(NodeIndex::make(d, 0)).unwrap(), - ), - ( - 1, - LEAVES4[1], - mtree.get_path(NodeIndex::make(d, 1)).unwrap(), - ), - ( - 2, - LEAVES4[2], - mtree.get_path(NodeIndex::make(d, 2)).unwrap(), - ), - ( - 3, - LEAVES4[3], - mtree.get_path(NodeIndex::make(d, 3)).unwrap(), - ), + (0, LEAVES4[0], mtree.get_path(NodeIndex::make(d, 0)).unwrap()), + (1, LEAVES4[1], mtree.get_path(NodeIndex::make(d, 1)).unwrap()), + (2, LEAVES4[2], mtree.get_path(NodeIndex::make(d, 2)).unwrap()), + (3, LEAVES4[3], mtree.get_path(NodeIndex::make(d, 3)).unwrap()), ]; - let store1 = MerkleStore::default().with_merkle_paths(paths.clone())?; - let store2 = MerkleStore::default() - .with_merkle_path(0, LEAVES4[0], mtree.get_path(NodeIndex::make(d, 0))?)? - .with_merkle_path(1, LEAVES4[1], mtree.get_path(NodeIndex::make(d, 1))?)? - .with_merkle_path(2, LEAVES4[2], mtree.get_path(NodeIndex::make(d, 2))?)? - .with_merkle_path(3, LEAVES4[3], mtree.get_path(NodeIndex::make(d, 3))?)?; + let mut store1 = MerkleStore::default(); + store1.add_merkle_paths(paths.clone())?; + + let mut store2 = MerkleStore::default(); + store2.add_merkle_path(0, LEAVES4[0], mtree.get_path(NodeIndex::make(d, 0))?)?; + store2.add_merkle_path(1, LEAVES4[1], mtree.get_path(NodeIndex::make(d, 1))?)?; + store2.add_merkle_path(2, LEAVES4[2], mtree.get_path(NodeIndex::make(d, 2))?)?; + store2.add_merkle_path(3, LEAVES4[3], mtree.get_path(NodeIndex::make(d, 3))?)?; let set = MerklePathSet::new(d).with_paths(paths).unwrap(); for key in [0, 1, 2, 3] { @@ -792,17 +715,15 @@ fn get_leaf_depth_works_with_depth_8() { // duplicate the tree on `a` and assert the depth is short-circuited by such sub-tree let index = NodeIndex::new(8, a).unwrap(); root = store.set_node(root, index, root).unwrap().root; - assert_eq!( - Err(MerkleError::DepthTooBig(9)), - store.get_leaf_depth(root, 8, a) - ); + assert_eq!(Err(MerkleError::DepthTooBig(9)), store.get_leaf_depth(root, 8, a)); } -#[cfg(std)] +#[cfg(feature = "std")] #[test] fn test_serialization() -> Result<(), Box> { - let original = MerkleStore::new().with_merkle_tree(LEAVES4)?; - let decoded = MerkleStore::read_from_bytes(&original.to_bytes())?; - assert_eq!(original, decoded); + let mtree = MerkleTree::new(LEAVES4.to_vec())?; + let store = MerkleStore::from(&mtree); + let decoded = MerkleStore::read_from_bytes(&store.to_bytes()).expect("deserialization failed"); + assert_eq!(store, decoded); Ok(()) }