1use crate::rstd::{
16 convert::TryInto, iter::Peekable, marker::PhantomData, result::Result, vec, vec::Vec,
17};
18use crate::{
19 CError, ChildReference, nibble::LeftNibbleSlice, nibble_ops::NIBBLE_LENGTH,
20 node::{Node, NodeHandle}, NodeCodec, TrieHash, TrieLayout,
21};
22use tetsy_hash_db::Hasher;
23
24
25#[derive(PartialEq, Eq)]
29#[cfg_attr(feature = "std", derive(Debug))]
30pub enum Error<HO, CE> {
31 DuplicateKey(Vec<u8>),
34 ExtraneousNode,
36 ExtraneousValue(Vec<u8>),
39 ExtraneousHashReference(HO),
41 InvalidChildReference(Vec<u8>),
43 ValueMismatch(Vec<u8>),
45 IncompleteProof,
47 RootMismatch(HO),
49 DecodeError(CE),
51}
52
53#[cfg(feature = "std")]
54impl<HO: std::fmt::Debug, CE: std::error::Error> std::fmt::Display for Error<HO, CE> {
55 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
56 match self {
57 Error::DuplicateKey(key) =>
58 write!(f, "Duplicate key in input statement: key={:?}", key),
59 Error::ExtraneousNode =>
60 write!(f, "Extraneous node found in proof"),
61 Error::ExtraneousValue(key) =>
62 write!(
63 f,
64 "Extraneous value found in proof should have been omitted: key={:?}",
65 key
66 ),
67 Error::ExtraneousHashReference(hash) =>
68 write!(
69 f,
70 "Extraneous hash reference found in proof should have been omitted: hash={:?}",
71 hash
72 ),
73 Error::InvalidChildReference(data) =>
74 write!(f, "Invalid child reference exceeds hash length: {:?}", data),
75 Error::ValueMismatch(key) =>
76 write!(f, "Expected value was not found in the trie: key={:?}", key),
77 Error::IncompleteProof =>
78 write!(f, "Proof is incomplete -- expected more nodes"),
79 Error::RootMismatch(hash) =>
80 write!(f, "Computed incorrect root {:?} from proof", hash),
81 Error::DecodeError(err) =>
82 write!(f, "Unable to decode proof node: {}", err),
83 }
84 }
85}
86
87#[cfg(feature = "std")]
88impl<HO: std::fmt::Debug, CE: std::error::Error + 'static> std::error::Error for Error<HO, CE> {
89 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
90 match self {
91 Error::DecodeError(err) => Some(err),
92 _ => None,
93 }
94 }
95}
96
97struct StackEntry<'a, C: NodeCodec> {
98 prefix: LeftNibbleSlice<'a>,
100 node: Node<'a>,
101 is_inline: bool,
102 value: Option<&'a [u8]>,
104 child_index: usize,
107 children: Vec<Option<ChildReference<C::HashOut>>>,
109 _marker: PhantomData<C>,
110}
111
112impl<'a, C: NodeCodec> StackEntry<'a, C> {
113 fn new(node_data: &'a [u8], prefix: LeftNibbleSlice<'a>, is_inline: bool)
114 -> Result<Self, Error<C::HashOut, C::Error>>
115 {
116 let node = C::decode(node_data)
117 .map_err(Error::DecodeError)?;
118 let children_len = match node {
119 Node::Empty | Node::Leaf(..) => 0,
120 Node::Extension(..) => 1,
121 Node::Branch(..) | Node::NibbledBranch(..) => NIBBLE_LENGTH,
122 };
123 let value = match node {
124 Node::Empty | Node::Extension(_, _) => None,
125 Node::Leaf(_, value) => Some(value),
126 Node::Branch(_, value) | Node::NibbledBranch(_, _, value) => value,
127 };
128 Ok(StackEntry {
129 node,
130 is_inline,
131 prefix,
132 value,
133 child_index: 0,
134 children: vec![None; children_len],
135 _marker: PhantomData::default(),
136 })
137 }
138
139 fn encode_node(mut self) -> Result<Vec<u8>, Error<C::HashOut, C::Error>> {
141 self.complete_children()?;
142 Ok(match self.node {
143 Node::Empty =>
144 C::empty_node().to_vec(),
145 Node::Leaf(partial, _) => {
146 let value = self.value
147 .expect(
148 "value is assigned to Some in StackEntry::new; \
149 value is only ever reassigned in the ValueMatch::MatchesLeaf match \
150 clause, which assigns only to Some"
151 );
152 C::leaf_node(partial.right(), value)
153 }
154 Node::Extension(partial, _) => {
155 let child = self.children[0]
156 .expect("the child must be completed since child_index is 1");
157 C::extension_node(
158 partial.right_iter(),
159 partial.len(),
160 child
161 )
162 }
163 Node::Branch(_, _) =>
164 C::branch_node(
165 self.children.iter(),
166 self.value,
167 ),
168 Node::NibbledBranch(partial, _, _) =>
169 C::branch_node_nibbled(
170 partial.right_iter(),
171 partial.len(),
172 self.children.iter(),
173 self.value,
174 ),
175 })
176 }
177
178 fn advance_child_index<I>(
179 &mut self,
180 child_prefix: LeftNibbleSlice<'a>,
181 proof_iter: &mut I,
182 ) -> Result<Self, Error<C::HashOut, C::Error>>
183 where
184 I: Iterator<Item=&'a Vec<u8>>,
185 {
186 match self.node {
187 Node::Extension(_, child) => {
188 assert_eq!(self.child_index, 0);
190 Self::make_child_entry(proof_iter, child, child_prefix)
191 }
192 Node::Branch(children, _) | Node::NibbledBranch(_, children, _) => {
193 assert!(child_prefix.len() > 0);
195 let child_index = child_prefix.at(child_prefix.len() - 1)
196 .expect("it's less than prefix.len(); qed")
197 as usize;
198 while self.child_index < child_index {
199 if let Some(child) = children[self.child_index] {
200 let child_ref = child.try_into()
201 .map_err(Error::InvalidChildReference)?;
202 self.children[self.child_index] = Some(child_ref);
203 }
204 self.child_index += 1;
205 }
206 let child = children[self.child_index]
207 .expect("guaranteed by advance_item");
208 Self::make_child_entry(proof_iter, child, child_prefix)
209 }
210 _ => panic!("cannot have children"),
211 }
212 }
213
214 fn complete_children(&mut self) -> Result<(), Error<C::HashOut, C::Error>> {
216 match self.node {
217 Node::Extension(_, child) if self.child_index == 0 => {
218 let child_ref = child.try_into()
219 .map_err(Error::InvalidChildReference)?;
220 self.children[self.child_index] = Some(child_ref);
221 self.child_index += 1;
222 }
223 Node::Branch(children, _) | Node::NibbledBranch(_, children, _) => {
224 while self.child_index < NIBBLE_LENGTH {
225 if let Some(child) = children[self.child_index] {
226 let child_ref = child.try_into()
227 .map_err(Error::InvalidChildReference)?;
228 self.children[self.child_index] = Some(child_ref);
229 }
230 self.child_index += 1;
231 }
232 }
233 _ => {}
234 }
235 Ok(())
236 }
237
238 fn make_child_entry<I>(
239 proof_iter: &mut I,
240 child: NodeHandle<'a>,
241 prefix: LeftNibbleSlice<'a>,
242 ) -> Result<Self, Error<C::HashOut, C::Error>>
243 where
244 I: Iterator<Item=&'a Vec<u8>>,
245 {
246 match child {
247 NodeHandle::Inline(data) => {
248 if data.is_empty() {
249 let node_data = proof_iter.next()
250 .ok_or(Error::IncompleteProof)?;
251 StackEntry::new(node_data, prefix, false)
252 } else {
253 StackEntry::new(data, prefix, true)
254 }
255 }
256 NodeHandle::Hash(data) => {
257 let mut hash = C::HashOut::default();
258 if data.len() != hash.as_ref().len() {
259 return Err(Error::InvalidChildReference(data.to_vec()));
260 }
261 hash.as_mut().copy_from_slice(data);
262 Err(Error::ExtraneousHashReference(hash))
263 }
264 }
265 }
266
267 fn advance_item<I>(&mut self, items_iter: &mut Peekable<I>)
268 -> Result<Step<'a>, Error<C::HashOut, C::Error>>
269 where
270 I: Iterator<Item=(&'a [u8], Option<&'a [u8]>)>
271 {
272 let step = loop {
273 if let Some((key_bytes, value)) = items_iter.peek().cloned() {
274 let key = LeftNibbleSlice::new(key_bytes);
275 if key.starts_with(&self.prefix) {
276 match match_key_to_node(&key, self.prefix.len(), &self.node) {
277 ValueMatch::MatchesLeaf => {
278 if value.is_none() {
279 return Err(Error::ValueMismatch(key_bytes.to_vec()));
280 }
281 self.value = value;
282 }
283 ValueMatch::MatchesBranch =>
284 self.value = value,
285 ValueMatch::NotFound =>
286 if value.is_some() {
287 return Err(Error::ValueMismatch(key_bytes.to_vec()));
288 },
289 ValueMatch::NotOmitted =>
290 return Err(Error::ExtraneousValue(key_bytes.to_vec())),
291 ValueMatch::IsChild(child_prefix) =>
292 break Step::Descend(child_prefix),
293 }
294
295 items_iter.next();
296 continue;
297 }
298 }
299 break Step::UnwindStack;
300 };
301 Ok(step)
302 }
303}
304
305enum ValueMatch<'a> {
306 MatchesLeaf,
308 MatchesBranch,
310 NotFound,
312 NotOmitted,
314 IsChild(LeftNibbleSlice<'a>),
316}
317
318fn match_key_to_node<'a>(key: &LeftNibbleSlice<'a>, prefix_len: usize, node: &Node)
321 -> ValueMatch<'a>
322{
323 match node {
324 Node::Empty => ValueMatch::NotFound,
325 Node::Leaf(partial, value) => {
326 if key.contains(partial, prefix_len) &&
327 key.len() == prefix_len + partial.len() {
328 if value.is_empty() {
329 ValueMatch::MatchesLeaf
330 } else {
331 ValueMatch::NotOmitted
332 }
333 } else {
334 ValueMatch::NotFound
335 }
336 }
337 Node::Extension(partial, _) => {
338 if key.contains(partial, prefix_len) {
339 ValueMatch::IsChild(key.truncate(prefix_len + partial.len()))
340 } else {
341 ValueMatch::NotFound
342 }
343 }
344 Node::Branch(children, value) => {
345 match_key_to_branch_node(key, prefix_len, children, value)
346 }
347 Node::NibbledBranch(partial, children, value) => {
348 if key.contains(partial, prefix_len) {
349 match_key_to_branch_node(key, prefix_len + partial.len(), children, value)
350 } else {
351 ValueMatch::NotFound
352 }
353 }
354 }
355}
356
357fn match_key_to_branch_node<'a>(
361 key: &LeftNibbleSlice<'a>,
362 prefix_plus_partial_len: usize,
363 children: &[Option<NodeHandle>; NIBBLE_LENGTH],
364 value: &Option<&[u8]>,
365) -> ValueMatch<'a>
366{
367 if key.len() == prefix_plus_partial_len {
368 if value.is_none() {
369 ValueMatch::MatchesBranch
370 } else {
371 ValueMatch::NotOmitted
372 }
373 } else {
374 let index = key.at(prefix_plus_partial_len)
375 .expect("it's less than prefix.len(); qed")
376 as usize;
377 if children[index].is_some() {
378 ValueMatch::IsChild(key.truncate(prefix_plus_partial_len + 1))
379 } else {
380 ValueMatch::NotFound
381 }
382 }
383}
384
385enum Step<'a> {
386 Descend(LeftNibbleSlice<'a>),
387 UnwindStack,
388}
389
390pub fn verify_proof<'a, L, I, K, V>(root: &<L::Hash as Hasher>::Out, proof: &[Vec<u8>], items: I)
392 -> Result<(), Error<TrieHash<L>, CError<L>>>
393 where
394 L: TrieLayout,
395 I: IntoIterator<Item=&'a (K, Option<V>)>,
396 K: 'a + AsRef<[u8]>,
397 V: 'a + AsRef<[u8]>,
398{
399 let mut items = items.into_iter()
401 .map(|(k, v)| (k.as_ref(), v.as_ref().map(|v| v.as_ref())))
402 .collect::<Vec<_>>();
403 items.sort();
404
405 if items.is_empty() {
406 return if proof.is_empty() {
407 Ok(())
408 } else {
409 Err(Error::ExtraneousNode)
410 };
411 }
412
413 for i in 1..items.len() {
415 if items[i].0 == items[i - 1].0 {
416 return Err(Error::DuplicateKey(items[i].0.to_vec()));
417 }
418 }
419
420 let mut proof_iter = proof.iter();
422 let mut items_iter = items.into_iter().peekable();
423
424 let mut stack: Vec<StackEntry<L::Codec>> = Vec::new();
427
428 let root_node = match proof_iter.next() {
429 Some(node) => node,
430 None => return Err(Error::IncompleteProof),
431 };
432 let mut last_entry = StackEntry::new(
433 root_node,
434 LeftNibbleSlice::new(&[]),
435 false
436 )?;
437 loop {
438 match last_entry.advance_item(&mut items_iter)? {
440 Step::Descend(child_prefix) => {
441 let next_entry = last_entry.advance_child_index(child_prefix, &mut proof_iter)?;
442 stack.push(last_entry);
443 last_entry = next_entry;
444 }
445 Step::UnwindStack => {
446 let is_inline = last_entry.is_inline;
447 let node_data = last_entry.encode_node()?;
448
449 let child_ref = if is_inline {
450 if node_data.len() > L::Hash::LENGTH {
451 return Err(Error::InvalidChildReference(node_data));
452 }
453 let mut hash = <TrieHash<L>>::default();
454 &mut hash.as_mut()[..node_data.len()].copy_from_slice(node_data.as_ref());
455 ChildReference::Inline(hash, node_data.len())
456 } else {
457 let hash = L::Hash::hash(&node_data);
458 ChildReference::Hash(hash)
459 };
460
461 if let Some(entry) = stack.pop() {
462 last_entry = entry;
463 last_entry.children[last_entry.child_index] = Some(child_ref);
464 last_entry.child_index += 1;
465 } else {
466 if proof_iter.next().is_some() {
467 return Err(Error::ExtraneousNode);
468 }
469 let computed_root = match child_ref {
470 ChildReference::Hash(hash) => hash,
471 ChildReference::Inline(_, _) => panic!(
472 "the bottom item on the stack has is_inline = false; qed"
473 ),
474 };
475 if computed_root != *root {
476 return Err(Error::RootMismatch(computed_root));
477 }
478 break;
479 }
480 }
481 }
482 }
483
484 Ok(())
485}