snarkvm_console_collections/kary_merkle_tree/path/
mod.rs1use super::*;
17
18#[derive(Clone, Debug, PartialEq, Eq, Hash)]
19pub struct KaryMerklePath<PH: PathHash, const DEPTH: u8, const ARITY: u8> {
20 leaf_index: u64,
22 siblings: Vec<Vec<PH::Hash>>,
24}
25
26impl<PH: PathHash, const DEPTH: u8, const ARITY: u8> KaryMerklePath<PH, DEPTH, ARITY> {
27 pub fn try_from((leaf_index, siblings): (u64, Vec<Vec<PH::Hash>>)) -> Result<Self> {
29 ensure!(DEPTH > 0, "Merkle tree depth must be greater than 0");
31 ensure!(DEPTH <= 64u8, "Merkle tree depth must be less than or equal to 64");
33 ensure!(ARITY > 1, "Merkle tree arity must be greater than 1");
35 ensure!((ARITY as u128).checked_pow(DEPTH as u32).is_some(), "Merkle tree size overflowed");
37 ensure!((leaf_index as u128) < (ARITY as u128).saturating_pow(DEPTH as u32), "Out of bounds Merkle leaf index");
39 ensure!(siblings.len() == DEPTH as usize, "Found an incorrect Merkle path length");
41 for sibling in &siblings {
42 ensure!(sibling.len() == (ARITY - 1) as usize, "Found an incorrect Merkle path arity");
44 }
45 Ok(Self { leaf_index, siblings })
47 }
48}
49
50impl<PH: PathHash, const DEPTH: u8, const ARITY: u8> KaryMerklePath<PH, DEPTH, ARITY> {
51 pub fn leaf_index(&self) -> u64 {
53 self.leaf_index
54 }
55
56 pub fn siblings(&self) -> &[Vec<PH::Hash>] {
58 &self.siblings
59 }
60
61 pub fn verify<LH: LeafHash<Hash = PH::Hash>>(
63 &self,
64 leaf_hasher: &LH,
65 path_hasher: &PH,
66 root: &PH::Hash,
67 leaf: &LH::Leaf,
68 ) -> bool {
69 if (self.leaf_index as u128) >= (ARITY as u128).saturating_pow(DEPTH as u32) {
71 eprintln!("Found an out of bounds Merkle leaf index");
72 return false;
73 }
74 if self.siblings.len() != DEPTH as usize {
76 eprintln!("Found an incorrect Merkle path length");
77 return false;
78 }
79
80 let mut current_hash = match leaf_hasher.hash_leaf(leaf) {
82 Ok(candidate_leaf_hash) => candidate_leaf_hash,
83 Err(error) => {
84 eprintln!("Failed to hash the Merkle leaf during verification: {error}");
85 return false;
86 }
87 };
88
89 let Ok(indicator_indexes) = (0..DEPTH)
92 .map(|i| {
93 usize::try_from(self.leaf_index as u128 / (ARITY as u128).saturating_pow(i as u32) % (ARITY as u128))
94 })
95 .collect::<Result<Vec<_>, _>>()
96 else {
97 eprintln!("Found an incorrect Merkle leaf index");
98 return false;
99 };
100
101 for (indicator_index, sibling_hashes) in indicator_indexes.into_iter().zip_eq(&self.siblings) {
103 let mut sibling_hashes = sibling_hashes.clone();
105
106 sibling_hashes.insert(indicator_index, current_hash);
108
109 match path_hasher.hash_children(&sibling_hashes) {
111 Ok(hash) => current_hash = hash,
112 Err(error) => {
113 eprintln!("Failed to hash the Merkle path during verification: {error}");
114 return false;
115 }
116 }
117 }
118
119 current_hash == *root
121 }
122}
123
124impl<PH: PathHash, const DEPTH: u8, const ARITY: u8> FromBytes for KaryMerklePath<PH, DEPTH, ARITY> {
125 #[inline]
127 fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
128 let leaf_index = u64::read_le(&mut reader)?;
130 let siblings = (0..DEPTH)
132 .map(|_| (0..ARITY).map(|_| FromBytes::read_le(&mut reader)).collect::<IoResult<Vec<_>>>())
133 .collect::<IoResult<Vec<_>>>()?;
134 Self::try_from((leaf_index, siblings)).map_err(error)
136 }
137}
138
139impl<PH: PathHash, const DEPTH: u8, const ARITY: u8> ToBytes for KaryMerklePath<PH, DEPTH, ARITY> {
140 #[inline]
142 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
143 self.leaf_index.write_le(&mut writer)?;
145 self.siblings
147 .iter()
148 .try_for_each(|siblings| siblings.iter().try_for_each(|sibling| sibling.write_le(&mut writer)))
149 }
150}
151
152impl<PH: PathHash, const DEPTH: u8, const ARITY: u8> Serialize for KaryMerklePath<PH, DEPTH, ARITY> {
153 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
154 ToBytesSerializer::serialize_with_size_encoding(self, serializer)
155 }
156}
157
158impl<'de, PH: PathHash, const DEPTH: u8, const ARITY: u8> Deserialize<'de> for KaryMerklePath<PH, DEPTH, ARITY> {
159 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
160 FromBytesDeserializer::<Self>::deserialize_with_size_encoding(deserializer, "K-ary Merkle path")
161 }
162}