1use alloc::{
2 collections::{BTreeMap, BTreeSet},
3 vec::Vec,
4};
5
6use super::{MmrDelta, MmrPath};
7use crate::{
8 Word,
9 hash::poseidon2::Poseidon2,
10 merkle::{
11 InnerNodeInfo, MerklePath,
12 mmr::{InOrderIndex, MmrError, MmrPeaks, forest::Forest},
13 },
14 utils::{ByteReader, ByteWriter, Deserializable, Serializable},
15};
16
17type NodeMap = BTreeMap<InOrderIndex, Word>;
21
22#[derive(Debug, Clone, PartialEq, Eq)]
30pub struct PartialMmr {
31 pub(crate) forest: Forest,
42
43 pub(crate) peaks: Vec<Word>,
55
56 pub(crate) nodes: NodeMap,
68
69 pub(crate) track_latest: bool,
74}
75
76impl Default for PartialMmr {
77 fn default() -> Self {
79 let forest = Forest::empty();
80 let peaks = Vec::new();
81 let nodes = BTreeMap::new();
82 let track_latest = false;
83
84 Self { forest, peaks, nodes, track_latest }
85 }
86}
87
88impl PartialMmr {
89 pub fn from_peaks(peaks: MmrPeaks) -> Self {
94 let forest = peaks.forest();
95 let peaks = peaks.into();
96 let nodes = BTreeMap::new();
97 let track_latest = false;
98
99 Self { forest, peaks, nodes, track_latest }
100 }
101
102 pub fn from_parts(peaks: MmrPeaks, nodes: NodeMap, track_latest: bool) -> Self {
107 let forest = peaks.forest();
108 let peaks = peaks.into();
109
110 Self { forest, peaks, nodes, track_latest }
111 }
112
113 pub fn forest(&self) -> Forest {
121 self.forest
122 }
123
124 pub fn num_leaves(&self) -> usize {
126 self.forest.num_leaves()
127 }
128
129 pub fn peaks(&self) -> MmrPeaks {
131 MmrPeaks::new(self.forest, self.peaks.clone()).expect("invalid MMR peaks")
134 }
135
136 pub fn is_tracked(&self, pos: usize) -> bool {
139 let leaves = self.forest.num_leaves();
140 if pos >= leaves {
141 return false;
142 } else if pos == leaves - 1 && self.forest.has_single_leaf_tree() {
143 return self.track_latest;
146 }
147
148 let leaf_index = InOrderIndex::from_leaf_pos(pos);
149 self.is_tracked_node(&leaf_index)
150 }
151
152 pub fn open(&self, pos: usize) -> Result<Option<MmrPath>, MmrError> {
163 let tree_bit = self
164 .forest
165 .leaf_to_corresponding_tree(pos)
166 .ok_or(MmrError::PositionNotFound(pos))?;
167 let depth = tree_bit as usize;
168
169 let mut nodes = Vec::with_capacity(depth);
170 let mut idx = InOrderIndex::from_leaf_pos(pos);
171
172 while let Some(node) = self.nodes.get(&idx.sibling()) {
173 nodes.push(*node);
174 idx = idx.parent();
175 }
176
177 debug_assert!(nodes.is_empty() || nodes.len() == depth);
179
180 if nodes.len() != depth {
181 Ok(None)
183 } else {
184 Ok(Some(MmrPath::new(self.forest, pos, MerklePath::new(nodes))))
185 }
186 }
187
188 pub fn nodes(&self) -> impl Iterator<Item = (&InOrderIndex, &Word)> {
193 self.nodes.iter()
194 }
195
196 pub fn inner_nodes<'a, I: Iterator<Item = (usize, Word)> + 'a>(
201 &'a self,
202 mut leaves: I,
203 ) -> impl Iterator<Item = InnerNodeInfo> + 'a {
204 let stack = if let Some((pos, leaf)) = leaves.next() {
205 let idx = InOrderIndex::from_leaf_pos(pos);
206 vec![(idx, leaf)]
207 } else {
208 Vec::new()
209 };
210
211 InnerNodeIterator {
212 nodes: &self.nodes,
213 leaves,
214 stack,
215 seen_nodes: BTreeSet::new(),
216 }
217 }
218
219 pub fn add(&mut self, leaf: Word, track: bool) -> Vec<(InOrderIndex, Word)> {
227 self.forest.append_leaf();
228 let merges = self.forest.smallest_tree_height_unchecked();
230 let mut new_nodes = Vec::with_capacity(merges);
231
232 let peak = if merges == 0 {
233 self.track_latest = track;
234 leaf
235 } else {
236 let mut track_right = track;
237 let mut track_left = self.track_latest;
238
239 let mut right = leaf;
240 let mut right_idx = self.forest.rightmost_in_order_index();
241
242 for _ in 0..merges {
243 let left = self.peaks.pop().expect("Missing peak");
244 let left_idx = right_idx.sibling();
245
246 if track_right {
247 let old = self.nodes.insert(left_idx, left);
248 new_nodes.push((left_idx, left));
249
250 debug_assert!(
251 old.is_none(),
252 "Idx {left_idx:?} already contained an element {old:?}",
253 );
254 };
255 if track_left {
256 let old = self.nodes.insert(right_idx, right);
257 new_nodes.push((right_idx, right));
258
259 debug_assert!(
260 old.is_none(),
261 "Idx {right_idx:?} already contained an element {old:?}",
262 );
263 };
264
265 right_idx = right_idx.parent();
270
271 right = Poseidon2::merge(&[left, right]);
274
275 track_right = track_right || track_left;
279
280 track_left = self.is_tracked_node(&right_idx.sibling());
283 }
284 right
285 };
286
287 self.peaks.push(peak);
288
289 new_nodes
290 }
291
292 pub fn track(
303 &mut self,
304 leaf_pos: usize,
305 leaf: Word,
306 path: &MerklePath,
307 ) -> Result<(), MmrError> {
308 let tree = Forest::new(1 << path.depth());
311 if (tree & self.forest).is_empty() {
312 return Err(MmrError::UnknownPeak(path.depth()));
313 };
314
315 if leaf_pos + 1 == self.forest.num_leaves()
316 && path.depth() == 0
317 && self.peaks.last().is_some_and(|v| *v == leaf)
318 {
319 self.track_latest = true;
320 return Ok(());
321 }
322
323 let target_forest = self.forest ^ (self.forest & tree.all_smaller_trees_unchecked());
326 let peak_pos = target_forest.num_trees() - 1;
327
328 let path_idx = leaf_pos - (target_forest ^ tree).num_leaves();
330
331 let computed = path
334 .compute_root(path_idx as u64, leaf)
335 .map_err(MmrError::MerkleRootComputationFailed)?;
336 if self.peaks[peak_pos] != computed {
337 return Err(MmrError::PeakPathMismatch);
338 }
339
340 let mut idx = InOrderIndex::from_leaf_pos(leaf_pos);
341 for leaf in path.nodes() {
342 self.nodes.insert(idx.sibling(), *leaf);
343 idx = idx.parent();
344 }
345
346 Ok(())
347 }
348
349 pub fn untrack(&mut self, leaf_pos: usize) -> Vec<(InOrderIndex, Word)> {
357 let mut idx = InOrderIndex::from_leaf_pos(leaf_pos);
358 let mut removed = Vec::new();
359
360 while let Some(word) = self.nodes.remove(&idx.sibling()) {
366 removed.push((idx.sibling(), word));
367 if self.nodes.contains_key(&idx) {
368 break;
369 }
370 idx = idx.parent();
371 }
372
373 removed
374 }
375
376 pub fn apply(&mut self, delta: MmrDelta) -> Result<Vec<(InOrderIndex, Word)>, MmrError> {
379 if delta.forest < self.forest {
380 return Err(MmrError::InvalidPeaks(format!(
381 "forest of mmr delta {} is less than current forest {}",
382 delta.forest, self.forest
383 )));
384 }
385
386 let mut inserted_nodes = Vec::new();
387
388 if delta.forest == self.forest {
389 if !delta.data.is_empty() {
390 return Err(MmrError::InvalidUpdate);
391 }
392
393 return Ok(inserted_nodes);
394 }
395
396 let changes = self.forest ^ delta.forest;
398 let largest = changes.largest_tree_unchecked();
401 let merges = self.forest & largest.all_smaller_trees_unchecked();
403
404 debug_assert!(
405 !self.track_latest || merges.has_single_leaf_tree(),
406 "if there is an odd element, a merge is required"
407 );
408
409 let (merge_count, new_peaks) = if !merges.is_empty() {
411 let depth = largest.smallest_tree_height_unchecked();
412 let skipped = merges.smallest_tree_height_unchecked();
414 let computed = merges.num_trees() - 1;
415 let merge_count = depth - skipped - computed;
416
417 let new_peaks = delta.forest & largest.all_smaller_trees_unchecked();
418
419 (merge_count, new_peaks)
420 } else {
421 (0, changes)
422 };
423
424 if delta.data.len() != merge_count + new_peaks.num_trees() {
426 return Err(MmrError::InvalidUpdate);
427 }
428
429 let mut update_count = 0;
431
432 if !merges.is_empty() {
433 let mut peak_idx = self.forest.root_in_order_index();
435
436 self.peaks.reverse();
438
439 let mut track = self.track_latest;
441 self.track_latest = false;
442
443 let mut peak_count = 0;
444 let mut target = merges.smallest_tree_unchecked();
445 let mut new = delta.data[0];
446 update_count += 1;
447
448 while target < largest {
449 if target != Forest::new(1) && !track {
452 track = self.is_tracked_node(&peak_idx);
453 }
454
455 let (left, right) = if !(target & merges).is_empty() {
458 let peak = self.peaks[peak_count];
459 let sibling_idx = peak_idx.sibling();
460
461 if self.is_tracked_node(&sibling_idx) {
464 self.nodes.insert(peak_idx, new);
465 inserted_nodes.push((peak_idx, new));
466 }
467 peak_count += 1;
468 (peak, new)
469 } else {
470 let update = delta.data[update_count];
471 update_count += 1;
472 (new, update)
473 };
474
475 if track {
476 let sibling_idx = peak_idx.sibling();
477 if peak_idx.is_left_child() {
478 self.nodes.insert(sibling_idx, right);
479 inserted_nodes.push((sibling_idx, right));
480 } else {
481 self.nodes.insert(sibling_idx, left);
482 inserted_nodes.push((sibling_idx, left));
483 }
484 }
485
486 peak_idx = peak_idx.parent();
487 new = Poseidon2::merge(&[left, right]);
488 target = target.next_larger_tree();
489 }
490
491 debug_assert!(peak_count == merges.num_trees());
492
493 self.peaks.reverse();
495 self.peaks.truncate(self.peaks.len() - peak_count);
497 self.peaks.push(new);
499 }
500
501 self.peaks.extend_from_slice(&delta.data[update_count..]);
505 self.forest = delta.forest;
506
507 debug_assert!(self.peaks.len() == self.forest.num_trees());
508
509 Ok(inserted_nodes)
510 }
511
512 fn is_tracked_node(&self, node_index: &InOrderIndex) -> bool {
518 if node_index.is_leaf() {
519 self.nodes.contains_key(&node_index.sibling())
520 } else {
521 let left_child = node_index.left_child();
522 let right_child = node_index.right_child();
523 self.nodes.contains_key(&left_child) | self.nodes.contains_key(&right_child)
524 }
525 }
526}
527
528impl From<MmrPeaks> for PartialMmr {
532 fn from(peaks: MmrPeaks) -> Self {
533 Self::from_peaks(peaks)
534 }
535}
536
537impl From<PartialMmr> for MmrPeaks {
538 fn from(partial_mmr: PartialMmr) -> Self {
539 MmrPeaks::new(partial_mmr.forest, partial_mmr.peaks).unwrap()
542 }
543}
544
545impl From<&MmrPeaks> for PartialMmr {
546 fn from(peaks: &MmrPeaks) -> Self {
547 Self::from_peaks(peaks.clone())
548 }
549}
550
551impl From<&PartialMmr> for MmrPeaks {
552 fn from(partial_mmr: &PartialMmr) -> Self {
553 MmrPeaks::new(partial_mmr.forest, partial_mmr.peaks.clone()).unwrap()
556 }
557}
558
559pub struct InnerNodeIterator<'a, I: Iterator<Item = (usize, Word)>> {
564 nodes: &'a NodeMap,
565 leaves: I,
566 stack: Vec<(InOrderIndex, Word)>,
567 seen_nodes: BTreeSet<InOrderIndex>,
568}
569
570impl<I: Iterator<Item = (usize, Word)>> Iterator for InnerNodeIterator<'_, I> {
571 type Item = InnerNodeInfo;
572
573 fn next(&mut self) -> Option<Self::Item> {
574 while let Some((idx, node)) = self.stack.pop() {
575 let parent_idx = idx.parent();
576 let new_node = self.seen_nodes.insert(parent_idx);
577
578 if new_node && let Some(sibling) = self.nodes.get(&idx.sibling()) {
581 let (left, right) = if parent_idx.left_child() == idx {
582 (node, *sibling)
583 } else {
584 (*sibling, node)
585 };
586 let parent = Poseidon2::merge(&[left, right]);
587 let inner_node = InnerNodeInfo { value: parent, left, right };
588
589 self.stack.push((parent_idx, parent));
590 return Some(inner_node);
591 }
592
593 if let Some((pos, leaf)) = self.leaves.next() {
595 let idx = InOrderIndex::from_leaf_pos(pos);
596 self.stack.push((idx, leaf));
597 }
598 }
599
600 None
601 }
602}
603
604impl Serializable for PartialMmr {
605 fn write_into<W: ByteWriter>(&self, target: &mut W) {
606 self.forest.num_leaves().write_into(target);
607 self.peaks.write_into(target);
608 self.nodes.write_into(target);
609 target.write_bool(self.track_latest);
610 }
611}
612
613impl Deserializable for PartialMmr {
614 fn read_from<R: ByteReader>(
615 source: &mut R,
616 ) -> Result<Self, crate::utils::DeserializationError> {
617 let forest = Forest::new(usize::read_from(source)?);
618 let peaks = Vec::<Word>::read_from(source)?;
619 let nodes = NodeMap::read_from(source)?;
620 let track_latest = source.read_bool()?;
621
622 Ok(Self { forest, peaks, nodes, track_latest })
623 }
624}
625
626#[cfg(test)]
630mod tests {
631 use alloc::{collections::BTreeSet, vec::Vec};
632
633 use super::{MmrPeaks, PartialMmr};
634 use crate::{
635 Word,
636 merkle::{
637 NodeIndex, int_to_node,
638 mmr::{Mmr, forest::Forest},
639 store::MerkleStore,
640 },
641 utils::{Deserializable, Serializable},
642 };
643
644 const LEAVES: [Word; 7] = [
645 int_to_node(0),
646 int_to_node(1),
647 int_to_node(2),
648 int_to_node(3),
649 int_to_node(4),
650 int_to_node(5),
651 int_to_node(6),
652 ];
653
654 #[test]
655 fn test_partial_mmr_apply_delta() {
656 let mut mmr = Mmr::default();
658 (0..10).for_each(|i| mmr.add(int_to_node(i)));
659 let mut partial_mmr: PartialMmr = mmr.peaks().into();
660
661 {
663 let node = mmr.get(1).unwrap();
664 let proof = mmr.open(1).unwrap();
665 partial_mmr.track(1, node, proof.path().merkle_path()).unwrap();
666 }
667
668 {
669 let node = mmr.get(8).unwrap();
670 let proof = mmr.open(8).unwrap();
671 partial_mmr.track(8, node, proof.path().merkle_path()).unwrap();
672 }
673
674 (10..12).for_each(|i| mmr.add(int_to_node(i)));
676 validate_apply_delta(&mmr, &mut partial_mmr);
677
678 mmr.add(int_to_node(12));
680 validate_apply_delta(&mmr, &mut partial_mmr);
681 {
682 let node = mmr.get(12).unwrap();
683 let proof = mmr.open(12).unwrap();
684 partial_mmr.track(12, node, proof.path().merkle_path()).unwrap();
685 assert!(partial_mmr.track_latest);
686 }
687
688 (13..16).for_each(|i| mmr.add(int_to_node(i)));
692 validate_apply_delta(&mmr, &mut partial_mmr);
693 }
694
695 fn validate_apply_delta(mmr: &Mmr, partial: &mut PartialMmr) {
696 let tracked_leaves = partial
697 .nodes
698 .iter()
699 .filter(|&(index, _)| index.is_leaf())
700 .map(|(index, _)| index.sibling())
701 .collect::<Vec<_>>();
702 let nodes_before = partial.nodes.clone();
703
704 let delta = mmr.get_delta(partial.forest(), mmr.forest()).unwrap();
706 let nodes_delta = partial.apply(delta).unwrap();
707
708 assert_eq!(mmr.peaks(), partial.peaks());
710
711 let mut expected_nodes = nodes_before;
712 for (key, value) in nodes_delta {
713 assert!(expected_nodes.insert(key, value).is_none());
715 }
716
717 assert_eq!(expected_nodes, partial.nodes);
719
720 for index in tracked_leaves {
722 let pos = index.inner() / 2;
723 let proof1 = partial.open(pos).unwrap().unwrap();
724 let proof2 = mmr.open(pos).unwrap();
725 assert_eq!(proof1, *proof2.path());
726 }
727 }
728
729 #[test]
730 fn test_partial_mmr_inner_nodes_iterator() {
731 let mmr: Mmr = LEAVES.into();
733 let first_peak = mmr.peaks().peaks()[0];
734
735 let node1 = mmr.get(1).unwrap();
739 let proof1 = mmr.open(1).unwrap();
740
741 let mut partial_mmr: PartialMmr = mmr.peaks().into();
743 partial_mmr.track(1, node1, proof1.path().merkle_path()).unwrap();
744
745 assert_eq!(partial_mmr.inner_nodes([].iter().cloned()).next(), None);
747
748 let mut store: MerkleStore = MerkleStore::new();
750 store.extend(partial_mmr.inner_nodes([(1, node1)].iter().cloned()));
751
752 let index1 = NodeIndex::new(2, 1).unwrap();
753 let path1 = store.get_path(first_peak, index1).unwrap().path;
754
755 assert_eq!(path1, *proof1.path().merkle_path());
756
757 let mut partial_mmr: PartialMmr = mmr.peaks().into();
761
762 let node0 = mmr.get(0).unwrap();
763 let proof0 = mmr.open(0).unwrap();
764
765 let node2 = mmr.get(2).unwrap();
766 let proof2 = mmr.open(2).unwrap();
767
768 partial_mmr.track(0, node0, proof0.path().merkle_path()).unwrap();
769 partial_mmr.track(1, node1, proof1.path().merkle_path()).unwrap();
770 partial_mmr.track(2, node2, proof2.path().merkle_path()).unwrap();
771
772 let leaves = [(0, node0), (1, node1), (2, node2)];
774 let mut nodes = BTreeSet::new();
775 for node in partial_mmr.inner_nodes(leaves.iter().cloned()) {
776 assert!(nodes.insert(node.value));
777 }
778
779 store.extend(partial_mmr.inner_nodes(leaves.iter().cloned()));
781
782 let index0 = NodeIndex::new(2, 0).unwrap();
783 let index1 = NodeIndex::new(2, 1).unwrap();
784 let index2 = NodeIndex::new(2, 2).unwrap();
785
786 let path0 = store.get_path(first_peak, index0).unwrap().path;
787 let path1 = store.get_path(first_peak, index1).unwrap().path;
788 let path2 = store.get_path(first_peak, index2).unwrap().path;
789
790 assert_eq!(path0, *proof0.path().merkle_path());
791 assert_eq!(path1, *proof1.path().merkle_path());
792 assert_eq!(path2, *proof2.path().merkle_path());
793
794 let mut partial_mmr: PartialMmr = mmr.peaks().into();
798
799 let node5 = mmr.get(5).unwrap();
800 let proof5 = mmr.open(5).unwrap();
801
802 partial_mmr.track(1, node1, proof1.path().merkle_path()).unwrap();
803 partial_mmr.track(5, node5, proof5.path().merkle_path()).unwrap();
804
805 let mut store: MerkleStore = MerkleStore::new();
807 store.extend(partial_mmr.inner_nodes([(1, node1), (5, node5)].iter().cloned()));
808
809 let index1 = NodeIndex::new(2, 1).unwrap();
810 let index5 = NodeIndex::new(1, 1).unwrap();
811
812 let second_peak = mmr.peaks().peaks()[1];
813
814 let path1 = store.get_path(first_peak, index1).unwrap().path;
815 let path5 = store.get_path(second_peak, index5).unwrap().path;
816
817 assert_eq!(path1, *proof1.path().merkle_path());
818 assert_eq!(path5, *proof5.path().merkle_path());
819 }
820
821 #[test]
822 fn test_partial_mmr_add_without_track() {
823 let mut mmr = Mmr::default();
824 let empty_peaks = MmrPeaks::new(Forest::empty(), vec![]).unwrap();
825 let mut partial_mmr = PartialMmr::from_peaks(empty_peaks);
826
827 for el in (0..256).map(int_to_node) {
828 mmr.add(el);
829 partial_mmr.add(el, false);
830
831 assert_eq!(mmr.peaks(), partial_mmr.peaks());
832 assert_eq!(mmr.forest(), partial_mmr.forest());
833 }
834 }
835
836 #[test]
837 fn test_partial_mmr_add_with_track() {
838 let mut mmr = Mmr::default();
839 let empty_peaks = MmrPeaks::new(Forest::empty(), vec![]).unwrap();
840 let mut partial_mmr = PartialMmr::from_peaks(empty_peaks);
841
842 for i in 0..256 {
843 let el = int_to_node(i as u64);
844 mmr.add(el);
845 partial_mmr.add(el, true);
846
847 assert_eq!(mmr.peaks(), partial_mmr.peaks());
848 assert_eq!(mmr.forest(), partial_mmr.forest());
849
850 for pos in 0..i {
851 let mmr_proof = mmr.open(pos).unwrap();
852 let partialmmr_proof = partial_mmr.open(pos).unwrap().unwrap();
853 assert_eq!(*mmr_proof.path(), partialmmr_proof);
854 }
855 }
856 }
857
858 #[test]
859 fn test_partial_mmr_add_existing_track() {
860 let mut mmr = Mmr::from((0..7).map(int_to_node));
861
862 let mut partial_mmr = PartialMmr::from_peaks(mmr.peaks());
864 let path_to_5 = mmr.open(5).unwrap().path().merkle_path().clone();
865 let leaf_at_5 = mmr.get(5).unwrap();
866 partial_mmr.track(5, leaf_at_5, &path_to_5).unwrap();
867
868 let leaf_at_7 = int_to_node(7);
870 mmr.add(leaf_at_7);
871 partial_mmr.add(leaf_at_7, false);
872
873 assert_eq!(*mmr.open(5).unwrap().path(), partial_mmr.open(5).unwrap().unwrap());
875 }
876
877 #[test]
878 fn test_partial_mmr_serialization() {
879 let mmr = Mmr::from((0..7).map(int_to_node));
880 let partial_mmr = PartialMmr::from_peaks(mmr.peaks());
881
882 let bytes = partial_mmr.to_bytes();
883 let decoded = PartialMmr::read_from_bytes(&bytes).unwrap();
884
885 assert_eq!(partial_mmr, decoded);
886 }
887
888 #[test]
889 fn test_partial_mmr_untrack() {
890 let mmr: Mmr = LEAVES.into();
892
893 let node1 = mmr.get(1).unwrap();
895 let proof1 = mmr.open(1).unwrap();
896
897 let node2 = mmr.get(2).unwrap();
899 let proof2 = mmr.open(2).unwrap();
900
901 let mut partial_mmr: PartialMmr = mmr.peaks().into();
903 partial_mmr.track(1, node1, proof1.path().merkle_path()).unwrap();
904 partial_mmr.track(2, node2, proof2.path().merkle_path()).unwrap();
905
906 partial_mmr.untrack(1);
908 partial_mmr.untrack(2);
909
910 assert!(!partial_mmr.is_tracked(1));
912 assert!(!partial_mmr.is_tracked(2));
913 assert_eq!(partial_mmr.nodes().count(), 0);
914 }
915
916 #[test]
917 fn test_partial_mmr_untrack_returns_removed_nodes() {
918 let mmr: Mmr = LEAVES.into();
920
921 let node1 = mmr.get(1).unwrap();
923 let proof1 = mmr.open(1).unwrap();
924
925 let mut partial_mmr: PartialMmr = mmr.peaks().into();
927
928 partial_mmr.track(1, node1, proof1.path().merkle_path()).unwrap();
930
931 let nodes_before: BTreeSet<_> =
933 partial_mmr.nodes().map(|(&idx, &word)| (idx, word)).collect();
934
935 let removed: BTreeSet<_> = partial_mmr.untrack(1).into_iter().collect();
937
938 assert_eq!(removed, nodes_before);
940
941 assert!(!partial_mmr.is_tracked(1));
943 assert_eq!(partial_mmr.nodes().count(), 0);
944 }
945
946 #[test]
947 fn test_partial_mmr_untrack_shared_nodes() {
948 let mmr: Mmr = LEAVES.into();
950
951 let node0 = mmr.get(0).unwrap();
953 let proof0 = mmr.open(0).unwrap();
954
955 let node1 = mmr.get(1).unwrap();
956 let proof1 = mmr.open(1).unwrap();
957
958 let mut partial_mmr: PartialMmr = mmr.peaks().into();
960
961 partial_mmr.track(0, node0, proof0.path().merkle_path()).unwrap();
963 partial_mmr.track(1, node1, proof1.path().merkle_path()).unwrap();
964
965 assert_eq!(partial_mmr.nodes().count(), 3);
970
971 let removed0 = partial_mmr.untrack(0);
975 assert_eq!(removed0.len(), 1);
976 assert_eq!(partial_mmr.nodes().count(), 2);
977 assert!(partial_mmr.is_tracked(1));
978
979 let removed1 = partial_mmr.untrack(1);
983 assert_eq!(removed1.len(), 2);
984 assert_eq!(partial_mmr.nodes().count(), 0);
985 assert!(!partial_mmr.is_tracked(1));
986 }
987}