Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix panic in PartialMmr::untrack #382

Merged
merged 2 commits into from
Feb 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## 0.13.3 (tbd)

- Implement `PartialSmt` (#372, #381).
- Fix panic in `PartialMmr::untrack` (#382).

## 0.13.2 (2025-01-24)

Expand Down
33 changes: 29 additions & 4 deletions src/merkle/mmr/partial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,16 +341,13 @@ impl PartialMmr {
pub fn untrack(&mut self, leaf_pos: usize) {
let mut idx = InOrderIndex::from_leaf_pos(leaf_pos);

self.nodes.remove(&idx.sibling());

// `idx` represent the element that can be computed by the authentication path, because
// these elements can be computed they are not saved for the authentication of the current
// target. In other words, if the idx is present it was added for the authentication of
// another element, and no more elements should be removed otherwise it would remove that
// element's authentication data.
while !self.nodes.contains_key(&idx) {
while self.nodes.remove(&idx.sibling()).is_some() && !self.nodes.contains_key(&idx) {
idx = idx.parent();
self.nodes.remove(&idx.sibling());
}
}

Expand Down Expand Up @@ -949,4 +946,32 @@ mod tests {

assert_eq!(partial_mmr, decoded);
}

#[test]
fn test_partial_mmr_untrack() {
// build the MMR
let mmr: Mmr = LEAVES.into();

// get path and node for position 1
let node1 = mmr.get(1).unwrap();
let proof1 = mmr.open(1).unwrap();

// get path and node for position 2
let node2 = mmr.get(2).unwrap();
let proof2 = mmr.open(2).unwrap();

// create partial MMR and add authentication path to nodes at position 1 and 2
let mut partial_mmr: PartialMmr = mmr.peaks().into();
partial_mmr.track(1, node1, &proof1.merkle_path).unwrap();
partial_mmr.track(2, node2, &proof2.merkle_path).unwrap();

// untrack nodes at positions 1 and 2
partial_mmr.untrack(1);
partial_mmr.untrack(2);

// nodes should not longer be tracked
assert!(!partial_mmr.is_tracked(1));
assert!(!partial_mmr.is_tracked(2));
assert_eq!(partial_mmr.nodes().count(), 0);
}
}
Loading