1use alloc::{borrow::Cow, vec::Vec};
2use core::{
3 iter::{self, FusedIterator},
4 num::NonZero,
5};
6
7use winter_utils::{Deserializable, DeserializationError, Serializable};
8
9use super::{
10 EmptySubtreeRoots, InnerNodeInfo, MerkleError, MerklePath, NodeIndex, Word, smt::SMT_MAX_DEPTH,
11};
12use crate::hash::rpo::Rpo256;
13
14#[derive(Clone, Debug, Default, PartialEq, Eq)]
26#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
27pub struct SparseMerklePath {
28 empty_nodes_mask: u64,
32 nodes: Vec<Word>,
34}
35
36impl SparseMerklePath {
37 pub fn from_parts(empty_nodes_mask: u64, nodes: Vec<Word>) -> Result<Self, MerkleError> {
51 let min_path_len = u64::BITS - empty_nodes_mask.leading_zeros();
59 let empty_nodes_count = empty_nodes_mask.count_ones();
60 let min_non_empty_nodes = (min_path_len - empty_nodes_count) as usize;
61
62 if nodes.len() < min_non_empty_nodes {
63 return Err(MerkleError::InvalidPathLength(min_non_empty_nodes));
64 }
65
66 let depth = Self::depth_from_parts(empty_nodes_mask, &nodes) as u8;
67 if depth > SMT_MAX_DEPTH {
68 return Err(MerkleError::DepthTooBig(depth as u64));
69 }
70
71 Ok(Self { empty_nodes_mask, nodes })
72 }
73
74 pub fn from_sized_iter<I>(iterator: I) -> Result<Self, MerkleError>
84 where
85 I: IntoIterator<IntoIter: ExactSizeIterator, Item = Word>,
86 {
87 let iterator = iterator.into_iter();
88 let tree_depth = iterator.len() as u8;
89
90 if tree_depth > SMT_MAX_DEPTH {
91 return Err(MerkleError::DepthTooBig(tree_depth as u64));
92 }
93
94 let mut empty_nodes_mask: u64 = 0;
95 let mut nodes: Vec<Word> = Default::default();
96
97 for (depth, node) in iter::zip(path_depth_iter(tree_depth), iterator) {
98 let &equivalent_empty_node = EmptySubtreeRoots::entry(tree_depth, depth.get());
99 let is_empty = node == equivalent_empty_node;
100 let node = if is_empty { None } else { Some(node) };
101
102 match node {
103 Some(node) => nodes.push(node),
104 None => empty_nodes_mask |= Self::bitmask_for_depth(depth),
105 }
106 }
107
108 Ok(SparseMerklePath { nodes, empty_nodes_mask })
109 }
110
111 pub fn depth(&self) -> u8 {
113 Self::depth_from_parts(self.empty_nodes_mask, &self.nodes) as u8
114 }
115
116 pub fn at_depth(&self, node_depth: NonZero<u8>) -> Result<Word, MerkleError> {
126 if node_depth.get() > self.depth() {
127 return Err(MerkleError::DepthTooBig(node_depth.get().into()));
128 }
129
130 let node = if let Some(nonempty_index) = self.get_nonempty_index(node_depth) {
131 self.nodes[nonempty_index]
132 } else {
133 *EmptySubtreeRoots::entry(self.depth(), node_depth.get())
134 };
135
136 Ok(node)
137 }
138
139 pub fn into_parts(self) -> (u64, Vec<Word>) {
146 (self.empty_nodes_mask, self.nodes)
147 }
148
149 pub fn iter(&self) -> impl ExactSizeIterator<Item = Word> {
155 self.into_iter()
156 }
157
158 pub fn compute_root(&self, index: u64, node_to_prove: Word) -> Result<Word, MerkleError> {
160 let mut index = NodeIndex::new(self.depth(), index)?;
161 let root = self.iter().fold(node_to_prove, |node, sibling| {
162 let children = index.build_node(node, sibling);
164 index.move_up();
165 Rpo256::merge(&children)
166 });
167
168 Ok(root)
169 }
170
171 pub fn verify(&self, index: u64, node: Word, &expected_root: &Word) -> Result<(), MerkleError> {
178 let computed_root = self.compute_root(index, node)?;
179 if computed_root != expected_root {
180 return Err(MerkleError::ConflictingRoots {
181 expected_root,
182 actual_root: computed_root,
183 });
184 }
185
186 Ok(())
187 }
188
189 pub fn authenticated_nodes(
205 &self,
206 index: u64,
207 node_to_prove: Word,
208 ) -> Result<InnerNodeIterator<'_>, MerkleError> {
209 let index = NodeIndex::new(self.depth(), index)?;
210 Ok(InnerNodeIterator { path: self, index, value: node_to_prove })
211 }
212
213 const fn bitmask_for_depth(node_depth: NonZero<u8>) -> u64 {
217 1 << (node_depth.get() - 1)
219 }
220
221 const fn is_depth_empty(&self, node_depth: NonZero<u8>) -> bool {
222 (self.empty_nodes_mask & Self::bitmask_for_depth(node_depth)) != 0
223 }
224
225 fn get_nonempty_index(&self, node_depth: NonZero<u8>) -> Option<usize> {
228 if self.is_depth_empty(node_depth) {
229 return None;
230 }
231
232 let bit_index = node_depth.get() - 1;
233 let without_shallower = self.empty_nodes_mask >> bit_index;
234 let empty_deeper = without_shallower.count_ones() as usize;
235 let normal_index = (self.depth() - node_depth.get()) as usize;
237 Some(normal_index - empty_deeper)
239 }
240
241 fn depth_from_parts(empty_nodes_mask: u64, nodes: &[Word]) -> usize {
243 nodes.len() + empty_nodes_mask.count_ones() as usize
244 }
245}
246
247impl Serializable for SparseMerklePath {
251 fn write_into<W: winter_utils::ByteWriter>(&self, target: &mut W) {
252 target.write_u8(self.depth());
253 target.write_u64(self.empty_nodes_mask);
254 target.write_many(&self.nodes);
255 }
256}
257
258impl Deserializable for SparseMerklePath {
259 fn read_from<R: winter_utils::ByteReader>(
260 source: &mut R,
261 ) -> Result<Self, DeserializationError> {
262 let depth = source.read_u8()?;
263 if depth > SMT_MAX_DEPTH {
264 return Err(DeserializationError::InvalidValue(format!(
265 "SparseMerklePath max depth exceeded ({depth} > {SMT_MAX_DEPTH})",
266 )));
267 }
268 let empty_nodes_mask = source.read_u64()?;
269 let empty_nodes_count = empty_nodes_mask.count_ones();
270 if empty_nodes_count > depth as u32 {
271 return Err(DeserializationError::InvalidValue(format!(
272 "SparseMerklePath has more empty nodes ({empty_nodes_count}) than its full length ({depth})",
273 )));
274 }
275 let count = depth as u32 - empty_nodes_count;
276 let nodes = source.read_many::<Word>(count as usize)?;
277 Ok(Self { empty_nodes_mask, nodes })
278 }
279}
280
281impl From<SparseMerklePath> for MerklePath {
285 fn from(sparse_path: SparseMerklePath) -> Self {
286 MerklePath::from_iter(sparse_path)
287 }
288}
289
290impl TryFrom<MerklePath> for SparseMerklePath {
291 type Error = MerkleError;
292
293 fn try_from(path: MerklePath) -> Result<Self, MerkleError> {
298 SparseMerklePath::from_sized_iter(path)
299 }
300}
301
302impl From<SparseMerklePath> for Vec<Word> {
303 fn from(path: SparseMerklePath) -> Self {
304 Vec::from_iter(path)
305 }
306}
307
308pub struct SparseMerklePathIter<'p> {
314 path: Cow<'p, SparseMerklePath>,
316
317 next_depth: u8,
320}
321
322impl Iterator for SparseMerklePathIter<'_> {
323 type Item = Word;
324
325 fn next(&mut self) -> Option<Word> {
326 let this_depth = self.next_depth;
327 let this_depth = NonZero::new(this_depth)?;
329 self.next_depth = this_depth.get() - 1;
330
331 let node = self
333 .path
334 .at_depth(this_depth)
335 .expect("current depth should never exceed the path depth");
336 Some(node)
337 }
338
339 fn size_hint(&self) -> (usize, Option<usize>) {
341 let remaining = ExactSizeIterator::len(self);
342 (remaining, Some(remaining))
343 }
344}
345
346impl ExactSizeIterator for SparseMerklePathIter<'_> {
347 fn len(&self) -> usize {
348 self.next_depth as usize
349 }
350}
351
352impl FusedIterator for SparseMerklePathIter<'_> {}
353
354impl IntoIterator for SparseMerklePath {
357 type IntoIter = SparseMerklePathIter<'static>;
358 type Item = <Self::IntoIter as Iterator>::Item;
359
360 fn into_iter(self) -> SparseMerklePathIter<'static> {
361 let tree_depth = self.depth();
362 SparseMerklePathIter {
363 path: Cow::Owned(self),
364 next_depth: tree_depth,
365 }
366 }
367}
368
369impl<'p> IntoIterator for &'p SparseMerklePath {
370 type Item = <SparseMerklePathIter<'p> as Iterator>::Item;
371 type IntoIter = SparseMerklePathIter<'p>;
372
373 fn into_iter(self) -> SparseMerklePathIter<'p> {
374 let tree_depth = self.depth();
375 SparseMerklePathIter {
376 path: Cow::Borrowed(self),
377 next_depth: tree_depth,
378 }
379 }
380}
381
382pub struct InnerNodeIterator<'p> {
385 path: &'p SparseMerklePath,
386 index: NodeIndex,
387 value: Word,
388}
389
390impl Iterator for InnerNodeIterator<'_> {
391 type Item = InnerNodeInfo;
392
393 fn next(&mut self) -> Option<Self::Item> {
394 if self.index.is_root() {
395 return None;
396 }
397
398 let index_depth = NonZero::new(self.index.depth()).expect("non-root depth cannot be 0");
399 let path_node = self.path.at_depth(index_depth).unwrap();
400
401 let children = self.index.build_node(self.value, path_node);
402 self.value = Rpo256::merge(&children);
403 self.index.move_up();
404
405 Some(InnerNodeInfo {
406 value: self.value,
407 left: children[0],
408 right: children[1],
409 })
410 }
411}
412
413impl PartialEq<MerklePath> for SparseMerklePath {
416 fn eq(&self, rhs: &MerklePath) -> bool {
417 if self.depth() != rhs.depth() {
418 return false;
419 }
420
421 for (node, &rhs_node) in iter::zip(self, rhs.iter()) {
422 if node != rhs_node {
423 return false;
424 }
425 }
426
427 true
428 }
429}
430
431impl PartialEq<SparseMerklePath> for MerklePath {
432 fn eq(&self, rhs: &SparseMerklePath) -> bool {
433 rhs == self
434 }
435}
436
437fn path_depth_iter(tree_depth: u8) -> impl ExactSizeIterator<Item = NonZero<u8>> {
443 let top_down_iter = (1..=tree_depth).map(|depth| {
444 unsafe { NonZero::new_unchecked(depth) }
448 });
449
450 top_down_iter.rev()
452}
453
454#[cfg(test)]
457mod tests {
458 use alloc::vec::Vec;
459 use core::num::NonZero;
460
461 use assert_matches::assert_matches;
462 use winter_math::FieldElement;
463
464 use super::SparseMerklePath;
465 use crate::{
466 Felt, ONE, Word,
467 merkle::{
468 EmptySubtreeRoots, MerkleError, MerklePath, MerkleTree, NodeIndex,
469 smt::{LeafIndex, SMT_MAX_DEPTH, SimpleSmt, Smt, SparseMerkleTree},
470 sparse_path::path_depth_iter,
471 },
472 };
473
474 fn make_smt(pair_count: u64) -> Smt {
475 let entries: Vec<(Word, Word)> = (0..pair_count)
476 .map(|n| {
477 let leaf_index = ((n as f64 / pair_count as f64) * 255.0) as u64;
478 let key = Word::new([ONE, ONE, Felt::new(n), Felt::new(leaf_index)]);
479 let value = Word::new([ONE, ONE, ONE, ONE]);
480 (key, value)
481 })
482 .collect();
483
484 Smt::with_entries(entries).unwrap()
485 }
486
487 #[test]
493 fn test_sparse_bits() {
494 const DEPTH: u8 = 8;
495 let raw_nodes: [Word; DEPTH as usize] = [
496 ([8u8, 8, 8, 8].into()),
498 *EmptySubtreeRoots::entry(DEPTH, 7),
500 *EmptySubtreeRoots::entry(DEPTH, 6),
502 [5u8, 5, 5, 5].into(),
504 [4u8, 4, 4, 4].into(),
506 *EmptySubtreeRoots::entry(DEPTH, 3),
508 *EmptySubtreeRoots::entry(DEPTH, 2),
510 *EmptySubtreeRoots::entry(DEPTH, 1),
512 ];
514
515 let sparse_nodes: [Option<Word>; DEPTH as usize] = [
516 Some([8u8, 8, 8, 8].into()),
518 None,
520 None,
522 Some([5u8, 5, 5, 5].into()),
524 Some([4u8, 4, 4, 4].into()),
526 None,
528 None,
530 None,
532 ];
534
535 const EMPTY_BITS: u64 = 0b0110_0111;
536
537 let sparse_path = SparseMerklePath::from_sized_iter(raw_nodes).unwrap();
538
539 assert_eq!(sparse_path.empty_nodes_mask, EMPTY_BITS);
540
541 let mut nonempty_idx = 0;
543
544 for depth in (1..=8).rev() {
546 let idx = (sparse_path.depth() - depth) as usize;
547 let bit = 1 << (depth - 1);
548
549 let is_set = (sparse_path.empty_nodes_mask & bit) != 0;
551 assert_eq!(is_set, sparse_nodes.get(idx).unwrap().is_none());
552
553 if is_set {
554 let &test_node = sparse_nodes.get(idx).unwrap();
556 assert_eq!(test_node, None);
557 } else {
558 let control_node = raw_nodes.get(idx).unwrap();
560 assert_eq!(
561 sparse_path.get_nonempty_index(NonZero::new(depth).unwrap()).unwrap(),
562 nonempty_idx
563 );
564 let test_node = sparse_path.nodes.get(nonempty_idx).unwrap();
565 assert_eq!(test_node, control_node);
566
567 nonempty_idx += 1;
568 }
569 }
570 }
571
572 #[test]
573 fn from_parts() {
574 const DEPTH: u8 = 8;
575 let raw_nodes: [Word; DEPTH as usize] = [
576 ([8u8, 8, 8, 8].into()),
578 *EmptySubtreeRoots::entry(DEPTH, 7),
580 *EmptySubtreeRoots::entry(DEPTH, 6),
582 [5u8, 5, 5, 5].into(),
584 [4u8, 4, 4, 4].into(),
586 *EmptySubtreeRoots::entry(DEPTH, 3),
588 *EmptySubtreeRoots::entry(DEPTH, 2),
590 *EmptySubtreeRoots::entry(DEPTH, 1),
592 ];
594
595 let empty_nodes_mask = 0b0110_0111;
596 let nodes = vec![[8u8, 8, 8, 8].into(), [5u8, 5, 5, 5].into(), [4u8, 4, 4, 4].into()];
597 let insufficient_nodes = vec![[4u8, 4, 4, 4].into()];
598
599 let error = SparseMerklePath::from_parts(empty_nodes_mask, insufficient_nodes).unwrap_err();
600 assert_matches!(error, MerkleError::InvalidPathLength(2));
601
602 let iter_sparse_path = SparseMerklePath::from_sized_iter(raw_nodes).unwrap();
603 let sparse_path = SparseMerklePath::from_parts(empty_nodes_mask, nodes).unwrap();
604
605 assert_eq!(sparse_path, iter_sparse_path);
606 }
607
608 #[test]
609 fn from_sized_iter() {
610 let tree = make_smt(8192);
611
612 for (key, _value) in tree.entries() {
613 let index = NodeIndex::from(Smt::key_to_leaf_index(key));
614 let sparse_path = tree.get_path(key);
615 for (sparse_node, proof_idx) in
616 itertools::zip_eq(sparse_path.clone(), index.proof_indices())
617 {
618 let proof_node = tree.get_node_hash(proof_idx);
619 assert_eq!(sparse_node, proof_node);
620 }
621 }
622 }
623
624 #[test]
625 fn test_zero_sized() {
626 let nodes: Vec<Word> = Default::default();
627
628 let sparse_path = SparseMerklePath::from_sized_iter(nodes).unwrap();
630 assert_eq!(sparse_path.depth(), 0);
631 assert_matches!(
632 sparse_path.at_depth(NonZero::new(1).unwrap()),
633 Err(MerkleError::DepthTooBig(1))
634 );
635 assert_eq!(sparse_path.iter().next(), None);
636 assert_eq!(sparse_path.into_iter().next(), None);
637 }
638
639 use proptest::prelude::*;
640
641 impl Arbitrary for Word {
643 type Parameters = ();
644 type Strategy = BoxedStrategy<Self>;
645
646 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
647 prop::collection::vec(any::<u64>(), 4)
648 .prop_map(|vals| {
649 Word::new([
650 Felt::new(vals[0]),
651 Felt::new(vals[1]),
652 Felt::new(vals[2]),
653 Felt::new(vals[3]),
654 ])
655 })
656 .no_shrink()
657 .boxed()
658 }
659 }
660
661 impl Arbitrary for MerklePath {
663 type Parameters = ();
664 type Strategy = BoxedStrategy<Self>;
665
666 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
667 prop::collection::vec(any::<Word>(), 0..=SMT_MAX_DEPTH as usize)
668 .prop_map(MerklePath::new)
669 .boxed()
670 }
671 }
672
673 impl Arbitrary for SparseMerklePath {
675 type Parameters = ();
676 type Strategy = BoxedStrategy<Self>;
677
678 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
679 (0..=SMT_MAX_DEPTH as usize)
680 .prop_flat_map(|depth| {
681 let max_mask = if depth > 0 && depth < 64 {
683 (1u64 << depth) - 1
684 } else if depth == 64 {
685 u64::MAX
686 } else {
687 0
688 };
689 let empty_nodes_mask =
690 prop::num::u64::ANY.prop_map(move |mask| mask & max_mask);
691
692 empty_nodes_mask.prop_flat_map(move |mask| {
694 let empty_count = mask.count_ones() as usize;
695 let non_empty_count = depth.saturating_sub(empty_count);
696
697 prop::collection::vec(any::<Word>(), non_empty_count).prop_map(
698 move |nodes| SparseMerklePath::from_parts(mask, nodes).unwrap(),
699 )
700 })
701 })
702 .boxed()
703 }
704 }
705
706 proptest! {
707 #[test]
708 fn sparse_merkle_path_roundtrip_equivalence(path in any::<MerklePath>()) {
709 let sparse_result = SparseMerklePath::try_from(path.clone());
711 if path.depth() <= SMT_MAX_DEPTH {
712 let sparse = sparse_result.unwrap();
713 let reconstructed = MerklePath::from(sparse);
714 prop_assert_eq!(path, reconstructed);
715 } else {
716 prop_assert!(sparse_result.is_err());
717 }
718 }
719 }
720 proptest! {
721
722 #[test]
723 fn merkle_path_roundtrip_equivalence(sparse in any::<SparseMerklePath>()) {
724 let merkle = MerklePath::from(sparse.clone());
726 let reconstructed = SparseMerklePath::try_from(merkle.clone()).unwrap();
727 prop_assert_eq!(sparse, reconstructed);
728 }
729 }
730 proptest! {
731
732 #[test]
733 fn path_equivalence_tests(path in any::<MerklePath>(), path2 in any::<MerklePath>()) {
734 if path.depth() > SMT_MAX_DEPTH {
735 return Ok(());
736 }
737
738 let sparse = SparseMerklePath::try_from(path.clone()).unwrap();
739
740 prop_assert_eq!(path.depth(), sparse.depth());
742
743 if path.depth() > 0 {
745 for depth in path_depth_iter(path.depth()) {
746 let merkle_node = path.at_depth(depth);
747 let sparse_node = sparse.at_depth(depth);
748
749 match (merkle_node, sparse_node) {
750 (Some(m), Ok(s)) => prop_assert_eq!(m, s),
751 (None, Err(_)) => {},
752 _ => prop_assert!(false, "Inconsistent node access at depth {}", depth.get()),
753 }
754 }
755 }
756
757 if path.depth() > 0 {
759 let merkle_nodes: Vec<_> = path.iter().collect();
760 let sparse_nodes: Vec<_> = sparse.iter().collect();
761
762 prop_assert_eq!(merkle_nodes.len(), sparse_nodes.len());
763 for (m, s) in merkle_nodes.iter().zip(sparse_nodes.iter()) {
764 prop_assert_eq!(*m, s);
765 }
766 }
767
768 if path2.depth() <= SMT_MAX_DEPTH {
770 let sparse2 = SparseMerklePath::try_from(path2.clone()).unwrap();
771 prop_assert_eq!(path == path2, sparse == sparse2);
772 prop_assert_eq!(path == sparse2, sparse == path2);
773 }
774 }
775 }
776 proptest! {
778 #![proptest_config(ProptestConfig::with_cases(100))]
779
780 #[test]
781 fn compute_root_consistency(
782 tree_data in any::<RandomMerkleTree>(),
783 node in any::<Word>()
784 ) {
785 let RandomMerkleTree { tree, leaves: _, indices } = tree_data;
786
787 for &leaf_index in indices.iter() {
788 let path = tree.get_path(NodeIndex::new(tree.depth(), leaf_index).unwrap()).unwrap();
789 let sparse = SparseMerklePath::from_sized_iter(path.clone().into_iter()).unwrap();
790
791 let merkle_root = path.compute_root(leaf_index, node);
792 let sparse_root = sparse.compute_root(leaf_index, node);
793
794 match (merkle_root, sparse_root) {
795 (Ok(m), Ok(s)) => prop_assert_eq!(m, s),
796 (Err(e1), Err(e2)) => {
797 prop_assert_eq!(format!("{:?}", e1), format!("{:?}", e2));
799 },
800 _ => prop_assert!(false, "Inconsistent compute_root results"),
801 }
802 }
803 }
804
805 #[test]
806 fn verify_consistency(
807 tree_data in any::<RandomMerkleTree>(),
808 node in any::<Word>()
809 ) {
810 let RandomMerkleTree { tree, leaves, indices } = tree_data;
811
812 for (i, &leaf_index) in indices.iter().enumerate() {
813 let leaf = leaves[i];
814 let path = tree.get_path(NodeIndex::new(tree.depth(), leaf_index).unwrap()).unwrap();
815 let sparse = SparseMerklePath::from_sized_iter(path.clone().into_iter()).unwrap();
816
817 let root = tree.root();
818
819 let merkle_verify = path.verify(leaf_index, leaf, &root);
820 let sparse_verify = sparse.verify(leaf_index, leaf, &root);
821
822 match (merkle_verify, sparse_verify) {
823 (Ok(()), Ok(())) => {},
824 (Err(e1), Err(e2)) => {
825 prop_assert_eq!(format!("{:?}", e1), format!("{:?}", e2));
827 },
828 _ => prop_assert!(false, "Inconsistent verify results"),
829 }
830
831 let wrong_verify = path.verify(leaf_index, node, &root);
833 let wrong_sparse_verify = sparse.verify(leaf_index, node, &root);
834
835 match (wrong_verify, wrong_sparse_verify) {
836 (Ok(()), Ok(())) => prop_assert!(false, "Verification should have failed with wrong node"),
837 (Err(_), Err(_)) => {},
838 _ => prop_assert!(false, "Inconsistent verification results with wrong node"),
839 }
840 }
841 }
842
843 #[test]
844 fn authenticated_nodes_consistency(
845 tree_data in any::<RandomMerkleTree>()
846 ) {
847 let RandomMerkleTree { tree, leaves, indices } = tree_data;
848
849 for (i, &leaf_index) in indices.iter().enumerate() {
850 let leaf = leaves[i];
851 let path = tree.get_path(NodeIndex::new(tree.depth(), leaf_index).unwrap()).unwrap();
852 let sparse = SparseMerklePath::from_sized_iter(path.clone().into_iter()).unwrap();
853
854 let merkle_result = path.authenticated_nodes(leaf_index, leaf);
855 let sparse_result = sparse.authenticated_nodes(leaf_index, leaf);
856
857 match (merkle_result, sparse_result) {
858 (Ok(m_iter), Ok(s_iter)) => {
859 let merkle_nodes: Vec<_> = m_iter.collect();
860 let sparse_nodes: Vec<_> = s_iter.collect();
861 prop_assert_eq!(merkle_nodes.len(), sparse_nodes.len());
862 for (m, s) in merkle_nodes.iter().zip(sparse_nodes.iter()) {
863 prop_assert_eq!(m, s);
864 }
865 },
866 (Err(e1), Err(e2)) => {
867 prop_assert_eq!(format!("{:?}", e1), format!("{:?}", e2));
868 },
869 _ => prop_assert!(false, "Inconsistent authenticated_nodes results"),
870 }
871 }
872 }
873 }
874
875 #[test]
876 fn test_api_differences() {
877 let merkle = MerklePath::new(vec![Word::default(); 3]);
881 let _vec_ref: &Vec<Word> = &merkle; let _vec_mut: &mut Vec<Word> = &mut merkle.clone(); let sparse = SparseMerklePath::from_parts(0b101, vec![Word::default(); 2]).unwrap();
886 assert_eq!(sparse.depth(), 4); let nodes = vec![Word::default(); 3];
890 let sparse_from_iter = SparseMerklePath::from_sized_iter(nodes.clone()).unwrap();
891 let merkle_from_iter = MerklePath::from_iter(nodes);
892 assert_eq!(sparse_from_iter.depth(), merkle_from_iter.depth());
893 }
894
895 #[derive(Debug, Clone)]
897 struct RandomMerkleTree {
898 tree: MerkleTree,
899 leaves: Vec<Word>,
900 indices: Vec<u64>,
901 }
902
903 impl Arbitrary for RandomMerkleTree {
904 type Parameters = ();
905 type Strategy = BoxedStrategy<Self>;
906
907 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
908 prop::sample::select(&[2, 4, 8, 16, 32, 64, 128, 256, 512, 1024])
910 .prop_flat_map(|num_leaves| {
911 prop::collection::vec(any::<Word>(), num_leaves).prop_map(|leaves| {
912 let tree = MerkleTree::new(leaves.clone()).unwrap();
913 let indices: Vec<u64> = (0..leaves.len() as u64).collect();
914 RandomMerkleTree { tree, leaves, indices }
915 })
916 })
917 .boxed()
918 }
919 }
920
921 #[derive(Debug, Clone)]
923 struct RandomSimpleSmt {
924 tree: SimpleSmt<10>, entries: Vec<(u64, Word)>,
926 }
927
928 impl Arbitrary for RandomSimpleSmt {
929 type Parameters = ();
930 type Strategy = BoxedStrategy<Self>;
931
932 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
933 (1..=100usize) .prop_flat_map(|num_entries| {
935 prop::collection::vec(
936 (
937 0..1024u64, any::<Word>(),
939 ),
940 num_entries,
941 )
942 .prop_map(|mut entries| {
943 let mut seen = alloc::collections::BTreeSet::new();
945 entries.retain(|(idx, _)| seen.insert(*idx));
946
947 let mut tree = SimpleSmt::new().unwrap();
948 for (idx, value) in &entries {
949 let leaf_idx = LeafIndex::new(*idx).unwrap();
950 tree.insert(leaf_idx, *value);
951 }
952 RandomSimpleSmt { tree, entries }
953 })
954 })
955 .boxed()
956 }
957 }
958
959 #[derive(Debug, Clone)]
961 struct RandomSmt {
962 tree: Smt,
963 entries: Vec<(Word, Word)>,
964 }
965
966 impl Arbitrary for RandomSmt {
967 type Parameters = ();
968 type Strategy = BoxedStrategy<Self>;
969
970 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
971 (1..=100usize) .prop_flat_map(|num_entries| {
973 prop::collection::vec((any::<u64>(), any::<Word>()), num_entries).prop_map(
974 |indices_n_values| {
975 let entries: Vec<(Word, Word)> = indices_n_values
976 .into_iter()
977 .enumerate()
978 .map(|(n, (leaf_index, value))| {
979 let valid_leaf_index = leaf_index % (1u64 << 60); let key = Word::new([
983 Felt::new(n as u64), Felt::new(n as u64 + 1), Felt::new(n as u64 + 2), Felt::new(valid_leaf_index), ]);
988 (key, value)
989 })
990 .collect();
991
992 let mut seen = alloc::collections::BTreeSet::new();
994 let unique_entries: Vec<_> =
995 entries.into_iter().filter(|(key, _)| seen.insert(*key)).collect();
996
997 let tree = Smt::with_entries(unique_entries.clone()).unwrap();
998 RandomSmt { tree, entries: unique_entries }
999 },
1000 )
1001 })
1002 .boxed()
1003 }
1004 }
1005
1006 proptest! {
1007 #![proptest_config(ProptestConfig::with_cases(20))]
1008
1009 #[test]
1010 fn simple_smt_path_consistency(tree_data in any::<RandomSimpleSmt>()) {
1011 let RandomSimpleSmt { tree, entries } = tree_data;
1012
1013 for (leaf_index, value) in &entries {
1014 let merkle_path = tree.get_path(&LeafIndex::new(*leaf_index).unwrap());
1015 let sparse_path = SparseMerklePath::from_sized_iter(merkle_path.clone().into_iter()).unwrap();
1016
1017 prop_assert_eq!(merkle_path.depth(), sparse_path.depth());
1019
1020 let merkle_root = merkle_path.compute_root(*leaf_index, *value).unwrap();
1022 let sparse_root = sparse_path.compute_root(*leaf_index, *value).unwrap();
1023 prop_assert_eq!(merkle_root, sparse_root);
1024
1025 let tree_root = tree.root();
1027 prop_assert!(merkle_path.verify(*leaf_index, *value, &tree_root).is_ok());
1028 prop_assert!(sparse_path.verify(*leaf_index, *value, &tree_root).is_ok());
1029
1030 let random_leaf = Word::new([Felt::ONE; 4]);
1032 let random_index = *leaf_index ^ 1; let merkle_wrong = merkle_path.verify(random_index, random_leaf, &tree_root);
1036 let sparse_wrong = sparse_path.verify(random_index, random_leaf, &tree_root);
1037 prop_assert_eq!(merkle_wrong.is_err(), sparse_wrong.is_err());
1038 }
1039 }
1040
1041 #[test]
1042 fn smt_path_consistency(tree_data in any::<RandomSmt>()) {
1043 let RandomSmt { tree, entries } = tree_data;
1044
1045 for (key, _value) in &entries {
1046 let (merkle_path, leaf) = tree.open(key).into_parts();
1047 let sparse_path = SparseMerklePath::from_sized_iter(merkle_path.clone().into_iter()).unwrap();
1048
1049 let leaf_index = Smt::key_to_leaf_index(key).value();
1050 let actual_value = leaf.hash(); prop_assert_eq!(merkle_path.depth(), sparse_path.depth());
1054
1055 let merkle_root = merkle_path.compute_root(leaf_index, actual_value).unwrap();
1057 let sparse_root = sparse_path.compute_root(leaf_index, actual_value).unwrap();
1058 prop_assert_eq!(merkle_root, sparse_root);
1059
1060 let tree_root = tree.root();
1062 prop_assert!(merkle_path.verify(leaf_index, actual_value, &tree_root).is_ok());
1063 prop_assert!(sparse_path.verify(leaf_index, actual_value, &tree_root).is_ok());
1064
1065 let merkle_auth = merkle_path.authenticated_nodes(leaf_index, actual_value).unwrap().collect::<Vec<_>>();
1067 let sparse_auth = sparse_path.authenticated_nodes(leaf_index, actual_value).unwrap().collect::<Vec<_>>();
1068 prop_assert_eq!(merkle_auth, sparse_auth);
1069 }
1070 }
1071
1072 #[test]
1073 fn reverse_conversion_from_sparse(tree_data in any::<RandomMerkleTree>()) {
1074 let RandomMerkleTree { tree, leaves, indices } = tree_data;
1075
1076 for (i, &leaf_index) in indices.iter().enumerate() {
1077 let leaf = leaves[i];
1078 let merkle_path = tree.get_path(NodeIndex::new(tree.depth(), leaf_index).unwrap()).unwrap();
1079
1080 let sparse_path = SparseMerklePath::from_sized_iter(merkle_path.clone().into_iter()).unwrap();
1082 let converted_merkle = MerklePath::from(sparse_path.clone());
1083
1084 let back_to_sparse = SparseMerklePath::try_from(converted_merkle.clone()).unwrap();
1086 prop_assert_eq!(sparse_path, back_to_sparse);
1087
1088 prop_assert_eq!(merkle_path.depth(), converted_merkle.depth());
1090
1091 let merkle_root = merkle_path.compute_root(leaf_index, leaf).unwrap();
1092 let converted_root = converted_merkle.compute_root(leaf_index, leaf).unwrap();
1093 prop_assert_eq!(merkle_root, converted_root);
1094 }
1095 }
1096 }
1097}