1#![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;
28mod node_codec;
29mod node_header;
30#[cfg(feature = "std")]
31pub mod recorder;
32pub mod recorder_ext;
33mod storage_proof;
34mod trie_codec;
35mod trie_stream;
36
37#[cfg(feature = "std")]
38pub mod proof_size_extension;
39
40use alloc::{borrow::Borrow, boxed::Box, vec, vec::Vec};
41use core::marker::PhantomData;
42pub use error::Error;
44pub use hash_db::{HashDB as HashDBT, EMPTY_PREFIX};
46use hash_db::{Hasher, Prefix};
47pub use memory_db::{prefixed_key, HashKey, KeyFunction, PrefixedKey};
49pub use node_codec::NodeCodec;
51pub use storage_proof::{CompactProof, StorageProof, StorageProofError};
52pub use trie_codec::{decode_compact, encode_compact, Error as CompactProofError};
55use trie_db::proof::{generate_proof, verify_proof};
56pub use trie_db::{
58 nibble_ops,
59 node::{NodePlan, ValuePlan},
60 triedb::{TrieDBDoubleEndedIterator, TrieDBKeyDoubleEndedIterator},
61 CError, DBValue, Query, Recorder, Trie, TrieCache, TrieConfiguration, TrieDBIterator,
62 TrieDBKeyIterator, TrieDBNodeDoubleEndedIterator, TrieDBRawIterator, TrieLayout, TrieMut,
63 TrieRecorder,
64};
65pub use trie_db::{proof::VerifyError, MerkleValue};
66pub use trie_stream::TrieStream;
68
69pub type RawStorageProof = Vec<Vec<u8>>;
71
72pub struct LayoutV0<H>(PhantomData<H>);
74
75pub struct LayoutV1<H>(PhantomData<H>);
77
78impl<H> TrieLayout for LayoutV0<H>
79where
80 H: Hasher,
81{
82 const USE_EXTENSION: bool = false;
83 const ALLOW_EMPTY: bool = true;
84 const MAX_INLINE_VALUE: Option<u32> = None;
85
86 type Hash = H;
87 type Codec = NodeCodec<Self::Hash>;
88}
89
90impl<H> TrieConfiguration for LayoutV0<H>
91where
92 H: Hasher,
93{
94 fn trie_root<I, A, B>(input: I) -> <Self::Hash as Hasher>::Out
95 where
96 I: IntoIterator<Item = (A, B)>,
97 A: AsRef<[u8]> + Ord,
98 B: AsRef<[u8]>,
99 {
100 trie_root::trie_root_no_extension::<H, TrieStream, _, _, _>(input, Self::MAX_INLINE_VALUE)
101 }
102
103 fn trie_root_unhashed<I, A, B>(input: I) -> Vec<u8>
104 where
105 I: IntoIterator<Item = (A, B)>,
106 A: AsRef<[u8]> + Ord,
107 B: AsRef<[u8]>,
108 {
109 trie_root::unhashed_trie_no_extension::<H, TrieStream, _, _, _>(
110 input,
111 Self::MAX_INLINE_VALUE,
112 )
113 }
114
115 fn encode_index(input: u32) -> Vec<u8> {
116 codec::Encode::encode(&codec::Compact(input))
117 }
118}
119
120impl<H> TrieLayout for LayoutV1<H>
121where
122 H: Hasher,
123{
124 const USE_EXTENSION: bool = false;
125 const ALLOW_EMPTY: bool = true;
126 const MAX_INLINE_VALUE: Option<u32> = Some(sp_core::storage::TRIE_VALUE_NODE_THRESHOLD);
127
128 type Hash = H;
129 type Codec = NodeCodec<Self::Hash>;
130}
131
132impl<H> TrieConfiguration for LayoutV1<H>
133where
134 H: Hasher,
135{
136 fn trie_root<I, A, B>(input: I) -> <Self::Hash as Hasher>::Out
137 where
138 I: IntoIterator<Item = (A, B)>,
139 A: AsRef<[u8]> + Ord,
140 B: AsRef<[u8]>,
141 {
142 trie_root::trie_root_no_extension::<H, TrieStream, _, _, _>(input, Self::MAX_INLINE_VALUE)
143 }
144
145 fn trie_root_unhashed<I, A, B>(input: I) -> Vec<u8>
146 where
147 I: IntoIterator<Item = (A, B)>,
148 A: AsRef<[u8]> + Ord,
149 B: AsRef<[u8]>,
150 {
151 trie_root::unhashed_trie_no_extension::<H, TrieStream, _, _, _>(
152 input,
153 Self::MAX_INLINE_VALUE,
154 )
155 }
156
157 fn encode_index(input: u32) -> Vec<u8> {
158 codec::Encode::encode(&codec::Compact(input))
159 }
160}
161
162pub trait TrieRecorderProvider<H: Hasher> {
167 type Recorder<'a>: trie_db::TrieRecorder<H::Out> + 'a
169 where
170 Self: 'a;
171
172 fn drain_storage_proof(self) -> Option<StorageProof>;
174
175 fn as_trie_recorder(&self, storage_root: H::Out) -> Self::Recorder<'_>;
177}
178
179pub trait ProofSizeProvider {
181 fn estimate_encoded_size(&self) -> usize;
183}
184
185pub type TrieError<L> = trie_db::TrieError<TrieHash<L>, CError<L>>;
187pub trait AsHashDB<H: Hasher>: hash_db::AsHashDB<H, trie_db::DBValue> {}
189impl<H: Hasher, T: hash_db::AsHashDB<H, trie_db::DBValue>> AsHashDB<H> for T {}
190pub type HashDB<'a, H> = dyn hash_db::HashDB<H, trie_db::DBValue> + 'a;
192pub type PrefixedMemoryDB<H> = memory_db::MemoryDB<H, memory_db::PrefixedKey<H>, trie_db::DBValue>;
196pub type MemoryDB<H> = memory_db::MemoryDB<H, memory_db::HashKey<H>, trie_db::DBValue>;
200pub type GenericMemoryDB<H, KF> = memory_db::MemoryDB<H, KF, trie_db::DBValue>;
202
203pub type TrieDB<'a, 'cache, L> = trie_db::TrieDB<'a, 'cache, L>;
205pub type TrieDBBuilder<'a, 'cache, L> = trie_db::TrieDBBuilder<'a, 'cache, L>;
207pub type TrieDBMut<'a, L> = trie_db::TrieDBMut<'a, L>;
209pub type TrieDBMutBuilder<'a, L> = trie_db::TrieDBMutBuilder<'a, L>;
211pub type Lookup<'a, 'cache, L, Q> = trie_db::Lookup<'a, 'cache, L, Q>;
213pub type TrieHash<L> = <<L as TrieLayout>::Hash as Hasher>::Out;
215pub mod trie_types {
218 use super::*;
219
220 pub type TrieDB<'a, 'cache, H> = super::TrieDB<'a, 'cache, LayoutV1<H>>;
224 pub type TrieDBBuilder<'a, 'cache, H> = super::TrieDBBuilder<'a, 'cache, LayoutV1<H>>;
226 pub type TrieDBMutV0<'a, H> = super::TrieDBMut<'a, LayoutV0<H>>;
228 pub type TrieDBMutBuilderV0<'a, H> = super::TrieDBMutBuilder<'a, LayoutV0<H>>;
230 pub type TrieDBMutV1<'a, H> = super::TrieDBMut<'a, LayoutV1<H>>;
232 pub type TrieDBMutBuilderV1<'a, H> = super::TrieDBMutBuilder<'a, LayoutV1<H>>;
234 pub type Lookup<'a, 'cache, H, Q> = trie_db::Lookup<'a, 'cache, LayoutV1<H>, Q>;
236 pub type TrieError<H> = trie_db::TrieError<H, super::Error<H>>;
238}
239
240pub fn generate_trie_proof<'a, L, I, K, DB>(
249 db: &DB,
250 root: TrieHash<L>,
251 keys: I,
252) -> Result<Vec<Vec<u8>>, Box<TrieError<L>>>
253where
254 L: TrieConfiguration,
255 I: IntoIterator<Item = &'a K>,
256 K: 'a + AsRef<[u8]>,
257 DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
258{
259 generate_proof::<_, L, _, _>(db, &root, keys)
260}
261
262pub fn verify_trie_proof<'a, L, I, K, V>(
271 root: &TrieHash<L>,
272 proof: &[Vec<u8>],
273 items: I,
274) -> Result<(), VerifyError<TrieHash<L>, CError<L>>>
275where
276 L: TrieConfiguration,
277 I: IntoIterator<Item = &'a (K, Option<V>)>,
278 K: 'a + AsRef<[u8]>,
279 V: 'a + AsRef<[u8]>,
280{
281 verify_proof::<L, _, _, _>(root, proof, items)
282}
283
284pub fn delta_trie_root<L: TrieConfiguration, I, A, B, DB, V>(
286 db: &mut DB,
287 mut root: TrieHash<L>,
288 delta: I,
289 recorder: Option<&mut dyn trie_db::TrieRecorder<TrieHash<L>>>,
290 cache: Option<&mut dyn TrieCache<L::Codec>>,
291) -> Result<TrieHash<L>, Box<TrieError<L>>>
292where
293 I: IntoIterator<Item = (A, B)>,
294 A: Borrow<[u8]>,
295 B: Borrow<Option<V>>,
296 V: Borrow<[u8]>,
297 DB: hash_db::HashDB<L::Hash, trie_db::DBValue>,
298{
299 {
300 let mut trie = TrieDBMutBuilder::<L>::from_existing(db, &mut root)
301 .with_optional_cache(cache)
302 .with_optional_recorder(recorder)
303 .build();
304
305 let mut delta = delta.into_iter().collect::<Vec<_>>();
306 delta.sort_by(|l, r| l.0.borrow().cmp(r.0.borrow()));
307
308 for (key, change) in delta {
309 match change.borrow() {
310 Some(val) => trie.insert(key.borrow(), val.borrow())?,
311 None => trie.remove(key.borrow())?,
312 };
313 }
314 }
315
316 Ok(root)
317}
318
319pub fn read_trie_value<L: TrieLayout, DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>>(
321 db: &DB,
322 root: &TrieHash<L>,
323 key: &[u8],
324 recorder: Option<&mut dyn TrieRecorder<TrieHash<L>>>,
325 cache: Option<&mut dyn TrieCache<L::Codec>>,
326) -> Result<Option<Vec<u8>>, Box<TrieError<L>>> {
327 TrieDBBuilder::<L>::new(db, root)
328 .with_optional_cache(cache)
329 .with_optional_recorder(recorder)
330 .build()
331 .get(key)
332}
333
334pub fn read_trie_first_descendant_value<L: TrieLayout, DB>(
337 db: &DB,
338 root: &TrieHash<L>,
339 key: &[u8],
340 recorder: Option<&mut dyn TrieRecorder<TrieHash<L>>>,
341 cache: Option<&mut dyn TrieCache<L::Codec>>,
342) -> Result<Option<MerkleValue<TrieHash<L>>>, Box<TrieError<L>>>
343where
344 DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
345{
346 TrieDBBuilder::<L>::new(db, root)
347 .with_optional_cache(cache)
348 .with_optional_recorder(recorder)
349 .build()
350 .lookup_first_descendant(key)
351}
352
353pub fn read_trie_value_with<
355 L: TrieLayout,
356 Q: Query<L::Hash, Item = Vec<u8>>,
357 DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
358>(
359 db: &DB,
360 root: &TrieHash<L>,
361 key: &[u8],
362 query: Q,
363) -> Result<Option<Vec<u8>>, Box<TrieError<L>>> {
364 TrieDBBuilder::<L>::new(db, root).build().get_with(key, query)
365}
366
367pub fn empty_trie_root<L: TrieConfiguration>() -> <L::Hash as Hasher>::Out {
369 L::trie_root::<_, Vec<u8>, Vec<u8>>(core::iter::empty())
370}
371
372pub fn empty_child_trie_root<L: TrieConfiguration>() -> <L::Hash as Hasher>::Out {
374 L::trie_root::<_, Vec<u8>, Vec<u8>>(core::iter::empty())
375}
376
377pub fn child_trie_root<L: TrieConfiguration, I, A, B>(input: I) -> <L::Hash as Hasher>::Out
380where
381 I: IntoIterator<Item = (A, B)>,
382 A: AsRef<[u8]> + Ord,
383 B: AsRef<[u8]>,
384{
385 L::trie_root(input)
386}
387
388pub fn child_delta_trie_root<L: TrieConfiguration, I, A, B, DB, RD, V>(
391 keyspace: &[u8],
392 db: &mut DB,
393 root_data: RD,
394 delta: I,
395 recorder: Option<&mut dyn TrieRecorder<TrieHash<L>>>,
396 cache: Option<&mut dyn TrieCache<L::Codec>>,
397) -> Result<<L::Hash as Hasher>::Out, Box<TrieError<L>>>
398where
399 I: IntoIterator<Item = (A, B)>,
400 A: Borrow<[u8]>,
401 B: Borrow<Option<V>>,
402 V: Borrow<[u8]>,
403 RD: AsRef<[u8]>,
404 DB: hash_db::HashDB<L::Hash, trie_db::DBValue>,
405{
406 let mut root = TrieHash::<L>::default();
407 root.as_mut().copy_from_slice(root_data.as_ref());
409
410 let mut db = KeySpacedDBMut::new(db, keyspace);
411 delta_trie_root::<L, _, _, _, _, _>(&mut db, root, delta, recorder, cache)
412}
413
414pub fn read_child_trie_value<L: TrieConfiguration, DB>(
416 keyspace: &[u8],
417 db: &DB,
418 root: &TrieHash<L>,
419 key: &[u8],
420 recorder: Option<&mut dyn TrieRecorder<TrieHash<L>>>,
421 cache: Option<&mut dyn TrieCache<L::Codec>>,
422) -> Result<Option<Vec<u8>>, Box<TrieError<L>>>
423where
424 DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
425{
426 let db = KeySpacedDB::new(db, keyspace);
427 TrieDBBuilder::<L>::new(&db, &root)
428 .with_optional_recorder(recorder)
429 .with_optional_cache(cache)
430 .build()
431 .get(key)
432 .map(|x| x.map(|val| val.to_vec()))
433}
434
435pub fn read_child_trie_hash<L: TrieConfiguration, DB>(
437 keyspace: &[u8],
438 db: &DB,
439 root: &TrieHash<L>,
440 key: &[u8],
441 recorder: Option<&mut dyn TrieRecorder<TrieHash<L>>>,
442 cache: Option<&mut dyn TrieCache<L::Codec>>,
443) -> Result<Option<TrieHash<L>>, Box<TrieError<L>>>
444where
445 DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
446{
447 let db = KeySpacedDB::new(db, keyspace);
448 TrieDBBuilder::<L>::new(&db, &root)
449 .with_optional_recorder(recorder)
450 .with_optional_cache(cache)
451 .build()
452 .get_hash(key)
453}
454
455pub fn read_child_trie_first_descendant_value<L: TrieConfiguration, DB>(
458 keyspace: &[u8],
459 db: &DB,
460 root: &TrieHash<L>,
461 key: &[u8],
462 recorder: Option<&mut dyn TrieRecorder<TrieHash<L>>>,
463 cache: Option<&mut dyn TrieCache<L::Codec>>,
464) -> Result<Option<MerkleValue<TrieHash<L>>>, Box<TrieError<L>>>
465where
466 DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
467{
468 let db = KeySpacedDB::new(db, keyspace);
469 TrieDBBuilder::<L>::new(&db, &root)
470 .with_optional_recorder(recorder)
471 .with_optional_cache(cache)
472 .build()
473 .lookup_first_descendant(key)
474}
475
476pub fn read_child_trie_value_with<L, Q, DB>(
478 keyspace: &[u8],
479 db: &DB,
480 root_slice: &[u8],
481 key: &[u8],
482 query: Q,
483) -> Result<Option<Vec<u8>>, Box<TrieError<L>>>
484where
485 L: TrieConfiguration,
486 Q: Query<L::Hash, Item = DBValue>,
487 DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
488{
489 let mut root = TrieHash::<L>::default();
490 root.as_mut().copy_from_slice(root_slice);
492
493 let db = KeySpacedDB::new(db, keyspace);
494 TrieDBBuilder::<L>::new(&db, &root)
495 .build()
496 .get_with(key, query)
497 .map(|x| x.map(|val| val.to_vec()))
498}
499
500pub struct KeySpacedDB<'a, DB: ?Sized, H>(&'a DB, &'a [u8], PhantomData<H>);
503
504pub struct KeySpacedDBMut<'a, DB: ?Sized, H>(&'a mut DB, &'a [u8], PhantomData<H>);
509
510fn keyspace_as_prefix_alloc(ks: &[u8], prefix: Prefix) -> (Vec<u8>, Option<u8>) {
513 let mut result = vec![0; ks.len() + prefix.0.len()];
514 result[..ks.len()].copy_from_slice(ks);
515 result[ks.len()..].copy_from_slice(prefix.0);
516 (result, prefix.1)
517}
518
519impl<'a, DB: ?Sized, H> KeySpacedDB<'a, DB, H> {
520 #[inline]
522 pub fn new(db: &'a DB, ks: &'a [u8]) -> Self {
523 KeySpacedDB(db, ks, PhantomData)
524 }
525}
526
527impl<'a, DB: ?Sized, H> KeySpacedDBMut<'a, DB, H> {
528 pub fn new(db: &'a mut DB, ks: &'a [u8]) -> Self {
530 KeySpacedDBMut(db, ks, PhantomData)
531 }
532}
533
534impl<'a, DB, H, T> hash_db::HashDBRef<H, T> for KeySpacedDB<'a, DB, H>
535where
536 DB: hash_db::HashDBRef<H, T> + ?Sized,
537 H: Hasher,
538 T: From<&'static [u8]>,
539{
540 fn get(&self, key: &H::Out, prefix: Prefix) -> Option<T> {
541 let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
542 self.0.get(key, (&derived_prefix.0, derived_prefix.1))
543 }
544
545 fn contains(&self, key: &H::Out, prefix: Prefix) -> bool {
546 let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
547 self.0.contains(key, (&derived_prefix.0, derived_prefix.1))
548 }
549}
550
551impl<'a, DB, H, T> hash_db::HashDB<H, T> for KeySpacedDBMut<'a, DB, H>
552where
553 DB: hash_db::HashDB<H, T>,
554 H: Hasher,
555 T: Default + PartialEq<T> + for<'b> From<&'b [u8]> + Clone + Send + Sync,
556{
557 fn get(&self, key: &H::Out, prefix: Prefix) -> Option<T> {
558 let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
559 self.0.get(key, (&derived_prefix.0, derived_prefix.1))
560 }
561
562 fn contains(&self, key: &H::Out, prefix: Prefix) -> bool {
563 let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
564 self.0.contains(key, (&derived_prefix.0, derived_prefix.1))
565 }
566
567 fn insert(&mut self, prefix: Prefix, value: &[u8]) -> H::Out {
568 let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
569 self.0.insert((&derived_prefix.0, derived_prefix.1), value)
570 }
571
572 fn emplace(&mut self, key: H::Out, prefix: Prefix, value: T) {
573 let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
574 self.0.emplace(key, (&derived_prefix.0, derived_prefix.1), value)
575 }
576
577 fn remove(&mut self, key: &H::Out, prefix: Prefix) {
578 let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
579 self.0.remove(key, (&derived_prefix.0, derived_prefix.1))
580 }
581}
582
583impl<'a, DB, H, T> hash_db::AsHashDB<H, T> for KeySpacedDBMut<'a, DB, H>
584where
585 DB: hash_db::HashDB<H, T>,
586 H: Hasher,
587 T: Default + PartialEq<T> + for<'b> From<&'b [u8]> + Clone + Send + Sync,
588{
589 fn as_hash_db(&self) -> &dyn hash_db::HashDB<H, T> {
590 self
591 }
592
593 fn as_hash_db_mut<'b>(&'b mut self) -> &'b mut (dyn hash_db::HashDB<H, T> + 'b) {
594 &mut *self
595 }
596}
597
598mod trie_constants {
600 const FIRST_PREFIX: u8 = 0b_00 << 6;
601 pub const LEAF_PREFIX_MASK: u8 = 0b_01 << 6;
602 pub const BRANCH_WITHOUT_MASK: u8 = 0b_10 << 6;
603 pub const BRANCH_WITH_MASK: u8 = 0b_11 << 6;
604 pub const EMPTY_TRIE: u8 = FIRST_PREFIX | (0b_00 << 4);
605 pub const ALT_HASHING_LEAF_PREFIX_MASK: u8 = FIRST_PREFIX | (0b_1 << 5);
606 pub const ALT_HASHING_BRANCH_WITH_MASK: u8 = FIRST_PREFIX | (0b_01 << 4);
607 pub const ESCAPE_COMPACT_HEADER: u8 = EMPTY_TRIE | 0b_00_01;
608}
609
610#[cfg(test)]
611mod tests {
612 use super::*;
613 use codec::{Compact, Decode, Encode};
614 use hash_db::{HashDB, Hasher};
615 use sp_core::Blake2Hasher;
616 use trie_db::{DBValue, NodeCodec as NodeCodecT, Trie, TrieMut};
617 use trie_standardmap::{Alphabet, StandardMap, ValueMode};
618
619 type LayoutV0 = super::LayoutV0<Blake2Hasher>;
620 type LayoutV1 = super::LayoutV1<Blake2Hasher>;
621
622 type MemoryDBMeta<H> = memory_db::MemoryDB<H, memory_db::HashKey<H>, trie_db::DBValue>;
623
624 pub fn create_trie<L: TrieLayout>(
625 data: &[(&[u8], &[u8])],
626 ) -> (MemoryDB<L::Hash>, trie_db::TrieHash<L>) {
627 let mut db = MemoryDB::default();
628 let mut root = Default::default();
629
630 {
631 let mut trie = trie_db::TrieDBMutBuilder::<L>::new(&mut db, &mut root).build();
632 for (k, v) in data {
633 trie.insert(k, v).expect("Inserts data");
634 }
635 }
636
637 let mut recorder = Recorder::<L>::new();
638 {
639 let trie = trie_db::TrieDBBuilder::<L>::new(&mut db, &mut root)
640 .with_recorder(&mut recorder)
641 .build();
642 for (k, _v) in data {
643 trie.get(k).unwrap();
644 }
645 }
646
647 (db, root)
648 }
649
650 pub fn create_storage_proof<L: TrieLayout>(
651 data: &[(&[u8], &[u8])],
652 ) -> (RawStorageProof, trie_db::TrieHash<L>) {
653 let (db, root) = create_trie::<L>(data);
654
655 let mut recorder = Recorder::<L>::new();
656 {
657 let trie = trie_db::TrieDBBuilder::<L>::new(&db, &root)
658 .with_recorder(&mut recorder)
659 .build();
660 for (k, _v) in data {
661 trie.get(k).unwrap();
662 }
663 }
664
665 (recorder.drain().into_iter().map(|record| record.data).collect(), root)
666 }
667
668 fn hashed_null_node<T: TrieConfiguration>() -> TrieHash<T> {
669 <T::Codec as NodeCodecT>::hashed_null_node()
670 }
671
672 fn check_equivalent<T: TrieConfiguration>(input: &Vec<(&[u8], &[u8])>) {
673 {
674 let closed_form = T::trie_root(input.clone());
675 let d = T::trie_root_unhashed(input.clone());
676 println!("Data: {:#x?}, {:#x?}", d, Blake2Hasher::hash(&d[..]));
677 let persistent = {
678 let mut memdb = MemoryDBMeta::default();
679 let mut root = Default::default();
680 let mut t = TrieDBMutBuilder::<T>::new(&mut memdb, &mut root).build();
681 for (x, y) in input.iter().rev() {
682 t.insert(x, y).unwrap();
683 }
684 *t.root()
685 };
686 assert_eq!(closed_form, persistent);
687 }
688 }
689
690 fn check_iteration<T: TrieConfiguration>(input: &Vec<(&[u8], &[u8])>) {
691 let mut memdb = MemoryDBMeta::default();
692 let mut root = Default::default();
693 {
694 let mut t = TrieDBMutBuilder::<T>::new(&mut memdb, &mut root).build();
695 for (x, y) in input.clone() {
696 t.insert(x, y).unwrap();
697 }
698 }
699 {
700 let t = TrieDBBuilder::<T>::new(&memdb, &root).build();
701 assert_eq!(
702 input.iter().map(|(i, j)| (i.to_vec(), j.to_vec())).collect::<Vec<_>>(),
703 t.iter()
704 .unwrap()
705 .map(|x| x.map(|y| (y.0, y.1.to_vec())).unwrap())
706 .collect::<Vec<_>>()
707 );
708 }
709 }
710
711 fn check_input(input: &Vec<(&[u8], &[u8])>) {
712 check_equivalent::<LayoutV0>(input);
713 check_iteration::<LayoutV0>(input);
714 check_equivalent::<LayoutV1>(input);
715 check_iteration::<LayoutV1>(input);
716 }
717
718 #[test]
719 fn default_trie_root() {
720 let mut db = MemoryDB::default();
721 let mut root = TrieHash::<LayoutV1>::default();
722 let mut empty = TrieDBMutBuilder::<LayoutV1>::new(&mut db, &mut root).build();
723 empty.commit();
724 let root1 = empty.root().as_ref().to_vec();
725 let root2: Vec<u8> = LayoutV1::trie_root::<_, Vec<u8>, Vec<u8>>(std::iter::empty())
726 .as_ref()
727 .iter()
728 .cloned()
729 .collect();
730
731 assert_eq!(root1, root2);
732 }
733
734 #[test]
735 fn empty_is_equivalent() {
736 let input: Vec<(&[u8], &[u8])> = vec![];
737 check_input(&input);
738 }
739
740 #[test]
741 fn leaf_is_equivalent() {
742 let input: Vec<(&[u8], &[u8])> = vec![(&[0xaa][..], &[0xbb][..])];
743 check_input(&input);
744 }
745
746 #[test]
747 fn branch_is_equivalent() {
748 let input: Vec<(&[u8], &[u8])> =
749 vec![(&[0xaa][..], &[0x10][..]), (&[0xba][..], &[0x11][..])];
750 check_input(&input);
751 }
752
753 #[test]
754 fn extension_and_branch_is_equivalent() {
755 let input: Vec<(&[u8], &[u8])> =
756 vec![(&[0xaa][..], &[0x10][..]), (&[0xab][..], &[0x11][..])];
757 check_input(&input);
758 }
759
760 #[test]
761 fn standard_is_equivalent() {
762 let st = StandardMap {
763 alphabet: Alphabet::All,
764 min_key: 32,
765 journal_key: 0,
766 value_mode: ValueMode::Random,
767 count: 1000,
768 };
769 let mut d = st.make();
770 d.sort_by(|(a, _), (b, _)| a.cmp(b));
771 let dr = d.iter().map(|v| (&v.0[..], &v.1[..])).collect();
772 check_input(&dr);
773 }
774
775 #[test]
776 fn extension_and_branch_with_value_is_equivalent() {
777 let input: Vec<(&[u8], &[u8])> = vec![
778 (&[0xaa][..], &[0xa0][..]),
779 (&[0xaa, 0xaa][..], &[0xaa][..]),
780 (&[0xaa, 0xbb][..], &[0xab][..]),
781 ];
782 check_input(&input);
783 }
784
785 #[test]
786 fn bigger_extension_and_branch_with_value_is_equivalent() {
787 let input: Vec<(&[u8], &[u8])> = vec![
788 (&[0xaa][..], &[0xa0][..]),
789 (&[0xaa, 0xaa][..], &[0xaa][..]),
790 (&[0xaa, 0xbb][..], &[0xab][..]),
791 (&[0xbb][..], &[0xb0][..]),
792 (&[0xbb, 0xbb][..], &[0xbb][..]),
793 (&[0xbb, 0xcc][..], &[0xbc][..]),
794 ];
795 check_input(&input);
796 }
797
798 #[test]
799 fn single_long_leaf_is_equivalent() {
800 let input: Vec<(&[u8], &[u8])> = vec![
801 (
802 &[0xaa][..],
803 &b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..],
804 ),
805 (&[0xba][..], &[0x11][..]),
806 ];
807 check_input(&input);
808 }
809
810 #[test]
811 fn two_long_leaves_is_equivalent() {
812 let input: Vec<(&[u8], &[u8])> = vec![
813 (
814 &[0xaa][..],
815 &b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..],
816 ),
817 (
818 &[0xba][..],
819 &b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..],
820 ),
821 ];
822 check_input(&input);
823 }
824
825 fn populate_trie<'db, T: TrieConfiguration>(
826 db: &'db mut dyn HashDB<T::Hash, DBValue>,
827 root: &'db mut TrieHash<T>,
828 v: &[(Vec<u8>, Vec<u8>)],
829 ) -> TrieDBMut<'db, T> {
830 let mut t = TrieDBMutBuilder::<T>::new(db, root).build();
831 for i in 0..v.len() {
832 let key: &[u8] = &v[i].0;
833 let val: &[u8] = &v[i].1;
834 t.insert(key, val).unwrap();
835 }
836 t
837 }
838
839 fn unpopulate_trie<T: TrieConfiguration>(t: &mut TrieDBMut<'_, T>, v: &[(Vec<u8>, Vec<u8>)]) {
840 for i in v {
841 let key: &[u8] = &i.0;
842 t.remove(key).unwrap();
843 }
844 }
845
846 #[test]
847 fn random_should_work() {
848 random_should_work_inner::<LayoutV1>();
849 random_should_work_inner::<LayoutV0>();
850 }
851 fn random_should_work_inner<L: TrieConfiguration>() {
852 let mut seed = <Blake2Hasher as Hasher>::Out::zero();
853 for test_i in 0..10_000 {
854 if test_i % 50 == 0 {
855 println!("{:?} of 10000 stress tests done", test_i);
856 }
857 let x = StandardMap {
858 alphabet: Alphabet::Custom(b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_".to_vec()),
859 min_key: 5,
860 journal_key: 0,
861 value_mode: ValueMode::Index,
862 count: 100,
863 }
864 .make_with(seed.as_fixed_bytes_mut());
865
866 let real = L::trie_root(x.clone());
867 let mut memdb = MemoryDB::default();
868 let mut root = Default::default();
869
870 let mut memtrie = populate_trie::<L>(&mut memdb, &mut root, &x);
871
872 memtrie.commit();
873 if *memtrie.root() != real {
874 println!("TRIE MISMATCH");
875 println!();
876 println!("{:?} vs {:?}", memtrie.root(), real);
877 for i in &x {
878 println!("{:#x?} -> {:#x?}", i.0, i.1);
879 }
880 }
881 assert_eq!(*memtrie.root(), real);
882 unpopulate_trie::<L>(&mut memtrie, &x);
883 memtrie.commit();
884 let hashed_null_node = hashed_null_node::<L>();
885 if *memtrie.root() != hashed_null_node {
886 println!("- TRIE MISMATCH");
887 println!();
888 println!("{:?} vs {:?}", memtrie.root(), hashed_null_node);
889 for i in &x {
890 println!("{:#x?} -> {:#x?}", i.0, i.1);
891 }
892 }
893 assert_eq!(*memtrie.root(), hashed_null_node);
894 }
895 }
896
897 fn to_compact(n: u8) -> u8 {
898 Compact(n).encode()[0]
899 }
900
901 #[test]
902 fn codec_trie_empty() {
903 let input: Vec<(&[u8], &[u8])> = vec![];
904 let trie = LayoutV1::trie_root_unhashed(input);
905 println!("trie: {:#x?}", trie);
906 assert_eq!(trie, vec![0x0]);
907 }
908
909 #[test]
910 fn codec_trie_single_tuple() {
911 let input = vec![(vec![0xaa], vec![0xbb])];
912 let trie = LayoutV1::trie_root_unhashed(input);
913 println!("trie: {:#x?}", trie);
914 assert_eq!(
915 trie,
916 vec![
917 0x42, 0xaa, to_compact(1), 0xbb ]
922 );
923 }
924
925 #[test]
926 fn codec_trie_two_tuples_disjoint_keys() {
927 let input = vec![(&[0x48, 0x19], &[0xfe]), (&[0x13, 0x14], &[0xff])];
928 let trie = LayoutV1::trie_root_unhashed(input);
929 println!("trie: {:#x?}", trie);
930 let mut ex = Vec::<u8>::new();
931 ex.push(0x80); ex.push(0x12); ex.push(0x00); ex.push(to_compact(0x05)); ex.push(0x43); ex.push(0x03); ex.push(0x14); ex.push(to_compact(0x01)); ex.push(0xff); ex.push(to_compact(0x05)); ex.push(0x43); ex.push(0x08); ex.push(0x19); ex.push(to_compact(0x01)); ex.push(0xfe); assert_eq!(trie, ex);
948 }
949
950 #[test]
951 fn iterator_works() {
952 iterator_works_inner::<LayoutV1>();
953 iterator_works_inner::<LayoutV0>();
954 }
955 fn iterator_works_inner<Layout: TrieConfiguration>() {
956 let pairs = vec![
957 (
958 array_bytes::hex2bytes_unchecked("0103000000000000000464"),
959 array_bytes::hex2bytes_unchecked("0400000000"),
960 ),
961 (
962 array_bytes::hex2bytes_unchecked("0103000000000000000469"),
963 array_bytes::hex2bytes_unchecked("0401000000"),
964 ),
965 ];
966
967 let mut mdb = MemoryDB::default();
968 let mut root = Default::default();
969 let _ = populate_trie::<Layout>(&mut mdb, &mut root, &pairs);
970
971 let trie = TrieDBBuilder::<Layout>::new(&mdb, &root).build();
972
973 let iter = trie.iter().unwrap();
974 let mut iter_pairs = Vec::new();
975 for pair in iter {
976 let (key, value) = pair.unwrap();
977 iter_pairs.push((key, value));
978 }
979
980 assert_eq!(pairs, iter_pairs);
981 }
982
983 #[test]
984 fn proof_non_inclusion_works() {
985 let pairs = vec![
986 (array_bytes::hex2bytes_unchecked("0102"), array_bytes::hex2bytes_unchecked("01")),
987 (array_bytes::hex2bytes_unchecked("0203"), array_bytes::hex2bytes_unchecked("0405")),
988 ];
989
990 let mut memdb = MemoryDB::default();
991 let mut root = Default::default();
992 populate_trie::<LayoutV1>(&mut memdb, &mut root, &pairs);
993
994 let non_included_key: Vec<u8> = array_bytes::hex2bytes_unchecked("0909");
995 let proof =
996 generate_trie_proof::<LayoutV1, _, _, _>(&memdb, root, &[non_included_key.clone()])
997 .unwrap();
998
999 assert!(verify_trie_proof::<LayoutV1, _, _, Vec<u8>>(
1001 &root,
1002 &proof,
1003 &[(non_included_key.clone(), None)],
1004 )
1005 .is_ok());
1006
1007 assert!(verify_trie_proof::<LayoutV1, _, _, Vec<u8>>(
1009 &root,
1010 &proof,
1011 &[(non_included_key, Some(array_bytes::hex2bytes_unchecked("1010")))],
1012 )
1013 .is_err());
1014 }
1015
1016 #[test]
1017 fn proof_inclusion_works() {
1018 let pairs = vec![
1019 (array_bytes::hex2bytes_unchecked("0102"), array_bytes::hex2bytes_unchecked("01")),
1020 (array_bytes::hex2bytes_unchecked("0203"), array_bytes::hex2bytes_unchecked("0405")),
1021 ];
1022
1023 let mut memdb = MemoryDB::default();
1024 let mut root = Default::default();
1025 populate_trie::<LayoutV1>(&mut memdb, &mut root, &pairs);
1026
1027 let proof =
1028 generate_trie_proof::<LayoutV1, _, _, _>(&memdb, root, &[pairs[0].0.clone()]).unwrap();
1029
1030 assert!(verify_trie_proof::<LayoutV1, _, _, _>(
1032 &root,
1033 &proof,
1034 &[(pairs[0].0.clone(), Some(pairs[0].1.clone()))]
1035 )
1036 .is_ok());
1037
1038 assert!(verify_trie_proof::<LayoutV1, _, _, Vec<u8>>(
1040 &root,
1041 &proof,
1042 &[(pairs[0].0.clone(), None)]
1043 )
1044 .is_err());
1045
1046 assert!(verify_trie_proof::<LayoutV1, _, _, _>(
1048 &root,
1049 &proof,
1050 &[(array_bytes::hex2bytes_unchecked("4242"), Some(pairs[0].1.clone()))]
1051 )
1052 .is_err());
1053
1054 assert!(verify_trie_proof::<LayoutV1, _, _, _>(
1056 &root,
1057 &proof,
1058 &[(pairs[1].0.clone(), Some(pairs[1].1.clone()))]
1059 )
1060 .is_err());
1061 }
1062
1063 #[test]
1064 fn generate_storage_root_with_proof_works_independently_from_the_delta_order() {
1065 let proof = StorageProof::decode(&mut &include_bytes!("../test-res/proof")[..]).unwrap();
1066 let storage_root =
1067 sp_core::H256::decode(&mut &include_bytes!("../test-res/storage_root")[..]).unwrap();
1068 let invalid_delta = Vec::<(Vec<u8>, Option<Vec<u8>>)>::decode(
1070 &mut &include_bytes!("../test-res/invalid-delta-order")[..],
1071 )
1072 .unwrap();
1073 let valid_delta = Vec::<(Vec<u8>, Option<Vec<u8>>)>::decode(
1075 &mut &include_bytes!("../test-res/valid-delta-order")[..],
1076 )
1077 .unwrap();
1078
1079 let proof_db = proof.into_memory_db::<Blake2Hasher>();
1080 let first_storage_root = delta_trie_root::<LayoutV0, _, _, _, _, _>(
1081 &mut proof_db.clone(),
1082 storage_root,
1083 valid_delta,
1084 None,
1085 None,
1086 )
1087 .unwrap();
1088 let second_storage_root = delta_trie_root::<LayoutV0, _, _, _, _, _>(
1089 &mut proof_db.clone(),
1090 storage_root,
1091 invalid_delta,
1092 None,
1093 None,
1094 )
1095 .unwrap();
1096
1097 assert_eq!(first_storage_root, second_storage_root);
1098 }
1099
1100 #[test]
1101 fn big_key() {
1102 let check = |keysize: usize| {
1103 let mut memdb = PrefixedMemoryDB::<Blake2Hasher>::default();
1104 let mut root = Default::default();
1105 let mut t = TrieDBMutBuilder::<LayoutV1>::new(&mut memdb, &mut root).build();
1106 t.insert(&vec![0x01u8; keysize][..], &[0x01u8, 0x23]).unwrap();
1107 std::mem::drop(t);
1108 let t = TrieDBBuilder::<LayoutV1>::new(&memdb, &root).build();
1109 assert_eq!(t.get(&vec![0x01u8; keysize][..]).unwrap(), Some(vec![0x01u8, 0x23]));
1110 };
1111 check(u16::MAX as usize / 2); check(u16::MAX as usize / 2 + 1); }
1114
1115 #[test]
1116 fn node_with_no_children_fail_decoding() {
1117 let branch = NodeCodec::<Blake2Hasher>::branch_node_nibbled(
1118 b"some_partial".iter().copied(),
1119 24,
1120 vec![None; 16].into_iter(),
1121 Some(trie_db::node::Value::Inline(b"value"[..].into())),
1122 );
1123 assert!(NodeCodec::<Blake2Hasher>::decode(branch.as_slice()).is_err());
1124 }
1125}