tp_trie/
lib.rs

1// This file is part of Tetcore.
2
3// Copyright (C) 2015-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
18//! Utility functions to interact with Tetcore's Base-16 Modified Merkle Patricia tree ("trie").
19
20#![cfg_attr(not(feature = "std"), no_std)]
21
22mod error;
23mod node_header;
24mod node_codec;
25mod storage_proof;
26mod trie_stream;
27
28use tetcore_std::{boxed::Box, marker::PhantomData, vec::Vec, borrow::Borrow};
29use tetsy_hash_db::{Hasher, Prefix};
30use tetsy_trie_db::proof::{generate_proof, verify_proof};
31pub use tetsy_trie_db::proof::VerifyError;
32/// Our `NodeCodec`-specific error.
33pub use error::Error;
34/// The Tetcore format implementation of `TrieStream`.
35pub use trie_stream::TrieStream;
36/// The Tetcore format implementation of `NodeCodec`.
37pub use node_codec::NodeCodec;
38pub use storage_proof::StorageProof;
39/// Various re-exports from the `tetsy-trie-db` crate.
40pub use tetsy_trie_db::{
41	Trie, TrieMut, DBValue, Recorder, CError, Query, TrieLayout, TrieConfiguration, nibble_ops, TrieDBIterator,
42};
43/// Various re-exports from the `memory-db` crate.
44pub use tetsy_memory_db::KeyFunction;
45pub use tetsy_memory_db::prefixed_key;
46/// Various re-exports from the `tetsy-hash-db` crate.
47pub use tetsy_hash_db::{HashDB as HashDBT, EMPTY_PREFIX};
48
49#[derive(Default)]
50/// tetcore trie layout
51pub struct Layout<H>(tetcore_std::marker::PhantomData<H>);
52
53impl<H: Hasher> TrieLayout for Layout<H> {
54	const USE_EXTENSION: bool = false;
55	const ALLOW_EMPTY: bool = true;
56	type Hash = H;
57	type Codec = NodeCodec<Self::Hash>;
58}
59
60impl<H: Hasher> TrieConfiguration for Layout<H> {
61	fn tetsy_trie_root<I, A, B>(input: I) -> <Self::Hash as Hasher>::Out where
62		I: IntoIterator<Item = (A, B)>,
63		A: AsRef<[u8]> + Ord,
64		B: AsRef<[u8]>,
65	{
66		tetsy_trie_root::tetsy_trie_root_no_extension::<H, TrieStream, _, _, _>(input)
67	}
68
69	fn tetsy_trie_root_unhashed<I, A, B>(input: I) -> Vec<u8> where
70		I: IntoIterator<Item = (A, B)>,
71		A: AsRef<[u8]> + Ord,
72		B: AsRef<[u8]>,
73	{
74		tetsy_trie_root::unhashed_trie_no_extension::<H, TrieStream, _, _, _>(input)
75	}
76
77	fn encode_index(input: u32) -> Vec<u8> {
78		codec::Encode::encode(&codec::Compact(input))
79	}
80}
81
82#[cfg(not(feature = "memory-tracker"))]
83type MemTracker = tetsy_memory_db::NoopTracker<tetsy_trie_db::DBValue>;
84#[cfg(feature = "memory-tracker")]
85type MemTracker = tetsy_memory_db::MemCounter<tetsy_trie_db::DBValue>;
86
87/// TrieDB error over `TrieConfiguration` trait.
88pub type TrieError<L> = tetsy_trie_db::TrieError<TrieHash<L>, CError<L>>;
89/// Reexport from `hash_db`, with genericity set for `Hasher` trait.
90pub trait AsHashDB<H: Hasher>: tetsy_hash_db::AsHashDB<H, tetsy_trie_db::DBValue> {}
91impl<H: Hasher, T: tetsy_hash_db::AsHashDB<H, tetsy_trie_db::DBValue>> AsHashDB<H> for T {}
92/// Reexport from `hash_db`, with genericity set for `Hasher` trait.
93pub type HashDB<'a, H> = dyn tetsy_hash_db::HashDB<H, tetsy_trie_db::DBValue> + 'a;
94/// Reexport from `hash_db`, with genericity set for `Hasher` trait.
95/// This uses a `KeyFunction` for prefixing keys internally (avoiding
96/// key conflict for non random keys).
97pub type PrefixedMemoryDB<H> = tetsy_memory_db::MemoryDB<
98	H, tetsy_memory_db::PrefixedKey<H>, tetsy_trie_db::DBValue, MemTracker
99>;
100/// Reexport from `hash_db`, with genericity set for `Hasher` trait.
101/// This uses a noops `KeyFunction` (key addressing must be hashed or using
102/// an encoding scheme that avoid key conflict).
103pub type MemoryDB<H> = tetsy_memory_db::MemoryDB<
104	H, tetsy_memory_db::HashKey<H>, tetsy_trie_db::DBValue, MemTracker,
105>;
106/// Reexport from `hash_db`, with genericity set for `Hasher` trait.
107pub type GenericMemoryDB<H, KF> = tetsy_memory_db::MemoryDB<
108	H, KF, tetsy_trie_db::DBValue, MemTracker
109>;
110
111/// Persistent trie database read-access interface for the a given hasher.
112pub type TrieDB<'a, L> = tetsy_trie_db::TrieDB<'a, L>;
113/// Persistent trie database write-access interface for the a given hasher.
114pub type TrieDBMut<'a, L> = tetsy_trie_db::TrieDBMut<'a, L>;
115/// Querying interface, as in `tetsy_trie_db` but less generic.
116pub type Lookup<'a, L, Q> = tetsy_trie_db::Lookup<'a, L, Q>;
117/// Hash type for a trie layout.
118pub type TrieHash<L> = <<L as TrieLayout>::Hash as Hasher>::Out;
119
120/// This module is for non generic definition of trie type.
121/// Only the `Hasher` trait is generic in this case.
122pub mod trie_types {
123	pub type Layout<H> = super::Layout<H>;
124	/// Persistent trie database read-access interface for the a given hasher.
125	pub type TrieDB<'a, H> = super::TrieDB<'a, Layout<H>>;
126	/// Persistent trie database write-access interface for the a given hasher.
127	pub type TrieDBMut<'a, H> = super::TrieDBMut<'a, Layout<H>>;
128	/// Querying interface, as in `tetsy_trie_db` but less generic.
129	pub type Lookup<'a, H, Q> = tetsy_trie_db::Lookup<'a, Layout<H>, Q>;
130	/// As in `tetsy_trie_db`, but less generic, error type for the crate.
131	pub type TrieError<H> = tetsy_trie_db::TrieError<H, super::Error>;
132}
133
134/// Create a proof for a subset of keys in a trie.
135///
136/// The `keys` may contain any set of keys regardless of each one of them is included
137/// in the `db`.
138///
139/// For a key `K` that is included in the `db` a proof of inclusion is generated.
140/// For a key `K` that is not included in the `db` a proof of non-inclusion is generated.
141/// These can be later checked in `verify_trie_proof`.
142pub fn generate_trie_proof<'a, L: TrieConfiguration, I, K, DB>(
143	db: &DB,
144	root: TrieHash<L>,
145	keys: I,
146) -> Result<Vec<Vec<u8>>, Box<TrieError<L>>> where
147	I: IntoIterator<Item=&'a K>,
148	K: 'a + AsRef<[u8]>,
149	DB: tetsy_hash_db::HashDBRef<L::Hash, tetsy_trie_db::DBValue>,
150{
151	let trie = TrieDB::<L>::new(db, &root)?;
152	generate_proof(&trie, keys)
153}
154
155/// Verify a set of key-value pairs against a trie root and a proof.
156///
157/// Checks a set of keys with optional values for inclusion in the proof that was generated by
158/// `generate_trie_proof`.
159/// If the value in the pair is supplied (`(key, Some(value))`), this key-value pair will be
160/// checked for inclusion in the proof.
161/// If the value is omitted (`(key, None)`), this key will be checked for non-inclusion in the
162/// proof.
163pub fn verify_trie_proof<'a, L: TrieConfiguration, I, K, V>(
164	root: &TrieHash<L>,
165	proof: &[Vec<u8>],
166	items: I,
167) -> Result<(), VerifyError<TrieHash<L>, error::Error>> where
168	I: IntoIterator<Item=&'a (K, Option<V>)>,
169	K: 'a + AsRef<[u8]>,
170	V: 'a + AsRef<[u8]>,
171{
172	verify_proof::<Layout<L::Hash>, _, _, _>(root, proof, items)
173}
174
175/// Determine a trie root given a hash DB and delta values.
176pub fn delta_trie_root<L: TrieConfiguration, I, A, B, DB, V>(
177	db: &mut DB,
178	mut root: TrieHash<L>,
179	delta: I
180) -> Result<TrieHash<L>, Box<TrieError<L>>> where
181	I: IntoIterator<Item = (A, B)>,
182	A: Borrow<[u8]>,
183	B: Borrow<Option<V>>,
184	V: Borrow<[u8]>,
185	DB: tetsy_hash_db::HashDB<L::Hash, tetsy_trie_db::DBValue>,
186{
187	{
188		let mut trie = TrieDBMut::<L>::from_existing(db, &mut root)?;
189
190		let mut delta = delta.into_iter().collect::<Vec<_>>();
191		delta.sort_by(|l, r| l.0.borrow().cmp(r.0.borrow()));
192
193		for (key, change) in delta {
194			match change.borrow() {
195				Some(val) => trie.insert(key.borrow(), val.borrow())?,
196				None => trie.remove(key.borrow())?,
197			};
198		}
199	}
200
201	Ok(root)
202}
203
204/// Read a value from the trie.
205pub fn read_trie_value<L: TrieConfiguration, DB: tetsy_hash_db::HashDBRef<L::Hash, tetsy_trie_db::DBValue>>(
206	db: &DB,
207	root: &TrieHash<L>,
208	key: &[u8]
209) -> Result<Option<Vec<u8>>, Box<TrieError<L>>> {
210	Ok(TrieDB::<L>::new(&*db, root)?.get(key).map(|x| x.map(|val| val.to_vec()))?)
211}
212
213/// Read a value from the trie with given Query.
214pub fn read_trie_value_with<
215	L: TrieConfiguration,
216	Q: Query<L::Hash, Item=DBValue>,
217	DB: tetsy_hash_db::HashDBRef<L::Hash, tetsy_trie_db::DBValue>
218>(
219	db: &DB,
220	root: &TrieHash<L>,
221	key: &[u8],
222	query: Q
223) -> Result<Option<Vec<u8>>, Box<TrieError<L>>> {
224	Ok(TrieDB::<L>::new(&*db, root)?.get_with(key, query).map(|x| x.map(|val| val.to_vec()))?)
225}
226
227/// Determine the empty trie root.
228pub fn empty_trie_root<L: TrieConfiguration>() -> <L::Hash as Hasher>::Out {
229	L::tetsy_trie_root::<_, Vec<u8>, Vec<u8>>(core::iter::empty())
230}
231
232/// Determine the empty child trie root.
233pub fn empty_child_trie_root<L: TrieConfiguration>() -> <L::Hash as Hasher>::Out {
234	L::tetsy_trie_root::<_, Vec<u8>, Vec<u8>>(core::iter::empty())
235}
236
237/// Determine a child trie root given its ordered contents, closed form. H is the default hasher,
238/// but a generic implementation may ignore this type parameter and use other hashers.
239pub fn child_trie_root<L: TrieConfiguration, I, A, B>(
240	input: I,
241) -> <L::Hash as Hasher>::Out
242	where
243		I: IntoIterator<Item = (A, B)>,
244		A: AsRef<[u8]> + Ord,
245		B: AsRef<[u8]>,
246{
247	L::tetsy_trie_root(input)
248}
249
250/// Determine a child trie root given a hash DB and delta values. H is the default hasher,
251/// but a generic implementation may ignore this type parameter and use other hashers.
252pub fn child_delta_trie_root<L: TrieConfiguration, I, A, B, DB, RD, V>(
253	keyspace: &[u8],
254	db: &mut DB,
255	root_data: RD,
256	delta: I,
257) -> Result<<L::Hash as Hasher>::Out, Box<TrieError<L>>>
258	where
259		I: IntoIterator<Item = (A, B)>,
260		A: Borrow<[u8]>,
261		B: Borrow<Option<V>>,
262		V: Borrow<[u8]>,
263		RD: AsRef<[u8]>,
264		DB: tetsy_hash_db::HashDB<L::Hash, tetsy_trie_db::DBValue>
265{
266	let mut root = TrieHash::<L>::default();
267	// root is fetched from DB, not writable by runtime, so it's always valid.
268	root.as_mut().copy_from_slice(root_data.as_ref());
269
270	let mut db = KeySpacedDBMut::new(&mut *db, keyspace);
271	delta_trie_root::<L, _, _, _, _, _>(
272		&mut db,
273		root,
274		delta,
275	)
276}
277
278/// Call `f` for all keys in a child trie.
279/// Aborts as soon as `f` returns false.
280pub fn for_keys_in_child_trie<L: TrieConfiguration, F: FnMut(&[u8]) -> bool, DB>(
281	keyspace: &[u8],
282	db: &DB,
283	root_slice: &[u8],
284	mut f: F
285) -> Result<(), Box<TrieError<L>>>
286	where
287		DB: tetsy_hash_db::HashDBRef<L::Hash, tetsy_trie_db::DBValue>
288{
289	let mut root = TrieHash::<L>::default();
290	// root is fetched from DB, not writable by runtime, so it's always valid.
291	root.as_mut().copy_from_slice(root_slice);
292
293	let db = KeySpacedDB::new(&*db, keyspace);
294	let trie = TrieDB::<L>::new(&db, &root)?;
295	let iter = trie.iter()?;
296
297	for x in iter {
298		let (key, _) = x?;
299		if !f(&key) {
300			break;
301		}
302	}
303
304	Ok(())
305}
306
307/// Record all keys for a given root.
308pub fn record_all_keys<L: TrieConfiguration, DB>(
309	db: &DB,
310	root: &TrieHash<L>,
311	recorder: &mut Recorder<TrieHash<L>>
312) -> Result<(), Box<TrieError<L>>> where
313	DB: tetsy_hash_db::HashDBRef<L::Hash, tetsy_trie_db::DBValue>
314{
315	let trie = TrieDB::<L>::new(&*db, root)?;
316	let iter = trie.iter()?;
317
318	for x in iter {
319		let (key, _) = x?;
320
321		// there's currently no API like iter_with()
322		// => use iter to enumerate all keys AND lookup each
323		// key using get_with
324		trie.get_with(&key, &mut *recorder)?;
325	}
326
327	Ok(())
328}
329
330/// Read a value from the child trie.
331pub fn read_child_trie_value<L: TrieConfiguration, DB>(
332	keyspace: &[u8],
333	db: &DB,
334	root_slice: &[u8],
335	key: &[u8]
336) -> Result<Option<Vec<u8>>, Box<TrieError<L>>>
337	where
338		DB: tetsy_hash_db::HashDBRef<L::Hash, tetsy_trie_db::DBValue>
339{
340	let mut root = TrieHash::<L>::default();
341	// root is fetched from DB, not writable by runtime, so it's always valid.
342	root.as_mut().copy_from_slice(root_slice);
343
344	let db = KeySpacedDB::new(&*db, keyspace);
345	Ok(TrieDB::<L>::new(&db, &root)?.get(key).map(|x| x.map(|val| val.to_vec()))?)
346}
347
348/// Read a value from the child trie with given query.
349pub fn read_child_trie_value_with<L: TrieConfiguration, Q: Query<L::Hash, Item=DBValue>, DB>(
350	keyspace: &[u8],
351	db: &DB,
352	root_slice: &[u8],
353	key: &[u8],
354	query: Q
355) -> Result<Option<Vec<u8>>, Box<TrieError<L>>>
356	where
357		DB: tetsy_hash_db::HashDBRef<L::Hash, tetsy_trie_db::DBValue>
358{
359	let mut root = TrieHash::<L>::default();
360	// root is fetched from DB, not writable by runtime, so it's always valid.
361	root.as_mut().copy_from_slice(root_slice);
362
363	let db = KeySpacedDB::new(&*db, keyspace);
364	Ok(TrieDB::<L>::new(&db, &root)?.get_with(key, query).map(|x| x.map(|val| val.to_vec()))?)
365}
366
367/// `HashDB` implementation that append a encoded prefix (unique id bytes) in addition to the
368/// prefix of every key value.
369pub struct KeySpacedDB<'a, DB, H>(&'a DB, &'a [u8], PhantomData<H>);
370
371/// `HashDBMut` implementation that append a encoded prefix (unique id bytes) in addition to the
372/// prefix of every key value.
373///
374/// Mutable variant of `KeySpacedDB`, see [`KeySpacedDB`].
375pub struct KeySpacedDBMut<'a, DB, H>(&'a mut DB, &'a [u8], PhantomData<H>);
376
377/// Utility function used to merge some byte data (keyspace) and `prefix` data
378/// before calling key value database primitives.
379fn keyspace_as_prefix_alloc(ks: &[u8], prefix: Prefix) -> (Vec<u8>, Option<u8>) {
380	let mut result = tetcore_std::vec![0; ks.len() + prefix.0.len()];
381	result[..ks.len()].copy_from_slice(ks);
382	result[ks.len()..].copy_from_slice(prefix.0);
383	(result, prefix.1)
384}
385
386impl<'a, DB, H> KeySpacedDB<'a, DB, H> where
387	H: Hasher,
388{
389	/// instantiate new keyspaced db
390	pub fn new(db: &'a DB, ks: &'a [u8]) -> Self {
391		KeySpacedDB(db, ks, PhantomData)
392	}
393}
394
395impl<'a, DB, H> KeySpacedDBMut<'a, DB, H> where
396	H: Hasher,
397{
398	/// instantiate new keyspaced db
399	pub fn new(db: &'a mut DB, ks: &'a [u8]) -> Self {
400		KeySpacedDBMut(db, ks, PhantomData)
401	}
402}
403
404impl<'a, DB, H, T> tetsy_hash_db::HashDBRef<H, T> for KeySpacedDB<'a, DB, H> where
405	DB: tetsy_hash_db::HashDBRef<H, T>,
406	H: Hasher,
407	T: From<&'static [u8]>,
408{
409	fn get(&self, key: &H::Out, prefix: Prefix) -> Option<T> {
410		let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
411		self.0.get(key, (&derived_prefix.0, derived_prefix.1))
412	}
413
414	fn contains(&self, key: &H::Out, prefix: Prefix) -> bool {
415		let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
416		self.0.contains(key, (&derived_prefix.0, derived_prefix.1))
417	}
418}
419
420impl<'a, DB, H, T> tetsy_hash_db::HashDB<H, T> for KeySpacedDBMut<'a, DB, H> where
421	DB: tetsy_hash_db::HashDB<H, T>,
422	H: Hasher,
423	T: Default + PartialEq<T> + for<'b> From<&'b [u8]> + Clone + Send + Sync,
424{
425	fn get(&self, key: &H::Out, prefix: Prefix) -> Option<T> {
426		let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
427		self.0.get(key, (&derived_prefix.0, derived_prefix.1))
428	}
429
430	fn contains(&self, key: &H::Out, prefix: Prefix) -> bool {
431		let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
432		self.0.contains(key, (&derived_prefix.0, derived_prefix.1))
433	}
434
435	fn insert(&mut self, prefix: Prefix, value: &[u8]) -> H::Out {
436		let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
437		self.0.insert((&derived_prefix.0, derived_prefix.1), value)
438	}
439
440	fn emplace(&mut self, key: H::Out, prefix: Prefix, value: T) {
441		let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
442		self.0.emplace(key, (&derived_prefix.0, derived_prefix.1), value)
443	}
444
445	fn remove(&mut self, key: &H::Out, prefix: Prefix) {
446		let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
447		self.0.remove(key, (&derived_prefix.0, derived_prefix.1))
448	}
449}
450
451impl<'a, DB, H, T> tetsy_hash_db::AsHashDB<H, T> for KeySpacedDBMut<'a, DB, H> where
452	DB: tetsy_hash_db::HashDB<H, T>,
453	H: Hasher,
454	T: Default + PartialEq<T> + for<'b> From<&'b [u8]> + Clone + Send + Sync,
455{
456	fn as_hash_db(&self) -> &dyn tetsy_hash_db::HashDB<H, T> { &*self }
457
458	fn as_hash_db_mut<'b>(&'b mut self) -> &'b mut (dyn tetsy_hash_db::HashDB<H, T> + 'b) {
459		&mut *self
460	}
461}
462
463/// Constants used into trie simplification codec.
464mod trie_constants {
465	pub const EMPTY_TRIE: u8 = 0;
466	pub const NIBBLE_SIZE_BOUND: usize = u16::max_value() as usize;
467	pub const LEAF_PREFIX_MASK: u8 = 0b_01 << 6;
468	pub const BRANCH_WITHOUT_MASK: u8 = 0b_10 << 6;
469	pub const BRANCH_WITH_MASK: u8 = 0b_11 << 6;
470}
471
472#[cfg(test)]
473mod tests {
474	use super::*;
475	use codec::{Encode, Decode, Compact};
476	use tet_core::Blake2Hasher;
477	use tetsy_hash_db::{HashDB, Hasher};
478	use tetsy_trie_db::{DBValue, TrieMut, Trie, NodeCodec as NodeCodecT};
479	use tetsy_trie_standardmap::{Alphabet, ValueMode, StandardMap};
480	use hex_literal::hex;
481
482	type Layout = super::Layout<Blake2Hasher>;
483
484	fn hashed_null_node<T: TrieConfiguration>() -> TrieHash<T> {
485		<T::Codec as NodeCodecT>::hashed_null_node()
486	}
487
488	fn check_equivalent<T: TrieConfiguration>(input: &Vec<(&[u8], &[u8])>) {
489		{
490			let closed_form = T::tetsy_trie_root(input.clone());
491			let d = T::tetsy_trie_root_unhashed(input.clone());
492			println!("Data: {:#x?}, {:#x?}", d, Blake2Hasher::hash(&d[..]));
493			let persistent = {
494				let mut memdb = MemoryDB::default();
495				let mut root = Default::default();
496				let mut t = TrieDBMut::<T>::new(&mut memdb, &mut root);
497				for (x, y) in input.iter().rev() {
498					t.insert(x, y).unwrap();
499				}
500				t.root().clone()
501			};
502			assert_eq!(closed_form, persistent);
503		}
504	}
505
506	fn check_iteration<T: TrieConfiguration>(input: &Vec<(&[u8], &[u8])>) {
507		let mut memdb = MemoryDB::default();
508		let mut root = Default::default();
509		{
510			let mut t = TrieDBMut::<T>::new(&mut memdb, &mut root);
511			for (x, y) in input.clone() {
512				t.insert(x, y).unwrap();
513			}
514		}
515		{
516			let t = TrieDB::<T>::new(&mut memdb, &root).unwrap();
517			assert_eq!(
518				input.iter().map(|(i, j)| (i.to_vec(), j.to_vec())).collect::<Vec<_>>(),
519				t.iter().unwrap()
520					.map(|x| x.map(|y| (y.0, y.1.to_vec())).unwrap())
521					.collect::<Vec<_>>()
522			);
523		}
524	}
525
526	#[test]
527	fn default_trie_root() {
528		let mut db = MemoryDB::default();
529		let mut root = TrieHash::<Layout>::default();
530		let mut empty = TrieDBMut::<Layout>::new(&mut db, &mut root);
531		empty.commit();
532		let root1 = empty.root().as_ref().to_vec();
533		let root2: Vec<u8> = Layout::tetsy_trie_root::<_, Vec<u8>, Vec<u8>>(
534			std::iter::empty(),
535		).as_ref().iter().cloned().collect();
536
537		assert_eq!(root1, root2);
538	}
539
540	#[test]
541	fn empty_is_equivalent() {
542		let input: Vec<(&[u8], &[u8])> = vec![];
543		check_equivalent::<Layout>(&input);
544		check_iteration::<Layout>(&input);
545	}
546
547	#[test]
548	fn leaf_is_equivalent() {
549		let input: Vec<(&[u8], &[u8])> = vec![(&[0xaa][..], &[0xbb][..])];
550		check_equivalent::<Layout>(&input);
551		check_iteration::<Layout>(&input);
552	}
553
554	#[test]
555	fn branch_is_equivalent() {
556		let input: Vec<(&[u8], &[u8])> = vec![
557			(&[0xaa][..], &[0x10][..]),
558			(&[0xba][..], &[0x11][..]),
559		];
560		check_equivalent::<Layout>(&input);
561		check_iteration::<Layout>(&input);
562	}
563
564	#[test]
565	fn extension_and_branch_is_equivalent() {
566		let input: Vec<(&[u8], &[u8])> = vec![
567			(&[0xaa][..], &[0x10][..]),
568			(&[0xab][..], &[0x11][..]),
569		];
570		check_equivalent::<Layout>(&input);
571		check_iteration::<Layout>(&input);
572	}
573
574	#[test]
575	fn standard_is_equivalent() {
576		let st = StandardMap {
577			alphabet: Alphabet::All,
578			min_key: 32,
579			journal_key: 0,
580			value_mode: ValueMode::Random,
581			count: 1000,
582		};
583		let mut d = st.make();
584		d.sort_by(|&(ref a, _), &(ref b, _)| a.cmp(b));
585		let dr = d.iter().map(|v| (&v.0[..], &v.1[..])).collect();
586		check_equivalent::<Layout>(&dr);
587		check_iteration::<Layout>(&dr);
588	}
589
590	#[test]
591	fn extension_and_branch_with_value_is_equivalent() {
592		let input: Vec<(&[u8], &[u8])> = vec![
593			(&[0xaa][..], &[0xa0][..]),
594			(&[0xaa, 0xaa][..], &[0xaa][..]),
595			(&[0xaa, 0xbb][..], &[0xab][..])
596		];
597		check_equivalent::<Layout>(&input);
598		check_iteration::<Layout>(&input);
599	}
600
601	#[test]
602	fn bigger_extension_and_branch_with_value_is_equivalent() {
603		let input: Vec<(&[u8], &[u8])> = vec![
604			(&[0xaa][..], &[0xa0][..]),
605			(&[0xaa, 0xaa][..], &[0xaa][..]),
606			(&[0xaa, 0xbb][..], &[0xab][..]),
607			(&[0xbb][..], &[0xb0][..]),
608			(&[0xbb, 0xbb][..], &[0xbb][..]),
609			(&[0xbb, 0xcc][..], &[0xbc][..]),
610		];
611		check_equivalent::<Layout>(&input);
612		check_iteration::<Layout>(&input);
613	}
614
615	#[test]
616	fn single_long_leaf_is_equivalent() {
617		let input: Vec<(&[u8], &[u8])> = vec![
618			(&[0xaa][..], &b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..]),
619			(&[0xba][..], &[0x11][..]),
620		];
621		check_equivalent::<Layout>(&input);
622		check_iteration::<Layout>(&input);
623	}
624
625	#[test]
626	fn two_long_leaves_is_equivalent() {
627		let input: Vec<(&[u8], &[u8])> = vec![
628			(&[0xaa][..], &b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..]),
629			(&[0xba][..], &b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..])
630		];
631		check_equivalent::<Layout>(&input);
632		check_iteration::<Layout>(&input);
633	}
634
635	fn populate_trie<'db, T: TrieConfiguration>(
636		db: &'db mut dyn HashDB<T::Hash, DBValue>,
637		root: &'db mut TrieHash<T>,
638		v: &[(Vec<u8>, Vec<u8>)]
639	) -> TrieDBMut<'db, T> {
640		let mut t = TrieDBMut::<T>::new(db, root);
641		for i in 0..v.len() {
642			let key: &[u8]= &v[i].0;
643			let val: &[u8] = &v[i].1;
644			t.insert(key, val).unwrap();
645		}
646		t
647	}
648
649	fn unpopulate_trie<'db, T: TrieConfiguration>(
650		t: &mut TrieDBMut<'db, T>,
651		v: &[(Vec<u8>, Vec<u8>)],
652	) {
653		for i in v {
654			let key: &[u8]= &i.0;
655			t.remove(key).unwrap();
656		}
657	}
658
659	#[test]
660	fn random_should_work() {
661		let mut seed = <Blake2Hasher as Hasher>::Out::zero();
662		for test_i in 0..10000 {
663			if test_i % 50 == 0 {
664				println!("{:?} of 10000 stress tests done", test_i);
665			}
666			let x = StandardMap {
667				alphabet: Alphabet::Custom(b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_".to_vec()),
668				min_key: 5,
669				journal_key: 0,
670				value_mode: ValueMode::Index,
671				count: 100,
672			}.make_with(seed.as_fixed_bytes_mut());
673
674			let real = Layout::tetsy_trie_root(x.clone());
675			let mut memdb = MemoryDB::default();
676			let mut root = Default::default();
677			let mut memtrie = populate_trie::<Layout>(&mut memdb, &mut root, &x);
678
679			memtrie.commit();
680			if *memtrie.root() != real {
681				println!("TRIE MISMATCH");
682				println!("");
683				println!("{:?} vs {:?}", memtrie.root(), real);
684				for i in &x {
685					println!("{:#x?} -> {:#x?}", i.0, i.1);
686				}
687			}
688			assert_eq!(*memtrie.root(), real);
689			unpopulate_trie::<Layout>(&mut memtrie, &x);
690			memtrie.commit();
691			let hashed_null_node = hashed_null_node::<Layout>();
692			if *memtrie.root() != hashed_null_node {
693				println!("- TRIE MISMATCH");
694				println!("");
695				println!("{:?} vs {:?}", memtrie.root(), hashed_null_node);
696				for i in &x {
697					println!("{:#x?} -> {:#x?}", i.0, i.1);
698				}
699			}
700			assert_eq!(*memtrie.root(), hashed_null_node);
701		}
702	}
703
704	fn to_compact(n: u8) -> u8 {
705		Compact(n).encode()[0]
706	}
707
708	#[test]
709	fn codec_trie_empty() {
710		let input: Vec<(&[u8], &[u8])> = vec![];
711		let trie = Layout::tetsy_trie_root_unhashed::<_, _, _>(input);
712		println!("trie: {:#x?}", trie);
713		assert_eq!(trie, vec![0x0]);
714	}
715
716	#[test]
717	fn codec_trie_single_tuple() {
718		let input = vec![
719			(vec![0xaa], vec![0xbb])
720		];
721		let trie = Layout::tetsy_trie_root_unhashed::<_, _, _>(input);
722		println!("trie: {:#x?}", trie);
723		assert_eq!(trie, vec![
724			0x42,					// leaf 0x40 (2^6) with (+) key of 2 nibbles (0x02)
725			0xaa,					// key data
726			to_compact(1),			// length of value in bytes as Compact
727			0xbb					// value data
728		]);
729	}
730
731	#[test]
732	fn codec_trie_two_tuples_disjoint_keys() {
733		let input = vec![(&[0x48, 0x19], &[0xfe]), (&[0x13, 0x14], &[0xff])];
734		let trie = Layout::tetsy_trie_root_unhashed::<_, _, _>(input);
735		println!("trie: {:#x?}", trie);
736		let mut ex = Vec::<u8>::new();
737		ex.push(0x80);									// branch, no value (0b_10..) no nibble
738		ex.push(0x12);									// slots 1 & 4 are taken from 0-7
739		ex.push(0x00);									// no slots from 8-15
740		ex.push(to_compact(0x05));						// first slot: LEAF, 5 bytes long.
741		ex.push(0x43);									// leaf 0x40 with 3 nibbles
742		ex.push(0x03);									// first nibble
743		ex.push(0x14);									// second & third nibble
744		ex.push(to_compact(0x01));						// 1 byte data
745		ex.push(0xff);									// value data
746		ex.push(to_compact(0x05));						// second slot: LEAF, 5 bytes long.
747		ex.push(0x43);									// leaf with 3 nibbles
748		ex.push(0x08);									// first nibble
749		ex.push(0x19);									// second & third nibble
750		ex.push(to_compact(0x01));						// 1 byte data
751		ex.push(0xfe);									// value data
752
753		assert_eq!(trie, ex);
754	}
755
756	#[test]
757	fn iterator_works() {
758		let pairs = vec![
759			(hex!("0103000000000000000464").to_vec(), hex!("0400000000").to_vec()),
760			(hex!("0103000000000000000469").to_vec(), hex!("0401000000").to_vec()),
761		];
762
763		let mut mdb = MemoryDB::default();
764		let mut root = Default::default();
765		let _ = populate_trie::<Layout>(&mut mdb, &mut root, &pairs);
766
767		let trie = TrieDB::<Layout>::new(&mdb, &root).unwrap();
768
769		let iter = trie.iter().unwrap();
770		let mut iter_pairs = Vec::new();
771		for pair in iter {
772			let (key, value) = pair.unwrap();
773			iter_pairs.push((key, value.to_vec()));
774		}
775
776		assert_eq!(pairs, iter_pairs);
777	}
778
779	#[test]
780	fn proof_non_inclusion_works() {
781		let pairs = vec![
782			(hex!("0102").to_vec(), hex!("01").to_vec()),
783			(hex!("0203").to_vec(), hex!("0405").to_vec()),
784		];
785
786		let mut memdb = MemoryDB::default();
787		let mut root = Default::default();
788		populate_trie::<Layout>(&mut memdb, &mut root, &pairs);
789
790		let non_included_key: Vec<u8> = hex!("0909").to_vec();
791		let proof = generate_trie_proof::<Layout, _, _, _>(
792			&memdb,
793			root,
794			&[non_included_key.clone()]
795		).unwrap();
796
797		// Verifying that the K was not included into the trie should work.
798		assert!(verify_trie_proof::<Layout, _, _, Vec<u8>>(
799				&root,
800				&proof,
801				&[(non_included_key.clone(), None)],
802			).is_ok()
803		);
804
805		// Verifying that the K was included into the trie should fail.
806		assert!(verify_trie_proof::<Layout, _, _, Vec<u8>>(
807				&root,
808				&proof,
809				&[(non_included_key, Some(hex!("1010").to_vec()))],
810			).is_err()
811		);
812	}
813
814	#[test]
815	fn proof_inclusion_works() {
816		let pairs = vec![
817			(hex!("0102").to_vec(), hex!("01").to_vec()),
818			(hex!("0203").to_vec(), hex!("0405").to_vec()),
819		];
820
821		let mut memdb = MemoryDB::default();
822		let mut root = Default::default();
823		populate_trie::<Layout>(&mut memdb, &mut root, &pairs);
824
825		let proof = generate_trie_proof::<Layout, _, _, _>(
826			&memdb,
827			root,
828			&[pairs[0].0.clone()]
829		).unwrap();
830
831		// Check that a K, V included into the proof are verified.
832		assert!(verify_trie_proof::<Layout, _, _, _>(
833				&root,
834				&proof,
835				&[(pairs[0].0.clone(), Some(pairs[0].1.clone()))]
836			).is_ok()
837		);
838
839		// Absence of the V is not verified with the proof that has K, V included.
840		assert!(verify_trie_proof::<Layout, _, _, Vec<u8>>(
841				&root,
842				&proof,
843				&[(pairs[0].0.clone(), None)]
844			).is_err()
845		);
846
847		// K not included into the trie is not verified.
848		assert!(verify_trie_proof::<Layout, _, _, _>(
849				&root,
850				&proof,
851				&[(hex!("4242").to_vec(), Some(pairs[0].1.clone()))]
852			).is_err()
853		);
854
855		// K included into the trie but not included into the proof is not verified.
856		assert!(verify_trie_proof::<Layout, _, _, _>(
857				&root,
858				&proof,
859				&[(pairs[1].0.clone(), Some(pairs[1].1.clone()))]
860			).is_err()
861		);
862	}
863
864	#[test]
865	fn generate_storage_root_with_proof_works_independently_from_the_delta_order() {
866		let proof = StorageProof::decode(&mut &include_bytes!("../test-res/proof")[..]).unwrap();
867		let storage_root = tet_core::H256::decode(
868			&mut &include_bytes!("../test-res/storage_root")[..],
869		).unwrap();
870		// Delta order that is "invalid" so that it would require a different proof.
871		let invalid_delta = Vec::<(Vec<u8>, Option<Vec<u8>>)>::decode(
872			&mut &include_bytes!("../test-res/invalid-delta-order")[..],
873		).unwrap();
874		// Delta order that is "valid"
875		let valid_delta = Vec::<(Vec<u8>, Option<Vec<u8>>)>::decode(
876			&mut &include_bytes!("../test-res/valid-delta-order")[..],
877		).unwrap();
878
879		let proof_db = proof.into_memory_db::<Blake2Hasher>();
880		let first_storage_root = delta_trie_root::<Layout, _, _, _, _, _>(
881			&mut proof_db.clone(),
882			storage_root,
883			valid_delta,
884		).unwrap();
885		let second_storage_root = delta_trie_root::<Layout, _, _, _, _, _>(
886			&mut proof_db.clone(),
887			storage_root,
888			invalid_delta,
889		).unwrap();
890
891		assert_eq!(first_storage_root, second_storage_root);
892	}
893}