Repository: paritytech/substrate
File: primitives/trie/src/trie_codec.rs (Rust)

Code before:
/// Takes as input a destination `db` for decoded node and `encoded`
/// an iterator of compact encoded nodes.
///
/// Child trie are decoded in order of child trie root present
/// in the top trie.
pub fn decode_compact<'a, L, DB, I>(
	db: &mut DB,
	encoded: I,
	expected_root: Option<&TrieHash<L>>,
) -> Result<TrieHash<L>, VerifyError<L>>
	where
		L: TrieConfiguration,
		DB: HashDBT<L::Hash, trie_db::DBValue> + hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
		I: IntoIterator<Item = &'a [u8]>,
{
	let mut nodes_iter = encoded.into_iter();
	let (top_root, _nb_used) = trie_db::decode_compact_from_iter::<L, _, _, _>(
		db,
		&mut nodes_iter,
	).map_err(verify_error::<L>)?;

	if let Some(expected_root) = expected_root {
		if expected_root != &top_root {
			return Err(VerifyError::<L>::RootMismatch(expected_root.clone()));
		}
	}

	let mut child_tries = Vec::new();
	{
		// fetch child trie roots
		let trie = crate::TrieDB::<L>::new(db, &top_root).map_err(verify_error::<L>)?;

		let mut iter = trie.iter().map_err(verify_error::<L>)?;

		let childtrie_roots = sp_core::storage::well_known_keys::DEFAULT_CHILD_STORAGE_KEY_PREFIX;
		if iter.seek(childtrie_roots).is_ok() {
			loop {
				match iter.next() {
					Some(Ok((key, value))) if key.starts_with(childtrie_roots) => {
						// we expect all default child trie root to be correctly encoded.
						// see other child trie functions.
						let mut root = TrieHash::<L>::default();
						// still in a proof so prevent panic
						if root.as_mut().len() != value.as_slice().len() {
							return Err(VerifyError::<L>::RootMismatch(Default::default()));
						}
						root.as_mut().copy_from_slice(value.as_ref());
						child_tries.push(root);
					},
					// allow incomplete database error: we only
					// require access to data in the proof.

Review comment (suggestion):
```suggestion
	if expected_root != top_root {
		return Err(VerifyError::<L>::RootMismatch(expected_root.clone()));
	}
```

Code after:
	RootMismatch(TrieHash<L>, TrieHash<L>),
	/// Missing nodes in proof.
	IncompleteProof,
	/// Compact node is not needed.
	ExtraneousChildNode,
	/// Child content with root not in proof.
	ExtraneousChildProof(TrieHash<L>),
	/// Bad child trie root.
	InvalidChildRoot(Vec<u8>, Vec<u8>),
	/// Errors from trie crate.
	TrieError(Box<TrieError<L>>),
}

impl<L: TrieConfiguration> From<Box<TrieError<L>>> for Error<L> {
	fn from(error: Box<TrieError<L>>) -> Self {
		Error::TrieError(error)
	}
}

#[cfg(feature="std")]
impl<L: TrieConfiguration> StdError for Error<L> {
	fn description(&self) -> &str {
		match self {
			Error::InvalidChildRoot(..) => "Invalid child root error",
			Error::TrieError(..) => "Trie db error",
			Error::RootMismatch(..) => "Trie db error",
			Error::IncompleteProof => "Incomplete proof",
			Error::ExtraneousChildNode => "Extraneous child node",
			Error::ExtraneousChildProof(..) => "Extraneous child proof",
		}
	}
}

#[cfg(feature="std")]
impl<L: TrieConfiguration> fmt::Debug for Error<L> {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		<Self as fmt::Display>::fmt(&self, f)
	}
}

#[cfg(feature="std")]
impl<L: TrieConfiguration> fmt::Display for Error<L> {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		match self {
			Error::InvalidChildRoot(k, v) => write!(f, "InvalidChildRoot at {:x?}: {:x?}", k, v),
			Error::TrieError(e) => write!(f, "Trie error: {}", e),
			Error::IncompleteProof => write!(f, "Incomplete proof"),
			Error::ExtraneousChildNode => write!(f, "Child node content with no root in proof"),
			Error::ExtraneousChildProof(root) => write!(f, "Proof of child trie {:x?} not in parent proof", root.as_ref()),
			Error::RootMismatch(root, expected) => write!(
				f,