tetsy_trie_db/
lib.rs

1// Copyright 2017, 2019 Parity Technologies
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14#![cfg_attr(not(feature = "std"), no_std)]
15
16//! Trie interface and implementation.
17
18#[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
79/// Database value
80pub type DBValue = Vec<u8>;
81
82/// Trie Errors.
83///
84/// These borrow the data within them to avoid excessive copying on every
85/// trie operation.
86#[derive(PartialEq, Eq, Clone, Debug)]
87pub enum TrieError<T, E> {
88	/// Attempted to create a trie with a state root not in the DB.
89	InvalidStateRoot(T),
90	/// Trie item not found in the database,
91	IncompleteDatabase(T),
92	/// A value was found in the trie with a nibble key that was not byte-aligned.
93	/// The first parameter is the byte-aligned part of the prefix and the second parameter is the
94	/// remaining nibble.
95	ValueAtIncompleteKey(Vec<u8>, u8),
96	/// Corrupt Trie item
97	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
127/// Trie result type.
128/// Boxed to avoid copying around extra space for the `Hasher`s `Out` on successful queries.
129pub type Result<T, H, E> = crate::rstd::result::Result<T, Box<TrieError<H, E>>>;
130
131
132/// Trie-Item type used for iterators over trie data.
133pub type TrieItem<'a, U, E> = Result<(Vec<u8>, DBValue), U, E>;
134
135/// Description of what kind of query will be made to the trie.
136///
137/// This is implemented for any &mut recorder (where the query will return
138/// a DBValue), any function taking raw bytes (where no recording will be made),
139/// or any tuple of (&mut Recorder, FnOnce(&[u8]))
140pub trait Query<H: Hasher> {
141	/// Output item.
142	type Item;
143
144	/// Decode a byte-slice into the desired item.
145	fn decode(self, data: &[u8]) -> Self::Item;
146
147	/// Record that a node has been passed through.
148	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
172/// A key-value datastore implemented as a database-backed modified Merkle tree.
173pub trait Trie<L: TrieLayout> {
174	/// Return the root of the trie.
175	fn root(&self) -> &TrieHash<L>;
176
177	/// Is the trie empty?
178	fn is_empty(&self) -> bool { *self.root() == L::Codec::hashed_null_node() }
179
180	/// Does the trie contain a given key?
181	fn contains(&self, key: &[u8]) -> Result<bool, TrieHash<L>, CError<L>> {
182		self.get(key).map(|x| x.is_some() )
183	}
184
185	/// What is the value of the given key in this trie?
186	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	/// Search for the key with the given query parameter. See the docs of the `Query`
194	/// trait for more details.
195	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	/// Returns a depth-first iterator over the elements of trie.
202	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
209/// A key-value datastore implemented as a database-backed modified Merkle tree.
210pub trait TrieMut<L: TrieLayout> {
211	/// Return the root of the trie.
212	fn root(&mut self) -> &TrieHash<L>;
213
214	/// Is the trie empty?
215	fn is_empty(&self) -> bool;
216
217	/// Does the trie contain a given key?
218	fn contains(&self, key: &[u8]) -> Result<bool, TrieHash<L>, CError<L>> {
219		self.get(key).map(|x| x.is_some())
220	}
221
222	/// What is the value of the given key in this trie?
223	fn get<'a, 'key>(
224		&'a self,
225		key: &'key [u8],
226	) -> Result<Option<DBValue>, TrieHash<L>, CError<L>> where 'a: 'key;
227
228	/// Insert a `key`/`value` pair into the trie. An empty value is equivalent to removing
229	/// `key` from the trie. Returns the old value associated with this key, if it existed.
230	fn insert(
231		&mut self,
232		key: &[u8],
233		value: &[u8],
234	) -> Result<Option<DBValue>, TrieHash<L>, CError<L>>;
235
236	/// Remove a `key` from the trie. Equivalent to making it equal to the empty
237	/// value. Returns the old value associated with this key, if it existed.
238	fn remove(&mut self, key: &[u8]) -> Result<Option<DBValue>, TrieHash<L>, CError<L>>;
239}
240
241/// A trie iterator that also supports random access (`seek()`).
242pub trait TrieIterator<L: TrieLayout>: Iterator {
243	/// Position the iterator on the first element with key >= `key`
244	fn seek(&mut self, key: &[u8]) -> Result<(), TrieHash<L>, CError<L>>;
245}
246
247/// Trie types
248#[derive(PartialEq, Clone)]
249#[cfg_attr(feature = "std", derive(Debug))]
250pub enum TrieSpec {
251	/// Generic trie.
252	Generic,
253	/// Secure trie.
254	Secure,
255	///	Secure trie with fat database.
256	Fat,
257}
258
259impl Default for TrieSpec {
260	fn default() -> TrieSpec {
261		TrieSpec::Secure
262	}
263}
264
265/// Trie factory.
266#[derive(Default, Clone)]
267pub struct TrieFactory<L: TrieLayout> {
268	spec: TrieSpec,
269	layout: L,
270}
271
272/// All different kinds of tries.
273/// This is used to prevent a heap allocation for every created trie.
274pub enum TrieKinds<'db, L: TrieLayout> {
275	/// A generic trie db.
276	Generic(TrieDB<'db, L>),
277	/// A secure trie db.
278	Secure(SecTrieDB<'db, L>),
279	/// A fat trie db.
280	Fat(FatDB<'db, L>),
281}
282
283// wrapper macro for making the match easier to deal with.
284macro_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	/// Creates new factory.
330	pub fn new(spec: TrieSpec, layout: L) -> Self {
331		TrieFactory { spec, layout }
332	}
333
334	/// Create new immutable instance of Trie.
335	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	/// Create new mutable instance of Trie.
348	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	/// Create new mutable instance of trie and check for errors.
361	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	/// Returns true iff the trie DB is a fat DB (allows enumeration of keys).
374	pub fn is_fat(&self) -> bool { self.spec == TrieSpec::Fat }
375}
376
377/// Trait with definition of trie layout.
378/// Contains all associated trait needed for
379/// a trie definition or implementation.
380pub trait TrieLayout {
381	/// If true, the trie will use extension nodes and
382	/// no partial in branch, if false the trie will only
383	/// use branch and node with partials in both.
384	const USE_EXTENSION: bool;
385	/// If true, the trie will allow empty values into `TrieDBMut`
386	const ALLOW_EMPTY: bool = false;
387	/// Hasher to use for this trie.
388	type Hash: Hasher;
389	/// Codec to use (needs to match hasher and nibble ops).
390	type Codec: NodeCodec<HashOut=<Self::Hash as Hasher>::Out>;
391}
392
393/// This trait associates a trie definition with preferred methods.
394/// It also contains own default implementations and can be
395/// used to allow switching implementation.
396pub trait TrieConfiguration: Sized + TrieLayout {
397	/// Operation to build a trie db from its ordered iterator over its key/values.
398	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	/// Determines a trie root given its ordered contents, closed form.
409	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	/// Determines a trie root node's data given its ordered contents, closed form.
419	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	/// Encoding of index as a key (when reusing general trie for
429	/// indexed trie).
430	fn encode_index(input: u32) -> Vec<u8> {
431		// be for byte ordering
432		input.to_be_bytes().to_vec()
433	}
434	/// A trie root formed from the items, with keys attached according to their
435	/// compact-encoded index (using `parity-codec` crate).
436	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
449/// Alias accessor to hasher hash output type from a `TrieLayout`.
450pub type TrieHash<L> = <<L as TrieLayout>::Hash as Hasher>::Out;
451/// Alias accessor to `NodeCodec` associated `Error` type from a `TrieLayout`.
452pub type CError<L> = <<L as TrieLayout>::Codec as NodeCodec>::Error;