referrerpolicy=no-referrer-when-downgrade

sp_trie/
lib.rs

1// This file is part of Substrate.
2
3// Copyright (C) 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
18//! Utility functions to interact with Substrate's Base-16 Modified Merkle Patricia tree ("trie").
19
20#![cfg_attr(not(feature = "std"), no_std)]
21
22extern crate alloc;
23
24pub mod accessed_nodes_tracker;
25#[cfg(feature = "std")]
26pub mod cache;
27mod error;
28#[cfg(any(not(feature = "std"), test))]
29mod hasher_random_state;
30mod node_codec;
31mod node_header;
32#[cfg(feature = "std")]
33pub mod recorder;
34pub mod recorder_ext;
35mod storage_proof;
36mod trie_codec;
37mod trie_stream;
38
39#[cfg(feature = "std")]
40pub mod proof_size_extension;
41
42#[cfg(feature = "std")]
43pub use std::hash::RandomState;
44
45#[cfg(not(feature = "std"))]
46pub use hasher_random_state::{add_extra_randomness, RandomState};
47
48use alloc::{borrow::Borrow, boxed::Box, vec, vec::Vec};
49use core::marker::PhantomData;
50/// Our `NodeCodec`-specific error.
51pub use error::Error;
52/// Various re-exports from the `hash-db` crate.
53pub use hash_db::{HashDB as HashDBT, EMPTY_PREFIX};
54use hash_db::{Hasher, Prefix};
55/// Various re-exports from the `memory-db` crate.
56pub use memory_db::{prefixed_key, HashKey, KeyFunction, PrefixedKey};
57/// The Substrate format implementation of `NodeCodec`.
58pub use node_codec::NodeCodec;
59pub use storage_proof::{CompactProof, StorageProof, StorageProofError};
60/// Trie codec reexport, mainly child trie support
61/// for trie compact proof.
62pub use trie_codec::{decode_compact, encode_compact, Error as CompactProofError};
63use trie_db::proof::{generate_proof, verify_proof};
64/// Various re-exports from the `trie-db` crate.
65pub use trie_db::{
66	nibble_ops,
67	node::{NodePlan, ValuePlan},
68	triedb::{TrieDBDoubleEndedIterator, TrieDBKeyDoubleEndedIterator},
69	CError, DBValue, Query, Recorder, Trie, TrieCache, TrieConfiguration, TrieDBIterator,
70	TrieDBKeyIterator, TrieDBNodeDoubleEndedIterator, TrieDBRawIterator, TrieLayout, TrieMut,
71	TrieRecorder,
72};
73pub use trie_db::{proof::VerifyError, MerkleValue};
74/// The Substrate format implementation of `TrieStream`.
75pub use trie_stream::TrieStream;
76
77/// Raw storage proof type (just raw trie nodes).
78pub type RawStorageProof = Vec<Vec<u8>>;
79
80/// substrate trie layout
81pub struct LayoutV0<H>(PhantomData<H>);
82
83/// substrate trie layout, with external value nodes.
84pub struct LayoutV1<H>(PhantomData<H>);
85
86impl<H> TrieLayout for LayoutV0<H>
87where
88	H: Hasher,
89{
90	const USE_EXTENSION: bool = false;
91	const ALLOW_EMPTY: bool = true;
92	const MAX_INLINE_VALUE: Option<u32> = None;
93
94	type Hash = H;
95	type Codec = NodeCodec<Self::Hash>;
96}
97
98impl<H> TrieConfiguration for LayoutV0<H>
99where
100	H: Hasher,
101{
102	fn trie_root<I, A, B>(input: I) -> <Self::Hash as Hasher>::Out
103	where
104		I: IntoIterator<Item = (A, B)>,
105		A: AsRef<[u8]> + Ord,
106		B: AsRef<[u8]>,
107	{
108		trie_root::trie_root_no_extension::<H, TrieStream, _, _, _>(input, Self::MAX_INLINE_VALUE)
109	}
110
111	fn trie_root_unhashed<I, A, B>(input: I) -> Vec<u8>
112	where
113		I: IntoIterator<Item = (A, B)>,
114		A: AsRef<[u8]> + Ord,
115		B: AsRef<[u8]>,
116	{
117		trie_root::unhashed_trie_no_extension::<H, TrieStream, _, _, _>(
118			input,
119			Self::MAX_INLINE_VALUE,
120		)
121	}
122
123	fn encode_index(input: u32) -> Vec<u8> {
124		codec::Encode::encode(&codec::Compact(input))
125	}
126}
127
128impl<H> TrieLayout for LayoutV1<H>
129where
130	H: Hasher,
131{
132	const USE_EXTENSION: bool = false;
133	const ALLOW_EMPTY: bool = true;
134	const MAX_INLINE_VALUE: Option<u32> = Some(sp_core::storage::TRIE_VALUE_NODE_THRESHOLD);
135
136	type Hash = H;
137	type Codec = NodeCodec<Self::Hash>;
138}
139
140impl<H> TrieConfiguration for LayoutV1<H>
141where
142	H: Hasher,
143{
144	fn trie_root<I, A, B>(input: I) -> <Self::Hash as Hasher>::Out
145	where
146		I: IntoIterator<Item = (A, B)>,
147		A: AsRef<[u8]> + Ord,
148		B: AsRef<[u8]>,
149	{
150		trie_root::trie_root_no_extension::<H, TrieStream, _, _, _>(input, Self::MAX_INLINE_VALUE)
151	}
152
153	fn trie_root_unhashed<I, A, B>(input: I) -> Vec<u8>
154	where
155		I: IntoIterator<Item = (A, B)>,
156		A: AsRef<[u8]> + Ord,
157		B: AsRef<[u8]>,
158	{
159		trie_root::unhashed_trie_no_extension::<H, TrieStream, _, _, _>(
160			input,
161			Self::MAX_INLINE_VALUE,
162		)
163	}
164
165	fn encode_index(input: u32) -> Vec<u8> {
166		codec::Encode::encode(&codec::Compact(input))
167	}
168}
169
170/// Type that is able to provide a [`trie_db::TrieRecorder`].
171///
172/// Types implementing this trait can be used to maintain recorded state
173/// across operations on different [`trie_db::TrieDB`] instances.
174pub trait TrieRecorderProvider<H: Hasher> {
175	/// Recorder type that is going to be returned by implementors of this trait.
176	type Recorder<'a>: trie_db::TrieRecorder<H::Out> + 'a
177	where
178		Self: 'a;
179
180	/// Create a [`StorageProof`] derived from the internal state.
181	fn drain_storage_proof(self) -> Option<StorageProof>;
182
183	/// Provide a recorder implementing [`trie_db::TrieRecorder`].
184	fn as_trie_recorder(&self, storage_root: H::Out) -> Self::Recorder<'_>;
185}
186
187/// Type that is able to provide a proof size estimation.
188pub trait ProofSizeProvider {
189	/// Returns the storage proof size.
190	fn estimate_encoded_size(&self) -> usize;
191}
192
193/// TrieDB error over `TrieConfiguration` trait.
194pub type TrieError<L> = trie_db::TrieError<TrieHash<L>, CError<L>>;
195/// Reexport from `hash_db`, with genericity set for `Hasher` trait.
196pub trait AsHashDB<H: Hasher>: hash_db::AsHashDB<H, trie_db::DBValue> {}
197impl<H: Hasher, T: hash_db::AsHashDB<H, trie_db::DBValue>> AsHashDB<H> for T {}
198/// Reexport from `hash_db`, with genericity set for `Hasher` trait.
199pub type HashDB<'a, H> = dyn hash_db::HashDB<H, trie_db::DBValue> + 'a;
200/// Reexport from `hash_db`, with genericity set for `Hasher` trait.
201/// This uses a `KeyFunction` for prefixing keys internally (avoiding
202/// key conflict for non random keys).
203pub type PrefixedMemoryDB<H, RS = RandomState> =
204	memory_db::MemoryDB<H, memory_db::PrefixedKey<H>, trie_db::DBValue, RS>;
205/// Reexport from `hash_db`, with genericity set for `Hasher` trait.
206/// This uses a noops `KeyFunction` (key addressing must be hashed or using
207/// an encoding scheme that avoid key conflict).
208pub type MemoryDB<H, RS = RandomState> =
209	memory_db::MemoryDB<H, memory_db::HashKey<H>, trie_db::DBValue, RS>;
210/// Reexport from `hash_db`, with genericity set for `Hasher` trait.
211pub type GenericMemoryDB<H, KF, RS = RandomState> =
212	memory_db::MemoryDB<H, KF, trie_db::DBValue, RS>;
213
214/// Persistent trie database read-access interface for a given hasher.
215pub type TrieDB<'a, 'cache, L> = trie_db::TrieDB<'a, 'cache, L>;
216/// Builder for creating a [`TrieDB`].
217pub type TrieDBBuilder<'a, 'cache, L> = trie_db::TrieDBBuilder<'a, 'cache, L>;
218/// Persistent trie database write-access interface for a given hasher.
219pub type TrieDBMut<'a, L> = trie_db::TrieDBMut<'a, L>;
220/// Builder for creating a [`TrieDBMut`].
221pub type TrieDBMutBuilder<'a, L> = trie_db::TrieDBMutBuilder<'a, L>;
222/// Querying interface, as in `trie_db` but less generic.
223pub type Lookup<'a, 'cache, L, Q> = trie_db::Lookup<'a, 'cache, L, Q>;
224/// Hash type for a trie layout.
225pub type TrieHash<L> = <<L as TrieLayout>::Hash as Hasher>::Out;
226/// This module is for non generic definition of trie type.
227/// Only the `Hasher` trait is generic in this case.
228pub mod trie_types {
229	use super::*;
230
231	/// Persistent trie database read-access interface for a given hasher.
232	///
233	/// Read only V1 and V0 are compatible, thus we always use V1.
234	pub type TrieDB<'a, 'cache, H> = super::TrieDB<'a, 'cache, LayoutV1<H>>;
235	/// Builder for creating a [`TrieDB`].
236	pub type TrieDBBuilder<'a, 'cache, H> = super::TrieDBBuilder<'a, 'cache, LayoutV1<H>>;
237	/// Persistent trie database write-access interface for a given hasher.
238	pub type TrieDBMutV0<'a, H> = super::TrieDBMut<'a, LayoutV0<H>>;
239	/// Builder for creating a [`TrieDBMutV0`].
240	pub type TrieDBMutBuilderV0<'a, H> = super::TrieDBMutBuilder<'a, LayoutV0<H>>;
241	/// Persistent trie database write-access interface for a given hasher.
242	pub type TrieDBMutV1<'a, H> = super::TrieDBMut<'a, LayoutV1<H>>;
243	/// Builder for creating a [`TrieDBMutV1`].
244	pub type TrieDBMutBuilderV1<'a, H> = super::TrieDBMutBuilder<'a, LayoutV1<H>>;
245	/// Querying interface, as in `trie_db` but less generic.
246	pub type Lookup<'a, 'cache, H, Q> = trie_db::Lookup<'a, 'cache, LayoutV1<H>, Q>;
247	/// As in `trie_db`, but less generic, error type for the crate.
248	pub type TrieError<H> = trie_db::TrieError<H, super::Error<H>>;
249}
250
251/// Create a proof for a subset of keys in a trie.
252///
253/// The `keys` may contain any set of keys regardless of each one of them is included
254/// in the `db`.
255///
256/// For a key `K` that is included in the `db` a proof of inclusion is generated.
257/// For a key `K` that is not included in the `db` a proof of non-inclusion is generated.
258/// These can be later checked in `verify_trie_proof`.
259pub fn generate_trie_proof<'a, L, I, K, DB>(
260	db: &DB,
261	root: TrieHash<L>,
262	keys: I,
263) -> Result<Vec<Vec<u8>>, Box<TrieError<L>>>
264where
265	L: TrieConfiguration,
266	I: IntoIterator<Item = &'a K>,
267	K: 'a + AsRef<[u8]>,
268	DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
269{
270	generate_proof::<_, L, _, _>(db, &root, keys)
271}
272
273/// Verify a set of key-value pairs against a trie root and a proof.
274///
275/// Checks a set of keys with optional values for inclusion in the proof that was generated by
276/// `generate_trie_proof`.
277/// If the value in the pair is supplied (`(key, Some(value))`), this key-value pair will be
278/// checked for inclusion in the proof.
279/// If the value is omitted (`(key, None)`), this key will be checked for non-inclusion in the
280/// proof.
281pub fn verify_trie_proof<'a, L, I, K, V>(
282	root: &TrieHash<L>,
283	proof: &[Vec<u8>],
284	items: I,
285) -> Result<(), VerifyError<TrieHash<L>, CError<L>>>
286where
287	L: TrieConfiguration,
288	I: IntoIterator<Item = &'a (K, Option<V>)>,
289	K: 'a + AsRef<[u8]>,
290	V: 'a + AsRef<[u8]>,
291{
292	verify_proof::<L, _, _, _>(root, proof, items)
293}
294
295/// Determine a trie root given a hash DB and delta values.
296pub fn delta_trie_root<L: TrieConfiguration, I, A, B, DB, V>(
297	db: &mut DB,
298	mut root: TrieHash<L>,
299	delta: I,
300	recorder: Option<&mut dyn trie_db::TrieRecorder<TrieHash<L>>>,
301	cache: Option<&mut dyn TrieCache<L::Codec>>,
302) -> Result<TrieHash<L>, Box<TrieError<L>>>
303where
304	I: IntoIterator<Item = (A, B)>,
305	A: Borrow<[u8]>,
306	B: Borrow<Option<V>>,
307	V: Borrow<[u8]>,
308	DB: hash_db::HashDB<L::Hash, trie_db::DBValue>,
309{
310	{
311		let mut trie = TrieDBMutBuilder::<L>::from_existing(db, &mut root)
312			.with_optional_cache(cache)
313			.with_optional_recorder(recorder)
314			.build();
315
316		let mut delta = delta.into_iter().collect::<Vec<_>>();
317		delta.sort_by(|l, r| l.0.borrow().cmp(r.0.borrow()));
318
319		for (key, change) in delta {
320			match change.borrow() {
321				Some(val) => trie.insert(key.borrow(), val.borrow())?,
322				None => trie.remove(key.borrow())?,
323			};
324		}
325	}
326
327	Ok(root)
328}
329
330/// Read a value from the trie.
331pub fn read_trie_value<L: TrieLayout, DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>>(
332	db: &DB,
333	root: &TrieHash<L>,
334	key: &[u8],
335	recorder: Option<&mut dyn TrieRecorder<TrieHash<L>>>,
336	cache: Option<&mut dyn TrieCache<L::Codec>>,
337) -> Result<Option<Vec<u8>>, Box<TrieError<L>>> {
338	TrieDBBuilder::<L>::new(db, root)
339		.with_optional_cache(cache)
340		.with_optional_recorder(recorder)
341		.build()
342		.get(key)
343}
344
345/// Read the [`trie_db::MerkleValue`] of the node that is the closest descendant for
346/// the provided key.
347pub fn read_trie_first_descendant_value<L: TrieLayout, DB>(
348	db: &DB,
349	root: &TrieHash<L>,
350	key: &[u8],
351	recorder: Option<&mut dyn TrieRecorder<TrieHash<L>>>,
352	cache: Option<&mut dyn TrieCache<L::Codec>>,
353) -> Result<Option<MerkleValue<TrieHash<L>>>, Box<TrieError<L>>>
354where
355	DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
356{
357	TrieDBBuilder::<L>::new(db, root)
358		.with_optional_cache(cache)
359		.with_optional_recorder(recorder)
360		.build()
361		.lookup_first_descendant(key)
362}
363
364/// Read a value from the trie with given Query.
365pub fn read_trie_value_with<
366	L: TrieLayout,
367	Q: Query<L::Hash, Item = Vec<u8>>,
368	DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
369>(
370	db: &DB,
371	root: &TrieHash<L>,
372	key: &[u8],
373	query: Q,
374) -> Result<Option<Vec<u8>>, Box<TrieError<L>>> {
375	TrieDBBuilder::<L>::new(db, root).build().get_with(key, query)
376}
377
378/// Determine the empty trie root.
379pub fn empty_trie_root<L: TrieConfiguration>() -> <L::Hash as Hasher>::Out {
380	L::trie_root::<_, Vec<u8>, Vec<u8>>(core::iter::empty())
381}
382
383/// Determine the empty child trie root.
384pub fn empty_child_trie_root<L: TrieConfiguration>() -> <L::Hash as Hasher>::Out {
385	L::trie_root::<_, Vec<u8>, Vec<u8>>(core::iter::empty())
386}
387
388/// Determine a child trie root given its ordered contents, closed form. H is the default hasher,
389/// but a generic implementation may ignore this type parameter and use other hashers.
390pub fn child_trie_root<L: TrieConfiguration, I, A, B>(input: I) -> <L::Hash as Hasher>::Out
391where
392	I: IntoIterator<Item = (A, B)>,
393	A: AsRef<[u8]> + Ord,
394	B: AsRef<[u8]>,
395{
396	L::trie_root(input)
397}
398
399/// Determine a child trie root given a hash DB and delta values. H is the default hasher,
400/// but a generic implementation may ignore this type parameter and use other hashers.
401pub fn child_delta_trie_root<L: TrieConfiguration, I, A, B, DB, RD, V>(
402	keyspace: &[u8],
403	db: &mut DB,
404	root_data: RD,
405	delta: I,
406	recorder: Option<&mut dyn TrieRecorder<TrieHash<L>>>,
407	cache: Option<&mut dyn TrieCache<L::Codec>>,
408) -> Result<<L::Hash as Hasher>::Out, Box<TrieError<L>>>
409where
410	I: IntoIterator<Item = (A, B)>,
411	A: Borrow<[u8]>,
412	B: Borrow<Option<V>>,
413	V: Borrow<[u8]>,
414	RD: AsRef<[u8]>,
415	DB: hash_db::HashDB<L::Hash, trie_db::DBValue>,
416{
417	let mut root = TrieHash::<L>::default();
418	// root is fetched from DB, not writable by runtime, so it's always valid.
419	root.as_mut().copy_from_slice(root_data.as_ref());
420
421	let mut db = KeySpacedDBMut::new(db, keyspace);
422	delta_trie_root::<L, _, _, _, _, _>(&mut db, root, delta, recorder, cache)
423}
424
425/// Read a value from the child trie.
426pub fn read_child_trie_value<L: TrieConfiguration, DB>(
427	keyspace: &[u8],
428	db: &DB,
429	root: &TrieHash<L>,
430	key: &[u8],
431	recorder: Option<&mut dyn TrieRecorder<TrieHash<L>>>,
432	cache: Option<&mut dyn TrieCache<L::Codec>>,
433) -> Result<Option<Vec<u8>>, Box<TrieError<L>>>
434where
435	DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
436{
437	let db = KeySpacedDB::new(db, keyspace);
438	TrieDBBuilder::<L>::new(&db, &root)
439		.with_optional_recorder(recorder)
440		.with_optional_cache(cache)
441		.build()
442		.get(key)
443		.map(|x| x.map(|val| val.to_vec()))
444}
445
446/// Read a hash from the child trie.
447pub fn read_child_trie_hash<L: TrieConfiguration, DB>(
448	keyspace: &[u8],
449	db: &DB,
450	root: &TrieHash<L>,
451	key: &[u8],
452	recorder: Option<&mut dyn TrieRecorder<TrieHash<L>>>,
453	cache: Option<&mut dyn TrieCache<L::Codec>>,
454) -> Result<Option<TrieHash<L>>, Box<TrieError<L>>>
455where
456	DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
457{
458	let db = KeySpacedDB::new(db, keyspace);
459	TrieDBBuilder::<L>::new(&db, &root)
460		.with_optional_recorder(recorder)
461		.with_optional_cache(cache)
462		.build()
463		.get_hash(key)
464}
465
466/// Read the [`trie_db::MerkleValue`] of the node that is the closest descendant for
467/// the provided child key.
468pub fn read_child_trie_first_descendant_value<L: TrieConfiguration, DB>(
469	keyspace: &[u8],
470	db: &DB,
471	root: &TrieHash<L>,
472	key: &[u8],
473	recorder: Option<&mut dyn TrieRecorder<TrieHash<L>>>,
474	cache: Option<&mut dyn TrieCache<L::Codec>>,
475) -> Result<Option<MerkleValue<TrieHash<L>>>, Box<TrieError<L>>>
476where
477	DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
478{
479	let db = KeySpacedDB::new(db, keyspace);
480	TrieDBBuilder::<L>::new(&db, &root)
481		.with_optional_recorder(recorder)
482		.with_optional_cache(cache)
483		.build()
484		.lookup_first_descendant(key)
485}
486
487/// Read a value from the child trie with given query.
488pub fn read_child_trie_value_with<L, Q, DB>(
489	keyspace: &[u8],
490	db: &DB,
491	root_slice: &[u8],
492	key: &[u8],
493	query: Q,
494) -> Result<Option<Vec<u8>>, Box<TrieError<L>>>
495where
496	L: TrieConfiguration,
497	Q: Query<L::Hash, Item = DBValue>,
498	DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
499{
500	let mut root = TrieHash::<L>::default();
501	// root is fetched from DB, not writable by runtime, so it's always valid.
502	root.as_mut().copy_from_slice(root_slice);
503
504	let db = KeySpacedDB::new(db, keyspace);
505	TrieDBBuilder::<L>::new(&db, &root)
506		.build()
507		.get_with(key, query)
508		.map(|x| x.map(|val| val.to_vec()))
509}
510
511/// `HashDB` implementation that append a encoded prefix (unique id bytes) in addition to the
512/// prefix of every key value.
513pub struct KeySpacedDB<'a, DB: ?Sized, H>(&'a DB, &'a [u8], PhantomData<H>);
514
515/// `HashDBMut` implementation that append a encoded prefix (unique id bytes) in addition to the
516/// prefix of every key value.
517///
518/// Mutable variant of `KeySpacedDB`, see [`KeySpacedDB`].
519pub struct KeySpacedDBMut<'a, DB: ?Sized, H>(&'a mut DB, &'a [u8], PhantomData<H>);
520
521/// Utility function used to merge some byte data (keyspace) and `prefix` data
522/// before calling key value database primitives.
523fn keyspace_as_prefix_alloc(ks: &[u8], prefix: Prefix) -> (Vec<u8>, Option<u8>) {
524	let mut result = vec![0; ks.len() + prefix.0.len()];
525	result[..ks.len()].copy_from_slice(ks);
526	result[ks.len()..].copy_from_slice(prefix.0);
527	(result, prefix.1)
528}
529
530impl<'a, DB: ?Sized, H> KeySpacedDB<'a, DB, H> {
531	/// instantiate new keyspaced db
532	#[inline]
533	pub fn new(db: &'a DB, ks: &'a [u8]) -> Self {
534		KeySpacedDB(db, ks, PhantomData)
535	}
536}
537
538impl<'a, DB: ?Sized, H> KeySpacedDBMut<'a, DB, H> {
539	/// instantiate new keyspaced db
540	pub fn new(db: &'a mut DB, ks: &'a [u8]) -> Self {
541		KeySpacedDBMut(db, ks, PhantomData)
542	}
543}
544
545impl<'a, DB, H, T> hash_db::HashDBRef<H, T> for KeySpacedDB<'a, DB, H>
546where
547	DB: hash_db::HashDBRef<H, T> + ?Sized,
548	H: Hasher,
549	T: From<&'static [u8]>,
550{
551	fn get(&self, key: &H::Out, prefix: Prefix) -> Option<T> {
552		let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
553		self.0.get(key, (&derived_prefix.0, derived_prefix.1))
554	}
555
556	fn contains(&self, key: &H::Out, prefix: Prefix) -> bool {
557		let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
558		self.0.contains(key, (&derived_prefix.0, derived_prefix.1))
559	}
560}
561
562impl<'a, DB, H, T> hash_db::HashDB<H, T> for KeySpacedDBMut<'a, DB, H>
563where
564	DB: hash_db::HashDB<H, T>,
565	H: Hasher,
566	T: Default + PartialEq<T> + for<'b> From<&'b [u8]> + Clone + Send + Sync,
567{
568	fn get(&self, key: &H::Out, prefix: Prefix) -> Option<T> {
569		let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
570		self.0.get(key, (&derived_prefix.0, derived_prefix.1))
571	}
572
573	fn contains(&self, key: &H::Out, prefix: Prefix) -> bool {
574		let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
575		self.0.contains(key, (&derived_prefix.0, derived_prefix.1))
576	}
577
578	fn insert(&mut self, prefix: Prefix, value: &[u8]) -> H::Out {
579		let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
580		self.0.insert((&derived_prefix.0, derived_prefix.1), value)
581	}
582
583	fn emplace(&mut self, key: H::Out, prefix: Prefix, value: T) {
584		let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
585		self.0.emplace(key, (&derived_prefix.0, derived_prefix.1), value)
586	}
587
588	fn remove(&mut self, key: &H::Out, prefix: Prefix) {
589		let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
590		self.0.remove(key, (&derived_prefix.0, derived_prefix.1))
591	}
592}
593
594impl<'a, DB, H, T> hash_db::AsHashDB<H, T> for KeySpacedDBMut<'a, DB, H>
595where
596	DB: hash_db::HashDB<H, T>,
597	H: Hasher,
598	T: Default + PartialEq<T> + for<'b> From<&'b [u8]> + Clone + Send + Sync,
599{
600	fn as_hash_db(&self) -> &dyn hash_db::HashDB<H, T> {
601		self
602	}
603
604	fn as_hash_db_mut<'b>(&'b mut self) -> &'b mut (dyn hash_db::HashDB<H, T> + 'b) {
605		&mut *self
606	}
607}
608
609/// Constants used into trie simplification codec.
610mod trie_constants {
611	const FIRST_PREFIX: u8 = 0b_00 << 6;
612	pub const LEAF_PREFIX_MASK: u8 = 0b_01 << 6;
613	pub const BRANCH_WITHOUT_MASK: u8 = 0b_10 << 6;
614	pub const BRANCH_WITH_MASK: u8 = 0b_11 << 6;
615	pub const EMPTY_TRIE: u8 = FIRST_PREFIX | (0b_00 << 4);
616	pub const ALT_HASHING_LEAF_PREFIX_MASK: u8 = FIRST_PREFIX | (0b_1 << 5);
617	pub const ALT_HASHING_BRANCH_WITH_MASK: u8 = FIRST_PREFIX | (0b_01 << 4);
618	pub const ESCAPE_COMPACT_HEADER: u8 = EMPTY_TRIE | 0b_00_01;
619}
620
621#[cfg(test)]
622mod tests {
623	use super::*;
624	use codec::{Compact, Decode, Encode};
625	use hash_db::{HashDB, Hasher};
626	use sp_core::Blake2Hasher;
627	use trie_db::{DBValue, NodeCodec as NodeCodecT, Trie, TrieMut};
628	use trie_standardmap::{Alphabet, StandardMap, ValueMode};
629
630	type LayoutV0 = super::LayoutV0<Blake2Hasher>;
631	type LayoutV1 = super::LayoutV1<Blake2Hasher>;
632
633	type MemoryDBMeta<H> = memory_db::MemoryDB<H, memory_db::HashKey<H>, trie_db::DBValue>;
634
635	pub fn create_trie<L: TrieLayout>(
636		data: &[(&[u8], &[u8])],
637	) -> (MemoryDB<L::Hash>, trie_db::TrieHash<L>) {
638		let mut db = MemoryDB::default();
639		let mut root = Default::default();
640
641		{
642			let mut trie = trie_db::TrieDBMutBuilder::<L>::new(&mut db, &mut root).build();
643			for (k, v) in data {
644				trie.insert(k, v).expect("Inserts data");
645			}
646		}
647
648		let mut recorder = Recorder::<L>::new();
649		{
650			let trie = trie_db::TrieDBBuilder::<L>::new(&mut db, &mut root)
651				.with_recorder(&mut recorder)
652				.build();
653			for (k, _v) in data {
654				trie.get(k).unwrap();
655			}
656		}
657
658		(db, root)
659	}
660
661	pub fn create_storage_proof<L: TrieLayout>(
662		data: &[(&[u8], &[u8])],
663	) -> (RawStorageProof, trie_db::TrieHash<L>) {
664		let (db, root) = create_trie::<L>(data);
665
666		let mut recorder = Recorder::<L>::new();
667		{
668			let trie = trie_db::TrieDBBuilder::<L>::new(&db, &root)
669				.with_recorder(&mut recorder)
670				.build();
671			for (k, _v) in data {
672				trie.get(k).unwrap();
673			}
674		}
675
676		(recorder.drain().into_iter().map(|record| record.data).collect(), root)
677	}
678
679	fn hashed_null_node<T: TrieConfiguration>() -> TrieHash<T> {
680		<T::Codec as NodeCodecT>::hashed_null_node()
681	}
682
683	fn check_equivalent<T: TrieConfiguration>(input: &Vec<(&[u8], &[u8])>) {
684		{
685			let closed_form = T::trie_root(input.clone());
686			let d = T::trie_root_unhashed(input.clone());
687			println!("Data: {:#x?}, {:#x?}", d, Blake2Hasher::hash(&d[..]));
688			let persistent = {
689				let mut memdb = MemoryDBMeta::default();
690				let mut root = Default::default();
691				let mut t = TrieDBMutBuilder::<T>::new(&mut memdb, &mut root).build();
692				for (x, y) in input.iter().rev() {
693					t.insert(x, y).unwrap();
694				}
695				*t.root()
696			};
697			assert_eq!(closed_form, persistent);
698		}
699	}
700
701	fn check_iteration<T: TrieConfiguration>(input: &Vec<(&[u8], &[u8])>) {
702		let mut memdb = MemoryDBMeta::default();
703		let mut root = Default::default();
704		{
705			let mut t = TrieDBMutBuilder::<T>::new(&mut memdb, &mut root).build();
706			for (x, y) in input.clone() {
707				t.insert(x, y).unwrap();
708			}
709		}
710		{
711			let t = TrieDBBuilder::<T>::new(&memdb, &root).build();
712			assert_eq!(
713				input.iter().map(|(i, j)| (i.to_vec(), j.to_vec())).collect::<Vec<_>>(),
714				t.iter()
715					.unwrap()
716					.map(|x| x.map(|y| (y.0, y.1.to_vec())).unwrap())
717					.collect::<Vec<_>>()
718			);
719		}
720	}
721
722	fn check_input(input: &Vec<(&[u8], &[u8])>) {
723		check_equivalent::<LayoutV0>(input);
724		check_iteration::<LayoutV0>(input);
725		check_equivalent::<LayoutV1>(input);
726		check_iteration::<LayoutV1>(input);
727	}
728
729	#[test]
730	fn default_trie_root() {
731		let mut db = MemoryDB::default();
732		let mut root = TrieHash::<LayoutV1>::default();
733		let mut empty = TrieDBMutBuilder::<LayoutV1>::new(&mut db, &mut root).build();
734		empty.commit();
735		let root1 = empty.root().as_ref().to_vec();
736		let root2: Vec<u8> = LayoutV1::trie_root::<_, Vec<u8>, Vec<u8>>(std::iter::empty())
737			.as_ref()
738			.iter()
739			.cloned()
740			.collect();
741
742		assert_eq!(root1, root2);
743	}
744
745	#[test]
746	fn empty_is_equivalent() {
747		let input: Vec<(&[u8], &[u8])> = vec![];
748		check_input(&input);
749	}
750
751	#[test]
752	fn leaf_is_equivalent() {
753		let input: Vec<(&[u8], &[u8])> = vec![(&[0xaa][..], &[0xbb][..])];
754		check_input(&input);
755	}
756
757	#[test]
758	fn branch_is_equivalent() {
759		let input: Vec<(&[u8], &[u8])> =
760			vec![(&[0xaa][..], &[0x10][..]), (&[0xba][..], &[0x11][..])];
761		check_input(&input);
762	}
763
764	#[test]
765	fn extension_and_branch_is_equivalent() {
766		let input: Vec<(&[u8], &[u8])> =
767			vec![(&[0xaa][..], &[0x10][..]), (&[0xab][..], &[0x11][..])];
768		check_input(&input);
769	}
770
771	#[test]
772	fn standard_is_equivalent() {
773		let st = StandardMap {
774			alphabet: Alphabet::All,
775			min_key: 32,
776			journal_key: 0,
777			value_mode: ValueMode::Random,
778			count: 1000,
779		};
780		let mut d = st.make();
781		d.sort_by(|(a, _), (b, _)| a.cmp(b));
782		let dr = d.iter().map(|v| (&v.0[..], &v.1[..])).collect();
783		check_input(&dr);
784	}
785
786	#[test]
787	fn extension_and_branch_with_value_is_equivalent() {
788		let input: Vec<(&[u8], &[u8])> = vec![
789			(&[0xaa][..], &[0xa0][..]),
790			(&[0xaa, 0xaa][..], &[0xaa][..]),
791			(&[0xaa, 0xbb][..], &[0xab][..]),
792		];
793		check_input(&input);
794	}
795
796	#[test]
797	fn bigger_extension_and_branch_with_value_is_equivalent() {
798		let input: Vec<(&[u8], &[u8])> = vec![
799			(&[0xaa][..], &[0xa0][..]),
800			(&[0xaa, 0xaa][..], &[0xaa][..]),
801			(&[0xaa, 0xbb][..], &[0xab][..]),
802			(&[0xbb][..], &[0xb0][..]),
803			(&[0xbb, 0xbb][..], &[0xbb][..]),
804			(&[0xbb, 0xcc][..], &[0xbc][..]),
805		];
806		check_input(&input);
807	}
808
809	#[test]
810	fn single_long_leaf_is_equivalent() {
811		let input: Vec<(&[u8], &[u8])> = vec![
812			(
813				&[0xaa][..],
814				&b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..],
815			),
816			(&[0xba][..], &[0x11][..]),
817		];
818		check_input(&input);
819	}
820
821	#[test]
822	fn two_long_leaves_is_equivalent() {
823		let input: Vec<(&[u8], &[u8])> = vec![
824			(
825				&[0xaa][..],
826				&b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..],
827			),
828			(
829				&[0xba][..],
830				&b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..],
831			),
832		];
833		check_input(&input);
834	}
835
836	fn populate_trie<'db, T: TrieConfiguration>(
837		db: &'db mut dyn HashDB<T::Hash, DBValue>,
838		root: &'db mut TrieHash<T>,
839		v: &[(Vec<u8>, Vec<u8>)],
840	) -> TrieDBMut<'db, T> {
841		let mut t = TrieDBMutBuilder::<T>::new(db, root).build();
842		for i in 0..v.len() {
843			let key: &[u8] = &v[i].0;
844			let val: &[u8] = &v[i].1;
845			t.insert(key, val).unwrap();
846		}
847		t
848	}
849
850	fn unpopulate_trie<T: TrieConfiguration>(t: &mut TrieDBMut<'_, T>, v: &[(Vec<u8>, Vec<u8>)]) {
851		for i in v {
852			let key: &[u8] = &i.0;
853			t.remove(key).unwrap();
854		}
855	}
856
857	#[test]
858	fn random_should_work() {
859		random_should_work_inner::<LayoutV1>();
860		random_should_work_inner::<LayoutV0>();
861	}
862	fn random_should_work_inner<L: TrieConfiguration>() {
863		let mut seed = <Blake2Hasher as Hasher>::Out::zero();
864		for test_i in 0..10_000 {
865			if test_i % 50 == 0 {
866				println!("{:?} of 10000 stress tests done", test_i);
867			}
868			let x = StandardMap {
869				alphabet: Alphabet::Custom(b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_".to_vec()),
870				min_key: 5,
871				journal_key: 0,
872				value_mode: ValueMode::Index,
873				count: 100,
874			}
875			.make_with(seed.as_fixed_bytes_mut());
876
877			let real = L::trie_root(x.clone());
878			let mut memdb = MemoryDB::default();
879			let mut root = Default::default();
880
881			let mut memtrie = populate_trie::<L>(&mut memdb, &mut root, &x);
882
883			memtrie.commit();
884			if *memtrie.root() != real {
885				println!("TRIE MISMATCH");
886				println!();
887				println!("{:?} vs {:?}", memtrie.root(), real);
888				for i in &x {
889					println!("{:#x?} -> {:#x?}", i.0, i.1);
890				}
891			}
892			assert_eq!(*memtrie.root(), real);
893			unpopulate_trie::<L>(&mut memtrie, &x);
894			memtrie.commit();
895			let hashed_null_node = hashed_null_node::<L>();
896			if *memtrie.root() != hashed_null_node {
897				println!("- TRIE MISMATCH");
898				println!();
899				println!("{:?} vs {:?}", memtrie.root(), hashed_null_node);
900				for i in &x {
901					println!("{:#x?} -> {:#x?}", i.0, i.1);
902				}
903			}
904			assert_eq!(*memtrie.root(), hashed_null_node);
905		}
906	}
907
908	fn to_compact(n: u8) -> u8 {
909		Compact(n).encode()[0]
910	}
911
912	#[test]
913	fn codec_trie_empty() {
914		let input: Vec<(&[u8], &[u8])> = vec![];
915		let trie = LayoutV1::trie_root_unhashed(input);
916		println!("trie: {:#x?}", trie);
917		assert_eq!(trie, vec![0x0]);
918	}
919
920	#[test]
921	fn codec_trie_single_tuple() {
922		let input = vec![(vec![0xaa], vec![0xbb])];
923		let trie = LayoutV1::trie_root_unhashed(input);
924		println!("trie: {:#x?}", trie);
925		assert_eq!(
926			trie,
927			vec![
928				0x42,          // leaf 0x40 (2^6) with (+) key of 2 nibbles (0x02)
929				0xaa,          // key data
930				to_compact(1), // length of value in bytes as Compact
931				0xbb           // value data
932			]
933		);
934	}
935
936	#[test]
937	fn codec_trie_two_tuples_disjoint_keys() {
938		let input = vec![(&[0x48, 0x19], &[0xfe]), (&[0x13, 0x14], &[0xff])];
939		let trie = LayoutV1::trie_root_unhashed(input);
940		println!("trie: {:#x?}", trie);
941		let mut ex = Vec::<u8>::new();
942		ex.push(0x80); // branch, no value (0b_10..) no nibble
943		ex.push(0x12); // slots 1 & 4 are taken from 0-7
944		ex.push(0x00); // no slots from 8-15
945		ex.push(to_compact(0x05)); // first slot: LEAF, 5 bytes long.
946		ex.push(0x43); // leaf 0x40 with 3 nibbles
947		ex.push(0x03); // first nibble
948		ex.push(0x14); // second & third nibble
949		ex.push(to_compact(0x01)); // 1 byte data
950		ex.push(0xff); // value data
951		ex.push(to_compact(0x05)); // second slot: LEAF, 5 bytes long.
952		ex.push(0x43); // leaf with 3 nibbles
953		ex.push(0x08); // first nibble
954		ex.push(0x19); // second & third nibble
955		ex.push(to_compact(0x01)); // 1 byte data
956		ex.push(0xfe); // value data
957
958		assert_eq!(trie, ex);
959	}
960
961	#[test]
962	fn iterator_works() {
963		iterator_works_inner::<LayoutV1>();
964		iterator_works_inner::<LayoutV0>();
965	}
966	fn iterator_works_inner<Layout: TrieConfiguration>() {
967		let pairs = vec![
968			(
969				array_bytes::hex2bytes_unchecked("0103000000000000000464"),
970				array_bytes::hex2bytes_unchecked("0400000000"),
971			),
972			(
973				array_bytes::hex2bytes_unchecked("0103000000000000000469"),
974				array_bytes::hex2bytes_unchecked("0401000000"),
975			),
976		];
977
978		let mut mdb = MemoryDB::default();
979		let mut root = Default::default();
980		let _ = populate_trie::<Layout>(&mut mdb, &mut root, &pairs);
981
982		let trie = TrieDBBuilder::<Layout>::new(&mdb, &root).build();
983
984		let iter = trie.iter().unwrap();
985		let mut iter_pairs = Vec::new();
986		for pair in iter {
987			let (key, value) = pair.unwrap();
988			iter_pairs.push((key, value));
989		}
990
991		assert_eq!(pairs, iter_pairs);
992	}
993
994	#[test]
995	fn proof_non_inclusion_works() {
996		let pairs = vec![
997			(array_bytes::hex2bytes_unchecked("0102"), array_bytes::hex2bytes_unchecked("01")),
998			(array_bytes::hex2bytes_unchecked("0203"), array_bytes::hex2bytes_unchecked("0405")),
999		];
1000
1001		let mut memdb = MemoryDB::default();
1002		let mut root = Default::default();
1003		populate_trie::<LayoutV1>(&mut memdb, &mut root, &pairs);
1004
1005		let non_included_key: Vec<u8> = array_bytes::hex2bytes_unchecked("0909");
1006		let proof =
1007			generate_trie_proof::<LayoutV1, _, _, _>(&memdb, root, &[non_included_key.clone()])
1008				.unwrap();
1009
1010		// Verifying that the K was not included into the trie should work.
1011		assert!(verify_trie_proof::<LayoutV1, _, _, Vec<u8>>(
1012			&root,
1013			&proof,
1014			&[(non_included_key.clone(), None)],
1015		)
1016		.is_ok());
1017
1018		// Verifying that the K was included into the trie should fail.
1019		assert!(verify_trie_proof::<LayoutV1, _, _, Vec<u8>>(
1020			&root,
1021			&proof,
1022			&[(non_included_key, Some(array_bytes::hex2bytes_unchecked("1010")))],
1023		)
1024		.is_err());
1025	}
1026
1027	#[test]
1028	fn proof_inclusion_works() {
1029		let pairs = vec![
1030			(array_bytes::hex2bytes_unchecked("0102"), array_bytes::hex2bytes_unchecked("01")),
1031			(array_bytes::hex2bytes_unchecked("0203"), array_bytes::hex2bytes_unchecked("0405")),
1032		];
1033
1034		let mut memdb = MemoryDB::default();
1035		let mut root = Default::default();
1036		populate_trie::<LayoutV1>(&mut memdb, &mut root, &pairs);
1037
1038		let proof =
1039			generate_trie_proof::<LayoutV1, _, _, _>(&memdb, root, &[pairs[0].0.clone()]).unwrap();
1040
1041		// Check that a K, V included into the proof are verified.
1042		assert!(verify_trie_proof::<LayoutV1, _, _, _>(
1043			&root,
1044			&proof,
1045			&[(pairs[0].0.clone(), Some(pairs[0].1.clone()))]
1046		)
1047		.is_ok());
1048
1049		// Absence of the V is not verified with the proof that has K, V included.
1050		assert!(verify_trie_proof::<LayoutV1, _, _, Vec<u8>>(
1051			&root,
1052			&proof,
1053			&[(pairs[0].0.clone(), None)]
1054		)
1055		.is_err());
1056
1057		// K not included into the trie is not verified.
1058		assert!(verify_trie_proof::<LayoutV1, _, _, _>(
1059			&root,
1060			&proof,
1061			&[(array_bytes::hex2bytes_unchecked("4242"), Some(pairs[0].1.clone()))]
1062		)
1063		.is_err());
1064
1065		// K included into the trie but not included into the proof is not verified.
1066		assert!(verify_trie_proof::<LayoutV1, _, _, _>(
1067			&root,
1068			&proof,
1069			&[(pairs[1].0.clone(), Some(pairs[1].1.clone()))]
1070		)
1071		.is_err());
1072	}
1073
1074	#[test]
1075	fn generate_storage_root_with_proof_works_independently_from_the_delta_order() {
1076		let proof = StorageProof::decode(&mut &include_bytes!("../test-res/proof")[..]).unwrap();
1077		let storage_root =
1078			sp_core::H256::decode(&mut &include_bytes!("../test-res/storage_root")[..]).unwrap();
1079		// Delta order that is "invalid" so that it would require a different proof.
1080		let invalid_delta = Vec::<(Vec<u8>, Option<Vec<u8>>)>::decode(
1081			&mut &include_bytes!("../test-res/invalid-delta-order")[..],
1082		)
1083		.unwrap();
1084		// Delta order that is "valid"
1085		let valid_delta = Vec::<(Vec<u8>, Option<Vec<u8>>)>::decode(
1086			&mut &include_bytes!("../test-res/valid-delta-order")[..],
1087		)
1088		.unwrap();
1089
1090		let proof_db = proof.into_memory_db::<Blake2Hasher>();
1091		let first_storage_root = delta_trie_root::<LayoutV0, _, _, _, _, _>(
1092			&mut proof_db.clone(),
1093			storage_root,
1094			valid_delta,
1095			None,
1096			None,
1097		)
1098		.unwrap();
1099		let second_storage_root = delta_trie_root::<LayoutV0, _, _, _, _, _>(
1100			&mut proof_db.clone(),
1101			storage_root,
1102			invalid_delta,
1103			None,
1104			None,
1105		)
1106		.unwrap();
1107
1108		assert_eq!(first_storage_root, second_storage_root);
1109	}
1110
1111	#[test]
1112	fn big_key() {
1113		let check = |keysize: usize| {
1114			let mut memdb = PrefixedMemoryDB::<Blake2Hasher>::default();
1115			let mut root = Default::default();
1116			let mut t = TrieDBMutBuilder::<LayoutV1>::new(&mut memdb, &mut root).build();
1117			t.insert(&vec![0x01u8; keysize][..], &[0x01u8, 0x23]).unwrap();
1118			std::mem::drop(t);
1119			let t = TrieDBBuilder::<LayoutV1>::new(&memdb, &root).build();
1120			assert_eq!(t.get(&vec![0x01u8; keysize][..]).unwrap(), Some(vec![0x01u8, 0x23]));
1121		};
1122		check(u16::MAX as usize / 2); // old limit
1123		check(u16::MAX as usize / 2 + 1); // value over old limit still works
1124	}
1125
1126	#[test]
1127	fn node_with_no_children_fail_decoding() {
1128		let branch = NodeCodec::<Blake2Hasher>::branch_node_nibbled(
1129			b"some_partial".iter().copied(),
1130			24,
1131			vec![None; 16].into_iter(),
1132			Some(trie_db::node::Value::Inline(b"value"[..].into())),
1133		);
1134		assert!(NodeCodec::<Blake2Hasher>::decode(branch.as_slice()).is_err());
1135	}
1136}