Compact proof utilities in sp_trie. (#8574)

* validation extension in sp_io

* need paths

* arc impl

* missing host function in executor

* io to pkdot

* decode function.

* encode primitive.

* trailing tab

* multiple patch

* fix child trie logic

* restore master versionning

* bench compact proof size

* trie-db 22.3 is needed

* line width

* split line

* fixes for bench (additional root may not be needed as original issue was
with empty proof).

* revert compact from block size calculation.

* New error type for compression.

* Adding test (incomplete (failing)).
Also lacking real proof checking (no good primitives in sp-trie crate).

* There is currently no proof recording utility in sp_trie, removing
test.

* small test of child root in proof without a child proof.

* remove empty test.

* remove non compact proof size

* Missing revert.

* proof method to encode decode.
This commit is contained in:
cheme
2021-06-07 11:06:38 +02:00
committed by GitHub
parent f0c5699bc6
commit f01c396677
8 changed files with 407 additions and 9 deletions
@@ -31,6 +31,12 @@ pub struct StorageProof {
trie_nodes: Vec<Vec<u8>>,
}
/// Storage proof in compact form.
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct CompactProof {
pub encoded_nodes: Vec<Vec<u8>>,
}
impl StorageProof {
/// Constructs a storage proof from a subset of encoded trie nodes in a storage backend.
pub fn new(trie_nodes: Vec<Vec<u8>>) -> Self {
@@ -79,6 +85,56 @@ impl StorageProof {
Self { trie_nodes }
}
/// Encode as a compact proof with default
/// trie layout.
pub fn into_compact_proof<H: Hasher>(
self,
root: H::Out,
) -> Result<CompactProof, crate::CompactProofError<crate::Layout<H>>> {
crate::encode_compact::<crate::Layout<H>>(self, root)
}
/// Returns the estimated encoded size of the compact proof.
///
/// Runing this operation is a slow operation (build the whole compact proof) and should only be
/// in non sensitive path.
/// Return `None` on error.
pub fn encoded_compact_size<H: Hasher>(self, root: H::Out) -> Option<usize> {
let compact_proof = self.into_compact_proof::<H>(root);
compact_proof.ok().map(|p| p.encoded_size())
}
}
impl CompactProof {
/// Return an iterator on the compact encoded nodes.
pub fn iter_compact_encoded_nodes(&self) -> impl Iterator<Item = &[u8]> {
self.encoded_nodes.iter().map(Vec::as_slice)
}
/// Decode to a full storage_proof.
///
/// Method use a temporary `HashDB`, and `sp_trie::decode_compact`
/// is often better.
pub fn to_storage_proof<H: Hasher>(
&self,
expected_root: Option<&H::Out>,
) -> Result<(StorageProof, H::Out), crate::CompactProofError<crate::Layout<H>>> {
let mut db = crate::MemoryDB::<H>::new(&[]);
let root = crate::decode_compact::<crate::Layout<H>, _, _>(
&mut db,
self.iter_compact_encoded_nodes(),
expected_root,
)?;
Ok((StorageProof::new(db.drain().into_iter().filter_map(|kv|
if (kv.1).1 > 0 {
Some((kv.1).0)
} else {
None
}
).collect()), root))
}
}
/// An iterator over trie nodes constructed from a storage proof. The nodes are not guaranteed to