Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit f2bc08a

Browse files
yjhmelodybkchr
andauthored
feat: generalize some functions in sp-trie (#12376)
* feat: add to_memory_db to StorageProof * feat: add iter method and generalize iter_nodes * fmt * feat: generalize `encode_compact` like `decode_compact`, add to_compact_proof to StorageProof * fix to_compact_proof * improve by suggestions * improve by suggestions Co-authored-by: Bastian Köcher <git@kchr.de>
1 parent d695386 commit f2bc08a

7 files changed

Lines changed: 56 additions & 45 deletions

File tree

client/rpc/src/state/state_full.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ where
346346
.and_then(|block| {
347347
self.client
348348
.read_proof(&block, &mut keys.iter().map(|key| key.0.as_ref()))
349-
.map(|proof| proof.iter_nodes().map(|node| node.into()).collect())
349+
.map(|proof| proof.into_iter_nodes().map(|node| node.into()).collect())
350350
.map(|proof| ReadProof { at: block, proof })
351351
})
352352
.map_err(client_err)
@@ -498,7 +498,7 @@ where
498498
&child_info,
499499
&mut keys.iter().map(|key| key.0.as_ref()),
500500
)
501-
.map(|proof| proof.iter_nodes().map(|node| node.into()).collect())
501+
.map(|proof| proof.into_iter_nodes().map(|node| node.into()).collect())
502502
.map(|proof| ReadProof { at: block, proof })
503503
})
504504
.map_err(client_err)

client/service/src/client/client.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,8 +1190,8 @@ where
11901190
let (proof, count) = prove_range_read_with_child_with_size::<_, HashFor<Block>>(
11911191
state, size_limit, start_key,
11921192
)?;
1193-
// This is read proof only, we can use either LayoutV0 or LayoutV1.
1194-
let proof = sp_trie::encode_compact::<sp_trie::LayoutV0<HashFor<Block>>>(proof, root)
1193+
let proof = proof
1194+
.into_compact_proof::<HashFor<Block>>(root)
11951195
.map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?;
11961196
Ok((proof, count))
11971197
}

