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;
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;
50pub use error::Error;
52pub use hash_db::{HashDB as HashDBT, EMPTY_PREFIX};
54use hash_db::{Hasher, Prefix};
55pub use memory_db::{prefixed_key, HashKey, KeyFunction, PrefixedKey};
57pub use node_codec::NodeCodec;
59pub use storage_proof::{CompactProof, StorageProof, StorageProofError};
60pub use trie_codec::{decode_compact, encode_compact, Error as CompactProofError};
63use trie_db::proof::{generate_proof, verify_proof};
64pub 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};
74pub use trie_stream::TrieStream;
76
77pub type RawStorageProof = Vec<Vec<u8>>;
79
80pub struct LayoutV0<H>(PhantomData<H>);
82
83pub 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
170pub trait TrieRecorderProvider<H: Hasher> {
175 type Recorder<'a>: trie_db::TrieRecorder<H::Out> + 'a
177 where
178 Self: 'a;
179
180 fn drain_storage_proof(self) -> Option<StorageProof>;
182
183 fn as_trie_recorder(&self, storage_root: H::Out) -> Self::Recorder<'_>;
185}
186
187pub trait ProofSizeProvider {
189 fn estimate_encoded_size(&self) -> usize;
191
192 fn start_transaction(&mut self, is_host: bool) {
196 let _ = is_host;
197 }
198
199 fn rollback_transaction(&mut self, is_host: bool) {
205 let _ = is_host;
206 }
207
208 fn commit_transaction(&mut self, is_host: bool) {
214 let _ = is_host;
215 }
216}
217
218pub type TrieError<L> = trie_db::TrieError<TrieHash<L>, CError<L>>;
220pub trait AsHashDB<H: Hasher>: hash_db::AsHashDB<H, trie_db::DBValue> {}
222impl<H: Hasher, T: hash_db::AsHashDB<H, trie_db::DBValue>> AsHashDB<H> for T {}
223pub type HashDB<'a, H> = dyn hash_db::HashDB<H, trie_db::DBValue> + 'a;
225pub type PrefixedMemoryDB<H, RS = RandomState> =
229 memory_db::MemoryDB<H, memory_db::PrefixedKey<H>, trie_db::DBValue, RS>;
230pub type MemoryDB<H, RS = RandomState> =
234 memory_db::MemoryDB<H, memory_db::HashKey<H>, trie_db::DBValue, RS>;
235pub type GenericMemoryDB<H, KF, RS = RandomState> =
237 memory_db::MemoryDB<H, KF, trie_db::DBValue, RS>;
238
239pub type TrieDB<'a, 'cache, L> = trie_db::TrieDB<'a, 'cache, L>;
241pub type TrieDBBuilder<'a, 'cache, L> = trie_db::TrieDBBuilder<'a, 'cache, L>;
243pub type TrieDBMut<'a, L> = trie_db::TrieDBMut<'a, L>;
245pub type TrieDBMutBuilder<'a, L> = trie_db::TrieDBMutBuilder<'a, L>;
247pub type Lookup<'a, 'cache, L, Q> = trie_db::Lookup<'a, 'cache, L, Q>;
249pub type TrieHash<L> = <<L as TrieLayout>::Hash as Hasher>::Out;
251pub mod trie_types {
254 use super::*;
255
256 pub type TrieDB<'a, 'cache, H> = super::TrieDB<'a, 'cache, LayoutV1<H>>;
260 pub type TrieDBBuilder<'a, 'cache, H> = super::TrieDBBuilder<'a, 'cache, LayoutV1<H>>;
262 pub type TrieDBMutV0<'a, H> = super::TrieDBMut<'a, LayoutV0<H>>;
264 pub type TrieDBMutBuilderV0<'a, H> = super::TrieDBMutBuilder<'a, LayoutV0<H>>;
266 pub type TrieDBMutV1<'a, H> = super::TrieDBMut<'a, LayoutV1<H>>;
268 pub type TrieDBMutBuilderV1<'a, H> = super::TrieDBMutBuilder<'a, LayoutV1<H>>;
270 pub type Lookup<'a, 'cache, H, Q> = trie_db::Lookup<'a, 'cache, LayoutV1<H>, Q>;
272 pub type TrieError<H> = trie_db::TrieError<H, super::Error<H>>;
274}
275
276pub fn generate_trie_proof<'a, L, I, K, DB>(
285 db: &DB,
286 root: TrieHash<L>,
287 keys: I,
288) -> Result<Vec<Vec<u8>>, Box<TrieError<L>>>
289where
290 L: TrieConfiguration,
291 I: IntoIterator<Item = &'a K>,
292 K: 'a + AsRef<[u8]>,
293 DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
294{
295 generate_proof::<_, L, _, _>(db, &root, keys)
296}
297
298pub fn verify_trie_proof<'a, L, I, K, V>(
307 root: &TrieHash<L>,
308 proof: &[Vec<u8>],
309 items: I,
310) -> Result<(), VerifyError<TrieHash<L>, CError<L>>>
311where
312 L: TrieConfiguration,
313 I: IntoIterator<Item = &'a (K, Option<V>)>,
314 K: 'a + AsRef<[u8]>,
315 V: 'a + AsRef<[u8]>,
316{
317 verify_proof::<L, _, _, _>(root, proof, items)
318}
319
320pub fn delta_trie_root<L: TrieConfiguration, I, A, B, DB, V>(
322 db: &mut DB,
323 mut root: TrieHash<L>,
324 delta: I,
325 recorder: Option<&mut dyn trie_db::TrieRecorder<TrieHash<L>>>,
326 cache: Option<&mut dyn TrieCache<L::Codec>>,
327) -> Result<TrieHash<L>, Box<TrieError<L>>>
328where
329 I: IntoIterator<Item = (A, B)>,
330 A: Borrow<[u8]>,
331 B: Borrow<Option<V>>,
332 V: Borrow<[u8]>,
333 DB: hash_db::HashDB<L::Hash, trie_db::DBValue>,
334{
335 {
336 let mut trie = TrieDBMutBuilder::<L>::from_existing(db, &mut root)
337 .with_optional_cache(cache)
338 .with_optional_recorder(recorder)
339 .build();
340
341 let mut delta = delta.into_iter().collect::<Vec<_>>();
342 delta.sort_by(|l, r| l.0.borrow().cmp(r.0.borrow()));
343
344 for (key, change) in delta {
345 match change.borrow() {
346 Some(val) => trie.insert(key.borrow(), val.borrow())?,
347 None => trie.remove(key.borrow())?,
348 };
349 }
350 }
351
352 Ok(root)
353}
354
355pub fn read_trie_value<L: TrieLayout, DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>>(
357 db: &DB,
358 root: &TrieHash<L>,
359 key: &[u8],
360 recorder: Option<&mut dyn TrieRecorder<TrieHash<L>>>,
361 cache: Option<&mut dyn TrieCache<L::Codec>>,
362) -> Result<Option<Vec<u8>>, Box<TrieError<L>>> {
363 TrieDBBuilder::<L>::new(db, root)
364 .with_optional_cache(cache)
365 .with_optional_recorder(recorder)
366 .build()
367 .get(key)
368}
369
370pub fn read_trie_first_descendant_value<L: TrieLayout, DB>(
373 db: &DB,
374 root: &TrieHash<L>,
375 key: &[u8],
376 recorder: Option<&mut dyn TrieRecorder<TrieHash<L>>>,
377 cache: Option<&mut dyn TrieCache<L::Codec>>,
378) -> Result<Option<MerkleValue<TrieHash<L>>>, Box<TrieError<L>>>
379where
380 DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
381{
382 TrieDBBuilder::<L>::new(db, root)
383 .with_optional_cache(cache)
384 .with_optional_recorder(recorder)
385 .build()
386 .lookup_first_descendant(key)
387}
388
389pub fn read_trie_value_with<
391 L: TrieLayout,
392 Q: Query<L::Hash, Item = Vec<u8>>,
393 DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
394>(
395 db: &DB,
396 root: &TrieHash<L>,
397 key: &[u8],
398 query: Q,
399) -> Result<Option<Vec<u8>>, Box<TrieError<L>>> {
400 TrieDBBuilder::<L>::new(db, root).build().get_with(key, query)
401}
402
403pub fn empty_trie_root<L: TrieConfiguration>() -> <L::Hash as Hasher>::Out {
405 L::trie_root::<_, Vec<u8>, Vec<u8>>(core::iter::empty())
406}
407
408pub fn empty_child_trie_root<L: TrieConfiguration>() -> <L::Hash as Hasher>::Out {
410 L::trie_root::<_, Vec<u8>, Vec<u8>>(core::iter::empty())
411}
412
413pub fn child_trie_root<L: TrieConfiguration, I, A, B>(input: I) -> <L::Hash as Hasher>::Out
416where
417 I: IntoIterator<Item = (A, B)>,
418 A: AsRef<[u8]> + Ord,
419 B: AsRef<[u8]>,
420{
421 L::trie_root(input)
422}
423
424pub fn child_delta_trie_root<L: TrieConfiguration, I, A, B, DB, RD, V>(
427 keyspace: &[u8],
428 db: &mut DB,
429 root_data: RD,
430 delta: I,
431 recorder: Option<&mut dyn TrieRecorder<TrieHash<L>>>,
432 cache: Option<&mut dyn TrieCache<L::Codec>>,
433) -> Result<<L::Hash as Hasher>::Out, Box<TrieError<L>>>
434where
435 I: IntoIterator<Item = (A, B)>,
436 A: Borrow<[u8]>,
437 B: Borrow<Option<V>>,
438 V: Borrow<[u8]>,
439 RD: AsRef<[u8]>,
440 DB: hash_db::HashDB<L::Hash, trie_db::DBValue>,
441{
442 let mut root = TrieHash::<L>::default();
443 root.as_mut().copy_from_slice(root_data.as_ref());
445
446 let mut db = KeySpacedDBMut::new(db, keyspace);
447 delta_trie_root::<L, _, _, _, _, _>(&mut db, root, delta, recorder, cache)
448}
449
450pub fn read_child_trie_value<L: TrieConfiguration, DB>(
452 keyspace: &[u8],
453 db: &DB,
454 root: &TrieHash<L>,
455 key: &[u8],
456 recorder: Option<&mut dyn TrieRecorder<TrieHash<L>>>,
457 cache: Option<&mut dyn TrieCache<L::Codec>>,
458) -> Result<Option<Vec<u8>>, Box<TrieError<L>>>
459where
460 DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
461{
462 let db = KeySpacedDB::new(db, keyspace);
463 TrieDBBuilder::<L>::new(&db, &root)
464 .with_optional_recorder(recorder)
465 .with_optional_cache(cache)
466 .build()
467 .get(key)
468 .map(|x| x.map(|val| val.to_vec()))
469}
470
471pub fn read_child_trie_hash<L: TrieConfiguration, DB>(
473 keyspace: &[u8],
474 db: &DB,
475 root: &TrieHash<L>,
476 key: &[u8],
477 recorder: Option<&mut dyn TrieRecorder<TrieHash<L>>>,
478 cache: Option<&mut dyn TrieCache<L::Codec>>,
479) -> Result<Option<TrieHash<L>>, Box<TrieError<L>>>
480where
481 DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
482{
483 let db = KeySpacedDB::new(db, keyspace);
484 TrieDBBuilder::<L>::new(&db, &root)
485 .with_optional_recorder(recorder)
486 .with_optional_cache(cache)
487 .build()
488 .get_hash(key)
489}
490
491pub fn read_child_trie_first_descendant_value<L: TrieConfiguration, DB>(
494 keyspace: &[u8],
495 db: &DB,
496 root: &TrieHash<L>,
497 key: &[u8],
498 recorder: Option<&mut dyn TrieRecorder<TrieHash<L>>>,
499 cache: Option<&mut dyn TrieCache<L::Codec>>,
500) -> Result<Option<MerkleValue<TrieHash<L>>>, Box<TrieError<L>>>
501where
502 DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
503{
504 let db = KeySpacedDB::new(db, keyspace);
505 TrieDBBuilder::<L>::new(&db, &root)
506 .with_optional_recorder(recorder)
507 .with_optional_cache(cache)
508 .build()
509 .lookup_first_descendant(key)
510}
511
512pub fn read_child_trie_value_with<L, Q, DB>(
514 keyspace: &[u8],
515 db: &DB,
516 root_slice: &[u8],
517 key: &[u8],
518 query: Q,
519) -> Result<Option<Vec<u8>>, Box<TrieError<L>>>
520where
521 L: TrieConfiguration,
522 Q: Query<L::Hash, Item = DBValue>,
523 DB: hash_db::HashDBRef<L::Hash, trie_db::DBValue>,
524{
525 let mut root = TrieHash::<L>::default();
526 root.as_mut().copy_from_slice(root_slice);
528
529 let db = KeySpacedDB::new(db, keyspace);
530 TrieDBBuilder::<L>::new(&db, &root)
531 .build()
532 .get_with(key, query)
533 .map(|x| x.map(|val| val.to_vec()))
534}
535
536pub struct KeySpacedDB<'a, DB: ?Sized, H>(&'a DB, &'a [u8], PhantomData<H>);
539
540pub struct KeySpacedDBMut<'a, DB: ?Sized, H>(&'a mut DB, &'a [u8], PhantomData<H>);
545
546fn keyspace_as_prefix_alloc(ks: &[u8], prefix: Prefix) -> (Vec<u8>, Option<u8>) {
549 let mut result = vec![0; ks.len() + prefix.0.len()];
550 result[..ks.len()].copy_from_slice(ks);
551 result[ks.len()..].copy_from_slice(prefix.0);
552 (result, prefix.1)
553}
554
555impl<'a, DB: ?Sized, H> KeySpacedDB<'a, DB, H> {
556 #[inline]
558 pub fn new(db: &'a DB, ks: &'a [u8]) -> Self {
559 KeySpacedDB(db, ks, PhantomData)
560 }
561}
562
563impl<'a, DB: ?Sized, H> KeySpacedDBMut<'a, DB, H> {
564 pub fn new(db: &'a mut DB, ks: &'a [u8]) -> Self {
566 KeySpacedDBMut(db, ks, PhantomData)
567 }
568}
569
570impl<'a, DB, H, T> hash_db::HashDBRef<H, T> for KeySpacedDB<'a, DB, H>
571where
572 DB: hash_db::HashDBRef<H, T> + ?Sized,
573 H: Hasher,
574 T: From<&'static [u8]>,
575{
576 fn get(&self, key: &H::Out, prefix: Prefix) -> Option<T> {
577 let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
578 self.0.get(key, (&derived_prefix.0, derived_prefix.1))
579 }
580
581 fn contains(&self, key: &H::Out, prefix: Prefix) -> bool {
582 let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
583 self.0.contains(key, (&derived_prefix.0, derived_prefix.1))
584 }
585}
586
587impl<'a, DB, H, T> hash_db::HashDB<H, T> for KeySpacedDBMut<'a, DB, H>
588where
589 DB: hash_db::HashDB<H, T>,
590 H: Hasher,
591 T: Default + PartialEq<T> + for<'b> From<&'b [u8]> + Clone + Send + Sync,
592{
593 fn get(&self, key: &H::Out, prefix: Prefix) -> Option<T> {
594 let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
595 self.0.get(key, (&derived_prefix.0, derived_prefix.1))
596 }
597
598 fn contains(&self, key: &H::Out, prefix: Prefix) -> bool {
599 let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
600 self.0.contains(key, (&derived_prefix.0, derived_prefix.1))
601 }
602
603 fn insert(&mut self, prefix: Prefix, value: &[u8]) -> H::Out {
604 let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
605 self.0.insert((&derived_prefix.0, derived_prefix.1), value)
606 }
607
608 fn emplace(&mut self, key: H::Out, prefix: Prefix, value: T) {
609 let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
610 self.0.emplace(key, (&derived_prefix.0, derived_prefix.1), value)
611 }
612
613 fn remove(&mut self, key: &H::Out, prefix: Prefix) {
614 let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix);
615 self.0.remove(key, (&derived_prefix.0, derived_prefix.1))
616 }
617}
618
619impl<'a, DB, H, T> hash_db::AsHashDB<H, T> for KeySpacedDBMut<'a, DB, H>
620where
621 DB: hash_db::HashDB<H, T>,
622 H: Hasher,
623 T: Default + PartialEq<T> + for<'b> From<&'b [u8]> + Clone + Send + Sync,
624{
625 fn as_hash_db(&self) -> &dyn hash_db::HashDB<H, T> {
626 self
627 }
628
629 fn as_hash_db_mut<'b>(&'b mut self) -> &'b mut (dyn hash_db::HashDB<H, T> + 'b) {
630 &mut *self
631 }
632}
633
634mod trie_constants {
636 const FIRST_PREFIX: u8 = 0b_00 << 6;
637 pub const LEAF_PREFIX_MASK: u8 = 0b_01 << 6;
638 pub const BRANCH_WITHOUT_MASK: u8 = 0b_10 << 6;
639 pub const BRANCH_WITH_MASK: u8 = 0b_11 << 6;
640 pub const EMPTY_TRIE: u8 = FIRST_PREFIX | (0b_00 << 4);
641 pub const ALT_HASHING_LEAF_PREFIX_MASK: u8 = FIRST_PREFIX | (0b_1 << 5);
642 pub const ALT_HASHING_BRANCH_WITH_MASK: u8 = FIRST_PREFIX | (0b_01 << 4);
643 pub const ESCAPE_COMPACT_HEADER: u8 = EMPTY_TRIE | 0b_00_01;
644}
645
646#[cfg(test)]
647mod tests {
648 use super::*;
649 use codec::{Compact, Decode, Encode};
650 use hash_db::{HashDB, Hasher};
651 use sp_core::Blake2Hasher;
652 use trie_db::{DBValue, NodeCodec as NodeCodecT, Trie, TrieMut};
653 use trie_standardmap::{Alphabet, StandardMap, ValueMode};
654
655 type LayoutV0 = super::LayoutV0<Blake2Hasher>;
656 type LayoutV1 = super::LayoutV1<Blake2Hasher>;
657
658 type MemoryDBMeta<H> = memory_db::MemoryDB<H, memory_db::HashKey<H>, trie_db::DBValue>;
659
660 pub fn create_trie<L: TrieLayout>(
661 data: &[(&[u8], &[u8])],
662 ) -> (MemoryDB<L::Hash>, trie_db::TrieHash<L>) {
663 let mut db = MemoryDB::default();
664 let mut root = Default::default();
665
666 {
667 let mut trie = trie_db::TrieDBMutBuilder::<L>::new(&mut db, &mut root).build();
668 for (k, v) in data {
669 trie.insert(k, v).expect("Inserts data");
670 }
671 }
672
673 let mut recorder = Recorder::<L>::new();
674 {
675 let trie = trie_db::TrieDBBuilder::<L>::new(&mut db, &mut root)
676 .with_recorder(&mut recorder)
677 .build();
678 for (k, _v) in data {
679 trie.get(k).unwrap();
680 }
681 }
682
683 (db, root)
684 }
685
686 pub fn create_storage_proof<L: TrieLayout>(
687 data: &[(&[u8], &[u8])],
688 ) -> (RawStorageProof, trie_db::TrieHash<L>) {
689 let (db, root) = create_trie::<L>(data);
690
691 let mut recorder = Recorder::<L>::new();
692 {
693 let trie = trie_db::TrieDBBuilder::<L>::new(&db, &root)
694 .with_recorder(&mut recorder)
695 .build();
696 for (k, _v) in data {
697 trie.get(k).unwrap();
698 }
699 }
700
701 (recorder.drain().into_iter().map(|record| record.data).collect(), root)
702 }
703
704 fn hashed_null_node<T: TrieConfiguration>() -> TrieHash<T> {
705 <T::Codec as NodeCodecT>::hashed_null_node()
706 }
707
708 fn check_equivalent<T: TrieConfiguration>(input: &Vec<(&[u8], &[u8])>) {
709 {
710 let closed_form = T::trie_root(input.clone());
711 let d = T::trie_root_unhashed(input.clone());
712 println!("Data: {:#x?}, {:#x?}", d, Blake2Hasher::hash(&d[..]));
713 let persistent = {
714 let mut memdb = MemoryDBMeta::default();
715 let mut root = Default::default();
716 let mut t = TrieDBMutBuilder::<T>::new(&mut memdb, &mut root).build();
717 for (x, y) in input.iter().rev() {
718 t.insert(x, y).unwrap();
719 }
720 *t.root()
721 };
722 assert_eq!(closed_form, persistent);
723 }
724 }
725
726 fn check_iteration<T: TrieConfiguration>(input: &Vec<(&[u8], &[u8])>) {
727 let mut memdb = MemoryDBMeta::default();
728 let mut root = Default::default();
729 {
730 let mut t = TrieDBMutBuilder::<T>::new(&mut memdb, &mut root).build();
731 for (x, y) in input.clone() {
732 t.insert(x, y).unwrap();
733 }
734 }
735 {
736 let t = TrieDBBuilder::<T>::new(&memdb, &root).build();
737 assert_eq!(
738 input.iter().map(|(i, j)| (i.to_vec(), j.to_vec())).collect::<Vec<_>>(),
739 t.iter()
740 .unwrap()
741 .map(|x| x.map(|y| (y.0, y.1.to_vec())).unwrap())
742 .collect::<Vec<_>>()
743 );
744 }
745 }
746
747 fn check_input(input: &Vec<(&[u8], &[u8])>) {
748 check_equivalent::<LayoutV0>(input);
749 check_iteration::<LayoutV0>(input);
750 check_equivalent::<LayoutV1>(input);
751 check_iteration::<LayoutV1>(input);
752 }
753
754 #[test]
755 fn default_trie_root() {
756 let mut db = MemoryDB::default();
757 let mut root = TrieHash::<LayoutV1>::default();
758 let mut empty = TrieDBMutBuilder::<LayoutV1>::new(&mut db, &mut root).build();
759 empty.commit();
760 let root1 = empty.root().as_ref().to_vec();
761 let root2: Vec<u8> = LayoutV1::trie_root::<_, Vec<u8>, Vec<u8>>(std::iter::empty())
762 .as_ref()
763 .iter()
764 .cloned()
765 .collect();
766
767 assert_eq!(root1, root2);
768 }
769
770 #[test]
771 fn empty_is_equivalent() {
772 let input: Vec<(&[u8], &[u8])> = vec![];
773 check_input(&input);
774 }
775
776 #[test]
777 fn leaf_is_equivalent() {
778 let input: Vec<(&[u8], &[u8])> = vec![(&[0xaa][..], &[0xbb][..])];
779 check_input(&input);
780 }
781
782 #[test]
783 fn branch_is_equivalent() {
784 let input: Vec<(&[u8], &[u8])> =
785 vec![(&[0xaa][..], &[0x10][..]), (&[0xba][..], &[0x11][..])];
786 check_input(&input);
787 }
788
789 #[test]
790 fn extension_and_branch_is_equivalent() {
791 let input: Vec<(&[u8], &[u8])> =
792 vec![(&[0xaa][..], &[0x10][..]), (&[0xab][..], &[0x11][..])];
793 check_input(&input);
794 }
795
796 #[test]
797 fn standard_is_equivalent() {
798 let st = StandardMap {
799 alphabet: Alphabet::All,
800 min_key: 32,
801 journal_key: 0,
802 value_mode: ValueMode::Random,
803 count: 1000,
804 };
805 let mut d = st.make();
806 d.sort_by(|(a, _), (b, _)| a.cmp(b));
807 let dr = d.iter().map(|v| (&v.0[..], &v.1[..])).collect();
808 check_input(&dr);
809 }
810
811 #[test]
812 fn extension_and_branch_with_value_is_equivalent() {
813 let input: Vec<(&[u8], &[u8])> = vec![
814 (&[0xaa][..], &[0xa0][..]),
815 (&[0xaa, 0xaa][..], &[0xaa][..]),
816 (&[0xaa, 0xbb][..], &[0xab][..]),
817 ];
818 check_input(&input);
819 }
820
821 #[test]
822 fn bigger_extension_and_branch_with_value_is_equivalent() {
823 let input: Vec<(&[u8], &[u8])> = vec![
824 (&[0xaa][..], &[0xa0][..]),
825 (&[0xaa, 0xaa][..], &[0xaa][..]),
826 (&[0xaa, 0xbb][..], &[0xab][..]),
827 (&[0xbb][..], &[0xb0][..]),
828 (&[0xbb, 0xbb][..], &[0xbb][..]),
829 (&[0xbb, 0xcc][..], &[0xbc][..]),
830 ];
831 check_input(&input);
832 }
833
834 #[test]
835 fn single_long_leaf_is_equivalent() {
836 let input: Vec<(&[u8], &[u8])> = vec![
837 (
838 &[0xaa][..],
839 &b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..],
840 ),
841 (&[0xba][..], &[0x11][..]),
842 ];
843 check_input(&input);
844 }
845
846 #[test]
847 fn two_long_leaves_is_equivalent() {
848 let input: Vec<(&[u8], &[u8])> = vec![
849 (
850 &[0xaa][..],
851 &b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..],
852 ),
853 (
854 &[0xba][..],
855 &b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..],
856 ),
857 ];
858 check_input(&input);
859 }
860
861 fn populate_trie<'db, T: TrieConfiguration>(
862 db: &'db mut dyn HashDB<T::Hash, DBValue>,
863 root: &'db mut TrieHash<T>,
864 v: &[(Vec<u8>, Vec<u8>)],
865 ) -> TrieDBMut<'db, T> {
866 let mut t = TrieDBMutBuilder::<T>::new(db, root).build();
867 for i in 0..v.len() {
868 let key: &[u8] = &v[i].0;
869 let val: &[u8] = &v[i].1;
870 t.insert(key, val).unwrap();
871 }
872 t
873 }
874
875 fn unpopulate_trie<T: TrieConfiguration>(t: &mut TrieDBMut<'_, T>, v: &[(Vec<u8>, Vec<u8>)]) {
876 for i in v {
877 let key: &[u8] = &i.0;
878 t.remove(key).unwrap();
879 }
880 }
881
882 #[test]
883 fn random_should_work() {
884 random_should_work_inner::<LayoutV1>();
885 random_should_work_inner::<LayoutV0>();
886 }
887 fn random_should_work_inner<L: TrieConfiguration>() {
888 let mut seed = <Blake2Hasher as Hasher>::Out::zero();
889 for test_i in 0..10_000 {
890 if test_i % 50 == 0 {
891 println!("{:?} of 10000 stress tests done", test_i);
892 }
893 let x = StandardMap {
894 alphabet: Alphabet::Custom(b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_".to_vec()),
895 min_key: 5,
896 journal_key: 0,
897 value_mode: ValueMode::Index,
898 count: 100,
899 }
900 .make_with(seed.as_fixed_bytes_mut());
901
902 let real = L::trie_root(x.clone());
903 let mut memdb = MemoryDB::default();
904 let mut root = Default::default();
905
906 let mut memtrie = populate_trie::<L>(&mut memdb, &mut root, &x);
907
908 memtrie.commit();
909 if *memtrie.root() != real {
910 println!("TRIE MISMATCH");
911 println!();
912 println!("{:?} vs {:?}", memtrie.root(), real);
913 for i in &x {
914 println!("{:#x?} -> {:#x?}", i.0, i.1);
915 }
916 }
917 assert_eq!(*memtrie.root(), real);
918 unpopulate_trie::<L>(&mut memtrie, &x);
919 memtrie.commit();
920 let hashed_null_node = hashed_null_node::<L>();
921 if *memtrie.root() != hashed_null_node {
922 println!("- TRIE MISMATCH");
923 println!();
924 println!("{:?} vs {:?}", memtrie.root(), hashed_null_node);
925 for i in &x {
926 println!("{:#x?} -> {:#x?}", i.0, i.1);
927 }
928 }
929 assert_eq!(*memtrie.root(), hashed_null_node);
930 }
931 }
932
933 fn to_compact(n: u8) -> u8 {
934 Compact(n).encode()[0]
935 }
936
937 #[test]
938 fn codec_trie_empty() {
939 let input: Vec<(&[u8], &[u8])> = vec![];
940 let trie = LayoutV1::trie_root_unhashed(input);
941 println!("trie: {:#x?}", trie);
942 assert_eq!(trie, vec![0x0]);
943 }
944
945 #[test]
946 fn codec_trie_single_tuple() {
947 let input = vec![(vec![0xaa], vec![0xbb])];
948 let trie = LayoutV1::trie_root_unhashed(input);
949 println!("trie: {:#x?}", trie);
950 assert_eq!(
951 trie,
952 vec![
953 0x42, 0xaa, to_compact(1), 0xbb ]
958 );
959 }
960
961 #[test]
962 fn codec_trie_two_tuples_disjoint_keys() {
963 let input = vec![(&[0x48, 0x19], &[0xfe]), (&[0x13, 0x14], &[0xff])];
964 let trie = LayoutV1::trie_root_unhashed(input);
965 println!("trie: {:#x?}", trie);
966 let mut ex = Vec::<u8>::new();
967 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);
984 }
985
986 #[test]
987 fn iterator_works() {
988 iterator_works_inner::<LayoutV1>();
989 iterator_works_inner::<LayoutV0>();
990 }
991 fn iterator_works_inner<Layout: TrieConfiguration>() {
992 let pairs = vec![
993 (
994 array_bytes::hex2bytes_unchecked("0103000000000000000464"),
995 array_bytes::hex2bytes_unchecked("0400000000"),
996 ),
997 (
998 array_bytes::hex2bytes_unchecked("0103000000000000000469"),
999 array_bytes::hex2bytes_unchecked("0401000000"),
1000 ),
1001 ];
1002
1003 let mut mdb = MemoryDB::default();
1004 let mut root = Default::default();
1005 let _ = populate_trie::<Layout>(&mut mdb, &mut root, &pairs);
1006
1007 let trie = TrieDBBuilder::<Layout>::new(&mdb, &root).build();
1008
1009 let iter = trie.iter().unwrap();
1010 let mut iter_pairs = Vec::new();
1011 for pair in iter {
1012 let (key, value) = pair.unwrap();
1013 iter_pairs.push((key, value));
1014 }
1015
1016 assert_eq!(pairs, iter_pairs);
1017 }
1018
1019 #[test]
1020 fn proof_non_inclusion_works() {
1021 let pairs = vec![
1022 (array_bytes::hex2bytes_unchecked("0102"), array_bytes::hex2bytes_unchecked("01")),
1023 (array_bytes::hex2bytes_unchecked("0203"), array_bytes::hex2bytes_unchecked("0405")),
1024 ];
1025
1026 let mut memdb = MemoryDB::default();
1027 let mut root = Default::default();
1028 populate_trie::<LayoutV1>(&mut memdb, &mut root, &pairs);
1029
1030 let non_included_key: Vec<u8> = array_bytes::hex2bytes_unchecked("0909");
1031 let proof =
1032 generate_trie_proof::<LayoutV1, _, _, _>(&memdb, root, &[non_included_key.clone()])
1033 .unwrap();
1034
1035 assert!(verify_trie_proof::<LayoutV1, _, _, Vec<u8>>(
1037 &root,
1038 &proof,
1039 &[(non_included_key.clone(), None)],
1040 )
1041 .is_ok());
1042
1043 assert!(verify_trie_proof::<LayoutV1, _, _, Vec<u8>>(
1045 &root,
1046 &proof,
1047 &[(non_included_key, Some(array_bytes::hex2bytes_unchecked("1010")))],
1048 )
1049 .is_err());
1050 }
1051
1052 #[test]
1053 fn proof_inclusion_works() {
1054 let pairs = vec![
1055 (array_bytes::hex2bytes_unchecked("0102"), array_bytes::hex2bytes_unchecked("01")),
1056 (array_bytes::hex2bytes_unchecked("0203"), array_bytes::hex2bytes_unchecked("0405")),
1057 ];
1058
1059 let mut memdb = MemoryDB::default();
1060 let mut root = Default::default();
1061 populate_trie::<LayoutV1>(&mut memdb, &mut root, &pairs);
1062
1063 let proof =
1064 generate_trie_proof::<LayoutV1, _, _, _>(&memdb, root, &[pairs[0].0.clone()]).unwrap();
1065
1066 assert!(verify_trie_proof::<LayoutV1, _, _, _>(
1068 &root,
1069 &proof,
1070 &[(pairs[0].0.clone(), Some(pairs[0].1.clone()))]
1071 )
1072 .is_ok());
1073
1074 assert!(verify_trie_proof::<LayoutV1, _, _, Vec<u8>>(
1076 &root,
1077 &proof,
1078 &[(pairs[0].0.clone(), None)]
1079 )
1080 .is_err());
1081
1082 assert!(verify_trie_proof::<LayoutV1, _, _, _>(
1084 &root,
1085 &proof,
1086 &[(array_bytes::hex2bytes_unchecked("4242"), Some(pairs[0].1.clone()))]
1087 )
1088 .is_err());
1089
1090 assert!(verify_trie_proof::<LayoutV1, _, _, _>(
1092 &root,
1093 &proof,
1094 &[(pairs[1].0.clone(), Some(pairs[1].1.clone()))]
1095 )
1096 .is_err());
1097 }
1098
1099 #[test]
1100 fn generate_storage_root_with_proof_works_independently_from_the_delta_order() {
1101 let proof = StorageProof::decode(&mut &include_bytes!("../test-res/proof")[..]).unwrap();
1102 let storage_root =
1103 sp_core::H256::decode(&mut &include_bytes!("../test-res/storage_root")[..]).unwrap();
1104 let invalid_delta = Vec::<(Vec<u8>, Option<Vec<u8>>)>::decode(
1106 &mut &include_bytes!("../test-res/invalid-delta-order")[..],
1107 )
1108 .unwrap();
1109 let valid_delta = Vec::<(Vec<u8>, Option<Vec<u8>>)>::decode(
1111 &mut &include_bytes!("../test-res/valid-delta-order")[..],
1112 )
1113 .unwrap();
1114
1115 let proof_db = proof.into_memory_db::<Blake2Hasher>();
1116 let first_storage_root = delta_trie_root::<LayoutV0, _, _, _, _, _>(
1117 &mut proof_db.clone(),
1118 storage_root,
1119 valid_delta,
1120 None,
1121 None,
1122 )
1123 .unwrap();
1124 let second_storage_root = delta_trie_root::<LayoutV0, _, _, _, _, _>(
1125 &mut proof_db.clone(),
1126 storage_root,
1127 invalid_delta,
1128 None,
1129 None,
1130 )
1131 .unwrap();
1132
1133 assert_eq!(first_storage_root, second_storage_root);
1134 }
1135
1136 #[test]
1137 fn big_key() {
1138 let check = |keysize: usize| {
1139 let mut memdb = PrefixedMemoryDB::<Blake2Hasher>::default();
1140 let mut root = Default::default();
1141 let mut t = TrieDBMutBuilder::<LayoutV1>::new(&mut memdb, &mut root).build();
1142 t.insert(&vec![0x01u8; keysize][..], &[0x01u8, 0x23]).unwrap();
1143 std::mem::drop(t);
1144 let t = TrieDBBuilder::<LayoutV1>::new(&memdb, &root).build();
1145 assert_eq!(t.get(&vec![0x01u8; keysize][..]).unwrap(), Some(vec![0x01u8, 0x23]));
1146 };
1147 check(u16::MAX as usize / 2); check(u16::MAX as usize / 2 + 1); }
1150
1151 #[test]
1152 fn node_with_no_children_fail_decoding() {
1153 let branch = NodeCodec::<Blake2Hasher>::branch_node_nibbled(
1154 b"some_partial".iter().copied(),
1155 24,
1156 vec![None; 16].into_iter(),
1157 Some(trie_db::node::Value::Inline(b"value"[..].into())),
1158 );
1159 assert!(NodeCodec::<Blake2Hasher>::decode(branch.as_slice()).is_err());
1160 }
1161}