1use alloc::{borrow::Cow, vec::Vec};
2use core::{
3 iter::{self, FusedIterator},
4 num::NonZero,
5};
6
7use super::{
8 EmptySubtreeRoots, InnerNodeInfo, MerkleError, MerklePath, NodeIndex, Word, smt::SMT_MAX_DEPTH,
9};
10use crate::{
11 hash::poseidon2::Poseidon2,
12 utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable},
13};
14
15#[derive(Clone, Debug, Default, PartialEq, Eq)]
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);
69 if depth > SMT_MAX_DEPTH as usize {
70 return Err(MerkleError::DepthTooBig(depth as u64));
71 }
72
73 Ok(Self { empty_nodes_mask, nodes })
74 }
75
76 pub fn from_sized_iter<I>(iterator: I) -> Result<Self, MerkleError>
86 where
87 I: IntoIterator<IntoIter: ExactSizeIterator, Item = Word>,
88 {
89 let iterator = iterator.into_iter();
90 let tree_depth = iterator.len();
93 if tree_depth > SMT_MAX_DEPTH as usize {
94 return Err(MerkleError::DepthTooBig(tree_depth as u64));
95 }
96 let tree_depth = tree_depth as u8;
97
98 let mut empty_nodes_mask: u64 = 0;
99 let mut nodes: Vec<Word> = Default::default();
100
101 for (depth, node) in iter::zip(path_depth_iter(tree_depth), iterator) {
102 let &equivalent_empty_node = EmptySubtreeRoots::entry(tree_depth, depth.get());
103 let is_empty = node == equivalent_empty_node;
104 let node = if is_empty { None } else { Some(node) };
105
106 match node {
107 Some(node) => nodes.push(node),
108 None => empty_nodes_mask |= Self::bitmask_for_depth(depth),
109 }
110 }
111
112 Ok(SparseMerklePath { nodes, empty_nodes_mask })
113 }
114
115 pub fn depth(&self) -> u8 {
117 Self::depth_from_parts(self.empty_nodes_mask, &self.nodes) as u8
118 }
119
120 pub fn at_depth(&self, node_depth: NonZero<u8>) -> Result<Word, MerkleError> {
130 if node_depth.get() > self.depth() {
131 return Err(MerkleError::DepthTooBig(node_depth.get().into()));
132 }
133
134 let node = if let Some(nonempty_index) = self.get_nonempty_index(node_depth) {
135 self.nodes[nonempty_index]
136 } else {
137 *EmptySubtreeRoots::entry(self.depth(), node_depth.get())
138 };
139
140 Ok(node)
141 }
142
143 pub fn into_parts(self) -> (u64, Vec<Word>) {
150 (self.empty_nodes_mask, self.nodes)
151 }
152
153 pub fn iter(&self) -> impl ExactSizeIterator<Item = Word> {
159 self.into_iter()
160 }
161
162 pub fn compute_root(&self, index: u64, node_to_prove: Word) -> Result<Word, MerkleError> {
164 let mut index = NodeIndex::new(self.depth(), index)?;
165 let root = self.iter().fold(node_to_prove, |node, sibling| {
166 let children = index.build_node(node, sibling);
168 index.move_up();
169 Poseidon2::merge(&children)
170 });
171
172 Ok(root)
173 }
174
175 pub fn verify(&self, index: u64, node: Word, &expected_root: &Word) -> Result<(), MerkleError> {
182 let computed_root = self.compute_root(index, node)?;
183 if computed_root != expected_root {
184 return Err(MerkleError::ConflictingRoots {
185 expected_root,
186 actual_root: computed_root,
187 });
188 }
189
190 Ok(())
191 }
192
193 pub fn authenticated_nodes(
209 &self,
210 index: u64,
211 node_to_prove: Word,
212 ) -> Result<InnerNodeIterator<'_>, MerkleError> {
213 let index = NodeIndex::new(self.depth(), index)?;
214 Ok(InnerNodeIterator { path: self, index, value: node_to_prove })
215 }
216
217 const fn bitmask_for_depth(node_depth: NonZero<u8>) -> u64 {
221 1 << (node_depth.get() - 1)
223 }
224
225 const fn is_depth_empty(&self, node_depth: NonZero<u8>) -> bool {
226 (self.empty_nodes_mask & Self::bitmask_for_depth(node_depth)) != 0
227 }
228
229 fn get_nonempty_index(&self, node_depth: NonZero<u8>) -> Option<usize> {
232 if self.is_depth_empty(node_depth) {
233 return None;
234 }
235
236 let bit_index = node_depth.get() - 1;
237 let without_shallower = self.empty_nodes_mask >> bit_index;
238 let empty_deeper = without_shallower.count_ones() as usize;
239 let normal_index = (self.depth() - node_depth.get()) as usize;
241 Some(normal_index - empty_deeper)
243 }
244
245 fn depth_from_parts(empty_nodes_mask: u64, nodes: &[Word]) -> usize {
247 nodes.len() + empty_nodes_mask.count_ones() as usize
248 }
249}
250
251impl Serializable for SparseMerklePath {
255 fn write_into<W: ByteWriter>(&self, target: &mut W) {
256 target.write_u8(self.depth());
257 target.write_u64(self.empty_nodes_mask);
258 target.write_many(&self.nodes);
259 }
260}
261
262impl Deserializable for SparseMerklePath {
263 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
264 let depth = source.read_u8()?;
265 if depth > SMT_MAX_DEPTH {
266 return Err(DeserializationError::InvalidValue(format!(
267 "SparseMerklePath max depth exceeded ({depth} > {SMT_MAX_DEPTH})",
268 )));
269 }
270 let empty_nodes_mask = source.read_u64()?;
271 let empty_nodes_count = empty_nodes_mask.count_ones();
272 if empty_nodes_count > depth as u32 {
273 return Err(DeserializationError::InvalidValue(format!(
274 "SparseMerklePath has more empty nodes ({empty_nodes_count}) than its full length ({depth})",
275 )));
276 }
277 let count = depth as u32 - empty_nodes_count;
278 let nodes: Vec<Word> = source.read_many_iter(count as usize)?.collect::<Result<_, _>>()?;
279 Self::from_parts(empty_nodes_mask, nodes).map_err(|err| {
284 DeserializationError::InvalidValue(format!("invalid SparseMerklePath: {err}"))
285 })
286 }
287}
288
289impl From<SparseMerklePath> for MerklePath {
293 fn from(sparse_path: SparseMerklePath) -> Self {
294 MerklePath::from_iter(sparse_path)
295 }
296}
297
298impl TryFrom<MerklePath> for SparseMerklePath {
299 type Error = MerkleError;
300
301 fn try_from(path: MerklePath) -> Result<Self, MerkleError> {
306 SparseMerklePath::from_sized_iter(path)
307 }
308}
309
310impl From<SparseMerklePath> for Vec<Word> {
311 fn from(path: SparseMerklePath) -> Self {
312 Vec::from_iter(path)
313 }
314}
315
316pub struct SparseMerklePathIter<'p> {
322 path: Cow<'p, SparseMerklePath>,
324
325 next_depth: u8,
328}
329
330impl Iterator for SparseMerklePathIter<'_> {
331 type Item = Word;
332
333 fn next(&mut self) -> Option<Word> {
334 let this_depth = self.next_depth;
335 let this_depth = NonZero::new(this_depth)?;
337 self.next_depth = this_depth.get() - 1;
338
339 let node = self
341 .path
342 .at_depth(this_depth)
343 .expect("current depth should never exceed the path depth");
344 Some(node)
345 }
346
347 fn size_hint(&self) -> (usize, Option<usize>) {
349 let remaining = ExactSizeIterator::len(self);
350 (remaining, Some(remaining))
351 }
352}
353
354impl ExactSizeIterator for SparseMerklePathIter<'_> {
355 fn len(&self) -> usize {
356 self.next_depth as usize
357 }
358}
359
360impl FusedIterator for SparseMerklePathIter<'_> {}
361
362impl IntoIterator for SparseMerklePath {
365 type IntoIter = SparseMerklePathIter<'static>;
366 type Item = <Self::IntoIter as Iterator>::Item;
367
368 fn into_iter(self) -> SparseMerklePathIter<'static> {
369 let tree_depth = self.depth();
370 SparseMerklePathIter {
371 path: Cow::Owned(self),
372 next_depth: tree_depth,
373 }
374 }
375}
376
377impl<'p> IntoIterator for &'p SparseMerklePath {
378 type Item = <SparseMerklePathIter<'p> as Iterator>::Item;
379 type IntoIter = SparseMerklePathIter<'p>;
380
381 fn into_iter(self) -> SparseMerklePathIter<'p> {
382 let tree_depth = self.depth();
383 SparseMerklePathIter {
384 path: Cow::Borrowed(self),
385 next_depth: tree_depth,
386 }
387 }
388}
389
390pub struct InnerNodeIterator<'p> {
393 path: &'p SparseMerklePath,
394 index: NodeIndex,
395 value: Word,
396}
397
398impl Iterator for InnerNodeIterator<'_> {
399 type Item = InnerNodeInfo;
400
401 fn next(&mut self) -> Option<Self::Item> {
402 if self.index.is_root() {
403 return None;
404 }
405
406 let index_depth = NonZero::new(self.index.depth()).expect("non-root depth cannot be 0");
407 let path_node = self.path.at_depth(index_depth).unwrap();
408
409 let children = self.index.build_node(self.value, path_node);
410 self.value = Poseidon2::merge(&children);
411 self.index.move_up();
412
413 Some(InnerNodeInfo {
414 value: self.value,
415 left: children[0],
416 right: children[1],
417 })
418 }
419}
420
421impl PartialEq<MerklePath> for SparseMerklePath {
424 fn eq(&self, rhs: &MerklePath) -> bool {
425 if self.depth() != rhs.depth() {
426 return false;
427 }
428
429 for (node, &rhs_node) in iter::zip(self, rhs.iter()) {
430 if node != rhs_node {
431 return false;
432 }
433 }
434
435 true
436 }
437}
438
439impl PartialEq<SparseMerklePath> for MerklePath {
440 fn eq(&self, rhs: &SparseMerklePath) -> bool {
441 rhs == self
442 }
443}
444
445fn path_depth_iter(tree_depth: u8) -> impl ExactSizeIterator<Item = NonZero<u8>> {
451 let top_down_iter = (1..=tree_depth).map(|depth| {
452 NonZero::new(depth).expect("range is bounded by 1")
454 });
455
456 top_down_iter.rev()
458}
459
460#[cfg(any(test, feature = "arbitrary"))]
464mod arbitrary {
465 use proptest::prelude::*;
466
467 use super::{MerklePath, SparseMerklePath};
468 use crate::{Word, merkle::smt::SMT_MAX_DEPTH};
469
470 impl Arbitrary for MerklePath {
471 type Parameters = ();
472 type Strategy = BoxedStrategy<Self>;
473
474 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
475 prop::collection::vec(any::<Word>(), 0..=SMT_MAX_DEPTH as usize)
476 .prop_map(MerklePath::new)
477 .boxed()
478 }
479 }
480
481 impl Arbitrary for SparseMerklePath {
482 type Parameters = ();
483 type Strategy = BoxedStrategy<Self>;
484
485 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
486 (0..=SMT_MAX_DEPTH as usize)
487 .prop_flat_map(|depth| {
488 let max_mask = if depth > 0 && depth < 64 {
489 (1u64 << depth) - 1
490 } else if depth == 64 {
491 u64::MAX
492 } else {
493 0
494 };
495 let empty_nodes_mask =
496 prop::num::u64::ANY.prop_map(move |mask| mask & max_mask);
497
498 empty_nodes_mask.prop_flat_map(move |mask| {
499 let empty_count = mask.count_ones() as usize;
500 let non_empty_count = depth.saturating_sub(empty_count);
501
502 prop::collection::vec(any::<Word>(), non_empty_count).prop_map(
503 move |nodes| SparseMerklePath::from_parts(mask, nodes).unwrap(),
504 )
505 })
506 })
507 .boxed()
508 }
509 }
510}
511
512#[cfg(test)]
515mod tests {
516 use alloc::vec::Vec;
517 use core::{
518 num::NonZero,
519 ops::{Deref, DerefMut},
520 };
521
522 use assert_matches::assert_matches;
523
524 use super::SparseMerklePath;
525 use crate::{
526 Felt, ONE, Word,
527 merkle::{
528 EmptySubtreeRoots, MerkleError, MerklePath, MerkleTree, NodeIndex,
529 smt::{LeafIndex, SMT_MAX_DEPTH, SimpleSmt, Smt, SparseMerkleTreeReader},
530 sparse_path::path_depth_iter,
531 },
532 };
533
534 #[test]
537 fn from_parts_rejects_depths_beyond_max_including_wrapped_ones() {
538 let node = Word::from([ONE, ONE, ONE, ONE]);
539 for len in [65usize, 256, 300] {
540 let result = SparseMerklePath::from_parts(0, vec![node; len]);
541 assert_matches!(result, Err(MerkleError::DepthTooBig(depth)) if depth == len as u64);
542 }
543 }
544
545 #[test]
547 fn from_sized_iter_rejects_depths_beyond_max_including_wrapped_ones() {
548 let node = Word::from([ONE, ONE, ONE, ONE]);
549 for len in [65usize, 256] {
550 let result = SparseMerklePath::from_sized_iter(vec![node; len]);
551 assert_matches!(result, Err(MerkleError::DepthTooBig(depth)) if depth == len as u64);
552 }
553 }
554
555 #[test]
559 fn deserialization_rejects_mask_bits_beyond_the_declared_depth() {
560 use crate::utils::{ByteWriter, Deserializable, Serializable};
561
562 let mut bytes = Vec::new();
563 bytes.write_u8(2);
564 bytes.write_u64(1u64 << 63);
565 Word::from([ONE, ONE, ONE, ONE]).write_into(&mut bytes);
566 assert!(SparseMerklePath::read_from_bytes(&bytes).is_err());
567 }
568
569 #[test]
570 fn binary_serialization_roundtrips_valid_boundary_paths() {
571 use crate::utils::{Deserializable, Serializable};
572
573 let node = Word::from([ONE, ONE, ONE, ONE]);
574 for (depth, empty_nodes_mask) in [
575 (0u8, 0u64),
576 (1, 0),
577 (1, 1),
578 (64, 0),
579 (64, 1u64 << 63),
580 (64, 0xaaaa_aaaa_aaaa_aaaa),
581 (64, u64::MAX),
582 ] {
583 let node_count = depth as usize - empty_nodes_mask.count_ones() as usize;
584 let path =
585 SparseMerklePath::from_parts(empty_nodes_mask, vec![node; node_count]).unwrap();
586
587 let decoded = SparseMerklePath::read_from_bytes(&path.to_bytes()).unwrap();
588 assert_eq!(decoded, path);
589 assert_eq!(decoded.depth(), depth);
590 }
591 }
592
593 fn make_smt(pair_count: u64) -> Smt {
594 let entries: Vec<(Word, Word)> = (0..pair_count)
595 .map(|n| {
596 let leaf_index = ((n as f64 / pair_count as f64) * 255.0) as u64;
597 let key =
598 Word::new([ONE, ONE, Felt::new_unchecked(n), Felt::new_unchecked(leaf_index)]);
599 let value = Word::new([ONE, ONE, ONE, ONE]);
600 (key, value)
601 })
602 .collect();
603
604 Smt::with_entries(entries).unwrap()
605 }
606
607 #[test]
613 fn test_sparse_bits() {
614 const DEPTH: u8 = 8;
615 let raw_nodes: [Word; DEPTH as usize] = [
616 ([8u8, 8, 8, 8].into()),
618 *EmptySubtreeRoots::entry(DEPTH, 7),
620 *EmptySubtreeRoots::entry(DEPTH, 6),
622 [5u8, 5, 5, 5].into(),
624 [4u8, 4, 4, 4].into(),
626 *EmptySubtreeRoots::entry(DEPTH, 3),
628 *EmptySubtreeRoots::entry(DEPTH, 2),
630 *EmptySubtreeRoots::entry(DEPTH, 1),
632 ];
634
635 let sparse_nodes: [Option<Word>; DEPTH as usize] = [
636 Some([8u8, 8, 8, 8].into()),
638 None,
640 None,
642 Some([5u8, 5, 5, 5].into()),
644 Some([4u8, 4, 4, 4].into()),
646 None,
648 None,
650 None,
652 ];
654
655 const EMPTY_BITS: u64 = 0b0110_0111;
656
657 let sparse_path = SparseMerklePath::from_sized_iter(raw_nodes).unwrap();
658
659 assert_eq!(sparse_path.empty_nodes_mask, EMPTY_BITS);
660
661 let mut nonempty_idx = 0;
663
664 for depth in (1..=8).rev() {
666 let idx = (sparse_path.depth() - depth) as usize;
667 let bit = 1 << (depth - 1);
668
669 let is_set = (sparse_path.empty_nodes_mask & bit) != 0;
671 assert_eq!(is_set, sparse_nodes.get(idx).unwrap().is_none());
672
673 if is_set {
674 let &test_node = sparse_nodes.get(idx).unwrap();
676 assert_eq!(test_node, None);
677 } else {
678 let control_node = raw_nodes.get(idx).unwrap();
680 assert_eq!(
681 sparse_path.get_nonempty_index(NonZero::new(depth).unwrap()).unwrap(),
682 nonempty_idx
683 );
684 let test_node = sparse_path.nodes.get(nonempty_idx).unwrap();
685 assert_eq!(test_node, control_node);
686
687 nonempty_idx += 1;
688 }
689 }
690 }
691
692 #[test]
693 fn from_parts() {
694 const DEPTH: u8 = 8;
695 let raw_nodes: [Word; DEPTH as usize] = [
696 ([8u8, 8, 8, 8].into()),
698 *EmptySubtreeRoots::entry(DEPTH, 7),
700 *EmptySubtreeRoots::entry(DEPTH, 6),
702 [5u8, 5, 5, 5].into(),
704 [4u8, 4, 4, 4].into(),
706 *EmptySubtreeRoots::entry(DEPTH, 3),
708 *EmptySubtreeRoots::entry(DEPTH, 2),
710 *EmptySubtreeRoots::entry(DEPTH, 1),
712 ];
714
715 let empty_nodes_mask = 0b0110_0111;
716 let nodes = vec![[8u8, 8, 8, 8].into(), [5u8, 5, 5, 5].into(), [4u8, 4, 4, 4].into()];
717 let insufficient_nodes = vec![[4u8, 4, 4, 4].into()];
718
719 let error = SparseMerklePath::from_parts(empty_nodes_mask, insufficient_nodes).unwrap_err();
720 assert_matches!(error, MerkleError::InvalidPathLength(2));
721
722 let iter_sparse_path = SparseMerklePath::from_sized_iter(raw_nodes).unwrap();
723 let sparse_path = SparseMerklePath::from_parts(empty_nodes_mask, nodes).unwrap();
724
725 assert_eq!(sparse_path, iter_sparse_path);
726 }
727
728 #[test]
729 fn from_sized_iter() {
730 let tree = make_smt(8192);
731
732 for (key, _value) in tree.entries() {
733 let index = NodeIndex::from(Smt::key_to_leaf_index(key));
734 let sparse_path = tree.get_path(key);
735 for (sparse_node, proof_idx) in
736 itertools::zip_eq(sparse_path.clone(), index.proof_indices())
737 {
738 let proof_node = tree.get_node_hash(proof_idx);
739 assert_eq!(sparse_node, proof_node);
740 }
741 }
742 }
743
744 #[test]
745 fn test_zero_sized() {
746 let nodes: Vec<Word> = Default::default();
747
748 let sparse_path = SparseMerklePath::from_sized_iter(nodes).unwrap();
750 assert_eq!(sparse_path.depth(), 0);
751 assert_matches!(
752 sparse_path.at_depth(NonZero::new(1).unwrap()),
753 Err(MerkleError::DepthTooBig(1))
754 );
755 assert_eq!(sparse_path.iter().next(), None);
756 assert_eq!(sparse_path.into_iter().next(), None);
757 }
758
759 use proptest::prelude::*;
760
761 proptest! {
762 #[test]
763 fn sparse_merkle_path_roundtrip_equivalence(path in any::<MerklePath>()) {
764 let sparse_result = SparseMerklePath::try_from(path.clone());
766 if path.depth() <= SMT_MAX_DEPTH {
767 let sparse = sparse_result.unwrap();
768 let reconstructed = MerklePath::from(sparse);
769 prop_assert_eq!(path, reconstructed);
770 } else {
771 prop_assert!(sparse_result.is_err());
772 }
773 }
774 }
775 proptest! {
776
777 #[test]
778 fn merkle_path_roundtrip_equivalence(sparse in any::<SparseMerklePath>()) {
779 let merkle = MerklePath::from(sparse.clone());
781 let reconstructed = SparseMerklePath::try_from(merkle).unwrap();
782 prop_assert_eq!(sparse, reconstructed);
783 }
784 }
785 proptest! {
786
787 #[test]
788 fn path_equivalence_tests(path in any::<MerklePath>(), path2 in any::<MerklePath>()) {
789 if path.depth() > SMT_MAX_DEPTH {
790 return Ok(());
791 }
792
793 let sparse = SparseMerklePath::try_from(path.clone()).unwrap();
794
795 prop_assert_eq!(path.depth(), sparse.depth());
797
798 if path.depth() > 0 {
800 for depth in path_depth_iter(path.depth()) {
801 let merkle_node = path.at_depth(depth);
802 let sparse_node = sparse.at_depth(depth);
803
804 match (merkle_node, sparse_node) {
805 (Some(m), Ok(s)) => prop_assert_eq!(m, s),
806 (None, Err(_)) => {},
807 _ => prop_assert!(false, "Inconsistent node access at depth {}", depth.get()),
808 }
809 }
810 }
811
812 if path.depth() > 0 {
814 let merkle_nodes: Vec<_> = path.iter().collect();
815 let sparse_nodes: Vec<_> = sparse.iter().collect();
816
817 prop_assert_eq!(merkle_nodes.len(), sparse_nodes.len());
818 for (m, s) in merkle_nodes.iter().zip(sparse_nodes.iter()) {
819 prop_assert_eq!(*m, s);
820 }
821 }
822
823 if path2.depth() <= SMT_MAX_DEPTH {
825 let sparse2 = SparseMerklePath::try_from(path2.clone()).unwrap();
826 prop_assert_eq!(path == path2, sparse == sparse2);
827 prop_assert_eq!(path == sparse2, sparse == path2);
828 }
829 }
830 }
831 proptest! {
833 #![proptest_config(ProptestConfig::with_cases(100))]
834
835 #[test]
836 fn compute_root_consistency(
837 tree_data in any::<RandomMerkleTree>(),
838 node in any::<Word>()
839 ) {
840 let RandomMerkleTree { tree, leaves: _, indices } = tree_data;
841
842 for &leaf_index in indices.iter() {
843 let path = tree.get_path(NodeIndex::new(tree.depth(), leaf_index).unwrap()).unwrap();
844 let sparse = SparseMerklePath::from_sized_iter(path.clone().into_iter()).unwrap();
845
846 let merkle_root = path.compute_root(leaf_index, node);
847 let sparse_root = sparse.compute_root(leaf_index, node);
848
849 match (merkle_root, sparse_root) {
850 (Ok(m), Ok(s)) => prop_assert_eq!(m, s),
851 (Err(e1), Err(e2)) => {
852 prop_assert_eq!(format!("{:?}", e1), format!("{:?}", e2));
854 },
855 _ => prop_assert!(false, "Inconsistent compute_root results"),
856 }
857 }
858 }
859
860 #[test]
861 fn verify_consistency(
862 tree_data in any::<RandomMerkleTree>(),
863 node in any::<Word>()
864 ) {
865 let RandomMerkleTree { tree, leaves, indices } = tree_data;
866
867 for (i, &leaf_index) in indices.iter().enumerate() {
868 let leaf = leaves[i];
869 let path = tree.get_path(NodeIndex::new(tree.depth(), leaf_index).unwrap()).unwrap();
870 let sparse = SparseMerklePath::from_sized_iter(path.clone().into_iter()).unwrap();
871
872 let root = tree.root();
873
874 let merkle_verify = path.verify(leaf_index, leaf, &root);
875 let sparse_verify = sparse.verify(leaf_index, leaf, &root);
876
877 match (merkle_verify, sparse_verify) {
878 (Ok(()), Ok(())) => {},
879 (Err(e1), Err(e2)) => {
880 prop_assert_eq!(format!("{:?}", e1), format!("{:?}", e2));
882 },
883 _ => prop_assert!(false, "Inconsistent verify results"),
884 }
885
886 let wrong_verify = path.verify(leaf_index, node, &root);
888 let wrong_sparse_verify = sparse.verify(leaf_index, node, &root);
889
890 match (wrong_verify, wrong_sparse_verify) {
891 (Ok(()), Ok(())) => prop_assert!(false, "Verification should have failed with wrong node"),
892 (Err(_), Err(_)) => {},
893 _ => prop_assert!(false, "Inconsistent verification results with wrong node"),
894 }
895 }
896 }
897
898 #[test]
899 fn authenticated_nodes_consistency(
900 tree_data in any::<RandomMerkleTree>()
901 ) {
902 let RandomMerkleTree { tree, leaves, indices } = tree_data;
903
904 for (i, &leaf_index) in indices.iter().enumerate() {
905 let leaf = leaves[i];
906 let path = tree.get_path(NodeIndex::new(tree.depth(), leaf_index).unwrap()).unwrap();
907 let sparse = SparseMerklePath::from_sized_iter(path.clone().into_iter()).unwrap();
908
909 let merkle_result = path.authenticated_nodes(leaf_index, leaf);
910 let sparse_result = sparse.authenticated_nodes(leaf_index, leaf);
911
912 match (merkle_result, sparse_result) {
913 (Ok(m_iter), Ok(s_iter)) => {
914 let merkle_nodes: Vec<_> = m_iter.collect();
915 let sparse_nodes: Vec<_> = s_iter.collect();
916 prop_assert_eq!(merkle_nodes.len(), sparse_nodes.len());
917 for (m, s) in merkle_nodes.iter().zip(sparse_nodes.iter()) {
918 prop_assert_eq!(m, s);
919 }
920 },
921 (Err(e1), Err(e2)) => {
922 prop_assert_eq!(format!("{:?}", e1), format!("{:?}", e2));
923 },
924 _ => prop_assert!(false, "Inconsistent authenticated_nodes results"),
925 }
926 }
927 }
928 }
929
930 #[test]
931 fn test_api_differences() {
932 fn assert_slice_deref<T>()
937 where
938 T: Deref<Target = [Word]> + DerefMut<Target = [Word]>,
939 {
940 }
941
942 assert_slice_deref::<MerklePath>();
943 let mut merkle = MerklePath::new(vec![Word::default(); 3]);
944 let replacement = Word::from([ONE, ONE, ONE, ONE]);
945 let nodes: &mut [Word] = &mut merkle;
946 nodes[0] = replacement;
947 assert_eq!(merkle[0], replacement);
948 assert_eq!(merkle.depth(), 3);
949
950 let sparse = SparseMerklePath::from_parts(0b101, vec![Word::default(); 2]).unwrap();
952 assert_eq!(sparse.depth(), 4); let nodes = vec![Word::default(); 3];
956 let sparse_from_iter = SparseMerklePath::from_sized_iter(nodes.clone()).unwrap();
957 let merkle_from_iter = MerklePath::from_iter(nodes);
958 assert_eq!(sparse_from_iter.depth(), merkle_from_iter.depth());
959 }
960
961 #[derive(Debug, Clone)]
963 struct RandomMerkleTree {
964 tree: MerkleTree,
965 leaves: Vec<Word>,
966 indices: Vec<u64>,
967 }
968
969 impl Arbitrary for RandomMerkleTree {
970 type Parameters = ();
971 type Strategy = BoxedStrategy<Self>;
972
973 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
974 prop::sample::select(&[2, 4, 8, 16, 32, 64, 128, 256, 512, 1024])
976 .prop_flat_map(|num_leaves| {
977 prop::collection::vec(any::<Word>(), num_leaves).prop_map(|leaves| {
978 let tree = MerkleTree::new(leaves.clone()).unwrap();
979 let indices: Vec<u64> = (0..leaves.len() as u64).collect();
980 RandomMerkleTree { tree, leaves, indices }
981 })
982 })
983 .boxed()
984 }
985 }
986
987 #[derive(Debug, Clone)]
989 struct RandomSimpleSmt {
990 tree: SimpleSmt<10>, entries: Vec<(u64, Word)>,
992 }
993
994 impl Arbitrary for RandomSimpleSmt {
995 type Parameters = ();
996 type Strategy = BoxedStrategy<Self>;
997
998 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
999 (1..=100usize) .prop_flat_map(|num_entries| {
1001 prop::collection::vec(
1002 (
1003 0..1024u64, any::<Word>(),
1005 ),
1006 num_entries,
1007 )
1008 .prop_map(|mut entries| {
1009 let mut seen = alloc::collections::BTreeSet::new();
1011 entries.retain(|(idx, _)| seen.insert(*idx));
1012
1013 let mut tree = SimpleSmt::new().unwrap();
1014 for (idx, value) in &entries {
1015 let leaf_idx = LeafIndex::new(*idx).unwrap();
1016 tree.insert(leaf_idx, *value);
1017 }
1018 RandomSimpleSmt { tree, entries }
1019 })
1020 })
1021 .boxed()
1022 }
1023 }
1024
1025 #[derive(Debug, Clone)]
1027 struct RandomSmt {
1028 tree: Smt,
1029 entries: Vec<(Word, Word)>,
1030 }
1031
1032 impl Arbitrary for RandomSmt {
1033 type Parameters = ();
1034 type Strategy = BoxedStrategy<Self>;
1035
1036 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
1037 (1..=100usize) .prop_flat_map(|num_entries| {
1039 prop::collection::vec((any::<u64>(), any::<Word>()), num_entries).prop_map(
1040 |indices_n_values| {
1041 let mut seen = alloc::collections::BTreeSet::new();
1043 let unique_entries: Vec<(Word, Word)> = indices_n_values
1044 .into_iter()
1045 .enumerate()
1046 .map(|(n, (leaf_index, value))| {
1047 let valid_leaf_index = leaf_index % (1u64 << 60); let key = Word::new([
1051 Felt::new_unchecked(n as u64), Felt::new_unchecked(n as u64 + 1), Felt::new_unchecked(n as u64 + 2), Felt::new_unchecked(valid_leaf_index), ]);
1056 (key, value)
1057 })
1058 .filter(|(key, _)| seen.insert(*key))
1059 .collect();
1060
1061 let tree = Smt::with_entries(unique_entries.clone()).unwrap();
1062 RandomSmt { tree, entries: unique_entries }
1063 },
1064 )
1065 })
1066 .boxed()
1067 }
1068 }
1069
1070 proptest! {
1071 #![proptest_config(ProptestConfig::with_cases(20))]
1072
1073 #[test]
1074 fn simple_smt_path_consistency(tree_data in any::<RandomSimpleSmt>()) {
1075 let RandomSimpleSmt { tree, entries } = tree_data;
1076
1077 for (leaf_index, value) in &entries {
1078 let merkle_path = tree.get_path(&LeafIndex::new(*leaf_index).unwrap());
1079 let sparse_path = SparseMerklePath::from_sized_iter(merkle_path.clone().into_iter()).unwrap();
1080
1081 prop_assert_eq!(merkle_path.depth(), sparse_path.depth());
1083
1084 let merkle_root = merkle_path.compute_root(*leaf_index, *value).unwrap();
1086 let sparse_root = sparse_path.compute_root(*leaf_index, *value).unwrap();
1087 prop_assert_eq!(merkle_root, sparse_root);
1088
1089 let tree_root = tree.root();
1091 prop_assert!(merkle_path.verify(*leaf_index, *value, &tree_root).is_ok());
1092 prop_assert!(sparse_path.verify(*leaf_index, *value, &tree_root).is_ok());
1093
1094 let random_leaf = Word::new([Felt::ONE; 4]);
1096 let random_index = *leaf_index ^ 1; let merkle_wrong = merkle_path.verify(random_index, random_leaf, &tree_root);
1100 let sparse_wrong = sparse_path.verify(random_index, random_leaf, &tree_root);
1101 prop_assert_eq!(merkle_wrong.is_err(), sparse_wrong.is_err());
1102 }
1103 }
1104
1105 #[test]
1106 fn smt_path_consistency(tree_data in any::<RandomSmt>()) {
1107 let RandomSmt { tree, entries } = tree_data;
1108
1109 for (key, _value) in &entries {
1110 let (merkle_path, leaf) = tree.open(key).into_parts();
1111 let sparse_path = SparseMerklePath::from_sized_iter(merkle_path.clone().into_iter()).unwrap();
1112
1113 let leaf_index = Smt::key_to_leaf_index(key).position();
1114 let actual_value = leaf.hash(); prop_assert_eq!(merkle_path.depth(), sparse_path.depth());
1118
1119 let merkle_root = merkle_path.compute_root(leaf_index, actual_value).unwrap();
1121 let sparse_root = sparse_path.compute_root(leaf_index, actual_value).unwrap();
1122 prop_assert_eq!(merkle_root, sparse_root);
1123
1124 let tree_root = tree.root();
1126 prop_assert!(merkle_path.verify(leaf_index, actual_value, &tree_root).is_ok());
1127 prop_assert!(sparse_path.verify(leaf_index, actual_value, &tree_root).is_ok());
1128
1129 let merkle_auth = merkle_path.authenticated_nodes(leaf_index, actual_value).unwrap().collect::<Vec<_>>();
1131 let sparse_auth = sparse_path.authenticated_nodes(leaf_index, actual_value).unwrap().collect::<Vec<_>>();
1132 prop_assert_eq!(merkle_auth, sparse_auth);
1133 }
1134 }
1135
1136 #[test]
1137 fn reverse_conversion_from_sparse(tree_data in any::<RandomMerkleTree>()) {
1138 let RandomMerkleTree { tree, leaves, indices } = tree_data;
1139
1140 for (i, &leaf_index) in indices.iter().enumerate() {
1141 let leaf = leaves[i];
1142 let merkle_path = tree.get_path(NodeIndex::new(tree.depth(), leaf_index).unwrap()).unwrap();
1143
1144 let sparse_path = SparseMerklePath::from_sized_iter(merkle_path.clone().into_iter()).unwrap();
1146 let converted_merkle = MerklePath::from(sparse_path.clone());
1147
1148 let back_to_sparse = SparseMerklePath::try_from(converted_merkle.clone()).unwrap();
1150 prop_assert_eq!(sparse_path, back_to_sparse);
1151
1152 prop_assert_eq!(merkle_path.depth(), converted_merkle.depth());
1154
1155 let merkle_root = merkle_path.compute_root(leaf_index, leaf).unwrap();
1156 let converted_root = converted_merkle.compute_root(leaf_index, leaf).unwrap();
1157 prop_assert_eq!(merkle_root, converted_root);
1158 }
1159 }
1160 }
1161}