2016-02-05 13:40:41 +01:00
|
|
|
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
|
|
|
// This file is part of Parity.
|
|
|
|
|
|
|
|
// Parity is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
|
|
|
|
// Parity is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
2016-02-01 15:22:42 +01:00
|
|
|
//! Trie interface and implementation.
|
|
|
|
|
2016-06-07 20:44:09 +02:00
|
|
|
use std::fmt;
|
2016-06-27 10:59:59 +02:00
|
|
|
use hash::H256;
|
2016-10-26 13:53:47 +02:00
|
|
|
use hashdb::{HashDB, DBValue};
|
2016-06-07 20:44:09 +02:00
|
|
|
|
2016-02-03 14:51:45 +01:00
|
|
|
/// Export the standardmap module.
|
2015-12-19 13:35:26 +01:00
|
|
|
pub mod standardmap;
|
2016-02-03 14:51:45 +01:00
|
|
|
/// Export the journal module.
|
2015-12-19 13:35:26 +01:00
|
|
|
pub mod journal;
|
2016-02-03 14:51:45 +01:00
|
|
|
/// Export the node module.
|
2015-12-19 13:35:26 +01:00
|
|
|
pub mod node;
|
2016-02-03 14:51:45 +01:00
|
|
|
/// Export the triedb module.
|
2015-12-19 13:35:26 +01:00
|
|
|
pub mod triedb;
|
2016-02-03 14:51:45 +01:00
|
|
|
/// Export the triedbmut module.
|
2015-12-19 13:35:26 +01:00
|
|
|
pub mod triedbmut;
|
2016-02-03 14:51:45 +01:00
|
|
|
/// Export the sectriedb module.
|
2016-01-06 13:53:23 +01:00
|
|
|
pub mod sectriedb;
|
2016-02-03 14:51:45 +01:00
|
|
|
/// Export the sectriedbmut module.
|
2016-01-06 13:53:23 +01:00
|
|
|
pub mod sectriedbmut;
|
2016-08-24 16:53:36 +02:00
|
|
|
/// Trie query recording.
|
|
|
|
pub mod recorder;
|
|
|
|
|
2015-12-19 13:35:26 +01:00
|
|
|
|
2016-06-27 09:16:34 +02:00
|
|
|
mod fatdb;
|
2016-06-27 10:59:59 +02:00
|
|
|
mod fatdbmut;
|
|
|
|
|
2016-06-07 20:44:09 +02:00
|
|
|
pub use self::standardmap::{Alphabet, StandardMap, ValueMode};
|
|
|
|
pub use self::triedbmut::TrieDBMut;
|
2016-06-27 09:16:34 +02:00
|
|
|
pub use self::triedb::{TrieDB, TrieDBIterator};
|
2016-06-07 20:44:09 +02:00
|
|
|
pub use self::sectriedbmut::SecTrieDBMut;
|
|
|
|
pub use self::sectriedb::SecTrieDB;
|
2016-06-27 09:16:34 +02:00
|
|
|
pub use self::fatdb::{FatDB, FatDBIterator};
|
2016-06-27 10:59:59 +02:00
|
|
|
pub use self::fatdbmut::FatDBMut;
|
2016-08-24 16:53:36 +02:00
|
|
|
pub use self::recorder::Recorder;
|
2016-06-07 20:44:09 +02:00
|
|
|
|
2016-08-03 18:35:48 +02:00
|
|
|
/// Trie Errors.
|
|
|
|
///
|
|
|
|
/// These borrow the data within them to avoid excessive copying on every
|
|
|
|
/// trie operation.
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
2016-06-07 20:44:09 +02:00
|
|
|
pub enum TrieError {
|
|
|
|
/// Attempted to create a trie with a state root not in the DB.
|
2016-08-03 18:35:48 +02:00
|
|
|
InvalidStateRoot(H256),
|
|
|
|
/// Trie item not found in the database,
|
|
|
|
IncompleteDatabase(H256),
|
2016-06-07 20:44:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for TrieError {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2016-08-03 18:35:48 +02:00
|
|
|
match *self {
|
|
|
|
TrieError::InvalidStateRoot(ref root) => write!(f, "Invalid state root: {}", root),
|
|
|
|
TrieError::IncompleteDatabase(ref missing) =>
|
|
|
|
write!(f, "Database missing expected key: {}", missing),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Trie result type. Boxed to avoid copying around extra space for `H256`s on successful queries.
|
|
|
|
pub type Result<T> = ::std::result::Result<T, Box<TrieError>>;
|
|
|
|
|
2016-09-21 12:56:13 +02:00
|
|
|
/// Trie-Item type.
|
2016-10-26 13:53:47 +02:00
|
|
|
pub type TrieItem<'a> = Result<(Vec<u8>, DBValue)>;
|
2016-09-21 12:56:13 +02:00
|
|
|
|
2016-08-03 18:35:48 +02:00
|
|
|
/// A key-value datastore implemented as a database-backed modified Merkle tree.
|
|
|
|
pub trait Trie {
|
|
|
|
/// Return the root of the trie.
|
|
|
|
fn root(&self) -> &H256;
|
|
|
|
|
|
|
|
/// Is the trie empty?
|
2016-09-01 13:36:32 +02:00
|
|
|
fn is_empty(&self) -> bool { *self.root() == ::sha3::SHA3_NULL_RLP }
|
2016-08-03 18:35:48 +02:00
|
|
|
|
|
|
|
/// Does the trie contain a given key?
|
|
|
|
fn contains(&self, key: &[u8]) -> Result<bool> {
|
|
|
|
self.get(key).map(|x| x.is_some())
|
2016-06-07 20:44:09 +02:00
|
|
|
}
|
2016-08-03 18:35:48 +02:00
|
|
|
|
|
|
|
/// What is the value of the given key in this trie?
|
2016-10-26 13:53:47 +02:00
|
|
|
fn get<'a, 'key>(&'a self, key: &'key [u8]) -> Result<Option<DBValue>> where 'a: 'key {
|
2016-08-24 16:53:36 +02:00
|
|
|
self.get_recorded(key, &mut recorder::NoOp)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Query the value of the given key in this trie while recording visited nodes
|
2016-11-15 14:53:30 +01:00
|
|
|
/// to the given recorder. If the query encounters an error, the nodes passed to the recorder are unspecified.
|
2016-10-26 13:53:47 +02:00
|
|
|
fn get_recorded<'a, 'b, R: 'b>(&'a self, key: &'b [u8], rec: &'b mut R) -> Result<Option<DBValue>>
|
2016-08-24 16:53:36 +02:00
|
|
|
where 'a: 'b, R: Recorder;
|
2016-08-03 18:35:48 +02:00
|
|
|
|
2016-12-02 10:06:09 +01:00
|
|
|
/// Returns a depth-first iterator over the elements of trie.
|
2016-11-24 11:44:24 +01:00
|
|
|
fn iter<'a>(&'a self) -> Result<Box<TrieIterator<Item = TrieItem> + 'a>>;
|
2016-06-27 09:16:34 +02:00
|
|
|
}
|
2016-06-27 10:59:59 +02:00
|
|
|
|
2016-08-03 18:35:48 +02:00
|
|
|
/// A key-value datastore implemented as a database-backed modified Merkle tree.
|
|
|
|
pub trait TrieMut {
|
|
|
|
/// Return the root of the trie.
|
|
|
|
fn root(&mut self) -> &H256;
|
|
|
|
|
|
|
|
/// Is the trie empty?
|
|
|
|
fn is_empty(&self) -> bool;
|
|
|
|
|
|
|
|
/// Does the trie contain a given key?
|
|
|
|
fn contains(&self, key: &[u8]) -> Result<bool> {
|
|
|
|
self.get(key).map(|x| x.is_some())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// What is the value of the given key in this trie?
|
2016-10-26 13:53:47 +02:00
|
|
|
fn get<'a, 'key>(&'a self, key: &'key [u8]) -> Result<Option<DBValue>> where 'a: 'key;
|
2016-08-03 18:35:48 +02:00
|
|
|
|
|
|
|
/// Insert a `key`/`value` pair into the trie. An `empty` value is equivalent to removing
|
|
|
|
/// `key` from the trie.
|
|
|
|
fn insert(&mut self, key: &[u8], value: &[u8]) -> Result<()>;
|
|
|
|
|
|
|
|
/// Remove a `key` from the trie. Equivalent to making it equal to the empty
|
|
|
|
/// value.
|
|
|
|
fn remove(&mut self, key: &[u8]) -> Result<()>;
|
|
|
|
}
|
|
|
|
|
2016-11-24 11:44:24 +01:00
|
|
|
/// A trie iterator that also supports random access.
|
|
|
|
pub trait TrieIterator : Iterator {
|
2016-11-27 11:11:56 +01:00
|
|
|
/// Position the iterator on the first element with key > `key`
|
2016-11-24 11:44:24 +01:00
|
|
|
fn seek(&mut self, key: &[u8]) -> Result<()>;
|
|
|
|
}
|
|
|
|
|
2016-06-27 10:59:59 +02:00
|
|
|
/// Trie types
|
2016-07-25 16:09:47 +02:00
|
|
|
#[derive(Debug, PartialEq, Clone)]
|
2016-06-27 10:59:59 +02:00
|
|
|
pub enum TrieSpec {
|
2016-06-27 11:19:27 +02:00
|
|
|
/// Generic trie.
|
|
|
|
Generic,
|
2016-06-27 10:59:59 +02:00
|
|
|
/// Secure trie.
|
|
|
|
Secure,
|
|
|
|
/// Secure trie with fat database.
|
|
|
|
Fat,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for TrieSpec {
|
|
|
|
fn default() -> TrieSpec {
|
|
|
|
TrieSpec::Secure
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Trie factory.
|
|
|
|
#[derive(Default, Clone)]
|
|
|
|
pub struct TrieFactory {
|
|
|
|
spec: TrieSpec,
|
|
|
|
}
|
|
|
|
|
2016-08-24 16:53:36 +02:00
|
|
|
/// All different kinds of tries.
|
|
|
|
/// This is used to prevent a heap allocation for every created trie.
|
|
|
|
pub enum TrieKinds<'db> {
|
|
|
|
/// A generic trie db.
|
|
|
|
Generic(TrieDB<'db>),
|
|
|
|
/// A secure trie db.
|
|
|
|
Secure(SecTrieDB<'db>),
|
|
|
|
/// A fat trie db.
|
|
|
|
Fat(FatDB<'db>),
|
|
|
|
}
|
|
|
|
|
|
|
|
// wrapper macro for making the match easier to deal with.
|
|
|
|
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> Trie for TrieKinds<'db> {
|
|
|
|
fn root(&self) -> &H256 {
|
|
|
|
wrapper!(self, root,)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_empty(&self) -> bool {
|
|
|
|
wrapper!(self, is_empty,)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn contains(&self, key: &[u8]) -> Result<bool> {
|
|
|
|
wrapper!(self, contains, key)
|
|
|
|
}
|
|
|
|
|
2016-10-26 13:53:47 +02:00
|
|
|
fn get_recorded<'a, 'b, R: 'b>(&'a self, key: &'b [u8], r: &'b mut R) -> Result<Option<DBValue>>
|
2016-08-24 16:53:36 +02:00
|
|
|
where 'a: 'b, R: Recorder {
|
|
|
|
wrapper!(self, get_recorded, key, r)
|
|
|
|
}
|
|
|
|
|
2016-11-24 11:44:24 +01:00
|
|
|
fn iter<'a>(&'a self) -> Result<Box<TrieIterator<Item = TrieItem> + 'a>> {
|
2016-08-24 16:53:36 +02:00
|
|
|
wrapper!(self, iter,)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-04 13:53:55 +02:00
|
|
|
#[cfg_attr(feature="dev", allow(wrong_self_convention))]
|
2016-06-27 10:59:59 +02:00
|
|
|
impl TrieFactory {
|
|
|
|
/// Creates new factory.
|
|
|
|
pub fn new(spec: TrieSpec) -> Self {
|
|
|
|
TrieFactory {
|
|
|
|
spec: spec,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Create new immutable instance of Trie.
|
2016-08-24 16:53:36 +02:00
|
|
|
pub fn readonly<'db>(&self, db: &'db HashDB, root: &'db H256) -> Result<TrieKinds<'db>> {
|
2016-06-27 10:59:59 +02:00
|
|
|
match self.spec {
|
2016-08-24 16:53:36 +02:00
|
|
|
TrieSpec::Generic => Ok(TrieKinds::Generic(try!(TrieDB::new(db, root)))),
|
|
|
|
TrieSpec::Secure => Ok(TrieKinds::Secure(try!(SecTrieDB::new(db, root)))),
|
|
|
|
TrieSpec::Fat => Ok(TrieKinds::Fat(try!(FatDB::new(db, root)))),
|
2016-06-27 10:59:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Create new mutable instance of Trie.
|
2016-06-27 13:50:08 +02:00
|
|
|
pub fn create<'db>(&self, db: &'db mut HashDB, root: &'db mut H256) -> Box<TrieMut + 'db> {
|
2016-06-27 10:59:59 +02:00
|
|
|
match self.spec {
|
2016-06-27 11:19:27 +02:00
|
|
|
TrieSpec::Generic => Box::new(TrieDBMut::new(db, root)),
|
|
|
|
TrieSpec::Secure => Box::new(SecTrieDBMut::new(db, root)),
|
|
|
|
TrieSpec::Fat => Box::new(FatDBMut::new(db, root)),
|
2016-06-27 10:59:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Create new mutable instance of trie and check for errors.
|
2016-08-03 18:35:48 +02:00
|
|
|
pub fn from_existing<'db>(&self, db: &'db mut HashDB, root: &'db mut H256) -> Result<Box<TrieMut + 'db>> {
|
2016-06-27 10:59:59 +02:00
|
|
|
match self.spec {
|
2016-06-27 11:19:27 +02:00
|
|
|
TrieSpec::Generic => Ok(Box::new(try!(TrieDBMut::from_existing(db, root)))),
|
2016-06-27 10:59:59 +02:00
|
|
|
TrieSpec::Secure => Ok(Box::new(try!(SecTrieDBMut::from_existing(db, root)))),
|
|
|
|
TrieSpec::Fat => Ok(Box::new(try!(FatDBMut::from_existing(db, root)))),
|
|
|
|
}
|
|
|
|
}
|
2016-10-03 11:13:10 +02:00
|
|
|
|
|
|
|
/// Returns true iff the trie DB is a fat DB (allows enumeration of keys).
|
2016-11-15 14:53:30 +01:00
|
|
|
pub fn is_fat(&self) -> bool { self.spec == TrieSpec::Fat }
|
2016-06-27 10:59:59 +02:00
|
|
|
}
|