1#![cfg_attr(not(feature = "std"), no_std)]
15
16#[cfg(not(feature = "std"))]
19extern crate alloc;
20
21#[cfg(feature = "std")]
22mod rstd {
23 pub use std::{borrow, boxed, cmp, convert, fmt, hash, iter, marker, mem, ops, rc, result, vec};
24 pub use std::collections::VecDeque;
25 pub use std::error::Error;
26}
27
28#[cfg(not(feature = "std"))]
29mod rstd {
30 pub use core::{borrow, convert, cmp, iter, fmt, hash, marker, mem, ops, result};
31 pub use alloc::{boxed, rc, vec};
32 pub use alloc::collections::VecDeque;
33 pub trait Error {}
34 impl<T> Error for T {}
35}
36
37#[cfg(feature = "std")]
38use self::rstd::{fmt, Error};
39
40use tetsy_hash_db::MaybeDebug;
41use self::rstd::{boxed::Box, vec::Vec};
42
43pub mod node;
44pub mod proof;
45pub mod triedb;
46pub mod triedbmut;
47pub mod sectriedb;
48pub mod sectriedbmut;
49pub mod recorder;
50
51mod fatdb;
52mod fatdbmut;
53mod iter_build;
54mod iterator;
55mod lookup;
56mod nibble;
57mod node_codec;
58mod trie_codec;
59
60pub use tetsy_hash_db::{HashDB, HashDBRef, Hasher};
61pub use self::triedb::{TrieDB, TrieDBIterator};
62pub use self::triedbmut::{TrieDBMut, ChildReference};
63pub use self::sectriedbmut::SecTrieDBMut;
64pub use self::sectriedb::SecTrieDB;
65pub use self::fatdb::{FatDB, FatDBIterator};
66pub use self::fatdbmut::FatDBMut;
67pub use self::recorder::{Recorder, Record};
68pub use self::lookup::Lookup;
69pub use self::nibble::{NibbleSlice, NibbleVec, nibble_ops};
70pub use crate::node_codec::{NodeCodec, Partial};
71pub use crate::iter_build::{trie_visit, ProcessEncodedNode,
72 TrieBuilder, TrieRoot, TrieRootUnhashed};
73pub use crate::iterator::TrieDBNodeIterator;
74pub use crate::trie_codec::{decode_compact, decode_compact_from_iter, encode_compact};
75
76#[cfg(feature = "std")]
77pub use crate::iter_build::TrieRootPrint;
78
79pub type DBValue = Vec<u8>;
81
82#[derive(PartialEq, Eq, Clone, Debug)]
87pub enum TrieError<T, E> {
88 InvalidStateRoot(T),
90 IncompleteDatabase(T),
92 ValueAtIncompleteKey(Vec<u8>, u8),
96 DecoderError(T, E),
98 InvalidHash(T, Vec<u8>),
99}
100
101#[cfg(feature = "std")]
102impl<T, E> fmt::Display for TrieError<T, E> where T: MaybeDebug, E: MaybeDebug {
103 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
104 match *self {
105 TrieError::InvalidStateRoot(ref root) =>
106 write!(f, "Invalid state root: {:?}", root),
107 TrieError::IncompleteDatabase(ref missing) =>
108 write!(f, "Database missing expected key: {:?}", missing),
109 TrieError::ValueAtIncompleteKey(ref bytes, ref extra) =>
110 write!(f, "Value found in trie at incomplete key {:?} + {:?}", bytes, extra),
111 TrieError::DecoderError(ref hash, ref decoder_err) => {
112 write!(f, "Decoding failed for hash {:?}; err: {:?}", hash, decoder_err)
113 }
114 TrieError::InvalidHash(ref hash, ref data) =>
115 write!(
116 f,
117 "Encoded node {:?} contains invalid hash reference with length: {}",
118 hash, data.len()
119 ),
120 }
121 }
122}
123
124#[cfg(feature = "std")]
125impl<T, E> Error for TrieError<T, E> where T: fmt::Debug, E: Error {}
126
127pub type Result<T, H, E> = crate::rstd::result::Result<T, Box<TrieError<H, E>>>;
130
131
132pub type TrieItem<'a, U, E> = Result<(Vec<u8>, DBValue), U, E>;
134
135pub trait Query<H: Hasher> {
141 type Item;
143
144 fn decode(self, data: &[u8]) -> Self::Item;
146
147 fn record(&mut self, _hash: &H::Out, _data: &[u8], _depth: u32) {}
149}
150
151impl<'a, H: Hasher> Query<H> for &'a mut Recorder<H::Out> {
152 type Item = DBValue;
153 fn decode(self, value: &[u8]) -> DBValue { value.to_vec() }
154 fn record(&mut self, hash: &H::Out, data: &[u8], depth: u32) {
155 (&mut **self).record(hash, data, depth);
156 }
157}
158
159impl<F, T, H: Hasher> Query<H> for F where F: for<'a> FnOnce(&'a [u8]) -> T {
160 type Item = T;
161 fn decode(self, value: &[u8]) -> T { (self)(value) }
162}
163
164impl<'a, F, T, H: Hasher> Query<H> for (&'a mut Recorder<H::Out>, F) where F: FnOnce(&[u8]) -> T {
165 type Item = T;
166 fn decode(self, value: &[u8]) -> T { (self.1)(value) }
167 fn record(&mut self, hash: &H::Out, data: &[u8], depth: u32) {
168 self.0.record(hash, data, depth)
169 }
170}
171
172pub trait Trie<L: TrieLayout> {
174 fn root(&self) -> &TrieHash<L>;
176
177 fn is_empty(&self) -> bool { *self.root() == L::Codec::hashed_null_node() }
179
180 fn contains(&self, key: &[u8]) -> Result<bool, TrieHash<L>, CError<L>> {
182 self.get(key).map(|x| x.is_some() )
183 }
184
185 fn get<'a, 'key>(
187 &'a self,
188 key: &'key [u8],
189 ) -> Result<Option<DBValue>, TrieHash<L>, CError<L>> where 'a: 'key {
190 self.get_with(key, |v: &[u8]| v.to_vec() )
191 }
192
193 fn get_with<'a, 'key, Q: Query<L::Hash>>(
196 &'a self,
197 key: &'key [u8],
198 query: Q
199 ) -> Result<Option<Q::Item>, TrieHash<L>, CError<L>> where 'a: 'key;
200
201 fn iter<'a>(&'a self) -> Result<
203 Box<dyn TrieIterator<L, Item = TrieItem<TrieHash<L>, CError<L> >> + 'a>,
204 TrieHash<L>,
205 CError<L>
206 >;
207}
208
209pub trait TrieMut<L: TrieLayout> {
211 fn root(&mut self) -> &TrieHash<L>;
213
214 fn is_empty(&self) -> bool;
216
217 fn contains(&self, key: &[u8]) -> Result<bool, TrieHash<L>, CError<L>> {
219 self.get(key).map(|x| x.is_some())
220 }
221
222 fn get<'a, 'key>(
224 &'a self,
225 key: &'key [u8],
226 ) -> Result<Option<DBValue>, TrieHash<L>, CError<L>> where 'a: 'key;
227
228 fn insert(
231 &mut self,
232 key: &[u8],
233 value: &[u8],
234 ) -> Result<Option<DBValue>, TrieHash<L>, CError<L>>;
235
236 fn remove(&mut self, key: &[u8]) -> Result<Option<DBValue>, TrieHash<L>, CError<L>>;
239}
240
241pub trait TrieIterator<L: TrieLayout>: Iterator {
243 fn seek(&mut self, key: &[u8]) -> Result<(), TrieHash<L>, CError<L>>;
245}
246
247#[derive(PartialEq, Clone)]
249#[cfg_attr(feature = "std", derive(Debug))]
250pub enum TrieSpec {
251 Generic,
253 Secure,
255 Fat,
257}
258
259impl Default for TrieSpec {
260 fn default() -> TrieSpec {
261 TrieSpec::Secure
262 }
263}
264
265#[derive(Default, Clone)]
267pub struct TrieFactory<L: TrieLayout> {
268 spec: TrieSpec,
269 layout: L,
270}
271
272pub enum TrieKinds<'db, L: TrieLayout> {
275 Generic(TrieDB<'db, L>),
277 Secure(SecTrieDB<'db, L>),
279 Fat(FatDB<'db, L>),
281}
282
283macro_rules! wrapper {
285 ($me: ident, $f_name: ident, $($param: ident),*) => {
286 match *$me {
287 TrieKinds::Generic(ref t) => t.$f_name($($param),*),
288 TrieKinds::Secure(ref t) => t.$f_name($($param),*),
289 TrieKinds::Fat(ref t) => t.$f_name($($param),*),
290 }
291 }
292}
293
294impl<'db, L: TrieLayout> Trie<L> for TrieKinds<'db, L> {
295 fn root(&self) -> &TrieHash<L> {
296 wrapper!(self, root,)
297 }
298
299 fn is_empty(&self) -> bool {
300 wrapper!(self, is_empty,)
301 }
302
303 fn contains(&self, key: &[u8]) -> Result<bool, TrieHash<L>, CError<L>> {
304 wrapper!(self, contains, key)
305 }
306
307 fn get_with<'a, 'key, Q: Query<L::Hash>>(
308 &'a self, key: &'key [u8],
309 query: Q,
310 ) -> Result<Option<Q::Item>, TrieHash<L>, CError<L>>
311 where 'a: 'key
312 {
313 wrapper!(self, get_with, key, query)
314 }
315
316 fn iter<'a>(&'a self) -> Result<
317 Box<dyn TrieIterator<L, Item = TrieItem<TrieHash<L>, CError<L>>> + 'a>,
318 TrieHash<L>,
319 CError<L>,
320 > {
321 wrapper!(self, iter,)
322 }
323}
324
325impl<'db, L> TrieFactory<L>
326where
327 L: TrieLayout + 'db,
328{
329 pub fn new(spec: TrieSpec, layout: L) -> Self {
331 TrieFactory { spec, layout }
332 }
333
334 pub fn readonly(
336 &self,
337 db: &'db dyn HashDBRef<L::Hash, DBValue>,
338 root: &'db TrieHash<L>
339 ) -> Result<TrieKinds<'db, L>, TrieHash<L>, CError<L>> {
340 match self.spec {
341 TrieSpec::Generic => Ok(TrieKinds::Generic(TrieDB::new(db, root)?)),
342 TrieSpec::Secure => Ok(TrieKinds::Secure(SecTrieDB::new(db, root)?)),
343 TrieSpec::Fat => Ok(TrieKinds::Fat(FatDB::new(db, root)?)),
344 }
345 }
346
347 pub fn create(
349 &self,
350 db: &'db mut dyn HashDB<L::Hash, DBValue>,
351 root: &'db mut TrieHash<L>,
352 ) -> Box<dyn TrieMut<L> + 'db> {
353 match self.spec {
354 TrieSpec::Generic => Box::new(TrieDBMut::<L>::new(db, root)),
355 TrieSpec::Secure => Box::new(SecTrieDBMut::<L>::new(db, root)),
356 TrieSpec::Fat => Box::new(FatDBMut::<L>::new(db, root)),
357 }
358 }
359
360 pub fn from_existing(
362 &self,
363 db: &'db mut dyn HashDB<L::Hash, DBValue>,
364 root: &'db mut TrieHash<L>,
365 ) -> Result<Box<dyn TrieMut<L> + 'db>, TrieHash<L>, CError<L>> {
366 match self.spec {
367 TrieSpec::Generic => Ok(Box::new(TrieDBMut::<L>::from_existing(db, root)?)),
368 TrieSpec::Secure => Ok(Box::new(SecTrieDBMut::<L>::from_existing(db, root)?)),
369 TrieSpec::Fat => Ok(Box::new(FatDBMut::<L>::from_existing(db, root)?)),
370 }
371 }
372
373 pub fn is_fat(&self) -> bool { self.spec == TrieSpec::Fat }
375}
376
377pub trait TrieLayout {
381 const USE_EXTENSION: bool;
385 const ALLOW_EMPTY: bool = false;
387 type Hash: Hasher;
389 type Codec: NodeCodec<HashOut=<Self::Hash as Hasher>::Out>;
391}
392
393pub trait TrieConfiguration: Sized + TrieLayout {
397 fn trie_build<DB, I, A, B>(db: &mut DB, input: I) -> <Self::Hash as Hasher>::Out where
399 DB: HashDB<Self::Hash, usize>,
400 I: IntoIterator<Item = (A, B)>,
401 A: AsRef<[u8]> + Ord,
402 B: AsRef<[u8]>,
403 {
404 let mut cb = TrieBuilder::new(db);
405 trie_visit::<Self, _, _, _, _>(input.into_iter(), &mut cb);
406 cb.root.unwrap_or_default()
407 }
408 fn tetsy_trie_root<I, A, B>(input: I) -> <Self::Hash as Hasher>::Out where
410 I: IntoIterator<Item = (A, B)>,
411 A: AsRef<[u8]> + Ord,
412 B: AsRef<[u8]>,
413 {
414 let mut cb = TrieRoot::<Self::Hash, _>::default();
415 trie_visit::<Self, _, _, _, _>(input.into_iter(), &mut cb);
416 cb.root.unwrap_or_default()
417 }
418 fn tetsy_trie_root_unhashed<I, A, B>(input: I) -> Vec<u8> where
420 I: IntoIterator<Item = (A, B)>,
421 A: AsRef<[u8]> + Ord,
422 B: AsRef<[u8]>,
423 {
424 let mut cb = TrieRootUnhashed::<Self::Hash>::default();
425 trie_visit::<Self, _, _, _, _>(input.into_iter(), &mut cb);
426 cb.root.unwrap_or_default()
427 }
428 fn encode_index(input: u32) -> Vec<u8> {
431 input.to_be_bytes().to_vec()
433 }
434 fn ordered_tetsy_trie_root<I, A>(input: I) -> <Self::Hash as Hasher>::Out
437 where
438 I: IntoIterator<Item = A>,
439 A: AsRef<[u8]>,
440 {
441 Self::tetsy_trie_root(input
442 .into_iter()
443 .enumerate()
444 .map(|(i, v)| (Self::encode_index(i as u32), v))
445 )
446 }
447}
448
449pub type TrieHash<L> = <<L as TrieLayout>::Hash as Hasher>::Out;
451pub type CError<L> = <<L as TrieLayout>::Codec as NodeCodec>::Error;