#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(not(feature = "std"))]
extern crate alloc;
#[cfg(feature = "std")]
mod rstd {
pub use std::{
borrow, boxed, cmp,
collections::{BTreeMap, VecDeque},
convert,
error::Error,
fmt, hash, iter, marker, mem, ops, result, sync, vec,
};
}
#[cfg(not(feature = "std"))]
mod rstd {
pub use alloc::{
borrow, boxed,
collections::{btree_map::BTreeMap, VecDeque},
rc, sync, vec,
};
pub use core::{cmp, convert, fmt, hash, iter, marker, mem, ops, result};
pub trait Error {}
impl<T> Error for T {}
}
#[cfg(feature = "std")]
use self::rstd::{fmt, Error};
use self::rstd::{boxed::Box, vec::Vec};
use hash_db::MaybeDebug;
pub use iterator::TrieDBNodeDoubleEndedIterator;
use node::NodeOwned;
pub mod node;
pub mod proof;
pub mod recorder;
pub mod sectriedb;
pub mod sectriedbmut;
pub mod triedb;
pub mod triedbmut;
mod fatdb;
mod fatdbmut;
mod iter_build;
mod iterator;
mod lookup;
mod nibble;
mod node_codec;
mod trie_codec;
pub use self::{
fatdb::{FatDB, FatDBIterator},
fatdbmut::FatDBMut,
lookup::Lookup,
nibble::{nibble_ops, NibbleSlice, NibbleVec},
recorder::Recorder,
sectriedb::SecTrieDB,
sectriedbmut::SecTrieDBMut,
triedb::{TrieDB, TrieDBBuilder, TrieDBIterator, TrieDBKeyIterator},
triedbmut::{ChildReference, TrieDBMut, TrieDBMutBuilder, Value},
};
pub use crate::{
iter_build::{trie_visit, ProcessEncodedNode, TrieBuilder, TrieRoot, TrieRootUnhashed},
iterator::{TrieDBNodeIterator, TrieDBRawIterator},
node_codec::{NodeCodec, Partial},
trie_codec::{decode_compact, decode_compact_from_iter, encode_compact},
};
pub use hash_db::{HashDB, HashDBRef, Hasher};
#[cfg(feature = "std")]
pub use crate::iter_build::TrieRootPrint;
pub type DBValue = Vec<u8>;
#[derive(PartialEq, Eq, Clone, Debug)]
pub enum TrieError<T, E> {
InvalidStateRoot(T),
IncompleteDatabase(T),
ValueAtIncompleteKey(Vec<u8>, u8),
DecoderError(T, E),
InvalidHash(T, Vec<u8>),
}
#[cfg(feature = "std")]
impl<T, E> fmt::Display for TrieError<T, E>
where
T: MaybeDebug,
E: MaybeDebug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
TrieError::InvalidStateRoot(ref root) => write!(f, "Invalid state root: {:?}", root),
TrieError::IncompleteDatabase(ref missing) =>
write!(f, "Database missing expected key: {:?}", missing),
TrieError::ValueAtIncompleteKey(ref bytes, ref extra) =>
write!(f, "Value found in trie at incomplete key {:?} + {:?}", bytes, extra),
TrieError::DecoderError(ref hash, ref decoder_err) => {
write!(f, "Decoding failed for hash {:?}; err: {:?}", hash, decoder_err)
},
TrieError::InvalidHash(ref hash, ref data) => write!(
f,
"Encoded node {:?} contains invalid hash reference with length: {}",
hash,
data.len()
),
}
}
}
#[cfg(feature = "std")]
impl<T, E> Error for TrieError<T, E>
where
T: fmt::Debug,
E: Error,
{
}
pub type Result<T, H, E> = crate::rstd::result::Result<T, Box<TrieError<H, E>>>;
pub type TrieItem<U, E> = Result<(Vec<u8>, DBValue), U, E>;
pub type TrieKeyItem<U, E> = Result<Vec<u8>, U, E>;
pub trait Query<H: Hasher> {
type Item;
fn decode(self, data: &[u8]) -> Self::Item;
}
#[cfg_attr(feature = "std", derive(Debug))]
pub enum TrieAccess<'a, H> {
NodeOwned { hash: H, node_owned: &'a NodeOwned<H> },
EncodedNode { hash: H, encoded_node: rstd::borrow::Cow<'a, [u8]> },
Value { hash: H, value: rstd::borrow::Cow<'a, [u8]>, full_key: &'a [u8] },
InlineValue { full_key: &'a [u8] },
Hash { full_key: &'a [u8] },
NonExisting { full_key: &'a [u8] },
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RecordedForKey {
Value,
Hash,
None,
}
impl RecordedForKey {
pub fn is_none(&self) -> bool {
matches!(self, Self::None)
}
}
pub trait TrieRecorder<H> {
fn record<'a>(&mut self, access: TrieAccess<'a, H>);
fn trie_nodes_recorded_for_key(&self, key: &[u8]) -> RecordedForKey;
}
impl<F, T, H: Hasher> Query<H> for F
where
F: for<'a> FnOnce(&'a [u8]) -> T,
{
type Item = T;
fn decode(self, value: &[u8]) -> T {
(self)(value)
}
}
pub trait Trie<L: TrieLayout> {
fn root(&self) -> &TrieHash<L>;
fn is_empty(&self) -> bool {
*self.root() == L::Codec::hashed_null_node()
}
fn contains(&self, key: &[u8]) -> Result<bool, TrieHash<L>, CError<L>> {
self.get(key).map(|x| x.is_some())
}
fn get_hash(&self, key: &[u8]) -> Result<Option<TrieHash<L>>, TrieHash<L>, CError<L>>;
fn get(&self, key: &[u8]) -> Result<Option<DBValue>, TrieHash<L>, CError<L>> {
self.get_with(key, |v: &[u8]| v.to_vec())
}
fn get_with<Q: Query<L::Hash>>(
&self,
key: &[u8],
query: Q,
) -> Result<Option<Q::Item>, TrieHash<L>, CError<L>>;
fn lookup_first_descendant(
&self,
key: &[u8],
) -> Result<Option<MerkleValue<TrieHash<L>>>, TrieHash<L>, CError<L>>;
fn iter<'a>(
&'a self,
) -> Result<
Box<dyn TrieIterator<L, Item = TrieItem<TrieHash<L>, CError<L>>> + 'a>,
TrieHash<L>,
CError<L>,
>;
fn key_iter<'a>(
&'a self,
) -> Result<
Box<dyn TrieIterator<L, Item = TrieKeyItem<TrieHash<L>, CError<L>>> + 'a>,
TrieHash<L>,
CError<L>,
>;
}
pub trait TrieMut<L: TrieLayout> {
fn root(&mut self) -> &TrieHash<L>;
fn is_empty(&self) -> bool;
fn contains(&self, key: &[u8]) -> Result<bool, TrieHash<L>, CError<L>> {
self.get(key).map(|x| x.is_some())
}
fn get<'a, 'key>(&'a self, key: &'key [u8]) -> Result<Option<DBValue>, TrieHash<L>, CError<L>>
where
'a: 'key;
fn insert(
&mut self,
key: &[u8],
value: &[u8],
) -> Result<Option<Value<L>>, TrieHash<L>, CError<L>>;
fn remove(&mut self, key: &[u8]) -> Result<Option<Value<L>>, TrieHash<L>, CError<L>>;
}
pub trait TrieIterator<L: TrieLayout>: Iterator {
fn seek(&mut self, key: &[u8]) -> Result<(), TrieHash<L>, CError<L>>;
}
pub trait TrieDoubleEndedIterator<L: TrieLayout>: TrieIterator<L> + DoubleEndedIterator {}
#[derive(PartialEq, Clone)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum TrieSpec {
Generic,
Secure,
Fat,
}
impl Default for TrieSpec {
fn default() -> TrieSpec {
TrieSpec::Secure
}
}
#[derive(Default, Clone)]
pub struct TrieFactory {
spec: TrieSpec,
}
pub enum TrieKinds<'db, 'cache, L: TrieLayout> {
Generic(TrieDB<'db, 'cache, L>),
Secure(SecTrieDB<'db, 'cache, L>),
Fat(FatDB<'db, 'cache, L>),
}
macro_rules! wrapper {
($me: ident, $f_name: ident, $($param: ident),*) => {
match *$me {
TrieKinds::Generic(ref t) => t.$f_name($($param),*),
TrieKinds::Secure(ref t) => t.$f_name($($param),*),
TrieKinds::Fat(ref t) => t.$f_name($($param),*),
}
}
}
impl<'db, 'cache, L: TrieLayout> Trie<L> for TrieKinds<'db, 'cache, L> {
fn root(&self) -> &TrieHash<L> {
wrapper!(self, root,)
}
fn is_empty(&self) -> bool {
wrapper!(self, is_empty,)
}
fn contains(&self, key: &[u8]) -> Result<bool, TrieHash<L>, CError<L>> {
wrapper!(self, contains, key)
}
fn get_hash(&self, key: &[u8]) -> Result<Option<TrieHash<L>>, TrieHash<L>, CError<L>> {
wrapper!(self, get_hash, key)
}
fn get_with<Q: Query<L::Hash>>(
&self,
key: &[u8],
query: Q,
) -> Result<Option<Q::Item>, TrieHash<L>, CError<L>> {
wrapper!(self, get_with, key, query)
}
fn lookup_first_descendant(
&self,
key: &[u8],
) -> Result<Option<MerkleValue<TrieHash<L>>>, TrieHash<L>, CError<L>> {
wrapper!(self, lookup_first_descendant, key)
}
fn iter<'a>(
&'a self,
) -> Result<
Box<dyn TrieIterator<L, Item = TrieItem<TrieHash<L>, CError<L>>> + 'a>,
TrieHash<L>,
CError<L>,
> {
wrapper!(self, iter,)
}
fn key_iter<'a>(
&'a self,
) -> Result<
Box<dyn TrieIterator<L, Item = TrieKeyItem<TrieHash<L>, CError<L>>> + 'a>,
TrieHash<L>,
CError<L>,
> {
wrapper!(self, key_iter,)
}
}
impl TrieFactory {
pub fn new(spec: TrieSpec) -> Self {
TrieFactory { spec }
}
pub fn readonly<'db, 'cache, L: TrieLayout>(
&self,
db: &'db dyn HashDBRef<L::Hash, DBValue>,
root: &'db TrieHash<L>,
) -> TrieKinds<'db, 'cache, L> {
match self.spec {
TrieSpec::Generic => TrieKinds::Generic(TrieDBBuilder::new(db, root).build()),
TrieSpec::Secure => TrieKinds::Secure(SecTrieDB::new(db, root)),
TrieSpec::Fat => TrieKinds::Fat(FatDB::new(db, root)),
}
}
pub fn create<'db, L: TrieLayout + 'db>(
&self,
db: &'db mut dyn HashDB<L::Hash, DBValue>,
root: &'db mut TrieHash<L>,
) -> Box<dyn TrieMut<L> + 'db> {
match self.spec {
TrieSpec::Generic => Box::new(TrieDBMutBuilder::<L>::new(db, root).build()),
TrieSpec::Secure => Box::new(SecTrieDBMut::<L>::new(db, root)),
TrieSpec::Fat => Box::new(FatDBMut::<L>::new(db, root)),
}
}
pub fn from_existing<'db, L: TrieLayout + 'db>(
&self,
db: &'db mut dyn HashDB<L::Hash, DBValue>,
root: &'db mut TrieHash<L>,
) -> Box<dyn TrieMut<L> + 'db> {
match self.spec {
TrieSpec::Generic => Box::new(TrieDBMutBuilder::<L>::from_existing(db, root).build()),
TrieSpec::Secure => Box::new(SecTrieDBMut::<L>::from_existing(db, root)),
TrieSpec::Fat => Box::new(FatDBMut::<L>::from_existing(db, root)),
}
}
pub fn is_fat(&self) -> bool {
self.spec == TrieSpec::Fat
}
}
pub trait TrieLayout {
const USE_EXTENSION: bool;
const ALLOW_EMPTY: bool = false;
const MAX_INLINE_VALUE: Option<u32>;
type Hash: Hasher;
type Codec: NodeCodec<HashOut = <Self::Hash as Hasher>::Out>;
}
pub trait TrieConfiguration: Sized + TrieLayout {
fn trie_build<DB, I, A, B>(db: &mut DB, input: I) -> <Self::Hash as Hasher>::Out
where
DB: HashDB<Self::Hash, DBValue>,
I: IntoIterator<Item = (A, B)>,
A: AsRef<[u8]> + Ord,
B: AsRef<[u8]>,
{
let mut cb = TrieBuilder::<Self, DB>::new(db);
trie_visit::<Self, _, _, _, _>(input.into_iter(), &mut cb);
cb.root.unwrap_or_default()
}
fn trie_root<I, A, B>(input: I) -> <Self::Hash as Hasher>::Out
where
I: IntoIterator<Item = (A, B)>,
A: AsRef<[u8]> + Ord,
B: AsRef<[u8]>,
{
let mut cb = TrieRoot::<Self>::default();
trie_visit::<Self, _, _, _, _>(input.into_iter(), &mut cb);
cb.root.unwrap_or_default()
}
fn trie_root_unhashed<I, A, B>(input: I) -> Vec<u8>
where
I: IntoIterator<Item = (A, B)>,
A: AsRef<[u8]> + Ord,
B: AsRef<[u8]>,
{
let mut cb = TrieRootUnhashed::<Self>::default();
trie_visit::<Self, _, _, _, _>(input.into_iter(), &mut cb);
cb.root.unwrap_or_default()
}
fn encode_index(input: u32) -> Vec<u8> {
input.to_be_bytes().to_vec()
}
fn ordered_trie_root<I, A>(input: I) -> <Self::Hash as Hasher>::Out
where
I: IntoIterator<Item = A>,
A: AsRef<[u8]>,
{
Self::trie_root(
input.into_iter().enumerate().map(|(i, v)| (Self::encode_index(i as u32), v)),
)
}
}
pub type TrieHash<L> = <<L as TrieLayout>::Hash as Hasher>::Out;
pub type CError<L> = <<L as TrieLayout>::Codec as NodeCodec>::Error;
#[derive(Clone, Debug)]
pub enum CachedValue<H> {
NonExisting,
ExistingHash(H),
Existing {
hash: H,
data: BytesWeak,
},
}
impl<H: Copy> CachedValue<H> {
pub fn data(&self) -> Option<Option<Bytes>> {
match self {
Self::Existing { data, .. } => Some(data.upgrade()),
_ => None,
}
}
pub fn hash(&self) -> Option<H> {
match self {
Self::ExistingHash(hash) | Self::Existing { hash, .. } => Some(*hash),
Self::NonExisting => None,
}
}
}
impl<H> From<(Bytes, H)> for CachedValue<H> {
fn from(value: (Bytes, H)) -> Self {
Self::Existing { hash: value.1, data: value.0.into() }
}
}
impl<H> From<H> for CachedValue<H> {
fn from(value: H) -> Self {
Self::ExistingHash(value)
}
}
impl<H> From<Option<(Bytes, H)>> for CachedValue<H> {
fn from(value: Option<(Bytes, H)>) -> Self {
value.map_or(Self::NonExisting, |v| Self::Existing { hash: v.1, data: v.0.into() })
}
}
impl<H> From<Option<H>> for CachedValue<H> {
fn from(value: Option<H>) -> Self {
value.map_or(Self::NonExisting, |v| Self::ExistingHash(v))
}
}
pub trait TrieCache<NC: NodeCodec> {
fn lookup_value_for_key(&mut self, key: &[u8]) -> Option<&CachedValue<NC::HashOut>>;
fn cache_value_for_key(&mut self, key: &[u8], value: CachedValue<NC::HashOut>);
fn get_or_insert_node(
&mut self,
hash: NC::HashOut,
fetch_node: &mut dyn FnMut() -> Result<NodeOwned<NC::HashOut>, NC::HashOut, NC::Error>,
) -> Result<&NodeOwned<NC::HashOut>, NC::HashOut, NC::Error>;
fn get_node(&mut self, hash: &NC::HashOut) -> Option<&NodeOwned<NC::HashOut>>;
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Bytes(rstd::sync::Arc<[u8]>);
impl rstd::ops::Deref for Bytes {
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.0.deref()
}
}
impl From<Vec<u8>> for Bytes {
fn from(bytes: Vec<u8>) -> Self {
Self(bytes.into())
}
}
impl From<&[u8]> for Bytes {
fn from(bytes: &[u8]) -> Self {
Self(bytes.into())
}
}
impl<T: AsRef<[u8]>> PartialEq<T> for Bytes {
fn eq(&self, other: &T) -> bool {
self.as_ref() == other.as_ref()
}
}
#[derive(Clone, Debug)]
pub struct BytesWeak(rstd::sync::Weak<[u8]>);
impl BytesWeak {
pub fn upgrade(&self) -> Option<Bytes> {
self.0.upgrade().map(Bytes)
}
}
impl From<Bytes> for BytesWeak {
fn from(bytes: Bytes) -> Self {
Self(rstd::sync::Arc::downgrade(&bytes.0))
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum MerkleValue<H> {
Node(Vec<u8>),
Hash(H),
}