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
193pub type TrieError<L> = trie_db::TrieError<TrieHash<L>, CError<L>>;
195pub 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 {}
198pub type HashDB<'a, H> = dyn hash_db::HashDB<H, trie_db::DBValue> + 'a;
200pub type PrefixedMemoryDB<H, RS = RandomState> =
204 memory_db::MemoryDB<H, memory_db::PrefixedKey<H>, trie_db::DBValue, RS>;
205pub type MemoryDB<H, RS = RandomState> =
209 memory_db::MemoryDB<H, memory_db::HashKey<H>, trie_db::DBValue, RS>;
210pub type GenericMemoryDB<H, KF, RS = RandomState> =
212 memory_db::MemoryDB<H, KF, trie_db::DBValue, RS>;
213
214pub type TrieDB<'a, 'cache, L> = trie_db::TrieDB<'a, 'cache, L>;
216pub type TrieDBBuilder<'a, 'cache, L> = trie_db::TrieDBBuilder<'a, 'cache, L>;
218pub type TrieDBMut<'a, L> = trie_db::TrieDBMut<'a, L>;
220pub type TrieDBMutBuilder<'a, L> = trie_db::TrieDBMutBuilder<'a, L>;
222pub type Lookup<'a, 'cache, L, Q> = trie_db::Lookup<'a, 'cache, L, Q>;
224pub type TrieHash<L> = <<L as TrieLayout>::Hash as Hasher>::Out;
226pub mod trie_types {
229 use super::*;
230
231 pub type TrieDB<'a, 'cache, H> = super::TrieDB<'a, 'cache, LayoutV1<H>>;
235 pub type TrieDBBuilder<'a, 'cache, H> = super::TrieDBBuilder<'a, 'cache, LayoutV1<H>>;
237 pub type TrieDBMutV0<'a, H> = super::TrieDBMut<'a, LayoutV0<H>>;
239 pub type TrieDBMutBuilderV0<'a, H> = super::TrieDBMutBuilder<'a, LayoutV0<H>>;
241 pub type TrieDBMutV1<'a, H> = super::TrieDBMut<'a, LayoutV1<H>>;
243 pub type TrieDBMutBuilderV1<'a, H> = super::TrieDBMutBuilder<'a, LayoutV1<H>>;
245 pub type Lookup<'a, 'cache, H, Q> = trie_db::Lookup<'a, 'cache, LayoutV1<H>, Q>;
247 pub type TrieError<H> = trie_db::TrieError<H, super::Error<H>>;
249}
250
251pub 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
273pub 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
295pub 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
330pub 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
345pub 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
364pub 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
378pub fn empty_trie_root<L: TrieConfiguration>() -> <L::Hash as Hasher>::Out {
380 L::trie_root::<_, Vec<u8>, Vec<u8>>(core::iter::empty())
381}
382
383pub 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
388pub 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
399pub 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.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
425pub 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
446pub 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
466pub 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
487pub 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.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
511pub struct KeySpacedDB<'a, DB: ?Sized, H>(&'a DB, &'a [u8], PhantomData<H>);
514
515pub struct KeySpacedDBMut<'a, DB: ?Sized, H>(&'a mut DB, &'a [u8], PhantomData<H>);
520
521fn 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 #[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 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
609mod 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, 0xaa, to_compact(1), 0xbb ]
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); 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);
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 assert!(verify_trie_proof::<LayoutV1, _, _, Vec<u8>>(
1012 &root,
1013 &proof,
1014 &[(non_included_key.clone(), None)],
1015 )
1016 .is_ok());
1017
1018 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 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 assert!(verify_trie_proof::<LayoutV1, _, _, Vec<u8>>(
1051 &root,
1052 &proof,
1053 &[(pairs[0].0.clone(), None)]
1054 )
1055 .is_err());
1056
1057 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 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 let invalid_delta = Vec::<(Vec<u8>, Option<Vec<u8>>)>::decode(
1081 &mut &include_bytes!("../test-res/invalid-delta-order")[..],
1082 )
1083 .unwrap();
1084 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); check(u16::MAX as usize / 2 + 1); }
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}