1#![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;
32pub use error::Error;
34pub use trie_stream::TrieStream;
36pub use node_codec::NodeCodec;
38pub use storage_proof::StorageProof;
39pub use tetsy_trie_db::{
41 Trie, TrieMut, DBValue, Recorder, CError, Query, TrieLayout, TrieConfiguration, nibble_ops, TrieDBIterator,
42};
43pub use tetsy_memory_db::KeyFunction;
45pub use tetsy_memory_db::prefixed_key;
46pub use tetsy_hash_db::{HashDB as HashDBT, EMPTY_PREFIX};
48
49#[derive(Default)]
50pub 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
87pub type TrieError<L> = tetsy_trie_db::TrieError<TrieHash<L>, CError<L>>;
89pub 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 {}
92pub type HashDB<'a, H> = dyn tetsy_hash_db::HashDB<H, tetsy_trie_db::DBValue> + 'a;
94pub type PrefixedMemoryDB<H> = tetsy_memory_db::MemoryDB<
98 H, tetsy_memory_db::PrefixedKey<H>, tetsy_trie_db::DBValue, MemTracker
99>;
100pub type MemoryDB<H> = tetsy_memory_db::MemoryDB<
104 H, tetsy_memory_db::HashKey<H>, tetsy_trie_db::DBValue, MemTracker,
105>;
106pub type GenericMemoryDB<H, KF> = tetsy_memory_db::MemoryDB<
108 H, KF, tetsy_trie_db::DBValue, MemTracker
109>;
110
111pub type TrieDB<'a, L> = tetsy_trie_db::TrieDB<'a, L>;
113pub type TrieDBMut<'a, L> = tetsy_trie_db::TrieDBMut<'a, L>;
115pub type Lookup<'a, L, Q> = tetsy_trie_db::Lookup<'a, L, Q>;
117pub type TrieHash<L> = <<L as TrieLayout>::Hash as Hasher>::Out;
119
120pub mod trie_types {
123 pub type Layout<H> = super::Layout<H>;
124 pub type TrieDB<'a, H> = super::TrieDB<'a, Layout<H>>;
126 pub type TrieDBMut<'a, H> = super::TrieDBMut<'a, Layout<H>>;
128 pub type Lookup<'a, H, Q> = tetsy_trie_db::Lookup<'a, Layout<H>, Q>;
130 pub type TrieError<H> = tetsy_trie_db::TrieError<H, super::Error>;
132}
133
134pub 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
155pub 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
175pub 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
204pub 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
213pub 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
227pub 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
232pub 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
237pub 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
250pub 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.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
278pub 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.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
307pub 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 trie.get_with(&key, &mut *recorder)?;
325 }
326
327 Ok(())
328}
329
330pub 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.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
348pub 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.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
367pub struct KeySpacedDB<'a, DB, H>(&'a DB, &'a [u8], PhantomData<H>);
370
371pub struct KeySpacedDBMut<'a, DB, H>(&'a mut DB, &'a [u8], PhantomData<H>);
376
377fn 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 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 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
463mod 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, 0xaa, to_compact(1), 0xbb ]);
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); 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);
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 assert!(verify_trie_proof::<Layout, _, _, Vec<u8>>(
799 &root,
800 &proof,
801 &[(non_included_key.clone(), None)],
802 ).is_ok()
803 );
804
805 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 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 assert!(verify_trie_proof::<Layout, _, _, Vec<u8>>(
841 &root,
842 &proof,
843 &[(pairs[0].0.clone(), None)]
844 ).is_err()
845 );
846
847 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 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 let invalid_delta = Vec::<(Vec<u8>, Option<Vec<u8>>)>::decode(
872 &mut &include_bytes!("../test-res/invalid-delta-order")[..],
873 ).unwrap();
874 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}