fix: decrement leaf count in simple SMT when inserting empty value (#303)
Bobbin Threadbare 43513081+bobbinth@users.noreply.github.com
Tue, 02 Apr 2024 13:01:00 -0700
3 files changed,
34 insertions(+),
11 deletions(-)
M
CHANGELOG.md
→
CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.9.1 (2024-04-02) + +* Added `num_leaves()` method to `SimpleSmt` (#302). + ## 0.9.0 (2024-03-24) * [BREAKING] Removed deprecated re-exports from liballoc/libstd (#290).
M
src/merkle/smt/simple/mod.rs
→
src/merkle/smt/simple/mod.rs
@@ -122,6 +122,11 @@ pub fn root(&self) -> RpoDigest {
<Self as SparseMerkleTree<DEPTH>>::root(self) } + /// Returns the number of non-empty leaves in this tree. + pub fn num_leaves(&self) -> usize { + self.leaves.len() + } + /// Returns the leaf at the specified index. pub fn get_leaf(&self, key: &LeafIndex<DEPTH>) -> Word { <Self as SparseMerkleTree<DEPTH>>::get_leaf(self, key)@@ -150,11 +155,6 @@ /// Returns an opening of the leaf associated with `key`. Conceptually, an opening is a Merkle
/// path to the leaf, as well as the leaf itself. pub fn open(&self, key: &LeafIndex<DEPTH>) -> ValuePath { <Self as SparseMerkleTree<DEPTH>>::open(self, key) - } - - /// Returns a count of non-empty leaves. - pub fn leaf_count(&self) -> usize { - self.leaves.len() } // ITERATORS@@ -281,17 +281,18 @@ let _ = self.inner_nodes.remove(&index);
} fn insert_value(&mut self, key: LeafIndex<DEPTH>, value: Word) -> Option<Word> { - self.leaves.insert(key.value(), value) + if value == Self::EMPTY_VALUE { + self.leaves.remove(&key.value()) + } else { + self.leaves.insert(key.value(), value) + } } fn get_leaf(&self, key: &LeafIndex<DEPTH>) -> Word { - // the lookup in empty_hashes could fail only if empty_hashes were not built correctly - // by the constructor as we check the depth of the lookup above. let leaf_pos = key.value(); - match self.leaves.get(&leaf_pos) { Some(word) => *word, - None => Word::from(*EmptySubtreeRoots::entry(DEPTH, DEPTH)), + None => Self::EMPTY_VALUE, } }
M
src/merkle/smt/simple/tests.rs
→
src/merkle/smt/simple/tests.rs
@@ -50,6 +50,8 @@ const DEPTH: u8 = 3;
let mut smt = SimpleSmt::<DEPTH>::new().unwrap(); let mut values = ZERO_VALUES8.to_vec(); + assert_eq!(smt.num_leaves(), 0); + // insert single value let key = 6; let new_node = int_to_leaf(7);@@ -62,6 +64,7 @@ mt2.get_path(NodeIndex::make(3, 6)).unwrap(),
smt.open(&LeafIndex::<3>::new(6).unwrap()).path ); assert_eq!(old_value, EMPTY_WORD); + assert_eq!(smt.num_leaves(), 1); // insert second value at distinct leaf branch let key = 2;@@ -75,6 +78,7 @@ mt3.get_path(NodeIndex::make(3, 2)).unwrap(),
smt.open(&LeafIndex::<3>::new(2).unwrap()).path ); assert_eq!(old_value, EMPTY_WORD); + assert_eq!(smt.num_leaves(), 2); } /// Tests that [`SimpleSmt::with_contiguous_leaves`] works as expected@@ -146,10 +150,11 @@ Ok(())
} #[test] -fn update_leaf() { +fn test_insert() { const DEPTH: u8 = 3; let mut tree = SimpleSmt::<DEPTH>::with_leaves(KEYS8.into_iter().zip(digests_to_words(&VALUES8))).unwrap(); + assert_eq!(tree.num_leaves(), 8); // update one value let key = 3;@@ -161,6 +166,7 @@
let old_leaf = tree.insert(LeafIndex::<DEPTH>::new(key as u64).unwrap(), new_node); assert_eq!(expected_tree.root(), tree.root); assert_eq!(old_leaf, *VALUES8[key]); + assert_eq!(tree.num_leaves(), 8); // update another value let key = 6;@@ -171,6 +177,18 @@
let old_leaf = tree.insert(LeafIndex::<DEPTH>::new(key as u64).unwrap(), new_node); assert_eq!(expected_tree.root(), tree.root); assert_eq!(old_leaf, *VALUES8[key]); + assert_eq!(tree.num_leaves(), 8); + + // set a leaf to empty value + let key = 5; + let new_node = EMPTY_WORD; + expected_values[key] = new_node; + let expected_tree = MerkleTree::new(expected_values.clone()).unwrap(); + + let old_leaf = tree.insert(LeafIndex::<DEPTH>::new(key as u64).unwrap(), new_node); + assert_eq!(expected_tree.root(), tree.root); + assert_eq!(old_leaf, *VALUES8[key]); + assert_eq!(tree.num_leaves(), 7); } #[test]