Skip to content
This repository was archived by the owner on Jul 26, 2021. It is now read-only.

Commit ddc815f

Browse files
committed
Fix the inconsistent root when insert zero value leaf
1 parent fda2e67 commit ddc815f

File tree

3 files changed

+187
-17
lines changed

3 files changed

+187
-17
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ blake2b-rs = { version = "0.1", optional = true }
2222
proptest = "0.9"
2323
criterion = "0.2"
2424
rand = "0.7"
25+
hex = "0.4"
2526

2627
[[bench]]
2728
name = "smt_benchmark"

src/tests.rs

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::{
44
SparseMerkleTree,
55
};
66
use proptest::prelude::*;
7+
use rand::prelude::SliceRandom;
78

89
type SMT = SparseMerkleTree<Blake2bHasher, H256, DefaultStore<H256>>;
910

@@ -99,6 +100,95 @@ fn test_merkle_root() {
99100
assert_eq!(tree.root(), &expected_root);
100101
}
101102

103+
#[test]
104+
fn test_zero_value_donot_change_root() {
105+
let mut tree = SMT::default();
106+
let key = [
107+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
108+
0, 1,
109+
]
110+
.into();
111+
let value = H256::zero();
112+
tree.update(key, value).unwrap();
113+
assert_eq!(tree.root(), &H256::zero());
114+
assert_eq!(tree.store().leaves_map().len(), 0);
115+
assert_eq!(tree.store().branches_map().len(), 0);
116+
}
117+
118+
#[test]
119+
fn test_zero_value_donot_change_store() {
120+
let mut tree = SMT::default();
121+
let key = [
122+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
123+
0, 0,
124+
]
125+
.into();
126+
let value = [
127+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
128+
0, 1,
129+
]
130+
.into();
131+
tree.update(key, value).unwrap();
132+
assert_ne!(tree.root(), &H256::zero());
133+
let root = *tree.root();
134+
let store = tree.store().clone();
135+
136+
// insert a zero value leaf
137+
let key = [
138+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
139+
0, 1,
140+
]
141+
.into();
142+
let value = [
143+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
144+
0, 0,
145+
]
146+
.into();
147+
tree.update(key, value).unwrap();
148+
assert_eq!(tree.root(), &root);
149+
assert_eq!(tree.store().leaves_map(), store.leaves_map());
150+
assert_eq!(tree.store().branches_map(), store.branches_map());
151+
}
152+
153+
#[test]
154+
fn test_delete_a_leaf() {
155+
let mut tree = SMT::default();
156+
let key = [
157+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
158+
0, 0,
159+
]
160+
.into();
161+
let value = [
162+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
163+
0, 1,
164+
]
165+
.into();
166+
tree.update(key, value).unwrap();
167+
assert_ne!(tree.root(), &H256::zero());
168+
let root = *tree.root();
169+
let store = tree.store().clone();
170+
171+
// insert a leaf
172+
let key = [
173+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
174+
0, 1,
175+
]
176+
.into();
177+
let value = [
178+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
179+
0, 1,
180+
]
181+
.into();
182+
tree.update(key, value).unwrap();
183+
assert_ne!(tree.root(), &root);
184+
185+
// delete a leaf
186+
tree.update(key, H256::zero()).unwrap();
187+
assert_eq!(tree.root(), &root);
188+
assert_eq!(tree.store().leaves_map(), store.leaves_map());
189+
assert_eq!(tree.store().branches_map(), store.branches_map());
190+
}
191+
102192
fn test_construct(key: H256, value: H256) {
103193
// insert same value to sibling key will construct a different root
104194

@@ -324,4 +414,79 @@ proptest! {
324414
assert_eq!(smt.get(&k), Ok(v));
325415
}
326416
}
417+
418+
#[test]
419+
fn test_smt_random_insert_order((pairs, _n) in leaves(5, 30)){
420+
let smt = new_smt(pairs.clone());
421+
let root = *smt.root();
422+
423+
let mut pairs = pairs;
424+
let mut rng = rand::thread_rng();
425+
for _i in 0..10 {
426+
pairs.shuffle(&mut rng);
427+
let smt = new_smt(pairs.clone());
428+
let current_root = *smt.root();
429+
assert_eq!(root, current_root);
430+
}
431+
}
432+
433+
}
434+
435+
#[test]
436+
fn test_v0_2_broken_sample() {
437+
fn parse_h256(s: &str) -> H256 {
438+
let data = hex::decode(s).unwrap();
439+
let mut inner = [0u8; 32];
440+
inner.copy_from_slice(&data);
441+
H256::from(inner)
442+
}
443+
444+
let keys = vec![
445+
"0000000000000000000000000000000000000000000000000000000000000000",
446+
"0000000000000000000000000000000000000000000000000000000000000002",
447+
"0000000000000000000000000000000000000000000000000000000000000003",
448+
"0000000000000000000000000000000000000000000000000000000000000004",
449+
"0000000000000000000000000000000000000000000000000000000000000005",
450+
"0000000000000000000000000000000000000000000000000000000000000006",
451+
"000000000000000000000000000000000000000000000000000000000000000e",
452+
"f652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f",
453+
"f652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d40",
454+
"5eff886ea0ce6ca488a3d6e336d6c0f75f46d19b42c06ce5ee98e42c96d256c7",
455+
"6d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6df",
456+
]
457+
.into_iter()
458+
.map(parse_h256)
459+
.collect::<Vec<_>>();
460+
let values = vec![
461+
"000000000000000000000000c8328aabcd9b9e8e64fbc566c4385c3bdeb219d7",
462+
"000000000000000000000001c8328aabcd9b9e8e64fbc566c4385c3bdeb219d7",
463+
"0000384000001c2000000e1000000708000002580000012c000000780000003c",
464+
"000000000000000000093a80000546000002a300000151800000e10000007080",
465+
"000000000000000000000000000000000000000000000000000000000000000f",
466+
"0000000000000000000000000000000000000000000000000000000000000001",
467+
"00000000000000000000000000000000000000000000000000071afd498d0000",
468+
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
469+
"0000000000000000000000000000000000000000000000000000000000000000",
470+
"0000000000000000000000000000000000000000000000000000000000000001",
471+
"0000000000000000000000000000000000000000000000000000000000000000",
472+
]
473+
.into_iter()
474+
.map(parse_h256)
475+
.collect::<Vec<_>>();
476+
let mut pairs = keys
477+
.clone()
478+
.into_iter()
479+
.zip(values.into_iter())
480+
.collect::<Vec<_>>();
481+
let smt = new_smt(pairs.clone());
482+
let base_root = *smt.root();
483+
484+
// insert in random order
485+
let mut rng = rand::thread_rng();
486+
for _i in 0..10 {
487+
pairs.shuffle(&mut rng);
488+
let smt = new_smt(pairs.clone());
489+
let current_root = *smt.root();
490+
assert_eq!(base_root, current_root);
491+
}
327492
}

