1use crate::maybestd::{mem, vec::Vec};
6use crate::{
7 namespaced_hash::{NamespaceId, NamespaceMerkleHasher, NamespacedHash},
8 simple_merkle::{
9 db::NoopDb, error::RangeProofError, proof::Proof, tree::MerkleHash,
10 utils::compute_num_left_siblings,
11 },
12 NamespaceMerkleTree,
13};
14
15#[derive(Debug, PartialEq, Clone)]
20#[cfg_attr(
21 feature = "borsh",
22 derive(borsh::BorshSerialize, borsh::BorshDeserialize)
23)]
24#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
25pub enum NamespaceProof<M: MerkleHash, const NS_ID_SIZE: usize> {
26 AbsenceProof {
28 proof: Proof<M>,
30 ignore_max_ns: bool,
32 leaf: Option<NamespacedHash<NS_ID_SIZE>>,
35 },
36 PresenceProof {
38 proof: Proof<M>,
40 ignore_max_ns: bool,
42 },
43}
44
45impl<M, const NS_ID_SIZE: usize> NamespaceProof<M, NS_ID_SIZE>
46where
47 M: NamespaceMerkleHasher<NS_ID_SIZE, Output = NamespacedHash<NS_ID_SIZE>>,
48{
49 pub fn verify_complete_namespace(
51 &self,
52 root: &NamespacedHash<NS_ID_SIZE>,
53 raw_leaves: &[impl AsRef<[u8]>],
54 namespace: NamespaceId<NS_ID_SIZE>,
55 ) -> Result<(), RangeProofError> {
56 if self.is_of_presence() && raw_leaves.len() != self.range_len() {
57 return Err(RangeProofError::WrongAmountOfLeavesProvided);
58 }
59
60 let tree = NamespaceMerkleTree::<NoopDb, M, NS_ID_SIZE>::with_hasher(
61 M::with_ignore_max_ns(self.ignores_max_ns()),
62 );
63 tree.verify_namespace(root, raw_leaves, namespace, self)
64 }
65
66 pub fn verify_range(
68 &self,
69 root: &NamespacedHash<NS_ID_SIZE>,
70 raw_leaves: &[impl AsRef<[u8]>],
71 leaf_namespace: NamespaceId<NS_ID_SIZE>,
72 ) -> Result<(), RangeProofError> {
73 if self.is_of_absence() {
74 return Err(RangeProofError::MalformedProof(
75 "Cannot prove that a partial namespace is absent",
76 ));
77 };
78
79 if raw_leaves.len() != self.range_len() {
80 return Err(RangeProofError::WrongAmountOfLeavesProvided);
81 }
82
83 let leaf_hashes: Vec<_> = raw_leaves
84 .iter()
85 .map(|data| {
86 M::with_ignore_max_ns(self.ignores_max_ns())
87 .hash_leaf_with_namespace(data.as_ref(), leaf_namespace)
88 })
89 .collect();
90 let tree = NamespaceMerkleTree::<NoopDb, M, NS_ID_SIZE>::with_hasher(
91 M::with_ignore_max_ns(self.ignores_max_ns()),
92 );
93 tree.inner.check_range_proof(
94 root,
95 &leaf_hashes,
96 self.siblings(),
97 self.start_idx() as usize,
98 )
99 }
100
101 pub fn narrow_range<L: AsRef<[u8]>>(
111 &self,
112 left_extra_raw_leaves: &[L],
113 right_extra_raw_leaves: &[L],
114 leaf_namespace: NamespaceId<NS_ID_SIZE>,
115 ) -> Result<Self, RangeProofError> {
116 if self.is_of_absence() {
117 return Err(RangeProofError::MalformedProof(
118 "Cannot narrow the range of an absence proof",
119 ));
120 }
121
122 let leaves_to_hashes = |l: &[L]| -> Vec<NamespacedHash<NS_ID_SIZE>> {
123 l.iter()
124 .map(|data| {
125 M::with_ignore_max_ns(self.ignores_max_ns())
126 .hash_leaf_with_namespace(data.as_ref(), leaf_namespace)
127 })
128 .collect()
129 };
130 let left_extra_hashes = leaves_to_hashes(left_extra_raw_leaves);
131 let right_extra_hashes = leaves_to_hashes(right_extra_raw_leaves);
132
133 let proof = self.merkle_proof().narrow_range_with_hasher(
134 &left_extra_hashes,
135 &right_extra_hashes,
136 M::with_ignore_max_ns(self.ignores_max_ns()),
137 )?;
138
139 Ok(Self::PresenceProof {
140 proof,
141 ignore_max_ns: self.ignores_max_ns(),
142 })
143 }
144
145 pub fn convert_to_absence_proof(&mut self, leaf: NamespacedHash<NS_ID_SIZE>) {
147 match self {
148 NamespaceProof::AbsenceProof { .. } => {}
149 NamespaceProof::PresenceProof {
150 proof,
151 ignore_max_ns,
152 } => {
153 let pf = mem::take(proof);
154 *self = Self::AbsenceProof {
155 proof: pf,
156 ignore_max_ns: *ignore_max_ns,
157 leaf: Some(leaf),
158 }
159 }
160 }
161 }
162
163 fn merkle_proof(&self) -> &Proof<M> {
164 match self {
165 NamespaceProof::AbsenceProof { proof, .. }
166 | NamespaceProof::PresenceProof { proof, .. } => proof,
167 }
168 }
169
170 pub fn siblings(&self) -> &[NamespacedHash<NS_ID_SIZE>] {
172 self.merkle_proof().siblings()
173 }
174
175 pub fn start_idx(&self) -> u32 {
177 self.merkle_proof().start_idx()
178 }
179
180 pub fn end_idx(&self) -> u32 {
182 self.merkle_proof().end_idx()
183 }
184
185 fn range_len(&self) -> usize {
187 self.merkle_proof().range_len()
188 }
189
190 pub fn leftmost_right_sibling(&self) -> Option<&NamespacedHash<NS_ID_SIZE>> {
192 let siblings = self.siblings();
193 let num_left_siblings = compute_num_left_siblings(self.start_idx() as usize);
194 if siblings.len() > num_left_siblings {
195 return Some(&siblings[num_left_siblings]);
196 }
197 None
198 }
199
200 pub fn rightmost_left_sibling(&self) -> Option<&NamespacedHash<NS_ID_SIZE>> {
202 let siblings = self.siblings();
203 let num_left_siblings = compute_num_left_siblings(self.start_idx() as usize);
204 if num_left_siblings != 0 && num_left_siblings <= siblings.len() {
205 return Some(&siblings[num_left_siblings - 1]);
206 }
207 None
208 }
209
210 fn ignores_max_ns(&self) -> bool {
211 match self {
212 Self::AbsenceProof { ignore_max_ns, .. }
213 | Self::PresenceProof { ignore_max_ns, .. } => *ignore_max_ns,
214 }
215 }
216
217 pub fn is_of_absence(&self) -> bool {
219 match self {
220 Self::AbsenceProof { .. } => true,
221 Self::PresenceProof { .. } => false,
222 }
223 }
224
225 pub fn is_of_presence(&self) -> bool {
227 !self.is_of_absence()
228 }
229}