Skip to main content

trie_db/
iterator.rs

1// Copyright 2017, 2021 Parity Technologies
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use 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	/// Move on to next status in the node's sequence.
45	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
61/// Iterator for going through all nodes in the trie in pre-order traversal order.
62pub struct TrieDBRawIterator<L: TrieLayout> {
63	trail: Vec<Crumb<L::Hash>>,
64	key_nibbles: NibbleVec,
65}
66
67impl<L: TrieLayout> TrieDBRawIterator<L> {
68	/// Create a new empty iterator.
69	pub fn empty() -> Self {
70		Self { trail: Vec::new(), key_nibbles: NibbleVec::new() }
71	}
72
73	/// Create a new iterator.
74	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	/// Create a new iterator, but limited to a given prefix.
88	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	/// Create a new iterator, but limited to a given prefix.
96	/// It then do a seek operation from prefixed context (using `seek` lose
97	/// prefix context by default).
98	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	/// Descend into a payload.
109	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	/// Fetch value by hash at a current node height
115	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	/// Seek a node position at 'key' for iterator.
126	/// Returns true if the cursor is at or after the key, but still shares
127	/// a common prefix with the key, return false if the key do not
128	/// share its prefix with the node.
129	/// This indicates if there is still nodes to iterate over in the case
130	/// where we limit iteration to 'key' as a prefix.
131	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	/// Advance the iterator into a prefix, no value out of the prefix will be accessed
269	/// or returned after this operation.
270	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	/// Advance the iterator into a prefix, no value out of the prefix will be accessed
284	/// or returned after this operation.
285	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			// There's no prefix, so just seek.
293			return self.seek(db, seek).map(|_| ())
294		}
295
296		if seek.is_empty() || seek <= prefix {
297			// Either we're not supposed to seek anywhere,
298			// or we're supposed to seek *before* the prefix,
299			// so just directly go to the prefix.
300			return self.prefix(db, prefix)
301		}
302
303		if !seek.starts_with(prefix) {
304			// We're supposed to seek *after* the prefix,
305			// so just return an empty iterator.
306			self.trail.clear();
307			return Ok(())
308		}
309
310		if !self.seek(db, prefix)? {
311			// The database doesn't have a key with such a prefix.
312			self.trail.clear();
313			return Ok(())
314		}
315
316		// Now seek forward again.
317		self.seek(db, seek)?;
318
319		let prefix_len = prefix.len() * crate::nibble::nibble_ops::NIBBLE_PER_BYTE;
320		let mut len = 0;
321		// look first prefix in trail
322		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	/// Fetches the next raw item.
350	//
351	/// Must be called with the same `db` as when the iterator was created.
352	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					// This is only necessary due to current borrow checker's limitation.
369					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	/// Fetches the next trie item.
451	///
452	/// Must be called with the same `db` as when the iterator was created.
453	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	/// Fetches the next key.
500	///
501	/// Must be called with the same `db` as when the iterator was created.
502	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
539/// Iterator for going through all nodes in the trie in pre-order traversal order.
540pub 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	/// Create a new iterator.
547	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	/// Restore an iterator from a raw iterator.
552	pub fn from_raw(db: &'a TrieDB<'a, 'cache, L>, raw_iter: TrieDBRawIterator<L>) -> Self {
553		Self { db, raw_iter }
554	}
555
556	/// Convert the iterator to a raw iterator.
557	pub fn into_raw(self) -> TrieDBRawIterator<L> {
558		self.raw_iter
559	}
560
561	/// Fetch value by hash at a current node height
562	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	/// Advance the iterator into a prefix, no value out of the prefix will be accessed
571	/// or returned after this operation.
572	pub fn prefix(&mut self, prefix: &[u8]) -> Result<(), TrieHash<L>, CError<L>> {
573		self.raw_iter.prefix(self.db, prefix)
574	}
575
576	/// Advance the iterator into a prefix, no value out of the prefix will be accessed
577	/// or returned after this operation.
578	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	/// Access inner hash db.
587	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}