src/tree.rs

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -138,17 +138,18 @@ impl<H: Hasher + Default, V: Value, S: Store<V>> SparseMerkleTree<H, V, S> {
138138
// notice when value is zero the leaf is deleted, so we do not need to store it
139139
if !node.is_zero() {
140140
self.store.insert_leaf(node, LeafNode { key, value })?;
141-
}
142-
// build at least one branch for leaf
143-
self.store.insert_branch(
144-
node,
145-
BranchNode {
146-
key,
147-
fork_height: 0,
141+
142+
// build at least one branch for leaf
143+
self.store.insert_branch(
148144
node,
149-
sibling: H256::zero(),
150-
},
151-
)?;
145+
BranchNode {
146+
key,
147+
fork_height: 0,
148+
node,
149+
sibling: H256::zero(),
150+
},
151+
)?;
152+
}
152153

153154
// recompute the tree from bottom to top
154155
while !path.is_empty() {
@@ -163,13 +164,16 @@ impl<H: Hasher + Default, V: Value, S: Store<V>> SparseMerkleTree<H, V, S> {
163164
merge::<H>(&node, &sibling)
164165
};
165166

166-
let branch_node = BranchNode {
167-
fork_height: height as u8,
168-
sibling,
169-
node,
170-
key,
171-
};
172-
self.store.insert_branch(parent, branch_node)?;
167+
if !node.is_zero() {
168+
let branch_node = BranchNode {
169+
fork_height: height as u8,
170+
sibling,
171+
node,
172+
key,
173+
};
174+
self.store.insert_branch(parent, branch_node)?;
175+
}
176+
173177
node = parent;
174178
}
175179
self.root = node;

0 commit comments

Comments
 (0)