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

Code before:
						// 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.
					Some(Err(error)) => match *error {
						trie_db::TrieError::IncompleteDatabase(..) => (),
						e => return Err(VerifyError::<L>::DecodeError(Box::new(e))),
					},
					_ => break,
				}
			}
		}
	}

	if !HashDBT::<L::Hash, _>::contains(db, &top_root, EMPTY_PREFIX) {
		return Err(VerifyError::<L>::IncompleteProof);
	}

	let mut previous_extracted_child_trie = None;
	for child_root in child_tries.into_iter() {
		if previous_extracted_child_trie == None {
			let (top_root, _) = trie_db::decode_compact_from_iter::<L, _, _, _>(
				db,
				&mut nodes_iter,
			).map_err(verify_error::<L>)?;
			previous_extracted_child_trie = Some(top_root);
		}

		// we allow skipping child root by only
		// decoding next on match.
		if Some(child_root) == previous_extracted_child_trie {
			previous_extracted_child_trie = None;
		}
	}
	if let Some(child_root) = previous_extracted_child_trie {
		return Err(VerifyError::<L>::RootMismatch(child_root));
	}

	if nodes_iter.next().is_some() {
		return Err(VerifyError::<L>::ExtraneousNode);
	}

	Ok(top_root)
}

/// Encode a compact proof.

Review comment (refactor):
```suggestion
		if previous_extracted_child_trie.is_none() {
```

Code after:
	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,
				"Verification error, root is {:x?}, expected: {:x?}",
				root.as_ref(),
				expected.as_ref(),
			),
		}
	}
}

/// Decode a compact proof.
///
/// 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>, Error<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,
	)?;

	// Only check root if expected root is passed as argument.
	if let Some(expected_root) = expected_root {
		if expected_root != &top_root {
			return Err(Error::RootMismatch(top_root.clone(), expected_root.clone()));
		}
	}

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