1use alloc::{
2 collections::{BTreeMap, BTreeSet},
3 vec::Vec,
4};
5
6use winter_utils::{Deserializable, Serializable};
7
8use super::{MmrDelta, MmrProof, Rpo256, RpoDigest};
9use crate::merkle::{
10 mmr::{leaf_to_corresponding_tree, nodes_in_forest},
11 InOrderIndex, InnerNodeInfo, MerklePath, MmrError, MmrPeaks,
12};
13
14type NodeMap = BTreeMap<InOrderIndex, RpoDigest>;
18
19#[derive(Debug, Clone, PartialEq, Eq)]
27pub struct PartialMmr {
28 pub(crate) forest: usize,
39
40 pub(crate) peaks: Vec<RpoDigest>,
52
53 pub(crate) nodes: NodeMap,
65
66 pub(crate) track_latest: bool,
71}
72
73impl PartialMmr {
74 pub fn from_peaks(peaks: MmrPeaks) -> Self {
79 let forest = peaks.num_leaves();
80 let peaks = peaks.into();
81 let nodes = BTreeMap::new();
82 let track_latest = false;
83
84 Self { forest, peaks, nodes, track_latest }
85 }
86
87 pub fn from_parts(peaks: MmrPeaks, nodes: NodeMap, track_latest: bool) -> Self {
92 let forest = peaks.num_leaves();
93 let peaks = peaks.into();
94
95 Self { forest, peaks, nodes, track_latest }
96 }
97
98 pub fn forest(&self) -> usize {
106 self.forest
107 }
108
109 pub fn num_leaves(&self) -> usize {
111 self.forest
112 }
113
114 pub fn peaks(&self) -> MmrPeaks {
116 MmrPeaks::new(self.forest, self.peaks.clone()).expect("invalid MMR peaks")
119 }
120
121 pub fn is_tracked(&self, pos: usize) -> bool {
124 if pos >= self.forest {
125 return false;
126 } else if pos == self.forest - 1 && self.forest & 1 != 0 {
127 return self.track_latest;
130 }
131
132 let leaf_index = InOrderIndex::from_leaf_pos(pos);
133 self.is_tracked_node(&leaf_index)
134 }
135
136 pub fn open(&self, pos: usize) -> Result<Option<MmrProof>, MmrError> {
147 let tree_bit =
148 leaf_to_corresponding_tree(pos, self.forest).ok_or(MmrError::PositionNotFound(pos))?;
149 let depth = tree_bit as usize;
150
151 let mut nodes = Vec::with_capacity(depth);
152 let mut idx = InOrderIndex::from_leaf_pos(pos);
153
154 while let Some(node) = self.nodes.get(&idx.sibling()) {
155 nodes.push(*node);
156 idx = idx.parent();
157 }
158
159 debug_assert!(nodes.is_empty() || nodes.len() == depth);
161
162 if nodes.len() != depth {
163 Ok(None)
165 } else {
166 Ok(Some(MmrProof {
167 forest: self.forest,
168 position: pos,
169 merkle_path: MerklePath::new(nodes),
170 }))
171 }
172 }
173
174 pub fn nodes(&self) -> impl Iterator<Item = (&InOrderIndex, &RpoDigest)> {
179 self.nodes.iter()
180 }
181
182 pub fn inner_nodes<'a, I: Iterator<Item = (usize, RpoDigest)> + 'a>(
187 &'a self,
188 mut leaves: I,
189 ) -> impl Iterator<Item = InnerNodeInfo> + 'a {
190 let stack = if let Some((pos, leaf)) = leaves.next() {
191 let idx = InOrderIndex::from_leaf_pos(pos);
192 vec![(idx, leaf)]
193 } else {
194 Vec::new()
195 };
196
197 InnerNodeIterator {
198 nodes: &self.nodes,
199 leaves,
200 stack,
201 seen_nodes: BTreeSet::new(),
202 }
203 }
204
205 pub fn add(&mut self, leaf: RpoDigest, track: bool) -> Vec<(InOrderIndex, RpoDigest)> {
213 self.forest += 1;
214 let merges = self.forest.trailing_zeros() as usize;
215 let mut new_nodes = Vec::with_capacity(merges);
216
217 let peak = if merges == 0 {
218 self.track_latest = track;
219 leaf
220 } else {
221 let mut track_right = track;
222 let mut track_left = self.track_latest;
223
224 let mut right = leaf;
225 let mut right_idx = forest_to_rightmost_index(self.forest);
226
227 for _ in 0..merges {
228 let left = self.peaks.pop().expect("Missing peak");
229 let left_idx = right_idx.sibling();
230
231 if track_right {
232 let old = self.nodes.insert(left_idx, left);
233 new_nodes.push((left_idx, left));
234
235 debug_assert!(
236 old.is_none(),
237 "Idx {:?} already contained an element {:?}",
238 left_idx,
239 old
240 );
241 };
242 if track_left {
243 let old = self.nodes.insert(right_idx, right);
244 new_nodes.push((right_idx, right));
245
246 debug_assert!(
247 old.is_none(),
248 "Idx {:?} already contained an element {:?}",
249 right_idx,
250 old
251 );
252 };
253
254 right_idx = right_idx.parent();
259
260 right = Rpo256::merge(&[left, right]);
263
264 track_right = track_right || track_left;
268
269 track_left = self.is_tracked_node(&right_idx.sibling());
272 }
273 right
274 };
275
276 self.peaks.push(peak);
277
278 new_nodes
279 }
280
281 pub fn track(
292 &mut self,
293 leaf_pos: usize,
294 leaf: RpoDigest,
295 path: &MerklePath,
296 ) -> Result<(), MmrError> {
297 let tree = 1 << path.depth();
300 if tree & self.forest == 0 {
301 return Err(MmrError::UnknownPeak(path.depth()));
302 };
303
304 if leaf_pos + 1 == self.forest
305 && path.depth() == 0
306 && self.peaks.last().is_some_and(|v| *v == leaf)
307 {
308 self.track_latest = true;
309 return Ok(());
310 }
311
312 let target_forest = self.forest ^ (self.forest & (tree - 1));
315 let peak_pos = (target_forest.count_ones() - 1) as usize;
316
317 let path_idx = leaf_pos - (target_forest ^ tree);
319
320 let computed = path
323 .compute_root(path_idx as u64, leaf)
324 .map_err(MmrError::MerkleRootComputationFailed)?;
325 if self.peaks[peak_pos] != computed {
326 return Err(MmrError::PeakPathMismatch);
327 }
328
329 let mut idx = InOrderIndex::from_leaf_pos(leaf_pos);
330 for leaf in path.nodes() {
331 self.nodes.insert(idx.sibling(), *leaf);
332 idx = idx.parent();
333 }
334
335 Ok(())
336 }
337
338 pub fn untrack(&mut self, leaf_pos: usize) {
342 let mut idx = InOrderIndex::from_leaf_pos(leaf_pos);
343
344 while self.nodes.remove(&idx.sibling()).is_some() && !self.nodes.contains_key(&idx) {
350 idx = idx.parent();
351 }
352 }
353
354 pub fn apply(&mut self, delta: MmrDelta) -> Result<Vec<(InOrderIndex, RpoDigest)>, MmrError> {
357 if delta.forest < self.forest {
358 return Err(MmrError::InvalidPeaks(format!(
359 "forest of mmr delta {} is less than current forest {}",
360 delta.forest, self.forest
361 )));
362 }
363
364 let mut inserted_nodes = Vec::new();
365
366 if delta.forest == self.forest {
367 if !delta.data.is_empty() {
368 return Err(MmrError::InvalidUpdate);
369 }
370
371 return Ok(inserted_nodes);
372 }
373
374 let changes = self.forest ^ delta.forest;
376 let largest = 1 << changes.ilog2();
377 let merges = self.forest & (largest - 1);
378
379 debug_assert!(
380 !self.track_latest || (merges & 1) == 1,
381 "if there is an odd element, a merge is required"
382 );
383
384 let (merge_count, new_peaks) = if merges != 0 {
386 let depth = largest.trailing_zeros();
387 let skipped = merges.trailing_zeros();
388 let computed = merges.count_ones() - 1;
389 let merge_count = depth - skipped - computed;
390
391 let new_peaks = delta.forest & (largest - 1);
392
393 (merge_count, new_peaks)
394 } else {
395 (0, changes)
396 };
397
398 if (delta.data.len() as u32) != merge_count + new_peaks.count_ones() {
400 return Err(MmrError::InvalidUpdate);
401 }
402
403 let mut update_count = 0;
405
406 if merges != 0 {
407 let mut peak_idx = forest_to_root_index(self.forest);
409
410 self.peaks.reverse();
412
413 let mut track = self.track_latest;
415 self.track_latest = false;
416
417 let mut peak_count = 0;
418 let mut target = 1 << merges.trailing_zeros();
419 let mut new = delta.data[0];
420 update_count += 1;
421
422 while target < largest {
423 if target != 1 && !track {
426 track = self.is_tracked_node(&peak_idx);
427 }
428
429 let (left, right) = if target & merges != 0 {
432 let peak = self.peaks[peak_count];
433 let sibling_idx = peak_idx.sibling();
434
435 if self.is_tracked_node(&sibling_idx) {
438 self.nodes.insert(peak_idx, new);
439 inserted_nodes.push((peak_idx, new));
440 }
441 peak_count += 1;
442 (peak, new)
443 } else {
444 let update = delta.data[update_count];
445 update_count += 1;
446 (new, update)
447 };
448
449 if track {
450 let sibling_idx = peak_idx.sibling();
451 if peak_idx.is_left_child() {
452 self.nodes.insert(sibling_idx, right);
453 inserted_nodes.push((sibling_idx, right));
454 } else {
455 self.nodes.insert(sibling_idx, left);
456 inserted_nodes.push((sibling_idx, left));
457 }
458 }
459
460 peak_idx = peak_idx.parent();
461 new = Rpo256::merge(&[left, right]);
462 target <<= 1;
463 }
464
465 debug_assert!(peak_count == (merges.count_ones() as usize));
466
467 self.peaks.reverse();
469 self.peaks.truncate(self.peaks.len() - peak_count);
471 self.peaks.push(new);
473 }
474
475 self.peaks.extend_from_slice(&delta.data[update_count..]);
479 self.forest = delta.forest;
480
481 debug_assert!(self.peaks.len() == (self.forest.count_ones() as usize));
482
483 Ok(inserted_nodes)
484 }
485
486 fn is_tracked_node(&self, node_index: &InOrderIndex) -> bool {
492 if node_index.is_leaf() {
493 self.nodes.contains_key(&node_index.sibling())
494 } else {
495 let left_child = node_index.left_child();
496 let right_child = node_index.right_child();
497 self.nodes.contains_key(&left_child) | self.nodes.contains_key(&right_child)
498 }
499 }
500}
501
502impl From<MmrPeaks> for PartialMmr {
506 fn from(peaks: MmrPeaks) -> Self {
507 Self::from_peaks(peaks)
508 }
509}
510
511impl From<PartialMmr> for MmrPeaks {
512 fn from(partial_mmr: PartialMmr) -> Self {
513 MmrPeaks::new(partial_mmr.forest, partial_mmr.peaks).unwrap()
516 }
517}
518
519impl From<&MmrPeaks> for PartialMmr {
520 fn from(peaks: &MmrPeaks) -> Self {
521 Self::from_peaks(peaks.clone())
522 }
523}
524
525impl From<&PartialMmr> for MmrPeaks {
526 fn from(partial_mmr: &PartialMmr) -> Self {
527 MmrPeaks::new(partial_mmr.forest, partial_mmr.peaks.clone()).unwrap()
530 }
531}
532
533pub struct InnerNodeIterator<'a, I: Iterator<Item = (usize, RpoDigest)>> {
538 nodes: &'a NodeMap,
539 leaves: I,
540 stack: Vec<(InOrderIndex, RpoDigest)>,
541 seen_nodes: BTreeSet<InOrderIndex>,
542}
543
544impl<I: Iterator<Item = (usize, RpoDigest)>> Iterator for InnerNodeIterator<'_, I> {
545 type Item = InnerNodeInfo;
546
547 fn next(&mut self) -> Option<Self::Item> {
548 while let Some((idx, node)) = self.stack.pop() {
549 let parent_idx = idx.parent();
550 let new_node = self.seen_nodes.insert(parent_idx);
551
552 if new_node {
555 if let Some(sibling) = self.nodes.get(&idx.sibling()) {
556 let (left, right) = if parent_idx.left_child() == idx {
557 (node, *sibling)
558 } else {
559 (*sibling, node)
560 };
561 let parent = Rpo256::merge(&[left, right]);
562 let inner_node = InnerNodeInfo { value: parent, left, right };
563
564 self.stack.push((parent_idx, parent));
565 return Some(inner_node);
566 }
567 }
568
569 if let Some((pos, leaf)) = self.leaves.next() {
571 let idx = InOrderIndex::from_leaf_pos(pos);
572 self.stack.push((idx, leaf));
573 }
574 }
575
576 None
577 }
578}
579
580impl Serializable for PartialMmr {
581 fn write_into<W: winter_utils::ByteWriter>(&self, target: &mut W) {
582 self.forest.write_into(target);
583 self.peaks.write_into(target);
584 self.nodes.write_into(target);
585 target.write_bool(self.track_latest);
586 }
587}
588
589impl Deserializable for PartialMmr {
590 fn read_from<R: winter_utils::ByteReader>(
591 source: &mut R,
592 ) -> Result<Self, winter_utils::DeserializationError> {
593 let forest = usize::read_from(source)?;
594 let peaks = Vec::<RpoDigest>::read_from(source)?;
595 let nodes = NodeMap::read_from(source)?;
596 let track_latest = source.read_bool()?;
597
598 Ok(Self { forest, peaks, nodes, track_latest })
599 }
600}
601
602fn forest_to_root_index(forest: usize) -> InOrderIndex {
608 let nodes = nodes_in_forest(forest);
610
611 let open_trees = (forest.count_ones() - 1) as usize;
614
615 let right_subtree_count = ((1u32 << forest.trailing_zeros()) - 1) as usize;
618
619 let idx = nodes + open_trees - right_subtree_count;
620
621 InOrderIndex::new(idx.try_into().unwrap())
622}
623
624fn forest_to_rightmost_index(forest: usize) -> InOrderIndex {
626 let nodes = nodes_in_forest(forest);
628
629 let open_trees = (forest.count_ones() - 1) as usize;
632
633 let idx = nodes + open_trees;
634
635 InOrderIndex::new(idx.try_into().unwrap())
636}
637
638#[cfg(test)]
642mod tests {
643 use alloc::{collections::BTreeSet, vec::Vec};
644
645 use winter_utils::{Deserializable, Serializable};
646
647 use super::{
648 forest_to_rightmost_index, forest_to_root_index, InOrderIndex, MmrPeaks, PartialMmr,
649 RpoDigest,
650 };
651 use crate::merkle::{int_to_node, MerkleStore, Mmr, NodeIndex};
652
653 const LEAVES: [RpoDigest; 7] = [
654 int_to_node(0),
655 int_to_node(1),
656 int_to_node(2),
657 int_to_node(3),
658 int_to_node(4),
659 int_to_node(5),
660 int_to_node(6),
661 ];
662
663 #[test]
664 fn test_forest_to_root_index() {
665 fn idx(pos: usize) -> InOrderIndex {
666 InOrderIndex::new(pos.try_into().unwrap())
667 }
668
669 assert_eq!(forest_to_root_index(0b0001), idx(1));
672 assert_eq!(forest_to_root_index(0b0010), idx(2));
673 assert_eq!(forest_to_root_index(0b0100), idx(4));
674 assert_eq!(forest_to_root_index(0b1000), idx(8));
675
676 assert_eq!(forest_to_root_index(0b0011), idx(5));
677 assert_eq!(forest_to_root_index(0b0101), idx(9));
678 assert_eq!(forest_to_root_index(0b1001), idx(17));
679 assert_eq!(forest_to_root_index(0b0111), idx(13));
680 assert_eq!(forest_to_root_index(0b1011), idx(21));
681 assert_eq!(forest_to_root_index(0b1111), idx(29));
682
683 assert_eq!(forest_to_root_index(0b0110), idx(10));
684 assert_eq!(forest_to_root_index(0b1010), idx(18));
685 assert_eq!(forest_to_root_index(0b1100), idx(20));
686 assert_eq!(forest_to_root_index(0b1110), idx(26));
687 }
688
689 #[test]
690 fn test_forest_to_rightmost_index() {
691 fn idx(pos: usize) -> InOrderIndex {
692 InOrderIndex::new(pos.try_into().unwrap())
693 }
694
695 for forest in 1..256 {
696 assert!(forest_to_rightmost_index(forest).inner() % 2 == 1, "Leaves are always odd");
697 }
698
699 assert_eq!(forest_to_rightmost_index(0b0001), idx(1));
700 assert_eq!(forest_to_rightmost_index(0b0010), idx(3));
701 assert_eq!(forest_to_rightmost_index(0b0011), idx(5));
702 assert_eq!(forest_to_rightmost_index(0b0100), idx(7));
703 assert_eq!(forest_to_rightmost_index(0b0101), idx(9));
704 assert_eq!(forest_to_rightmost_index(0b0110), idx(11));
705 assert_eq!(forest_to_rightmost_index(0b0111), idx(13));
706 assert_eq!(forest_to_rightmost_index(0b1000), idx(15));
707 assert_eq!(forest_to_rightmost_index(0b1001), idx(17));
708 assert_eq!(forest_to_rightmost_index(0b1010), idx(19));
709 assert_eq!(forest_to_rightmost_index(0b1011), idx(21));
710 assert_eq!(forest_to_rightmost_index(0b1100), idx(23));
711 assert_eq!(forest_to_rightmost_index(0b1101), idx(25));
712 assert_eq!(forest_to_rightmost_index(0b1110), idx(27));
713 assert_eq!(forest_to_rightmost_index(0b1111), idx(29));
714 }
715
716 #[test]
717 fn test_partial_mmr_apply_delta() {
718 let mut mmr = Mmr::default();
720 (0..10).for_each(|i| mmr.add(int_to_node(i)));
721 let mut partial_mmr: PartialMmr = mmr.peaks().into();
722
723 {
725 let node = mmr.get(1).unwrap();
726 let proof = mmr.open(1).unwrap();
727 partial_mmr.track(1, node, &proof.merkle_path).unwrap();
728 }
729
730 {
731 let node = mmr.get(8).unwrap();
732 let proof = mmr.open(8).unwrap();
733 partial_mmr.track(8, node, &proof.merkle_path).unwrap();
734 }
735
736 (10..12).for_each(|i| mmr.add(int_to_node(i)));
738 validate_apply_delta(&mmr, &mut partial_mmr);
739
740 mmr.add(int_to_node(12));
742 validate_apply_delta(&mmr, &mut partial_mmr);
743 {
744 let node = mmr.get(12).unwrap();
745 let proof = mmr.open(12).unwrap();
746 partial_mmr.track(12, node, &proof.merkle_path).unwrap();
747 assert!(partial_mmr.track_latest);
748 }
749
750 (13..16).for_each(|i| mmr.add(int_to_node(i)));
754 validate_apply_delta(&mmr, &mut partial_mmr);
755 }
756
757 fn validate_apply_delta(mmr: &Mmr, partial: &mut PartialMmr) {
758 let tracked_leaves = partial
759 .nodes
760 .iter()
761 .filter_map(|(index, _)| if index.is_leaf() { Some(index.sibling()) } else { None })
762 .collect::<Vec<_>>();
763 let nodes_before = partial.nodes.clone();
764
765 let delta = mmr.get_delta(partial.forest(), mmr.forest()).unwrap();
767 let nodes_delta = partial.apply(delta).unwrap();
768
769 assert_eq!(mmr.peaks(), partial.peaks());
771
772 let mut expected_nodes = nodes_before;
773 for (key, value) in nodes_delta {
774 assert!(expected_nodes.insert(key, value).is_none());
776 }
777
778 assert_eq!(expected_nodes, partial.nodes);
780
781 for index in tracked_leaves {
783 let index_value: u64 = index.into();
784 let pos = index_value / 2;
785 let proof1 = partial.open(pos as usize).unwrap().unwrap();
786 let proof2 = mmr.open(pos as usize).unwrap();
787 assert_eq!(proof1, proof2);
788 }
789 }
790
791 #[test]
792 fn test_partial_mmr_inner_nodes_iterator() {
793 let mmr: Mmr = LEAVES.into();
795 let first_peak = mmr.peaks().peaks()[0];
796
797 let node1 = mmr.get(1).unwrap();
801 let proof1 = mmr.open(1).unwrap();
802
803 let mut partial_mmr: PartialMmr = mmr.peaks().into();
805 partial_mmr.track(1, node1, &proof1.merkle_path).unwrap();
806
807 assert_eq!(partial_mmr.inner_nodes([].iter().cloned()).next(), None);
809
810 let mut store: MerkleStore = MerkleStore::new();
812 store.extend(partial_mmr.inner_nodes([(1, node1)].iter().cloned()));
813
814 let index1 = NodeIndex::new(2, 1).unwrap();
815 let path1 = store.get_path(first_peak, index1).unwrap().path;
816
817 assert_eq!(path1, proof1.merkle_path);
818
819 let mut partial_mmr: PartialMmr = mmr.peaks().into();
823
824 let node0 = mmr.get(0).unwrap();
825 let proof0 = mmr.open(0).unwrap();
826
827 let node2 = mmr.get(2).unwrap();
828 let proof2 = mmr.open(2).unwrap();
829
830 partial_mmr.track(0, node0, &proof0.merkle_path).unwrap();
831 partial_mmr.track(1, node1, &proof1.merkle_path).unwrap();
832 partial_mmr.track(2, node2, &proof2.merkle_path).unwrap();
833
834 let leaves = [(0, node0), (1, node1), (2, node2)];
836 let mut nodes = BTreeSet::new();
837 for node in partial_mmr.inner_nodes(leaves.iter().cloned()) {
838 assert!(nodes.insert(node.value));
839 }
840
841 store.extend(partial_mmr.inner_nodes(leaves.iter().cloned()));
843
844 let index0 = NodeIndex::new(2, 0).unwrap();
845 let index1 = NodeIndex::new(2, 1).unwrap();
846 let index2 = NodeIndex::new(2, 2).unwrap();
847
848 let path0 = store.get_path(first_peak, index0).unwrap().path;
849 let path1 = store.get_path(first_peak, index1).unwrap().path;
850 let path2 = store.get_path(first_peak, index2).unwrap().path;
851
852 assert_eq!(path0, proof0.merkle_path);
853 assert_eq!(path1, proof1.merkle_path);
854 assert_eq!(path2, proof2.merkle_path);
855
856 let mut partial_mmr: PartialMmr = mmr.peaks().into();
860
861 let node5 = mmr.get(5).unwrap();
862 let proof5 = mmr.open(5).unwrap();
863
864 partial_mmr.track(1, node1, &proof1.merkle_path).unwrap();
865 partial_mmr.track(5, node5, &proof5.merkle_path).unwrap();
866
867 let mut store: MerkleStore = MerkleStore::new();
869 store.extend(partial_mmr.inner_nodes([(1, node1), (5, node5)].iter().cloned()));
870
871 let index1 = NodeIndex::new(2, 1).unwrap();
872 let index5 = NodeIndex::new(1, 1).unwrap();
873
874 let second_peak = mmr.peaks().peaks()[1];
875
876 let path1 = store.get_path(first_peak, index1).unwrap().path;
877 let path5 = store.get_path(second_peak, index5).unwrap().path;
878
879 assert_eq!(path1, proof1.merkle_path);
880 assert_eq!(path5, proof5.merkle_path);
881 }
882
883 #[test]
884 fn test_partial_mmr_add_without_track() {
885 let mut mmr = Mmr::default();
886 let empty_peaks = MmrPeaks::new(0, vec![]).unwrap();
887 let mut partial_mmr = PartialMmr::from_peaks(empty_peaks);
888
889 for el in (0..256).map(int_to_node) {
890 mmr.add(el);
891 partial_mmr.add(el, false);
892
893 assert_eq!(mmr.peaks(), partial_mmr.peaks());
894 assert_eq!(mmr.forest(), partial_mmr.forest());
895 }
896 }
897
898 #[test]
899 fn test_partial_mmr_add_with_track() {
900 let mut mmr = Mmr::default();
901 let empty_peaks = MmrPeaks::new(0, vec![]).unwrap();
902 let mut partial_mmr = PartialMmr::from_peaks(empty_peaks);
903
904 for i in 0..256 {
905 let el = int_to_node(i);
906 mmr.add(el);
907 partial_mmr.add(el, true);
908
909 assert_eq!(mmr.peaks(), partial_mmr.peaks());
910 assert_eq!(mmr.forest(), partial_mmr.forest());
911
912 for pos in 0..i {
913 let mmr_proof = mmr.open(pos as usize).unwrap();
914 let partialmmr_proof = partial_mmr.open(pos as usize).unwrap().unwrap();
915 assert_eq!(mmr_proof, partialmmr_proof);
916 }
917 }
918 }
919
920 #[test]
921 fn test_partial_mmr_add_existing_track() {
922 let mut mmr = Mmr::from((0..7).map(int_to_node));
923
924 let mut partial_mmr = PartialMmr::from_peaks(mmr.peaks());
926 let path_to_5 = mmr.open(5).unwrap().merkle_path;
927 let leaf_at_5 = mmr.get(5).unwrap();
928 partial_mmr.track(5, leaf_at_5, &path_to_5).unwrap();
929
930 let leaf_at_7 = int_to_node(7);
932 mmr.add(leaf_at_7);
933 partial_mmr.add(leaf_at_7, false);
934
935 assert_eq!(mmr.open(5).unwrap(), partial_mmr.open(5).unwrap().unwrap());
937 }
938
939 #[test]
940 fn test_partial_mmr_serialization() {
941 let mmr = Mmr::from((0..7).map(int_to_node));
942 let partial_mmr = PartialMmr::from_peaks(mmr.peaks());
943
944 let bytes = partial_mmr.to_bytes();
945 let decoded = PartialMmr::read_from_bytes(&bytes).unwrap();
946
947 assert_eq!(partial_mmr, decoded);
948 }
949
950 #[test]
951 fn test_partial_mmr_untrack() {
952 let mmr: Mmr = LEAVES.into();
954
955 let node1 = mmr.get(1).unwrap();
957 let proof1 = mmr.open(1).unwrap();
958
959 let node2 = mmr.get(2).unwrap();
961 let proof2 = mmr.open(2).unwrap();
962
963 let mut partial_mmr: PartialMmr = mmr.peaks().into();
965 partial_mmr.track(1, node1, &proof1.merkle_path).unwrap();
966 partial_mmr.track(2, node2, &proof2.merkle_path).unwrap();
967
968 partial_mmr.untrack(1);
970 partial_mmr.untrack(2);
971
972 assert!(!partial_mmr.is_tracked(1));
974 assert!(!partial_mmr.is_tracked(2));
975 assert_eq!(partial_mmr.nodes().count(), 0);
976 }
977}