From 8161477d6a03d8dcd510f49be030d9291fa0b7db Mon Sep 17 00:00:00 2001 From: "Augusto F. Hack" Date: Wed, 19 Apr 2023 15:30:16 +0200 Subject: [PATCH 1/6] store: support adding existing structures --- src/merkle/store/mod.rs | 77 +++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 42 deletions(-) diff --git a/src/merkle/store/mod.rs b/src/merkle/store/mod.rs index a510826..5182bd2 100644 --- a/src/merkle/store/mod.rs +++ b/src/merkle/store/mod.rs @@ -1,7 +1,7 @@ use super::mmr::{Mmr, MmrPeaks}; 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}; @@ -310,6 +310,20 @@ impl MerkleStore { // STATE MUTATORS // -------------------------------------------------------------------------------------------- + /// Adds a new [InnerNodeInfo] into the store. + pub fn extend(&mut self, iter: impl Iterator) -> &mut MerkleStore { + 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 }); + } + + self + } + /// 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 @@ -330,15 +344,7 @@ impl MerkleStore { } 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(), - }, - ); - } + self.extend(tree.inner_nodes()); Ok(tree.root()) } @@ -361,15 +367,7 @@ impl MerkleStore { 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(), - }, - ); - } + self.extend(smt.inner_nodes()); Ok(smt.root()) } @@ -441,15 +439,7 @@ impl MerkleStore { 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(), - }, - ); - } + self.extend(mmr.inner_nodes()); Ok(mmr.accumulator()) } @@ -482,19 +472,22 @@ impl MerkleStore { /// /// 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 parent: Word = Rpo256::merge(&[root1, root2]).into(); - self.nodes.insert( - parent.into(), - Node { - left: root1, - right: root2, - }, - ); - - Ok(parent) + let left: RpoDigest = root1.into(); + let right: RpoDigest = root2.into(); + + let parent = Rpo256::merge(&[left, right]); + self.nodes.insert(parent, Node { left, right }); + + Ok(parent.into()) + } +} + +// ITERATORS +// ================================================================================================ + +impl Extend for MerkleStore { + fn extend>(&mut self, iter: T) { + self.extend(iter.into_iter()); } } From eb316f51bca0486a76585c2282db8302ee49d8c0 Mon Sep 17 00:00:00 2001 From: "Augusto F. Hack" Date: Thu, 20 Apr 2023 22:42:42 +0200 Subject: [PATCH 2/6] store: remove SimpleSMT/MerkleTree/Mmr add/with methods --- benches/store.rs | 46 +++++++++------- src/merkle/store/mod.rs | 107 ++++---------------------------------- src/merkle/store/tests.rs | 49 +++++++++-------- 3 files changed, 62 insertions(+), 140 deletions(-) diff --git a/benches/store.rs b/benches/store.rs index 83ac348..2ad2790 100644 --- a/benches/store.rs +++ b/benches/store.rs @@ -66,7 +66,8 @@ 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 mut store = MerkleStore::new(); + store.extend(mtree.inner_nodes()); let depth = mtree.depth(); let root = mtree.root(); let size_u64 = size as u64; @@ -108,9 +109,8 @@ 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 mut store = MerkleStore::new(); + store.extend(smt.inner_nodes()); let depth = smt.depth(); let root = smt.root(); let size_u64 = size as u64; @@ -178,7 +178,8 @@ 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 mut store = MerkleStore::new(); + store.extend(mtree.inner_nodes()); let root = mtree.root(); let half_depth = mtree.depth() / 2; let half_size = 2_u64.pow(half_depth as u32); @@ -221,9 +222,8 @@ 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 mut store = MerkleStore::new(); + store.extend(smt.inner_nodes()); let root = smt.root(); let half_depth = smt.depth() / 2; let half_size = 2_u64.pow(half_depth as u32); @@ -258,7 +258,8 @@ 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 mut store = MerkleStore::new(); + store.extend(mtree.inner_nodes()); let depth = mtree.depth(); let root = mtree.root(); let size_u64 = size as u64; @@ -300,9 +301,8 @@ 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 mut store = MerkleStore::new(); + store.extend(smt.inner_nodes()); let depth = smt.depth(); let root = smt.root(); let size_u64 = size as u64; @@ -347,10 +347,13 @@ 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| { + group.bench_function(BenchmarkId::new("MerkleStore::extend::MerkleTree", size), |b| { b.iter_batched( || leaves.iter().map(|v| v.into()).collect::>(), - |l| black_box(MerkleStore::new().with_merkle_tree(l)), + |l| { + let mtree = MerkleTree::new(l).unwrap(); + black_box(MerkleStore::new().extend(mtree.inner_nodes())); + }, BatchSize::SmallInput, ) }); @@ -369,7 +372,7 @@ fn new(c: &mut Criterion) { ) }); - group.bench_function(BenchmarkId::new("MerkleStore::with_sparse_merkle_tree", size), |b| { + group.bench_function(BenchmarkId::new("MerkleStore::extend::SimpleSmt", size), |b| { b.iter_batched( || { leaves @@ -378,7 +381,10 @@ fn new(c: &mut Criterion) { .map(|(c, v)| (c.try_into().unwrap(), v.into())) .collect::>() }, - |l| black_box(MerkleStore::new().with_sparse_merkle_tree(SimpleSmt::MAX_DEPTH, l)), + |l| { + let smt = SimpleSmt::new(SimpleSmt::MAX_DEPTH).unwrap().with_leaves(l).unwrap(); + black_box(MerkleStore::new().extend(smt.inner_nodes())); + }, BatchSize::SmallInput, ) }); @@ -397,7 +403,8 @@ 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::new(); + store.extend(mtree.inner_nodes()); let depth = mtree.depth(); let root = mtree.root(); let size_u64 = size as u64; @@ -446,9 +453,8 @@ 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::new(); + store.extend(smt.inner_nodes()); let depth = smt.depth(); let root = smt.root(); let size_u64 = size as u64; diff --git a/src/merkle/store/mod.rs b/src/merkle/store/mod.rs index 5182bd2..776da47 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, InnerNodeInfo, MerkleError, MerklePath, MerklePathSet, MerkleTree, - NodeIndex, RootPath, Rpo256, RpoDigest, SimpleSmt, ValuePath, Vec, Word, + BTreeMap, EmptySubtreeRoots, InnerNodeInfo, MerkleError, MerklePath, MerklePathSet, NodeIndex, + RootPath, Rpo256, RpoDigest, 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,31 +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, @@ -156,15 +135,6 @@ impl MerkleStore { 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 // -------------------------------------------------------------------------------------------- @@ -324,54 +294,6 @@ impl MerkleStore { self } - /// 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 - where - I: IntoIterator, - { - let leaves: Vec<_> = leaves.into_iter().collect(); - if leaves.len() < 2 { - return Err(MerkleError::DepthTooSmall(leaves.len() as u8)); - } - - let tree = MerkleTree::new(leaves)?; - self.extend(tree.inner_nodes()); - - 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)?; - self.extend(smt.inner_nodes()); - - Ok(smt.root()) - } - /// Adds all the nodes of a Merkle path represented by `path`, opening to `node`. Returns the /// new root. /// @@ -433,17 +355,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); - self.extend(mmr.inner_nodes()); - - Ok(mmr.accumulator()) - } - /// Sets a node to `value`. /// /// # Errors diff --git a/src/merkle/store/tests.rs b/src/merkle/store/tests.rs index 251cd9a..3df4f21 100644 --- a/src/merkle/store/tests.rs +++ b/src/merkle/store/tests.rs @@ -1,7 +1,7 @@ use super::*; use crate::{ hash::rpo::Rpo256, - merkle::{int_to_node, MerklePathSet}, + merkle::{int_to_node, MerklePathSet, MerkleTree, SimpleSmt}, Felt, Word, WORD_SIZE, ZERO, }; @@ -15,7 +15,8 @@ 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 mut store = MerkleStore::new(); + store.extend(mtree.inner_nodes()); assert_eq!( store.get_node(LEAVES4[0], NodeIndex::make(mtree.depth(), 0)), Err(MerkleError::RootNotInStore(LEAVES4[0])), @@ -32,10 +33,9 @@ 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 mut store = MerkleStore::default(); + store.extend(mtree.inner_nodes()); // STORE LEAVES ARE CORRECT ============================================================== // checks the leaves in the store corresponds to the expected values @@ -176,24 +176,22 @@ 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 mut store = MerkleStore::default(); + store.extend(mtree.inner_nodes()); 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 mut store = MerkleStore::default(); + store.extend(smt.inner_nodes()); let idx = NodeIndex::make(1, 0); assert_eq!(smt.get_node(idx).unwrap(), leaves2[0]); @@ -208,15 +206,14 @@ fn test_add_sparse_merkle_tree_one_level() -> Result<(), MerkleError> { #[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 mut store = MerkleStore::default(); + store.extend(smt.inner_nodes()); + // STORE LEAVES ARE CORRECT ============================================================== // checks the leaves in the store corresponds to the expected values assert_eq!( @@ -472,7 +469,9 @@ 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 mut store = MerkleStore::new(); + store.extend(mtree.inner_nodes()); let index = NodeIndex::root(); let err = store.get_node(root, index).err().unwrap(); assert_eq!(err, MerkleError::RootNotInStore(root)); @@ -499,7 +498,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 mtree = MerkleTree::new(vec![a, b, c, d, e, f, g, h]).unwrap(); + let mut store = MerkleStore::new(); + store.extend(mtree.inner_nodes()); 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()); @@ -509,7 +510,8 @@ 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::new(); + store.extend(mtree.inner_nodes()); let value = int_to_node(42); let index = NodeIndex::make(mtree.depth(), 0); let new_root = store.set_node(mtree.root(), index, value)?.root; @@ -520,8 +522,9 @@ fn test_set_node() -> Result<(), MerkleError> { #[test] fn test_constructors() -> Result<(), MerkleError> { - let store = MerkleStore::new().with_merkle_tree(LEAVES4)?; let mtree = MerkleTree::new(LEAVES4.to_vec())?; + let mut store = MerkleStore::new(); + store.extend(mtree.inner_nodes()); let depth = mtree.depth(); let leaves = 2u64.pow(depth.into()); @@ -532,12 +535,12 @@ 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 mut store = MerkleStore::new(); + store.extend(smt.inner_nodes()); let depth = smt.depth(); for key in KEYS4 { @@ -726,7 +729,9 @@ fn get_leaf_depth_works_with_depth_8() { #[cfg(std)] #[test] fn test_serialization() -> Result<(), Box> { - let original = MerkleStore::new().with_merkle_tree(LEAVES4)?; + let mtree = MerkleTree::new(LEAVES4.to_vec())?; + let mut store = MerkleStore::new(); + store.extend(mtree.inner_nodes()); let decoded = MerkleStore::read_from_bytes(&original.to_bytes())?; assert_eq!(original, decoded); Ok(()) From 59595a2e0465ccf7de1893e986bb909176bc23d9 Mon Sep 17 00:00:00 2001 From: "Augusto F. Hack" Date: Fri, 21 Apr 2023 14:45:50 +0200 Subject: [PATCH 3/6] feat: added From convertions for the MerkleStore --- benches/store.rs | 32 ++++++++++++-------------------- src/merkle/store/mod.rs | 31 +++++++++++++++++++++++++++++-- src/merkle/store/tests.rs | 33 +++++++++++---------------------- 3 files changed, 52 insertions(+), 44 deletions(-) diff --git a/benches/store.rs b/benches/store.rs index 2ad2790..2319128 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 = smt.clone().into(); let root = smt.root(); group.bench_function(BenchmarkId::new("SimpleSmt", depth), |b| { @@ -66,8 +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 mut store = MerkleStore::new(); - store.extend(mtree.inner_nodes()); + let store: MerkleStore = mtree.clone().into(); let depth = mtree.depth(); let root = mtree.root(); let size_u64 = size as u64; @@ -109,8 +108,7 @@ fn get_leaf_simplesmt(c: &mut Criterion) { .unwrap() .with_leaves(smt_leaves.clone()) .unwrap(); - let mut store = MerkleStore::new(); - store.extend(smt.inner_nodes()); + let store: MerkleStore = smt.clone().into(); 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 = smt.clone().into(); let root = smt.root(); let half_depth = depth / 2; let half_size = 2_u64.pow(half_depth as u32); @@ -178,8 +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 mut store = MerkleStore::new(); - store.extend(mtree.inner_nodes()); + let store: MerkleStore = mtree.clone().into(); let root = mtree.root(); let half_depth = mtree.depth() / 2; let half_size = 2_u64.pow(half_depth as u32); @@ -222,8 +219,7 @@ fn get_node_simplesmt(c: &mut Criterion) { .unwrap() .with_leaves(smt_leaves.clone()) .unwrap(); - let mut store = MerkleStore::new(); - store.extend(smt.inner_nodes()); + let store: MerkleStore = smt.clone().into(); let root = smt.root(); let half_depth = smt.depth() / 2; let half_size = 2_u64.pow(half_depth as u32); @@ -258,8 +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 mut store = MerkleStore::new(); - store.extend(mtree.inner_nodes()); + let store: MerkleStore = mtree.clone().into(); let depth = mtree.depth(); let root = mtree.root(); let size_u64 = size as u64; @@ -301,8 +296,7 @@ fn get_leaf_path_simplesmt(c: &mut Criterion) { .unwrap() .with_leaves(smt_leaves.clone()) .unwrap(); - let mut store = MerkleStore::new(); - store.extend(smt.inner_nodes()); + let store: MerkleStore = smt.clone().into(); let depth = smt.depth(); let root = smt.root(); let size_u64 = size as u64; @@ -352,7 +346,7 @@ fn new(c: &mut Criterion) { || leaves.iter().map(|v| v.into()).collect::>(), |l| { let mtree = MerkleTree::new(l).unwrap(); - black_box(MerkleStore::new().extend(mtree.inner_nodes())); + black_box(MerkleStore::from(mtree)); }, BatchSize::SmallInput, ) @@ -383,7 +377,7 @@ fn new(c: &mut Criterion) { }, |l| { let smt = SimpleSmt::new(SimpleSmt::MAX_DEPTH).unwrap().with_leaves(l).unwrap(); - black_box(MerkleStore::new().extend(smt.inner_nodes())); + black_box(MerkleStore::from(smt)); }, BatchSize::SmallInput, ) @@ -403,8 +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(); - store.extend(mtree.inner_nodes()); + let mut store: MerkleStore = mtree.clone().into(); let depth = mtree.depth(); let root = mtree.root(); let size_u64 = size as u64; @@ -453,8 +446,7 @@ fn update_leaf_simplesmt(c: &mut Criterion) { .unwrap() .with_leaves(smt_leaves.clone()) .unwrap(); - let mut store = MerkleStore::new(); - store.extend(smt.inner_nodes()); + let mut store: MerkleStore = smt.clone().into(); let depth = smt.depth(); let root = smt.root(); let size_u64 = size as u64; diff --git a/src/merkle/store/mod.rs b/src/merkle/store/mod.rs index 776da47..8ed03e7 100644 --- a/src/merkle/store/mod.rs +++ b/src/merkle/store/mod.rs @@ -1,7 +1,7 @@ use super::mmr::Mmr; use super::{ - BTreeMap, EmptySubtreeRoots, InnerNodeInfo, MerkleError, MerklePath, MerklePathSet, NodeIndex, - RootPath, Rpo256, RpoDigest, 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}; @@ -393,6 +393,33 @@ impl MerkleStore { } } +// CONVERTIONS +// ================================================================================================ + +impl From for MerkleStore { + fn from(value: MerkleTree) -> Self { + let mut store = MerkleStore::new(); + store.extend(value.inner_nodes()); + store + } +} + +impl From for MerkleStore { + fn from(value: SimpleSmt) -> Self { + let mut store = MerkleStore::new(); + store.extend(value.inner_nodes()); + store + } +} + +impl From for MerkleStore { + fn from(value: Mmr) -> Self { + let mut store = MerkleStore::new(); + store.extend(value.inner_nodes()); + store + } +} + // ITERATORS // ================================================================================================ diff --git a/src/merkle/store/tests.rs b/src/merkle/store/tests.rs index 3df4f21..4c5eeb4 100644 --- a/src/merkle/store/tests.rs +++ b/src/merkle/store/tests.rs @@ -15,8 +15,7 @@ const EMPTY: Word = [ZERO; WORD_SIZE]; #[test] fn test_root_not_in_store() -> Result<(), MerkleError> { let mtree = MerkleTree::new(LEAVES4.to_vec())?; - let mut store = MerkleStore::new(); - store.extend(mtree.inner_nodes()); + let store: MerkleStore = mtree.clone().into(); assert_eq!( store.get_node(LEAVES4[0], NodeIndex::make(mtree.depth(), 0)), Err(MerkleError::RootNotInStore(LEAVES4[0])), @@ -34,8 +33,7 @@ fn test_root_not_in_store() -> Result<(), MerkleError> { #[test] fn test_merkle_tree() -> Result<(), MerkleError> { let mtree = MerkleTree::new(LEAVES4.to_vec())?; - let mut store = MerkleStore::default(); - store.extend(mtree.inner_nodes()); + let store: MerkleStore = mtree.clone().into(); // STORE LEAVES ARE CORRECT ============================================================== // checks the leaves in the store corresponds to the expected values @@ -177,8 +175,7 @@ fn test_leaf_paths_for_empty_trees() -> Result<(), MerkleError> { #[test] fn test_get_invalid_node() { let mtree = MerkleTree::new(LEAVES4.to_vec()).expect("creating a merkle tree must work"); - let mut store = MerkleStore::default(); - store.extend(mtree.inner_nodes()); + let store: MerkleStore = mtree.clone().into(); let _ = store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 3)); } @@ -190,8 +187,7 @@ fn test_add_sparse_merkle_tree_one_level() -> Result<(), MerkleError> { .unwrap() .with_leaves(keys2.into_iter().zip(leaves2.into_iter())) .unwrap(); - let mut store = MerkleStore::default(); - store.extend(smt.inner_nodes()); + let store: MerkleStore = smt.clone().into(); let idx = NodeIndex::make(1, 0); assert_eq!(smt.get_node(idx).unwrap(), leaves2[0]); @@ -211,8 +207,7 @@ fn test_sparse_merkle_tree() -> Result<(), MerkleError> { .with_leaves(KEYS4.into_iter().zip(LEAVES4.into_iter())) .unwrap(); - let mut store = MerkleStore::default(); - store.extend(smt.inner_nodes()); + let store: MerkleStore = smt.clone().into(); // STORE LEAVES ARE CORRECT ============================================================== // checks the leaves in the store corresponds to the expected values @@ -470,8 +465,7 @@ fn wont_open_to_different_depth_root() { // attempt to fetch a node on the maximum depth, and it should fail because the root shouldn't // exist for the set. let mtree = MerkleTree::new(vec![a, b]).unwrap(); - let mut store = MerkleStore::new(); - store.extend(mtree.inner_nodes()); + let store: MerkleStore = mtree.clone().into(); let index = NodeIndex::root(); let err = store.get_node(root, index).err().unwrap(); assert_eq!(err, MerkleError::RootNotInStore(root)); @@ -499,8 +493,7 @@ fn store_path_opens_from_leaf() { let root = Rpo256::merge(&[m.into(), n.into()]); let mtree = MerkleTree::new(vec![a, b, c, d, e, f, g, h]).unwrap(); - let mut store = MerkleStore::new(); - store.extend(mtree.inner_nodes()); + let store: MerkleStore = mtree.clone().into(); 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()); @@ -510,8 +503,7 @@ fn store_path_opens_from_leaf() { #[test] fn test_set_node() -> Result<(), MerkleError> { let mtree = MerkleTree::new(LEAVES4.to_vec())?; - let mut store = MerkleStore::new(); - store.extend(mtree.inner_nodes()); + let mut store: MerkleStore = mtree.clone().into(); let value = int_to_node(42); let index = NodeIndex::make(mtree.depth(), 0); let new_root = store.set_node(mtree.root(), index, value)?.root; @@ -523,8 +515,7 @@ fn test_set_node() -> Result<(), MerkleError> { #[test] fn test_constructors() -> Result<(), MerkleError> { let mtree = MerkleTree::new(LEAVES4.to_vec())?; - let mut store = MerkleStore::new(); - store.extend(mtree.inner_nodes()); + let store: MerkleStore = mtree.clone().into(); let depth = mtree.depth(); let leaves = 2u64.pow(depth.into()); @@ -539,8 +530,7 @@ fn test_constructors() -> Result<(), MerkleError> { .unwrap() .with_leaves(KEYS4.into_iter().zip(LEAVES4.into_iter())) .unwrap(); - let mut store = MerkleStore::new(); - store.extend(smt.inner_nodes()); + let store: MerkleStore = smt.clone().into(); let depth = smt.depth(); for key in KEYS4 { @@ -730,8 +720,7 @@ fn get_leaf_depth_works_with_depth_8() { #[test] fn test_serialization() -> Result<(), Box> { let mtree = MerkleTree::new(LEAVES4.to_vec())?; - let mut store = MerkleStore::new(); - store.extend(mtree.inner_nodes()); + let store: MerkleStore = mtree.clone().into(); let decoded = MerkleStore::read_from_bytes(&original.to_bytes())?; assert_eq!(original, decoded); Ok(()) From 9be4253f195a2e2249a1b451dd3984a316616e13 Mon Sep 17 00:00:00 2001 From: Bobbin Threadbare Date: Fri, 21 Apr 2023 11:22:36 -0700 Subject: [PATCH 4/6] feat: remove clone requirement for MerkleStore From constructors --- benches/store.rs | 24 ++++++++++++------------ src/merkle/merkle_tree.rs | 3 +++ src/merkle/store/mod.rs | 22 +++++++++++++++------- src/merkle/store/tests.rs | 20 ++++++++++---------- 4 files changed, 40 insertions(+), 29 deletions(-) diff --git a/benches/store.rs b/benches/store.rs index 2319128..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 = smt.clone().into(); + 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 = mtree.clone().into(); + let store = MerkleStore::from(&mtree); let depth = mtree.depth(); let root = mtree.root(); let size_u64 = size as u64; @@ -108,7 +108,7 @@ fn get_leaf_simplesmt(c: &mut Criterion) { .unwrap() .with_leaves(smt_leaves.clone()) .unwrap(); - let store: MerkleStore = smt.clone().into(); + let store = MerkleStore::from(&smt); let depth = smt.depth(); let root = smt.root(); let size_u64 = size as u64; @@ -141,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 = smt.clone().into(); + let store = MerkleStore::from(&smt); let root = smt.root(); let half_depth = depth / 2; let half_size = 2_u64.pow(half_depth as u32); @@ -176,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 = mtree.clone().into(); + 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); @@ -219,7 +219,7 @@ fn get_node_simplesmt(c: &mut Criterion) { .unwrap() .with_leaves(smt_leaves.clone()) .unwrap(); - let store: MerkleStore = smt.clone().into(); + 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); @@ -254,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 = mtree.clone().into(); + let store = MerkleStore::from(&mtree); let depth = mtree.depth(); let root = mtree.root(); let size_u64 = size as u64; @@ -296,7 +296,7 @@ fn get_leaf_path_simplesmt(c: &mut Criterion) { .unwrap() .with_leaves(smt_leaves.clone()) .unwrap(); - let store: MerkleStore = smt.clone().into(); + let store = MerkleStore::from(&smt); let depth = smt.depth(); let root = smt.root(); let size_u64 = size as u64; @@ -346,7 +346,7 @@ fn new(c: &mut Criterion) { || leaves.iter().map(|v| v.into()).collect::>(), |l| { let mtree = MerkleTree::new(l).unwrap(); - black_box(MerkleStore::from(mtree)); + black_box(MerkleStore::from(&mtree)); }, BatchSize::SmallInput, ) @@ -377,7 +377,7 @@ fn new(c: &mut Criterion) { }, |l| { let smt = SimpleSmt::new(SimpleSmt::MAX_DEPTH).unwrap().with_leaves(l).unwrap(); - black_box(MerkleStore::from(smt)); + black_box(MerkleStore::from(&smt)); }, BatchSize::SmallInput, ) @@ -397,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 = mtree.clone().into(); + let mut store = MerkleStore::from(&mtree); let depth = mtree.depth(); let root = mtree.root(); let size_u64 = size as u64; @@ -446,7 +446,7 @@ fn update_leaf_simplesmt(c: &mut Criterion) { .unwrap() .with_leaves(smt_leaves.clone()) .unwrap(); - let mut store: MerkleStore = smt.clone().into(); + let mut store = MerkleStore::from(&smt); let depth = smt.depth(); let root = smt.root(); let size_u64 = size as u64; diff --git a/src/merkle/merkle_tree.rs b/src/merkle/merkle_tree.rs index 4e39a09..106ec27 100644 --- a/src/merkle/merkle_tree.rs +++ b/src/merkle/merkle_tree.rs @@ -192,6 +192,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 = " "; diff --git a/src/merkle/store/mod.rs b/src/merkle/store/mod.rs index 8ed03e7..442ff00 100644 --- a/src/merkle/store/mod.rs +++ b/src/merkle/store/mod.rs @@ -393,33 +393,41 @@ impl MerkleStore { } } -// CONVERTIONS +// CONVERSIONS // ================================================================================================ -impl From for MerkleStore { - fn from(value: MerkleTree) -> Self { +impl From<&MerkleTree> for MerkleStore { + fn from(value: &MerkleTree) -> Self { let mut store = MerkleStore::new(); store.extend(value.inner_nodes()); store } } -impl From for MerkleStore { - fn from(value: SimpleSmt) -> Self { +impl From<&SimpleSmt> for MerkleStore { + fn from(value: &SimpleSmt) -> Self { let mut store = MerkleStore::new(); store.extend(value.inner_nodes()); store } } -impl From for MerkleStore { - fn from(value: Mmr) -> Self { +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 // ================================================================================================ diff --git a/src/merkle/store/tests.rs b/src/merkle/store/tests.rs index 4c5eeb4..ca5be9e 100644 --- a/src/merkle/store/tests.rs +++ b/src/merkle/store/tests.rs @@ -15,7 +15,7 @@ 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 = mtree.clone().into(); + let store = MerkleStore::from(&mtree); assert_eq!( store.get_node(LEAVES4[0], NodeIndex::make(mtree.depth(), 0)), Err(MerkleError::RootNotInStore(LEAVES4[0])), @@ -33,7 +33,7 @@ fn test_root_not_in_store() -> Result<(), MerkleError> { #[test] fn test_merkle_tree() -> Result<(), MerkleError> { let mtree = MerkleTree::new(LEAVES4.to_vec())?; - let store: MerkleStore = mtree.clone().into(); + let store = MerkleStore::from(&mtree); // STORE LEAVES ARE CORRECT ============================================================== // checks the leaves in the store corresponds to the expected values @@ -175,7 +175,7 @@ fn test_leaf_paths_for_empty_trees() -> Result<(), MerkleError> { #[test] fn test_get_invalid_node() { let mtree = MerkleTree::new(LEAVES4.to_vec()).expect("creating a merkle tree must work"); - let store: MerkleStore = mtree.clone().into(); + let store = MerkleStore::from(&mtree); let _ = store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 3)); } @@ -187,7 +187,7 @@ fn test_add_sparse_merkle_tree_one_level() -> Result<(), MerkleError> { .unwrap() .with_leaves(keys2.into_iter().zip(leaves2.into_iter())) .unwrap(); - let store: MerkleStore = smt.clone().into(); + let store = MerkleStore::from(&smt); let idx = NodeIndex::make(1, 0); assert_eq!(smt.get_node(idx).unwrap(), leaves2[0]); @@ -207,7 +207,7 @@ fn test_sparse_merkle_tree() -> Result<(), MerkleError> { .with_leaves(KEYS4.into_iter().zip(LEAVES4.into_iter())) .unwrap(); - let store: MerkleStore = smt.clone().into(); + let store = MerkleStore::from(&smt); // STORE LEAVES ARE CORRECT ============================================================== // checks the leaves in the store corresponds to the expected values @@ -465,7 +465,7 @@ fn wont_open_to_different_depth_root() { // attempt to fetch a node on the maximum depth, and it should fail because the root shouldn't // exist for the set. let mtree = MerkleTree::new(vec![a, b]).unwrap(); - let store: MerkleStore = mtree.clone().into(); + let store = MerkleStore::from(&mtree); let index = NodeIndex::root(); let err = store.get_node(root, index).err().unwrap(); assert_eq!(err, MerkleError::RootNotInStore(root)); @@ -493,7 +493,7 @@ fn store_path_opens_from_leaf() { let root = Rpo256::merge(&[m.into(), n.into()]); let mtree = MerkleTree::new(vec![a, b, c, d, e, f, g, h]).unwrap(); - let store: MerkleStore = mtree.clone().into(); + 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()); @@ -503,7 +503,7 @@ fn store_path_opens_from_leaf() { #[test] fn test_set_node() -> Result<(), MerkleError> { let mtree = MerkleTree::new(LEAVES4.to_vec())?; - let mut store: MerkleStore = mtree.clone().into(); + 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; @@ -515,7 +515,7 @@ fn test_set_node() -> Result<(), MerkleError> { #[test] fn test_constructors() -> Result<(), MerkleError> { let mtree = MerkleTree::new(LEAVES4.to_vec())?; - let store: MerkleStore = mtree.clone().into(); + let store = MerkleStore::from(&mtree); let depth = mtree.depth(); let leaves = 2u64.pow(depth.into()); @@ -530,7 +530,7 @@ fn test_constructors() -> Result<(), MerkleError> { .unwrap() .with_leaves(KEYS4.into_iter().zip(LEAVES4.into_iter())) .unwrap(); - let store: MerkleStore = smt.clone().into(); + let store = MerkleStore::from(&smt); let depth = smt.depth(); for key in KEYS4 { From 22c9f382c497462bdca7e35a989f9dc60a3caa06 Mon Sep 17 00:00:00 2001 From: Bobbin Threadbare Date: Fri, 21 Apr 2023 11:39:49 -0700 Subject: [PATCH 5/6] fix: serialization test --- src/merkle/store/tests.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/merkle/store/tests.rs b/src/merkle/store/tests.rs index ca5be9e..28ac8d7 100644 --- a/src/merkle/store/tests.rs +++ b/src/merkle/store/tests.rs @@ -5,7 +5,7 @@ use crate::{ Felt, Word, WORD_SIZE, ZERO, }; -#[cfg(std)] +#[cfg(feature = "std")] use std::error::Error; const KEYS4: [u64; 4] = [0, 1, 2, 3]; @@ -716,12 +716,12 @@ fn get_leaf_depth_works_with_depth_8() { 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 mtree = MerkleTree::new(LEAVES4.to_vec())?; - let store: MerkleStore = mtree.clone().into(); - let decoded = MerkleStore::read_from_bytes(&original.to_bytes())?; - assert_eq!(original, decoded); + let store = MerkleStore::from(&mtree); + let decoded = MerkleStore::read_from_bytes(&store.to_bytes()).expect("deserialization failed"); + assert_eq!(store, decoded); Ok(()) } From 130ae3d12a54cae50ffc49f59456236146719060 Mon Sep 17 00:00:00 2001 From: Bobbin Threadbare Date: Fri, 21 Apr 2023 14:27:58 -0700 Subject: [PATCH 6/6] feat: add inner node iterator to MerklePath --- src/merkle/merkle_tree.rs | 12 +++--- src/merkle/path.rs | 84 ++++++++++++++++++++++++++++++++++++--- src/merkle/store/mod.rs | 59 ++++++++------------------- src/merkle/store/tests.rs | 14 ++++--- 4 files changed, 109 insertions(+), 60 deletions(-) diff --git a/src/merkle/merkle_tree.rs b/src/merkle/merkle_tree.rs index 106ec27..42f289a 100644 --- a/src/merkle/merkle_tree.rs +++ b/src/merkle/merkle_tree.rs @@ -150,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 } @@ -165,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 { 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/store/mod.rs b/src/merkle/store/mod.rs index 442ff00..96ca54a 100644 --- a/src/merkle/store/mod.rs +++ b/src/merkle/store/mod.rs @@ -115,26 +115,6 @@ impl MerkleStore { MerkleStore { nodes } } - /// 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) - } - // PUBLIC ACCESSORS // -------------------------------------------------------------------------------------------- @@ -280,8 +260,11 @@ impl MerkleStore { // STATE MUTATORS // -------------------------------------------------------------------------------------------- - /// Adds a new [InnerNodeInfo] into the store. - pub fn extend(&mut self, iter: impl Iterator) -> &mut MerkleStore { + /// Adds a sequence of nodes yielded by the provided iterator into the store. + pub fn extend(&mut self, iter: I) -> &mut MerkleStore + where + I: Iterator, + { for node in iter { let value: RpoDigest = node.value.into(); let left: RpoDigest = node.left.into(); @@ -301,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(), - }, - ); - - index.move_up(); - node = parent.into(); - } + debug_assert_eq!(Rpo256::merge(&[left, right]), value); + self.nodes.insert(value, Node { left, right }); - Ok(node) + node.value + }); + Ok(root) } /// Adds all the nodes of multiple Merkle paths into the store. diff --git a/src/merkle/store/tests.rs b/src/merkle/store/tests.rs index 28ac8d7..02e12b2 100644 --- a/src/merkle/store/tests.rs +++ b/src/merkle/store/tests.rs @@ -547,12 +547,14 @@ fn test_constructors() -> Result<(), MerkleError> { (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] {