1use super::{CError, DBValue, Result, Trie, TrieHash, TrieIterator, TrieLayout};
16use crate::{
17 nibble::{nibble_ops, NibbleSlice, NibbleVec},
18 node::{Node, NodeHandle, NodePlan, OwnedNode, Value},
19 triedb::TrieDB,
20 TrieError, TrieItem, TrieKeyItem,
21};
22use hash_db::{Hasher, Prefix, EMPTY_PREFIX};
23
24use crate::rstd::{boxed::Box, sync::Arc, vec::Vec};
25
26#[cfg_attr(feature = "std", derive(Debug))]
27#[derive(Clone, Copy, Eq, PartialEq)]
28enum Status {
29 Entering,
30 At,
31 AtChild(usize),
32 Exiting,
33}
34
35#[cfg_attr(feature = "std", derive(Debug))]
36#[derive(Eq, PartialEq)]
37struct Crumb<H: Hasher> {
38 hash: Option<H::Out>,
39 node: Arc<OwnedNode<DBValue>>,
40 status: Status,
41}
42
43impl<H: Hasher> Crumb<H> {
44 fn increment(&mut self) {
46 self.status = match (self.status, self.node.node_plan()) {
47 (Status::Entering, NodePlan::Extension { .. }) => Status::At,
48 (Status::Entering, NodePlan::Branch { .. }) |
49 (Status::Entering, NodePlan::NibbledBranch { .. }) => Status::At,
50 (Status::At, NodePlan::Branch { .. }) |
51 (Status::At, NodePlan::NibbledBranch { .. }) => Status::AtChild(0),
52 (Status::AtChild(x), NodePlan::Branch { .. }) |
53 (Status::AtChild(x), NodePlan::NibbledBranch { .. })
54 if x < (nibble_ops::NIBBLE_LENGTH - 1) =>
55 Status::AtChild(x + 1),
56 _ => Status::Exiting,
57 }
58 }
59}
60
61pub struct TrieDBRawIterator<L: TrieLayout> {
63 trail: Vec<Crumb<L::Hash>>,
64 key_nibbles: NibbleVec,
65}
66
67impl<L: TrieLayout> TrieDBRawIterator<L> {
68 pub fn empty() -> Self {
70 Self { trail: Vec::new(), key_nibbles: NibbleVec::new() }
71 }
72
73 pub fn new(db: &TrieDB<L>) -> Result<Self, TrieHash<L>, CError<L>> {
75 let mut r =
76 TrieDBRawIterator { trail: Vec::with_capacity(8), key_nibbles: NibbleVec::new() };
77 let (root_node, root_hash) = db.get_raw_or_lookup(
78 *db.root(),
79 NodeHandle::Hash(db.root().as_ref()),
80 EMPTY_PREFIX,
81 true,
82 )?;
83 r.descend(root_node, root_hash);
84 Ok(r)
85 }
86
87 pub fn new_prefixed(db: &TrieDB<L>, prefix: &[u8]) -> Result<Self, TrieHash<L>, CError<L>> {
89 let mut iter = TrieDBRawIterator::new(db)?;
90 iter.prefix(db, prefix)?;
91
92 Ok(iter)
93 }
94
95 pub fn new_prefixed_then_seek(
99 db: &TrieDB<L>,
100 prefix: &[u8],
101 start_at: &[u8],
102 ) -> Result<Self, TrieHash<L>, CError<L>> {
103 let mut iter = TrieDBRawIterator::new(db)?;
104 iter.prefix_then_seek(db, prefix, start_at)?;
105 Ok(iter)
106 }
107
108 fn descend(&mut self, node: OwnedNode<DBValue>, node_hash: Option<TrieHash<L>>) {
110 self.trail
111 .push(Crumb { hash: node_hash, status: Status::Entering, node: Arc::new(node) });
112 }
113
114 pub(crate) fn fetch_value(
116 db: &TrieDB<L>,
117 key: &[u8],
118 prefix: Prefix,
119 ) -> Result<DBValue, TrieHash<L>, CError<L>> {
120 let mut res = TrieHash::<L>::default();
121 res.as_mut().copy_from_slice(key);
122 db.fetch_value(res, prefix)
123 }
124
125 pub(crate) fn seek(
132 &mut self,
133 db: &TrieDB<L>,
134 key: &[u8],
135 ) -> Result<bool, TrieHash<L>, CError<L>> {
136 self.trail.clear();
137 self.key_nibbles.clear();
138 let key = NibbleSlice::new(key);
139
140 let (mut node, mut node_hash) = db.get_raw_or_lookup(
141 <TrieHash<L>>::default(),
142 NodeHandle::Hash(db.root().as_ref()),
143 EMPTY_PREFIX,
144 true,
145 )?;
146 let mut partial = key;
147 let mut full_key_nibbles = 0;
148 loop {
149 let (next_node, next_node_hash) = {
150 self.descend(node, node_hash);
151 let crumb = self.trail.last_mut().expect(
152 "descend_into_node pushes a crumb onto the trial; \
153 thus the trail is non-empty; qed",
154 );
155 let node_data = crumb.node.data();
156
157 match crumb.node.node_plan() {
158 NodePlan::Leaf { partial: partial_plan, .. } => {
159 let slice = partial_plan.build(node_data);
160 if slice < partial {
161 crumb.status = Status::Exiting;
162 return Ok(false)
163 }
164 return Ok(slice.starts_with(&partial))
165 },
166 NodePlan::Extension { partial: partial_plan, child } => {
167 let slice = partial_plan.build(node_data);
168 if !partial.starts_with(&slice) {
169 if slice < partial {
170 crumb.status = Status::Exiting;
171 self.key_nibbles.append_partial(slice.right());
172 return Ok(false)
173 }
174 return Ok(slice.starts_with(&partial))
175 }
176
177 full_key_nibbles += slice.len();
178 partial = partial.mid(slice.len());
179 crumb.status = Status::At;
180 self.key_nibbles.append_partial(slice.right());
181
182 let prefix = key.back(full_key_nibbles);
183 db.get_raw_or_lookup(
184 node_hash.unwrap_or_default(),
185 child.build(node_data),
186 prefix.left(),
187 true,
188 )?
189 },
190 NodePlan::Branch { value: _, children } => {
191 if partial.is_empty() {
192 return Ok(true)
193 }
194
195 let i = partial.at(0);
196 crumb.status = Status::AtChild(i as usize);
197 self.key_nibbles.push(i);
198
199 if let Some(child) = &children[i as usize] {
200 full_key_nibbles += 1;
201 partial = partial.mid(1);
202
203 let prefix = key.back(full_key_nibbles);
204 db.get_raw_or_lookup(
205 node_hash.unwrap_or_default(),
206 child.build(node_data),
207 prefix.left(),
208 true,
209 )?
210 } else {
211 return Ok(false)
212 }
213 },
214 NodePlan::NibbledBranch { partial: partial_plan, value: _, children } => {
215 let slice = partial_plan.build(node_data);
216 if !partial.starts_with(&slice) {
217 if slice < partial {
218 crumb.status = Status::Exiting;
219 self.key_nibbles.append_partial(slice.right());
220 self.key_nibbles.push((nibble_ops::NIBBLE_LENGTH - 1) as u8);
221 return Ok(false)
222 }
223 return Ok(slice.starts_with(&partial))
224 }
225
226 full_key_nibbles += slice.len();
227 partial = partial.mid(slice.len());
228
229 if partial.is_empty() {
230 return Ok(true)
231 }
232
233 let i = partial.at(0);
234 crumb.status = Status::AtChild(i as usize);
235 self.key_nibbles.append_partial(slice.right());
236 self.key_nibbles.push(i);
237
238 if let Some(child) = &children[i as usize] {
239 full_key_nibbles += 1;
240 partial = partial.mid(1);
241
242 let prefix = key.back(full_key_nibbles);
243 db.get_raw_or_lookup(
244 node_hash.unwrap_or_default(),
245 child.build(node_data),
246 prefix.left(),
247 true,
248 )?
249 } else {
250 return Ok(false)
251 }
252 },
253 NodePlan::Empty => {
254 if !partial.is_empty() {
255 crumb.status = Status::Exiting;
256 return Ok(false)
257 }
258 return Ok(true)
259 },
260 }
261 };
262
263 node = next_node;
264 node_hash = next_node_hash;
265 }
266 }
267
268 fn prefix(&mut self, db: &TrieDB<L>, prefix: &[u8]) -> Result<(), TrieHash<L>, CError<L>> {
271 if self.seek(db, prefix)? {
272 if let Some(v) = self.trail.pop() {
273 self.trail.clear();
274 self.trail.push(v);
275 }
276 } else {
277 self.trail.clear();
278 }
279
280 Ok(())
281 }
282
283 fn prefix_then_seek(
286 &mut self,
287 db: &TrieDB<L>,
288 prefix: &[u8],
289 seek: &[u8],
290 ) -> Result<(), TrieHash<L>, CError<L>> {
291 if prefix.is_empty() {
292 return self.seek(db, seek).map(|_| ())
294 }
295
296 if seek.is_empty() || seek <= prefix {
297 return self.prefix(db, prefix)
301 }
302
303 if !seek.starts_with(prefix) {
304 self.trail.clear();
307 return Ok(())
308 }
309
310 if !self.seek(db, prefix)? {
311 self.trail.clear();
313 return Ok(())
314 }
315
316 self.seek(db, seek)?;
318
319 let prefix_len = prefix.len() * crate::nibble::nibble_ops::NIBBLE_PER_BYTE;
320 let mut len = 0;
321 for i in 0..self.trail.len() {
323 match self.trail[i].node.node_plan() {
324 NodePlan::Empty => {},
325 NodePlan::Branch { .. } => {
326 len += 1;
327 },
328 NodePlan::Leaf { partial, .. } => {
329 len += partial.len();
330 },
331 NodePlan::Extension { partial, .. } => {
332 len += partial.len();
333 },
334 NodePlan::NibbledBranch { partial, .. } => {
335 len += 1;
336 len += partial.len();
337 },
338 }
339 if len > prefix_len {
340 self.trail = self.trail.split_off(i);
341 return Ok(())
342 }
343 }
344
345 self.trail.clear();
346 Ok(())
347 }
348
349 pub(crate) fn next_raw_item(
353 &mut self,
354 db: &TrieDB<L>,
355 ) -> Option<
356 Result<
357 (&NibbleVec, Option<&TrieHash<L>>, &Arc<OwnedNode<DBValue>>),
358 TrieHash<L>,
359 CError<L>,
360 >,
361 > {
362 loop {
363 let crumb = self.trail.last_mut()?;
364 let node_data = crumb.node.data();
365
366 match (crumb.status, crumb.node.node_plan()) {
367 (Status::Entering, _) => {
368 let crumb = self.trail.last_mut().expect("we've just fetched the last element using `last_mut` so this cannot fail; qed");
370 crumb.increment();
371 return Some(Ok((&self.key_nibbles, crumb.hash.as_ref(), &crumb.node)))
372 },
373 (Status::Exiting, node) => {
374 match node {
375 NodePlan::Empty | NodePlan::Leaf { .. } => {},
376 NodePlan::Extension { partial, .. } => {
377 self.key_nibbles.drop_lasts(partial.len());
378 },
379 NodePlan::Branch { .. } => {
380 self.key_nibbles.pop();
381 },
382 NodePlan::NibbledBranch { partial, .. } => {
383 self.key_nibbles.drop_lasts(partial.len() + 1);
384 },
385 }
386 self.trail.pop().expect("we've just fetched the last element using `last_mut` so this cannot fail; qed");
387 self.trail.last_mut()?.increment();
388 },
389 (Status::At, NodePlan::Extension { partial: partial_plan, child }) => {
390 let partial = partial_plan.build(node_data);
391 self.key_nibbles.append_partial(partial.right());
392
393 match db.get_raw_or_lookup(
394 crumb.hash.unwrap_or_default(),
395 child.build(node_data),
396 self.key_nibbles.as_prefix(),
397 true,
398 ) {
399 Ok((node, node_hash)) => {
400 self.descend(node, node_hash);
401 },
402 Err(err) => {
403 crumb.increment();
404 return Some(Err(err))
405 },
406 }
407 },
408 (Status::At, NodePlan::Branch { .. }) => {
409 self.key_nibbles.push(0);
410 crumb.increment();
411 },
412 (Status::At, NodePlan::NibbledBranch { partial: partial_plan, .. }) => {
413 let partial = partial_plan.build(node_data);
414 self.key_nibbles.append_partial(partial.right());
415 self.key_nibbles.push(0);
416 crumb.increment();
417 },
418 (Status::AtChild(i), NodePlan::Branch { children, .. }) |
419 (Status::AtChild(i), NodePlan::NibbledBranch { children, .. }) => {
420 if let Some(child) = &children[i] {
421 self.key_nibbles.pop();
422 self.key_nibbles.push(i as u8);
423
424 match db.get_raw_or_lookup(
425 crumb.hash.unwrap_or_default(),
426 child.build(node_data),
427 self.key_nibbles.as_prefix(),
428 true,
429 ) {
430 Ok((node, node_hash)) => {
431 self.descend(node, node_hash);
432 },
433 Err(err) => {
434 crumb.increment();
435 return Some(Err(err))
436 },
437 }
438 } else {
439 crumb.increment();
440 }
441 },
442 _ => panic!(
443 "Crumb::increment and TrieDBNodeIterator are implemented so that \
444 the above arms are the only possible states"
445 ),
446 }
447 }
448 }
449
450 pub fn next_item(&mut self, db: &TrieDB<L>) -> Option<TrieItem<TrieHash<L>, CError<L>>> {
454 while let Some(raw_item) = self.next_raw_item(db) {
455 let (prefix, _, node) = match raw_item {
456 Ok(raw_item) => raw_item,
457 Err(err) => return Some(Err(err)),
458 };
459
460 let mut prefix = prefix.clone();
461 let value = match node.node() {
462 Node::Leaf(partial, value) => {
463 prefix.append_partial(partial.right());
464 value
465 },
466 Node::Branch(_, value) => match value {
467 Some(value) => value,
468 None => continue,
469 },
470 Node::NibbledBranch(partial, _, value) => {
471 prefix.append_partial(partial.right());
472 match value {
473 Some(value) => value,
474 None => continue,
475 }
476 },
477 _ => continue,
478 };
479
480 let (key_slice, maybe_extra_nibble) = prefix.as_prefix();
481 let key = key_slice.to_vec();
482 if let Some(extra_nibble) = maybe_extra_nibble {
483 return Some(Err(Box::new(TrieError::ValueAtIncompleteKey(key, extra_nibble))))
484 }
485
486 let value = match value {
487 Value::Node(hash) => match Self::fetch_value(db, &hash, (key_slice, None)) {
488 Ok(value) => value,
489 Err(err) => return Some(Err(err)),
490 },
491 Value::Inline(value) => value.to_vec(),
492 };
493
494 return Some(Ok((key, value)))
495 }
496 None
497 }
498
499 pub fn next_key(&mut self, db: &TrieDB<L>) -> Option<TrieKeyItem<TrieHash<L>, CError<L>>> {
503 while let Some(raw_item) = self.next_raw_item(db) {
504 let (prefix, _, node) = match raw_item {
505 Ok(raw_item) => raw_item,
506 Err(err) => return Some(Err(err)),
507 };
508
509 let mut prefix = prefix.clone();
510 match node.node() {
511 Node::Leaf(partial, _) => {
512 prefix.append_partial(partial.right());
513 },
514 Node::Branch(_, value) =>
515 if value.is_none() {
516 continue
517 },
518 Node::NibbledBranch(partial, _, value) => {
519 prefix.append_partial(partial.right());
520 if value.is_none() {
521 continue
522 }
523 },
524 _ => continue,
525 };
526
527 let (key_slice, maybe_extra_nibble) = prefix.as_prefix();
528 let key = key_slice.to_vec();
529 if let Some(extra_nibble) = maybe_extra_nibble {
530 return Some(Err(Box::new(TrieError::ValueAtIncompleteKey(key, extra_nibble))))
531 }
532
533 return Some(Ok(key))
534 }
535 None
536 }
537}
538
539pub struct TrieDBNodeIterator<'a, 'cache, L: TrieLayout> {
541 db: &'a TrieDB<'a, 'cache, L>,
542 raw_iter: TrieDBRawIterator<L>,
543}
544
545impl<'a, 'cache, L: TrieLayout> TrieDBNodeIterator<'a, 'cache, L> {
546 pub fn new(db: &'a TrieDB<'a, 'cache, L>) -> Result<Self, TrieHash<L>, CError<L>> {
548 Ok(Self { raw_iter: TrieDBRawIterator::new(db)?, db })
549 }
550
551 pub fn from_raw(db: &'a TrieDB<'a, 'cache, L>, raw_iter: TrieDBRawIterator<L>) -> Self {
553 Self { db, raw_iter }
554 }
555
556 pub fn into_raw(self) -> TrieDBRawIterator<L> {
558 self.raw_iter
559 }
560
561 pub fn fetch_value(
563 &self,
564 key: &[u8],
565 prefix: Prefix,
566 ) -> Result<DBValue, TrieHash<L>, CError<L>> {
567 TrieDBRawIterator::fetch_value(self.db, key, prefix)
568 }
569
570 pub fn prefix(&mut self, prefix: &[u8]) -> Result<(), TrieHash<L>, CError<L>> {
573 self.raw_iter.prefix(self.db, prefix)
574 }
575
576 pub fn prefix_then_seek(
579 &mut self,
580 prefix: &[u8],
581 seek: &[u8],
582 ) -> Result<(), TrieHash<L>, CError<L>> {
583 self.raw_iter.prefix_then_seek(self.db, prefix, seek)
584 }
585
586 pub fn db(&self) -> &dyn hash_db::HashDBRef<L::Hash, DBValue> {
588 self.db.db()
589 }
590}
591
592impl<'a, 'cache, L: TrieLayout> TrieIterator<L> for TrieDBNodeIterator<'a, 'cache, L> {
593 fn seek(&mut self, key: &[u8]) -> Result<(), TrieHash<L>, CError<L>> {
594 self.raw_iter.seek(self.db, key).map(|_| ())
595 }
596}
597
598impl<'a, 'cache, L: TrieLayout> Iterator for TrieDBNodeIterator<'a, 'cache, L> {
599 type Item =
600 Result<(NibbleVec, Option<TrieHash<L>>, Arc<OwnedNode<DBValue>>), TrieHash<L>, CError<L>>;
601
602 fn next(&mut self) -> Option<Self::Item> {
603 self.raw_iter.next_raw_item(self.db).map(|result| {
604 result.map(|(nibble, hash, node)| (nibble.clone(), hash.cloned(), node.clone()))
605 })
606 }
607}