tp_trie/
storage_proof.rs

1// This file is part of Tetcore.
2
3// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18use tetcore_std::vec::Vec;
19use codec::{Encode, Decode};
20use tetsy_hash_db::{Hasher, HashDB};
21
22/// A proof that some set of key-value pairs are included in the storage trie. The proof contains
23/// the storage values so that the partial storage backend can be reconstructed by a verifier that
24/// does not already have access to the key-value pairs.
25///
26/// The proof consists of the set of serialized nodes in the storage trie accessed when looking up
27/// the keys covered by the proof. Verifying the proof requires constructing the partial trie from
28/// the serialized nodes and performing the key lookups.
29#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
30pub struct StorageProof {
31	trie_nodes: Vec<Vec<u8>>,
32}
33
34impl StorageProof {
35	/// Constructs a storage proof from a subset of encoded trie nodes in a storage backend.
36	pub fn new(trie_nodes: Vec<Vec<u8>>) -> Self {
37		StorageProof { trie_nodes }
38	}
39
40	/// Returns a new empty proof.
41	///
42	/// An empty proof is capable of only proving trivial statements (ie. that an empty set of
43	/// key-value pairs exist in storage).
44	pub fn empty() -> Self {
45		StorageProof {
46			trie_nodes: Vec::new(),
47		}
48	}
49
50	/// Returns whether this is an empty proof.
51	pub fn is_empty(&self) -> bool {
52		self.trie_nodes.is_empty()
53	}
54
55	/// Create an iterator over trie nodes constructed from the proof. The nodes are not guaranteed
56	/// to be traversed in any particular order.
57	pub fn iter_nodes(self) -> StorageProofNodeIterator {
58		StorageProofNodeIterator::new(self)
59	}
60
61	/// Creates a `MemoryDB` from `Self`.
62	pub fn into_memory_db<H: Hasher>(self) -> crate::MemoryDB<H> {
63		self.into()
64	}
65
66	/// Merges multiple storage proofs covering potentially different sets of keys into one proof
67	/// covering all keys. The merged proof output may be smaller than the aggregate size of the input
68	/// proofs due to deduplication of trie nodes.
69	pub fn merge<I>(proofs: I) -> Self where I: IntoIterator<Item=Self> {
70		let trie_nodes = proofs.into_iter()
71			.flat_map(|proof| proof.iter_nodes())
72			.collect::<tetcore_std::collections::btree_set::BTreeSet<_>>()
73			.into_iter()
74			.collect();
75
76		Self { trie_nodes }
77	}
78}
79
80/// An iterator over trie nodes constructed from a storage proof. The nodes are not guaranteed to
81/// be traversed in any particular order.
82pub struct StorageProofNodeIterator {
83	inner: <Vec<Vec<u8>> as IntoIterator>::IntoIter,
84}
85
86impl StorageProofNodeIterator {
87	fn new(proof: StorageProof) -> Self {
88		StorageProofNodeIterator {
89			inner: proof.trie_nodes.into_iter(),
90		}
91	}
92}
93
94impl Iterator for StorageProofNodeIterator {
95	type Item = Vec<u8>;
96
97	fn next(&mut self) -> Option<Self::Item> {
98		self.inner.next()
99	}
100}
101
102impl<H: Hasher> From<StorageProof> for crate::MemoryDB<H> {
103	fn from(proof: StorageProof) -> Self {
104		let mut db = crate::MemoryDB::default();
105		for item in proof.iter_nodes() {
106			db.insert(crate::EMPTY_PREFIX, &item);
107		}
108		db
109	}
110}