// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Parity is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // Parity is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with Parity. If not, see . use sp_std::vec::Vec; use codec::{Encode, Decode}; use hash_db::{Hasher, HashDB}; /// A proof that some set of key-value pairs are included in the storage trie. The proof contains /// the storage values so that the partial storage backend can be reconstructed by a verifier that /// does not already have access to the key-value pairs. /// /// The proof consists of the set of serialized nodes in the storage trie accessed when looking up /// the keys covered by the proof. Verifying the proof requires constructing the partial trie from /// the serialized nodes and performing the key lookups. #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] pub struct StorageProof { trie_nodes: Vec>, } impl StorageProof { /// Constructs a storage proof from a subset of encoded trie nodes in a storage backend. pub fn new(trie_nodes: Vec>) -> Self { StorageProof { trie_nodes } } /// Returns a new empty proof. /// /// An empty proof is capable of only proving trivial statements (ie. that an empty set of /// key-value pairs exist in storage). pub fn empty() -> Self { StorageProof { trie_nodes: Vec::new(), } } /// Returns whether this is an empty proof. pub fn is_empty(&self) -> bool { self.trie_nodes.is_empty() } /// Create an iterator over trie nodes constructed from the proof. The nodes are not guaranteed /// to be traversed in any particular order. pub fn iter_nodes(self) -> StorageProofNodeIterator { StorageProofNodeIterator::new(self) } /// Creates a `MemoryDB` from `Self`. pub fn into_memory_db(self) -> crate::MemoryDB { self.into() } /// Merges multiple storage proofs covering potentially different sets of keys into one proof /// covering all keys. The merged proof output may be smaller than the aggregate size of the input /// proofs due to deduplication of trie nodes. pub fn merge(proofs: I) -> Self where I: IntoIterator { let trie_nodes = proofs.into_iter() .flat_map(|proof| proof.iter_nodes()) .collect::>() .into_iter() .collect(); Self { trie_nodes } } } /// An iterator over trie nodes constructed from a storage proof. The nodes are not guaranteed to /// be traversed in any particular order. pub struct StorageProofNodeIterator { inner: > as IntoIterator>::IntoIter, } impl StorageProofNodeIterator { fn new(proof: StorageProof) -> Self { StorageProofNodeIterator { inner: proof.trie_nodes.into_iter(), } } } impl Iterator for StorageProofNodeIterator { type Item = Vec; fn next(&mut self) -> Option { self.inner.next() } } impl From for crate::MemoryDB { fn from(proof: StorageProof) -> Self { let mut db = crate::MemoryDB::default(); for item in proof.iter_nodes() { db.insert(crate::EMPTY_PREFIX, &item); } db } }