Skip to main content

trie_db/
trie_codec.rs

1// Copyright 2019, 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
15//! Compact encoding/decoding functions for partial Merkle-Patricia tries.
16//!
17//! A partial trie is a subset of the nodes in a complete trie, which can still be used to
18//! perform authenticated lookups on a subset of keys. A naive encoding is the set of encoded nodes
19//! in the partial trie. This, however, includes redundant hashes of other nodes in the partial
20//! trie which could be computed directly. The compact encoding strips out all hash child
21//! references to other nodes in the partial trie and replaces them with empty inline references,
22//! indicating that the child reference is omitted. The nodes are then ordered in pre-order
23//! traversal order so that the full nodes can be efficiently reconstructed recursively. Note that
24//! hash references to nodes not in the partial trie are left intact. The compact encoding can be
25//! expected to save roughly (n - 1) hashes in size where n is the number of nodes in the partial
26//! trie.
27//!
28//! A value node contained in the partial trie (see [`TrieLayout::MAX_INLINE_VALUE`]) is
29//! "detached": the referencing node is emitted with an escape header (see
30//! `NodeCodec::ESCAPE_HEADER`) and an empty inline value, directly followed by the value bytes
31//! as a standalone item. A node whose value node is *not* part of the partial trie is emitted
32//! unmodified, still referencing its value by hash.
33//!
34//! `encode_compact` re-emits a shared item once per position (a detached value per referencing
35//! node, a duplicated subtree per occurrence). [`encode_compact_skip_duplicates`] instead emits
36//! each distinct item only once; later occurrences keep a plain hash reference, like any
37//! reference to an item outside the partial trie.
38
39use crate::{
40	nibble_ops::NIBBLE_LENGTH,
41	node::{decode_hash, Node, NodeHandle, NodeHandlePlan, NodePlan, OwnedNode, ValuePlan},
42	rstd::{
43		boxed::Box, convert::TryInto, marker::PhantomData, result, sync::Arc, vec, vec::Vec,
44		BTreeSet,
45	},
46	CError, ChildReference, DBValue, NibbleVec, NodeCodec, Result, TrieDB, TrieDBRawIterator,
47	TrieError, TrieHash, TrieLayout,
48};
49use hash_db::{HashDB, Prefix};
50
51const OMIT_VALUE_HASH: crate::node::Value<'static> = crate::node::Value::Inline(&[]);
52
53struct EncoderStackEntry<C: NodeCodec> {
54	/// The prefix is the nibble path to the node in the trie.
55	prefix: NibbleVec,
56	/// Node in memory content.
57	node: Arc<OwnedNode<DBValue>>,
58	/// The next entry in the stack is a child of the preceding entry at this index. For branch
59	/// nodes, the index is in [0, NIBBLE_LENGTH] and for extension nodes, the index is in [0, 1].
60	child_index: usize,
61	/// Flags indicating whether each child is omitted in the encoded node.
62	omit_children: Vec<bool>,
63	/// Skip value if value node is after.
64	omit_value: bool,
65	/// The encoding of the subtrie nodes rooted at this entry, which is built up in
66	/// `encode_compact`.
67	output_index: usize,
68	_marker: PhantomData<C>,
69}
70
71impl<C: NodeCodec> EncoderStackEntry<C> {
72	/// Given the prefix of the next child node, identify its index and advance `child_index` to
73	/// that. For a given entry, this must be called sequentially only with strictly increasing
74	/// child prefixes. Returns an error if the child prefix is not a child of this entry or if
75	/// called with children out of order.
76	///
77	/// Preconditions:
78	/// - self.prefix + partial must be a prefix of child_prefix.
79	/// - if self.node is a branch, then child_prefix must be longer than self.prefix + partial.
80	fn advance_child_index(
81		&mut self,
82		child_prefix: &NibbleVec,
83	) -> result::Result<(), &'static str> {
84		match self.node.node_plan() {
85			NodePlan::Empty | NodePlan::Leaf { .. } =>
86				return Err("empty and leaf nodes have no children"),
87			NodePlan::Extension { .. } =>
88				if self.child_index != 0 {
89					return Err("extension node cannot have multiple children")
90				},
91			NodePlan::Branch { .. } => {
92				if child_prefix.len() <= self.prefix.len() {
93					return Err("child_prefix does not contain prefix")
94				}
95				let child_index = child_prefix.at(self.prefix.len()) as usize;
96				if child_index < self.child_index {
97					return Err("iterator returned children in non-ascending order by prefix")
98				}
99				self.child_index = child_index;
100			},
101			NodePlan::NibbledBranch { partial, .. } => {
102				if child_prefix.len() <= self.prefix.len() + partial.len() {
103					return Err("child_prefix does not contain prefix and node partial")
104				}
105				let child_index = child_prefix.at(self.prefix.len() + partial.len()) as usize;
106				if child_index < self.child_index {
107					return Err("iterator returned children in non-ascending order by prefix")
108				}
109				self.child_index = child_index;
110			},
111		}
112		Ok(())
113	}
114
115	/// Generates the encoding of the subtrie rooted at this entry.
116	fn encode_node(&mut self) -> Result<Vec<u8>, C::HashOut, C::Error> {
117		let node_data = self.node.data();
118		let node_plan = self.node.node_plan();
119		let mut encoded = match node_plan {
120			NodePlan::Empty => node_data.to_vec(),
121			NodePlan::Leaf { partial, value: _ } =>
122				if self.omit_value {
123					let partial = partial.build(node_data);
124					C::leaf_node(partial.right_iter(), partial.len(), OMIT_VALUE_HASH)
125				} else {
126					node_data.to_vec()
127				},
128			NodePlan::Extension { partial, child: _ } =>
129				if !self.omit_children[0] {
130					node_data.to_vec()
131				} else {
132					let partial = partial.build(node_data);
133					let empty_child = ChildReference::Inline(C::HashOut::default(), 0);
134					C::extension_node(partial.right_iter(), partial.len(), empty_child)
135				},
136			NodePlan::Branch { value, children } => {
137				let value = if self.omit_value {
138					value.is_some().then_some(OMIT_VALUE_HASH)
139				} else {
140					value.as_ref().map(|v| v.build(node_data))
141				};
142				C::branch_node(
143					Self::branch_children(node_data, &children, &self.omit_children)?.iter(),
144					value,
145				)
146			},
147			NodePlan::NibbledBranch { partial, value, children } => {
148				let partial = partial.build(node_data);
149				let value = if self.omit_value {
150					value.is_some().then_some(OMIT_VALUE_HASH)
151				} else {
152					value.as_ref().map(|v| v.build(node_data))
153				};
154				C::branch_node_nibbled(
155					partial.right_iter(),
156					partial.len(),
157					Self::branch_children(node_data, &children, &self.omit_children)?.iter(),
158					value,
159				)
160			},
161		};
162
163		if self.omit_value {
164			if let Some(header) = C::ESCAPE_HEADER {
165				encoded.insert(0, header);
166			} else {
167				return Err(Box::new(TrieError::InvalidStateRoot(Default::default())))
168			}
169		}
170		Ok(encoded)
171	}
172
173	/// Generate the list of child references for a branch node with certain children omitted.
174	///
175	/// Preconditions:
176	/// - omit_children has size NIBBLE_LENGTH.
177	/// - omit_children[i] is only true if child_handles[i] is Some
178	fn branch_children(
179		node_data: &[u8],
180		child_handles: &[Option<NodeHandlePlan>; NIBBLE_LENGTH],
181		omit_children: &[bool],
182	) -> Result<[Option<ChildReference<C::HashOut>>; NIBBLE_LENGTH], C::HashOut, C::Error> {
183		let empty_child = ChildReference::Inline(C::HashOut::default(), 0);
184		let mut children = [None; NIBBLE_LENGTH];
185		for i in 0..NIBBLE_LENGTH {
186			children[i] = if omit_children[i] {
187				Some(empty_child)
188			} else if let Some(child_plan) = &child_handles[i] {
189				let child_ref = child_plan.build(node_data).try_into().map_err(|hash| {
190					Box::new(TrieError::InvalidHash(C::HashOut::default(), hash))
191				})?;
192				Some(child_ref)
193			} else {
194				None
195			};
196		}
197		Ok(children)
198	}
199}
200
201/// Hashes of items already emitted by [`encode_compact_skip_duplicates`], so later occurrences
202/// keep a plain hash reference instead of being emitted again.
203///
204/// Node and value hashes are kept in separate namespaces: skipping a node drops its whole subtree
205/// and is only sound once that subtree was emitted, which a value can never guarantee. A shared
206/// set would let a value equal to a node's encoding trigger the skip and drop the subtree.
207pub struct SeenHashes<L: TrieLayout> {
208	nodes: BTreeSet<TrieHash<L>>,
209	values: BTreeSet<TrieHash<L>>,
210}
211
212// Hand-written impls: deriving would add a spurious `L: Default`/`L: Clone` bound.
213impl<L: TrieLayout> Default for SeenHashes<L> {
214	fn default() -> Self {
215		SeenHashes { nodes: BTreeSet::new(), values: BTreeSet::new() }
216	}
217}
218
219impl<L: TrieLayout> Clone for SeenHashes<L> {
220	fn clone(&self) -> Self {
221		SeenHashes { nodes: self.nodes.clone(), values: self.values.clone() }
222	}
223}
224
225/// Detached value if included does write a reserved header,
226/// followed by node encoded with 0 length value and the value
227/// as a standalone vec.
228///
229/// When `seen` is given, a value whose hash is already in the value namespace is not detached
230/// again. Only hashes of actually emitted values are added to the set.
231fn detached_value<L: TrieLayout>(
232	db: &TrieDB<L>,
233	value: &ValuePlan,
234	node_data: &[u8],
235	node_prefix: Prefix,
236	seen: Option<&mut SeenHashes<L>>,
237) -> Option<Vec<u8>> {
238	let hash_plan = match value {
239		ValuePlan::Node(hash_plan) => hash_plan,
240		_ => return None,
241	};
242	let value_hash = &node_data[hash_plan.clone()];
243
244	let dedup_key = seen.as_ref().and_then(|_| decode_hash::<L::Hash>(value_hash));
245	if let (Some(seen), Some(key)) = (&seen, &dedup_key) {
246		// Already emitted once: keep the plain hash reference instead of detaching again.
247		if seen.values.contains(key) {
248			return None
249		}
250	}
251	let fetched = TrieDBRawIterator::fetch_value(db, value_hash, node_prefix).ok()?;
252	if let (Some(seen), Some(key)) = (seen, dedup_key) {
253		seen.values.insert(key);
254	}
255	Some(fetched)
256}
257
258/// Generates a compact representation of the partial trie stored in the given DB. The encoding
259/// is a vector of mutated trie nodes with those child references omitted. The mutated trie nodes
260/// are listed in pre-order traversal order so that the full nodes can be efficiently
261/// reconstructed recursively.
262///
263/// A shared detached value node is emitted once per referencing node and a duplicated subtree
264/// once per occurrence (see [`encode_compact_skip_duplicates`]).
265///
266/// This function makes the assumption that all child references in an inline trie node are inline
267/// references.
268pub fn encode_compact<L>(db: &TrieDB<L>) -> Result<Vec<Vec<u8>>, TrieHash<L>, CError<L>>
269where
270	L: TrieLayout,
271{
272	encode_compact_inner(db, None)
273}
274
275/// Variant of [`encode_compact`] that emits each distinct item — trie node or detached value
276/// node — only once. Later occurrences keep a plain hash reference to the emitted item, exactly
277/// like references to items outside the partial trie. Only items at least as large as a hash are
278/// referenced this way, so deduplication never grows the encoding.
279///
280/// `seen` collects the emitted hashes, keeping trie-node and detached-value hashes in disjoint
281/// namespaces (see [`SeenHashes`]).
282///
283/// All encodings sharing one `seen` set must be generated from a single, fixed backing
284/// node set: a skipped subtree is reconstructable only if everything below it was emitted when
285/// its root was first seen. Encoding from per-proof recorded sets whose coverage of a shared
286/// node diverges silently drops the divergent nodes and produces unverifiable proofs.
287///
288/// A deduplicated occurrence is indistinguishable from a reference to an item outside the
289/// partial trie, so any decoder reconstructs a readable hash-keyed
290/// node set: every item is present under its hash from its first occurrence. Per-position
291/// bookkeeping is deliberately not reconstructable: decoding into a position-keyed (prefixed)
292/// database, or relying on the reconstruction's reference counts, is unsupported.
293///
294/// Assumes occurrences of an item are interchangeable, as they are when `db` is hash-keyed.
295pub fn encode_compact_skip_duplicates<L>(
296	db: &TrieDB<L>,
297	seen: &mut SeenHashes<L>,
298) -> Result<Vec<Vec<u8>>, TrieHash<L>, CError<L>>
299where
300	L: TrieLayout,
301{
302	encode_compact_inner(db, Some(seen))
303}
304
305fn encode_compact_inner<L>(
306	db: &TrieDB<L>,
307	mut seen: Option<&mut SeenHashes<L>>,
308) -> Result<Vec<Vec<u8>>, TrieHash<L>, CError<L>>
309where
310	L: TrieLayout,
311{
312	let mut output = Vec::new();
313
314	// The stack of nodes through a path in the trie. Each entry is a child node of the preceding
315	// entry.
316	let mut stack: Vec<EncoderStackEntry<L::Codec>> = Vec::new();
317
318	// TrieDBRawIterator guarantees that:
319	// - It yields at least one node.
320	// - The first node yielded is the root node with an empty prefix and is not inline.
321	// - The prefixes yielded are in strictly increasing lexographic order.
322	let mut iter = TrieDBRawIterator::new(db)?;
323
324	// Following from the guarantees about TrieDBRawIterator, we guarantee that after the first
325	// iteration of the loop below, the stack always has at least one entry and the bottom (front)
326	// of the stack is the root node, which is not inline. Furthermore, the iterator is not empty,
327	// so at least one iteration always occurs.
328	while let Some(item) = iter.next_raw_item(db, true) {
329		match item {
330			Ok((prefix, node_hash, node)) => {
331				// Skip inline nodes, as they cannot contain hash references to other nodes by
332				// assumption.
333				let Some(node_hash) = node_hash else { continue };
334
335				if let Some(seen) = seen.as_deref_mut() {
336					let is_root = stack.is_empty();
337					// A subtree whose root was already emitted is skipped entirely; the parent's
338					// `omit_children` bit stays unset, keeping a plain hash reference. The root is
339					// never skipped, so each encoding stays individually decodable when
340					// `seen` is threaded across successive encodings. Sound only under the
341					// fixed-backing-set precondition (see `encode_compact_skip_duplicates`): the
342					// subtree below a seen hash must not have grown since it was emitted.
343					if !is_root && seen.nodes.contains(node_hash) {
344						iter.skip_current_subtree();
345						continue
346					}
347					seen.nodes.insert(*node_hash);
348				}
349
350				// Unwind the stack until the new entry is a child of the last entry on the stack.
351				// If the stack entry prefix is a prefix of the new entry prefix, then it must be a
352				// direct parent as the nodes are yielded from the iterator in pre-order traversal
353				// order.
354				while let Some(mut last_entry) = stack.pop() {
355					if prefix.starts_with(&last_entry.prefix) {
356						// advance_child_index preconditions are satisfied because of iterator
357						// correctness.
358						last_entry.advance_child_index(&prefix).expect(
359							"all errors from advance_child_index indicate bugs with \
360								TrieDBRawIterator or this function",
361						);
362						last_entry.omit_children[last_entry.child_index] = true;
363						last_entry.child_index += 1;
364						stack.push(last_entry);
365						break
366					} else {
367						output[last_entry.output_index] = last_entry.encode_node()?;
368					}
369				}
370
371				let (children_len, detached_value) = match node.node_plan() {
372					NodePlan::Empty => (0, None),
373					NodePlan::Leaf { value, .. } => (
374						0,
375						detached_value(
376							db,
377							value,
378							node.data(),
379							prefix.as_prefix(),
380							seen.as_deref_mut(),
381						),
382					),
383					NodePlan::Extension { .. } => (1, None),
384					NodePlan::NibbledBranch { value: Some(value), .. } |
385					NodePlan::Branch { value: Some(value), .. } => (
386						NIBBLE_LENGTH,
387						detached_value(
388							db,
389							value,
390							node.data(),
391							prefix.as_prefix(),
392							seen.as_deref_mut(),
393						),
394					),
395					NodePlan::NibbledBranch { value: None, .. } |
396					NodePlan::Branch { value: None, .. } => (NIBBLE_LENGTH, None),
397				};
398
399				stack.push(EncoderStackEntry {
400					prefix: prefix.clone(),
401					node: node.clone(),
402					child_index: 0,
403					omit_children: vec![false; children_len],
404					omit_value: detached_value.is_some(),
405					output_index: output.len(),
406					_marker: PhantomData::default(),
407				});
408				// Insert a placeholder into output which will be replaced when this new entry is
409				// popped from the stack.
410				output.push(Vec::new());
411				if let Some(value) = detached_value {
412					output.push(value);
413				}
414			},
415			Err(err) => match *err {
416				// If we hit an IncompleteDatabaseError, just ignore it and continue encoding the
417				// incomplete trie. This encoding must support partial tries, which can be used for
418				// space-efficient storage proofs.
419				TrieError::IncompleteDatabase(_) => {},
420				_ => return Err(err),
421			},
422		}
423	}
424
425	while let Some(mut entry) = stack.pop() {
426		output[entry.output_index] = entry.encode_node()?;
427	}
428
429	Ok(output)
430}
431
432struct DecoderStackEntry<'a, C: NodeCodec> {
433	node: Node<'a>,
434	/// The next entry in the stack is a child of the preceding entry at this index. For branch
435	/// nodes, the index is in [0, NIBBLE_LENGTH] and for extension nodes, the index is in [0, 1].
436	child_index: usize,
437	/// The reconstructed child references.
438	children: Vec<Option<ChildReference<C::HashOut>>>,
439	/// A value attached as a node. The node will need to use its hash as value.
440	attached_value: Option<&'a [u8]>,
441	_marker: PhantomData<C>,
442}
443
444impl<'a, C: NodeCodec> DecoderStackEntry<'a, C> {
445	/// Advance the child index until either it exceeds the number of children or the child is
446	/// marked as omitted. Omitted children are indicated by an empty inline reference. For each
447	/// child that is passed over and not omitted, copy over the child reference from the node to
448	/// this entries `children` list.
449	///
450	/// Returns true if the child index is past the last child, meaning the `children` references
451	/// list is complete. If this returns true and the entry is an extension node, then
452	/// `children[0]` is guaranteed to be Some.
453	fn advance_child_index(&mut self) -> Result<bool, C::HashOut, C::Error> {
454		match self.node {
455			Node::Extension(_, child) if self.child_index == 0 => {
456				match child {
457					NodeHandle::Inline(data) if data.is_empty() => return Ok(false),
458					_ => {
459						let child_ref = child.try_into().map_err(|hash| {
460							Box::new(TrieError::InvalidHash(C::HashOut::default(), hash))
461						})?;
462						self.children[self.child_index] = Some(child_ref);
463					},
464				}
465				self.child_index += 1;
466			},
467			Node::Branch(children, _) | Node::NibbledBranch(_, children, _) => {
468				while self.child_index < NIBBLE_LENGTH {
469					match children[self.child_index] {
470						Some(NodeHandle::Inline(data)) if data.is_empty() => return Ok(false),
471						Some(child) => {
472							let child_ref = child.try_into().map_err(|hash| {
473								Box::new(TrieError::InvalidHash(C::HashOut::default(), hash))
474							})?;
475							self.children[self.child_index] = Some(child_ref);
476						},
477						None => {},
478					}
479					self.child_index += 1;
480				}
481			},
482			_ => {},
483		}
484		Ok(true)
485	}
486
487	/// Push the partial key of this entry's node (including the branch nibble) to the given
488	/// prefix.
489	fn push_to_prefix(&self, prefix: &mut NibbleVec) {
490		match self.node {
491			Node::Empty => {},
492			Node::Leaf(partial, _) | Node::Extension(partial, _) => {
493				prefix.append_partial(partial.right());
494			},
495			Node::Branch(_, _) => {
496				prefix.push(self.child_index as u8);
497			},
498			Node::NibbledBranch(partial, _, _) => {
499				prefix.append_partial(partial.right());
500				prefix.push(self.child_index as u8);
501			},
502		}
503	}
504
505	/// Pop the partial key of this entry's node (including the branch nibble) from the given
506	/// prefix.
507	fn pop_from_prefix(&self, prefix: &mut NibbleVec) {
508		match self.node {
509			Node::Empty => {},
510			Node::Leaf(partial, _) | Node::Extension(partial, _) => {
511				prefix.drop_lasts(partial.len());
512			},
513			Node::Branch(_, _) => {
514				prefix.pop();
515			},
516			Node::NibbledBranch(partial, _, _) => {
517				prefix.pop();
518				prefix.drop_lasts(partial.len());
519			},
520		}
521	}
522
523	/// Reconstruct the encoded full trie node from the node and the entry's child references.
524	///
525	/// Preconditions:
526	/// - if node is an extension node, then `children[0]` is Some.
527	fn encode_node(self, attached_hash: Option<&[u8]>) -> Vec<u8> {
528		let attached_hash = attached_hash.map(|h| crate::node::Value::Node(h));
529		match self.node {
530			Node::Empty => C::empty_node().to_vec(),
531			Node::Leaf(partial, value) =>
532				C::leaf_node(partial.right_iter(), partial.len(), attached_hash.unwrap_or(value)),
533			Node::Extension(partial, _) => C::extension_node(
534				partial.right_iter(),
535				partial.len(),
536				self.children[0].expect("required by method precondition; qed"),
537			),
538			Node::Branch(_, value) => C::branch_node(
539				self.children.into_iter(),
540				if attached_hash.is_some() { attached_hash } else { value },
541			),
542			Node::NibbledBranch(partial, _, value) => C::branch_node_nibbled(
543				partial.right_iter(),
544				partial.len(),
545				self.children.iter(),
546				if attached_hash.is_some() { attached_hash } else { value },
547			),
548		}
549	}
550}
551
552/// Reconstructs a partial trie DB from a compact representation. The encoding is a vector of
553/// mutated trie nodes with those child references omitted. The decode function reads them in order
554/// from the given slice, reconstructing the full nodes and inserting them into the given `HashDB`.
555/// It stops after fully constructing one partial trie and returns the root hash and the number of
556/// items read — trie nodes plus any detached value items consumed. If an error occurs during
557/// decoding, there are no guarantees about which entries were or were not added to the DB.
558///
559/// This count may be fewer than the total number of items in `encoded`. This allows one to
560/// concatenate multiple compact encodings together and still reconstruct them all: decode the
561/// next encoding starting at the returned offset.
562///
563/// This function makes the assumption that all child references in an inline trie node are inline
564/// references.
565pub fn decode_compact<L, DB>(
566	db: &mut DB,
567	encoded: &[Vec<u8>],
568) -> Result<(TrieHash<L>, usize), TrieHash<L>, CError<L>>
569where
570	L: TrieLayout,
571	DB: HashDB<L::Hash, DBValue>,
572{
573	decode_compact_from_iter::<L, DB, _>(db, encoded.iter().map(Vec::as_slice))
574}
575
576/// Variant of 'decode_compact' that accept an iterator of encoded nodes as input.
577pub fn decode_compact_from_iter<'a, L, DB, I>(
578	db: &mut DB,
579	encoded: I,
580) -> Result<(TrieHash<L>, usize), TrieHash<L>, CError<L>>
581where
582	L: TrieLayout,
583	DB: HashDB<L::Hash, DBValue>,
584	I: IntoIterator<Item = &'a [u8]>,
585{
586	// The stack of nodes through a path in the trie. Each entry is a child node of the preceding
587	// entry.
588	let mut stack: Vec<DecoderStackEntry<L::Codec>> = Vec::new();
589
590	// The prefix of the next item to be read from the slice of encoded items.
591	let mut prefix = NibbleVec::new();
592
593	let mut iter = encoded.into_iter().enumerate();
594	while let Some((i, encoded_node)) = iter.next() {
595		let mut attached_node = 0;
596		if let Some(header) = L::Codec::ESCAPE_HEADER {
597			if encoded_node.starts_with(&[header]) {
598				attached_node = 1;
599			}
600		}
601		let node = L::Codec::decode(&encoded_node[attached_node..])
602			.map_err(|err| Box::new(TrieError::DecoderError(<TrieHash<L>>::default(), err)))?;
603
604		let children_len = match node {
605			Node::Empty | Node::Leaf(..) => 0,
606			Node::Extension(..) => 1,
607			Node::Branch(..) | Node::NibbledBranch(..) => NIBBLE_LENGTH,
608		};
609		let mut last_entry = DecoderStackEntry {
610			node,
611			child_index: 0,
612			children: vec![None; children_len],
613			attached_value: None,
614			_marker: PhantomData::default(),
615		};
616
617		if attached_node > 0 {
618			// Read value
619			if let Some((_, fetched_value)) = iter.next() {
620				last_entry.attached_value = Some(fetched_value);
621			} else {
622				return Err(Box::new(TrieError::IncompleteDatabase(<TrieHash<L>>::default())))
623			}
624		}
625
626		loop {
627			if !last_entry.advance_child_index()? {
628				last_entry.push_to_prefix(&mut prefix);
629				stack.push(last_entry);
630				break
631			}
632
633			// Since `advance_child_index` returned true, the preconditions for `encode_node` are
634			// satisfied.
635			let hash = last_entry.attached_value.as_ref().map(|value| {
636				let partial_prefix_len = match &last_entry.node {
637					Node::Leaf(partial, _) | Node::NibbledBranch(partial, _, _) => {
638						prefix.append_partial(partial.right());
639						partial.len()
640					},
641					_ => 0,
642				};
643				let hash = db.insert(prefix.as_prefix(), value);
644				prefix.drop_lasts(partial_prefix_len);
645				hash
646			});
647			let node_data = last_entry.encode_node(hash.as_ref().map(|h| h.as_ref()));
648			let node_hash = db.insert(prefix.as_prefix(), node_data.as_ref());
649
650			if let Some(entry) = stack.pop() {
651				last_entry = entry;
652				last_entry.pop_from_prefix(&mut prefix);
653				last_entry.children[last_entry.child_index] = Some(ChildReference::Hash(node_hash));
654				last_entry.child_index += 1;
655			} else {
656				return Ok((node_hash, i + 1 + attached_node))
657			}
658		}
659	}
660
661	Err(Box::new(TrieError::IncompleteDatabase(<TrieHash<L>>::default())))
662}