Skip to content

Commit 528a69b

Browse files
authored
Merge pull request #18 from nervosnetwork/update-all
feat: Add update_all function
2 parents 08c7122 + 5d6c1b2 commit 528a69b

File tree

2 files changed

+88
-0
lines changed

2 files changed

+88
-0
lines changed

src/tests/tree.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,17 @@ proptest! {
467467
}
468468
}
469469

470+
#[test]
471+
fn test_smt_update_all((pairs, _n) in leaves(1, 20), (pairs2, _n2) in leaves(1, 10)){
472+
let mut smt = new_smt(pairs.clone());
473+
for (k, v) in pairs2.clone().into_iter() {
474+
smt.update(k, v).expect("update");
475+
}
476+
let mut smt2 = new_smt(pairs.clone());
477+
smt2.update_all(pairs2).expect("update all");
478+
assert_eq!(smt.root(), smt2.root());
479+
}
480+
470481
#[test]
471482
fn test_smt_random_insert_order((pairs, _n) in leaves(5, 50)){
472483
let smt = new_smt(pairs.clone());

src/tree.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,83 @@ impl<H: Hasher + Default, V: Value, S: Store<V>> SparseMerkleTree<H, V, S> {
139139
Ok(&self.root)
140140
}
141141

142+
/// Update multiple leaves at once
143+
pub fn update_all(&mut self, mut leaves: Vec<(H256, V)>) -> Result<&H256> {
144+
// Dedup(only keep the last of each key) and sort leaves
145+
leaves.reverse();
146+
leaves.sort_by_key(|(a, _)| a.clone());
147+
leaves.dedup_by_key(|(a, _)| a.clone());
148+
149+
let mut nodes: Vec<(H256, MergeValue)> = Vec::new();
150+
for (k, v) in leaves {
151+
let value = MergeValue::from_h256(v.to_h256());
152+
if !value.is_zero() {
153+
self.store.insert_leaf(k, v)?;
154+
} else {
155+
self.store.remove_leaf(&k)?;
156+
}
157+
nodes.push((k, value));
158+
}
159+
160+
for height in 0..=core::u8::MAX {
161+
let mut next_nodes: Vec<(H256, MergeValue)> = Vec::new();
162+
let mut i = 0;
163+
while i < nodes.len() {
164+
let (current_key, current_merge_value) = &nodes[i];
165+
i += 1;
166+
let parent_key = current_key.parent_path(height);
167+
let parent_branch_key = BranchKey::new(height, parent_key);
168+
169+
// Test for neighbors
170+
let mut right = None;
171+
if i < nodes.len() && (!current_key.is_right(height)) {
172+
let (neighbor_key, neighbor_value) = &nodes[i];
173+
let mut right_key = current_key.clone();
174+
right_key.set_bit(height);
175+
if right_key == *neighbor_key {
176+
right = Some(neighbor_value.clone());
177+
i += 1;
178+
}
179+
}
180+
181+
let (left, right) = if let Some(right_merge_value) = right {
182+
(current_merge_value.clone(), right_merge_value)
183+
} else {
184+
// In case neighbor is not available, fetch from store
185+
if let Some(parent_branch) = self.store.get_branch(&parent_branch_key)? {
186+
if current_key.is_right(height) {
187+
(parent_branch.left, current_merge_value.clone())
188+
} else {
189+
(current_merge_value.clone(), parent_branch.right)
190+
}
191+
} else if current_key.is_right(height) {
192+
(MergeValue::zero(), current_merge_value.clone())
193+
} else {
194+
(current_merge_value.clone(), MergeValue::zero())
195+
}
196+
};
197+
198+
if !left.is_zero() || !right.is_zero() {
199+
self.store.insert_branch(
200+
parent_branch_key,
201+
BranchNode {
202+
left: left.clone(),
203+
right: right.clone(),
204+
},
205+
)?;
206+
} else {
207+
self.store.remove_branch(&parent_branch_key)?;
208+
}
209+
next_nodes.push((parent_key, merge::<H>(height, &parent_key, &left, &right)));
210+
}
211+
nodes = next_nodes;
212+
}
213+
214+
assert!(nodes.len() == 1);
215+
self.root = nodes[0].1.hash::<H>();
216+
Ok(&self.root)
217+
}
218+
142219
/// Get value of a leaf
143220
/// return zero value if leaf not exists
144221
pub fn get(&self, key: &H256) -> Result<V> {

0 commit comments

Comments
 (0)