primitives/state-machine/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1939,13 +1939,13 @@ mod tests {
19391939
let (proof, count) =
19401940
prove_range_read_with_size(remote_backend, None, None, 0, None).unwrap();
19411941
// Always contains at least some nodes.
1942-
assert_eq!(proof.into_memory_db::<BlakeTwo256>().drain().len(), 3);
1942+
assert_eq!(proof.to_memory_db::<BlakeTwo256>().drain().len(), 3);
19431943
assert_eq!(count, 1);
19441944

19451945
let remote_backend = trie_backend::tests::test_trie(state_version, None, None);
19461946
let (proof, count) =
19471947
prove_range_read_with_size(remote_backend, None, None, 800, Some(&[])).unwrap();
1948-
assert_eq!(proof.clone().into_memory_db::<BlakeTwo256>().drain().len(), 9);
1948+
assert_eq!(proof.to_memory_db::<BlakeTwo256>().drain().len(), 9);
19491949
assert_eq!(count, 85);
19501950
let (results, completed) = read_range_proof_check::<BlakeTwo256>(
19511951
remote_root,
@@ -1968,7 +1968,7 @@ mod tests {
19681968
let remote_backend = trie_backend::tests::test_trie(state_version, None, None);
19691969
let (proof, count) =
19701970
prove_range_read_with_size(remote_backend, None, None, 50000, Some(&[])).unwrap();
1971-
assert_eq!(proof.clone().into_memory_db::<BlakeTwo256>().drain().len(), 11);
1971+
assert_eq!(proof.to_memory_db::<BlakeTwo256>().drain().len(), 11);
19721972
assert_eq!(count, 132);
19731973
let (results, completed) =
19741974
read_range_proof_check::<BlakeTwo256>(remote_root, proof, None, None, None, None)
@@ -2053,7 +2053,7 @@ mod tests {
20532053
)
20542054
.unwrap();
20552055
// Always contains at least some nodes.
2056-
assert!(proof.clone().into_memory_db::<BlakeTwo256>().drain().len() > 0);
2056+
assert!(proof.to_memory_db::<BlakeTwo256>().drain().len() > 0);
20572057
assert!(count < 3); // when doing child we include parent and first child key.
20582058

20592059
let (result, completed_depth) = read_range_proof_check_with_child::<BlakeTwo256>(

primitives/state-machine/src/trie_backend.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -980,7 +980,7 @@ pub mod tests {
980980
let proof = backend.extract_proof().unwrap();
981981

982982
let mut nodes = Vec::new();
983-
for node in proof.iter_nodes() {
983+
for node in proof.into_iter_nodes() {
984984
let hash = BlakeTwo256::hash(&node);
985985
// Only insert the node/value that contains the important data.
986986
if hash != value_hash {

primitives/trie/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,10 @@ pub use trie_db::{
5757
pub use trie_stream::TrieStream;
5858

5959
/// substrate trie layout
60-
pub struct LayoutV0<H>(sp_std::marker::PhantomData<H>);
60+
pub struct LayoutV0<H>(PhantomData<H>);
6161

6262
/// substrate trie layout, with external value nodes.
63-
pub struct LayoutV1<H>(sp_std::marker::PhantomData<H>);
63+
pub struct LayoutV1<H>(PhantomData<H>);
6464

6565
impl<H> TrieLayout for LayoutV0<H>
6666
where

primitives/trie/src/storage_proof.rs

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@
1818
use codec::{Decode, Encode};
1919
use hash_db::{HashDB, Hasher};
2020
use scale_info::TypeInfo;
21-
use sp_std::{collections::btree_set::BTreeSet, iter::IntoIterator, vec::Vec};
21+
use sp_std::{
22+
collections::btree_set::BTreeSet,
23+
iter::{DoubleEndedIterator, IntoIterator},
24+
vec::Vec,
25+
};
2226
// Note that `LayoutV1` usage here (proof compaction) is compatible
2327
// with `LayoutV0`.
2428
use crate::LayoutV1 as Layout;
@@ -54,10 +58,16 @@ impl StorageProof {
5458
self.trie_nodes.is_empty()
5559
}
5660

61+
/// Convert into an iterator over encoded trie nodes in lexicographical order constructed
62+
/// from the proof.
63+
pub fn into_iter_nodes(self) -> impl Sized + DoubleEndedIterator<Item = Vec<u8>> {
64+
self.trie_nodes.into_iter()
65+
}
66+
5767
/// Create an iterator over encoded trie nodes in lexicographical order constructed
5868
/// from the proof.
59-
pub fn iter_nodes(self) -> StorageProofNodeIterator {
60-
StorageProofNodeIterator::new(self)
69+
pub fn iter_nodes(&self) -> impl Sized + DoubleEndedIterator<Item = &Vec<u8>> {
70+
self.trie_nodes.iter()
6171
}
6272

6373
/// Convert into plain node vector.
@@ -70,14 +80,19 @@ impl StorageProof {
7080
self.into()
7181
}
7282

83+
/// Creates a [`MemoryDB`](crate::MemoryDB) from `Self` reference.
84+
pub fn to_memory_db<H: Hasher>(&self) -> crate::MemoryDB<H> {
85+
self.into()
86+
}
87+
7388
/// Merges multiple storage proofs covering potentially different sets of keys into one proof
7489
/// covering all keys. The merged proof output may be smaller than the aggregate size of the
7590
/// input proofs due to deduplication of trie nodes.
7691
pub fn merge(proofs: impl IntoIterator<Item = Self>) -> Self {
7792
let trie_nodes = proofs
7893
.into_iter()
79-
.flat_map(|proof| proof.iter_nodes())
80-
.collect::<sp_std::collections::btree_set::BTreeSet<_>>()
94+
.flat_map(|proof| proof.into_iter_nodes())
95+
.collect::<BTreeSet<_>>()
8196
.into_iter()
8297
.collect();
8398

@@ -89,7 +104,17 @@ impl StorageProof {
89104
self,
90105
root: H::Out,
91106
) -> Result<CompactProof, crate::CompactProofError<H::Out, crate::Error<H::Out>>> {
92-
crate::encode_compact::<Layout<H>>(self, root)
107+
let db = self.into_memory_db();
108+
crate::encode_compact::<Layout<H>, crate::MemoryDB<H>>(&db, &root)
109+
}
110+
111+
/// Encode as a compact proof with default trie layout.
112+
pub fn to_compact_proof<H: Hasher>(
113+
&self,
114+
root: H::Out,
115+
) -> Result<CompactProof, crate::CompactProofError<H::Out, crate::Error<H::Out>>> {
116+
let db = self.to_memory_db();
117+
crate::encode_compact::<Layout<H>, crate::MemoryDB<H>>(&db, &root)
93118
}
94119

95120
/// Returns the estimated encoded size of the compact proof.
@@ -106,6 +131,12 @@ impl StorageProof {
106131

107132
impl<H: Hasher> From<StorageProof> for crate::MemoryDB<H> {
108133
fn from(proof: StorageProof) -> Self {
134+
From::from(&proof)
135+
}
136+
}
137+
138+
impl<H: Hasher> From<&StorageProof> for crate::MemoryDB<H> {
139+
fn from(proof: &StorageProof) -> Self {
109140
let mut db = crate::MemoryDB::default();
110141
proof.iter_nodes().for_each(|n| {
111142
db.insert(crate::EMPTY_PREFIX, &n);
@@ -169,23 +200,3 @@ impl CompactProof {
169200
Ok((db, root))
170201
}
171202
}
172-
173-
/// An iterator over trie nodes constructed from a storage proof. The nodes are not guaranteed to
174-
/// be traversed in any particular order.
175-
pub struct StorageProofNodeIterator {
176-
inner: <BTreeSet<Vec<u8>> as IntoIterator>::IntoIter,
177-
}
178-
179-
impl StorageProofNodeIterator {
180-
fn new(proof: StorageProof) -> Self {
181-
StorageProofNodeIterator { inner: proof.trie_nodes.into_iter() }
182-
}
183-
}
184-
185-
impl Iterator for StorageProofNodeIterator {
186-
type Item = Vec<u8>;
187-
188-
fn next(&mut self) -> Option<Self::Item> {
189-
self.inner.next()
190-
}
191-
}

primitives/trie/src/trie_codec.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
//! This uses compact proof from trie crate and extends
2121
//! it to substrate specific layout and child trie system.
2222
23-
use crate::{CompactProof, HashDBT, StorageProof, TrieConfiguration, TrieHash, EMPTY_PREFIX};
23+
use crate::{CompactProof, HashDBT, TrieConfiguration, TrieHash, EMPTY_PREFIX};
2424
use sp_std::{boxed::Box, vec::Vec};
2525
use trie_db::{CError, Trie};
2626

@@ -149,17 +149,17 @@ where
149149
/// Then parse all child trie root and compress main trie content first
150150
/// then all child trie contents.
151151
/// Child trie are ordered by the order of their roots in the top trie.
152-
pub fn encode_compact<L>(
153-
proof: StorageProof,
154-
root: TrieHash<L>,
152+
pub fn encode_compact<L, DB>(
153+
partial_db: &DB,
154+
root: &TrieHash<L>,
155155
) -> Result<CompactProof, Error<TrieHash<L>, CError<L>>>
156156
where
157157
L: TrieConfiguration,
158+
DB: HashDBT<L::Hash, trie_db::DBValue> + hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
158159
{
159160
let mut child_tries = Vec::new();
160-
let partial_db = proof.into_memory_db();
161161
let mut compact_proof = {
162-
let trie = crate::TrieDBBuilder::<L>::new(&partial_db, &root).build();
162+
let trie = crate::TrieDBBuilder::<L>::new(partial_db, root).build();
163163

164164
let mut iter = trie.iter()?;
165165

@@ -191,13 +191,13 @@ where
191191
};
192192

193193
for child_root in child_tries {
194-
if !HashDBT::<L::Hash, _>::contains(&partial_db, &child_root, EMPTY_PREFIX) {
194+
if !HashDBT::<L::Hash, _>::contains(partial_db, &child_root, EMPTY_PREFIX) {
195195
// child proof are allowed to be missing (unused root can be included
196196
// due to trie structure modification).
197197
continue
198198
}
199199

200-
let trie = crate::TrieDBBuilder::<L>::new(&partial_db, &child_root).build();
200+
let trie = crate::TrieDBBuilder::<L>::new(partial_db, &child_root).build();
201201
let child_proof = trie_db::encode_compact::<L>(&trie)?;
202202

203203
compact_proof.extend(child_proof);

0 commit comments

Comments
 (0)