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