From 013666f3c5bd0e23d72338c4d76151aba3ca743b Mon Sep 17 00:00:00 2001 From: David Palm Date: Wed, 30 May 2018 12:23:15 +0200 Subject: [PATCH] TrieDB, TrieDBMut, SecTrieDB, FatDB typechecks --- util/patricia_trie/src/fatdb.rs | 52 ++++----- util/patricia_trie/src/fatdbmut.rs | 29 +++-- util/patricia_trie/src/lib.rs | 141 ++++++++++++------------ util/patricia_trie/src/lookup.rs | 13 +-- util/patricia_trie/src/node.rs | 9 +- util/patricia_trie/src/recorder.rs | 8 +- util/patricia_trie/src/sectriedb.rs | 23 ++-- util/patricia_trie/src/sectriedbmut.rs | 13 ++- util/patricia_trie/src/triedb.rs | 89 ++++++++------- util/patricia_trie/src/triedbmut.rs | 144 ++++++++++++------------- 10 files changed, 254 insertions(+), 267 deletions(-) diff --git a/util/patricia_trie/src/fatdb.rs b/util/patricia_trie/src/fatdb.rs index 4cdd131c95a..3d96564c934 100644 --- a/util/patricia_trie/src/fatdb.rs +++ b/util/patricia_trie/src/fatdb.rs @@ -14,10 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use ethereum_types::H256; -use keccak::keccak; use hashdb::{HashDB, Hasher}; use super::{TrieDB, Trie, TrieDBIterator, TrieItem, TrieIterator, Query}; +use rlp::{Decodable, Encodable}; /// A `Trie` implementation which hashes keys and uses a generic `HashDB` backing database. /// Additionaly it stores inserted hash-key mappings for later retrieval. @@ -27,43 +26,35 @@ pub struct FatDB<'db, H: Hasher + 'db> { raw: TrieDB<'db, H>, } -impl<'db, H: Hasher> FatDB<'db, H> { +impl<'db, H: Hasher> FatDB<'db, H> where H::Out: Decodable { /// Create a new trie with the backing database `db` and empty `root` /// Initialise to the state entailed by the genesis block. /// This guarantees the trie is built correctly. - pub fn new(db: &'db HashDB, root: &'db H256) -> super::Result { - let fatdb = FatDB { - raw: TrieDB::new(db, root)? - }; - - Ok(fatdb) + pub fn new(db: &'db HashDB, root: &'db H::Out) -> super::Result { + Ok(FatDB { raw: TrieDB::new(db, root)? }) } /// Get the backing database. - pub fn db(&self) -> &HashDB { - self.raw.db() - } + pub fn db(&self) -> &HashDB { self.raw.db() } } -impl<'db, H: Hasher> Trie for FatDB<'db, H> { +impl<'db, H: Hasher> Trie for FatDB<'db, H> where H::Out: Decodable + Encodable { type H = H; - fn root(&self) -> &::Out { - self.raw.root() - } + fn root(&self) -> &::Out { self.raw.root() } - fn contains(&self, key: &[u8]) -> super::Result { - self.raw.contains(&keccak(key)) // TODO + fn contains(&self, key: &[u8]) -> super::Result::Out> { + self.raw.contains(&Self::H::hash(key).as_ref()) } - fn get_with<'a, 'key, Q: Query>(&'a self, key: &'key [u8], query: Q) -> super::Result> + fn get_with<'a, 'key, Q: Query>(&'a self, key: &'key [u8], query: Q) -> super::Result, ::Out> where 'a: 'key { - self.raw.get_with(&keccak(key), query) // TODO + self.raw.get_with(&Self::H::hash(key).as_ref(), query) } - fn iter<'a>(&'a self) -> super::Result + 'a>> { - FatDBIterator::new(&self.raw).map(|iter| Box::new(iter) as Box<_>) + fn iter<'a>(&'a self) -> super::Result> + 'a>, ::Out> { + FatDBIterator::::new(&self.raw).map(|iter| Box::new(iter) as Box<_>) } } @@ -73,9 +64,9 @@ pub struct FatDBIterator<'db, H: Hasher + 'db> { trie: &'db TrieDB<'db, H>, } -impl<'db, H: Hasher> FatDBIterator<'db, H> { +impl<'db, H: Hasher> FatDBIterator<'db, H> where H::Out: Decodable { /// Creates new iterator. - pub fn new(trie: &'db TrieDB) -> super::Result { + pub fn new(trie: &'db TrieDB) -> super::Result { Ok(FatDBIterator { trie_iterator: TrieDBIterator::new(trie)?, trie: trie, @@ -83,20 +74,21 @@ impl<'db, H: Hasher> FatDBIterator<'db, H> { } } -impl<'db, H: Hasher> TrieIterator for FatDBIterator<'db, H> { - fn seek(&mut self, key: &[u8]) -> super::Result<()> { - self.trie_iterator.seek(&keccak(key)) +impl<'db, H: Hasher> TrieIterator for FatDBIterator<'db, H> where H::Out: Decodable { + fn seek(&mut self, key: &[u8]) -> super::Result<(), H::Out> { + let hashed_key = H::hash(key); + self.trie_iterator.seek(&hashed_key.as_ref()) } } -impl<'db, H: Hasher> Iterator for FatDBIterator<'db, H> { - type Item = TrieItem<'db>; +impl<'db, H: Hasher> Iterator for FatDBIterator<'db, H> where H::Out: Decodable { + type Item = TrieItem<'db, H>; fn next(&mut self) -> Option { self.trie_iterator.next() .map(|res| res.map(|(hash, value)| { - let aux_hash = keccak(hash); + let aux_hash = &H::hash(&hash); (self.trie.db().get(&aux_hash).expect("Missing fatdb hash").into_vec(), value) }) ) diff --git a/util/patricia_trie/src/fatdbmut.rs b/util/patricia_trie/src/fatdbmut.rs index 1d007586365..57f691cf6dc 100644 --- a/util/patricia_trie/src/fatdbmut.rs +++ b/util/patricia_trie/src/fatdbmut.rs @@ -14,8 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use ethereum_types::H256; -use keccak::keccak; +//use ethereum_types::H256; +//use keccak::keccak; use hashdb::{HashDB, DBValue, Hasher}; use super::{TrieDBMut, TrieMut}; @@ -31,14 +31,14 @@ impl<'db, H: Hasher> FatDBMut<'db, H> { /// Create a new trie with the backing database `db` and empty `root` /// Initialise to the state entailed by the genesis block. /// This guarantees the trie is built correctly. - pub fn new(db: &'db mut HashDB, root: &'db mut H256) -> Self { + pub fn new(db: &'db mut HashDB, root: &'db mut H::Out) -> Self { FatDBMut { raw: TrieDBMut::new(db, root) } } /// Create a new trie with the backing database `db` and `root`. /// /// Returns an error if root does not exist. - pub fn from_existing(db: &'db mut HashDB, root: &'db mut H256) -> super::Result { + pub fn from_existing(db: &'db mut HashDB, root: &'db mut H::Out) -> super::Result { Ok(FatDBMut { raw: TrieDBMut::from_existing(db, root)? }) } @@ -52,33 +52,27 @@ impl<'db, H: Hasher> FatDBMut<'db, H> { self.raw.db_mut() } - fn to_aux_key(key: &[u8]) -> H256 { - keccak(key) - } // TODO + fn to_aux_key(key: &[u8]) -> H::Out { H::hash(key) } } impl<'db, H: Hasher> TrieMut for FatDBMut<'db, H> { type H = H; - fn root(&mut self) -> &::Out { - self.raw.root() - } + fn root(&mut self) -> &::Out { self.raw.root() } - fn is_empty(&self) -> bool { - self.raw.is_empty() - } + fn is_empty(&self) -> bool { self.raw.is_empty() } fn contains(&self, key: &[u8]) -> super::Result { - self.raw.contains(&keccak(key)) + self.raw.contains(Self::H::hash(key)) } fn get<'a, 'key>(&'a self, key: &'key [u8]) -> super::Result> where 'a: 'key { - self.raw.get(&keccak(key)) // TODO + self.raw.get(Self::H::hash(key)) } fn insert(&mut self, key: &[u8], value: &[u8]) -> super::Result> { - let hash = keccak(key); // TODO + let hash = Self::H::hash(key); let out = self.raw.insert(&hash, value)?; let db = self.raw.db_mut(); @@ -90,7 +84,8 @@ impl<'db, H: Hasher> TrieMut for FatDBMut<'db, H> { } fn remove(&mut self, key: &[u8]) -> super::Result> { - let hash = keccak(key); +// let hash = keccak(key); //TODO + let hash = Self::H::hash(key); let out = self.raw.remove(&hash)?; // don't remove if it already exists. diff --git a/util/patricia_trie/src/lib.rs b/util/patricia_trie/src/lib.rs index a744c8d6501..da353c2389f 100644 --- a/util/patricia_trie/src/lib.rs +++ b/util/patricia_trie/src/lib.rs @@ -32,30 +32,28 @@ extern crate trie_standardmap as standardmap; extern crate log; use std::{fmt, error}; -use ethereum_types::H256; -use keccak::KECCAK_NULL_RLP; -use hashdb::{HashDB, DBValue, Hasher, KeccakHasher}; +use hashdb::{HashDB, DBValue, Hasher}; use std::marker::PhantomData; pub mod node; pub mod triedb; pub mod triedbmut; pub mod sectriedb; -pub mod sectriedbmut; +//pub mod sectriedbmut; pub mod recorder; mod fatdb; -mod fatdbmut; +//mod fatdbmut; mod lookup; mod nibbleslice; mod nibblevec; -pub use self::triedbmut::TrieDBMut; pub use self::triedb::{TrieDB, TrieDBIterator}; -pub use self::sectriedbmut::SecTrieDBMut; +pub use self::triedbmut::TrieDBMut; +//pub use self::sectriedbmut::SecTrieDBMut; pub use self::sectriedb::SecTrieDB; pub use self::fatdb::{FatDB, FatDBIterator}; -pub use self::fatdbmut::FatDBMut; +//pub use self::fatdbmut::FatDBMut; pub use self::recorder::Recorder; /// Trie Errors. @@ -63,27 +61,26 @@ pub use self::recorder::Recorder; /// These borrow the data within them to avoid excessive copying on every /// trie operation. #[derive(Debug, PartialEq, Eq, Clone)] -pub enum TrieError { +pub enum TrieError { /// Attempted to create a trie with a state root not in the DB. - InvalidStateRoot(H256), + InvalidStateRoot(T), /// Trie item not found in the database, - IncompleteDatabase(H256), + IncompleteDatabase(T), /// Corrupt Trie item DecoderError(rlp::DecoderError), } -impl fmt::Display for TrieError { +impl fmt::Display for TrieError where T: std::fmt::Debug { 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::InvalidStateRoot(ref root) => write!(f, "Invalid state root: {:?}", root), + TrieError::IncompleteDatabase(ref missing) => write!(f, "Database missing expected key: {:?}", missing), TrieError::DecoderError(ref err) => write!(f, "Decoding failed with {}", err), } } } -impl error::Error for TrieError { +impl error::Error for TrieError where T: std::fmt::Debug { fn description(&self) -> &str { match *self { TrieError::InvalidStateRoot(_) => "Invalid state root", @@ -93,55 +90,50 @@ impl error::Error for TrieError { } } -impl From for Box { +impl From for Box> { fn from(e: rlp::DecoderError) -> Self { Box::new(TrieError::DecoderError(e)) } } /// Trie result type. Boxed to avoid copying around extra space for `H256`s on successful queries. -pub type Result = ::std::result::Result>; +pub type Result = ::std::result::Result>>; /// Trie-Item type. -pub type TrieItem<'a> = Result<(Vec, DBValue)>; +pub type TrieItem<'a, U> = Result<(Vec, DBValue), U>; /// Description of what kind of query will be made to the trie. /// /// This is implemented for any &mut recorder (where the query will return /// a DBValue), any function taking raw bytes (where no recording will be made), /// or any tuple of (&mut Recorder, FnOnce(&[u8])) -pub trait Query { - type H: Hasher; +pub trait Query { /// Output item. type Item; /// Decode a byte-slice into the desired item. - fn decode(self, &[u8]) -> Self::Item; + fn decode(self, data: &[u8]) -> Self::Item; /// Record that a node has been passed through. - fn record(&mut self, hash: &::Out, &[u8], u32) { } + #[allow(unused_variables)] + fn record(&mut self, hash: &H::Out, data: &[u8], depth: u32) {} } -impl<'a, H: Hasher> Query for &'a mut Recorder { - type H = H; +impl<'a, H: Hasher> Query for &'a mut Recorder { type Item = DBValue; fn decode(self, value: &[u8]) -> DBValue { DBValue::from_slice(value) } - fn record(&mut self, hash: &::Out, data: &[u8], depth: u32) { + fn record(&mut self, hash: &H::Out, data: &[u8], depth: u32) { (&mut **self).record(hash, data, depth); } } -// TODO: fix "the type parameter `H` is not constrained by the impl trait, self type, or predicates" -//impl Query for F where F: for<'a> FnOnce(&'a [u8]) -> T { -// type H = H; -// type Item = T; -// -// fn decode(self, value: &[u8]) -> T { (self)(value) } -//} +impl Query for F where F: for<'a> FnOnce(&'a [u8]) -> T { + type Item = T; + fn decode(self, value: &[u8]) -> T { (self)(value) } +} -impl<'a, F, T, H: Hasher> Query for (&'a mut Recorder, F) where F: FnOnce(&[u8]) -> T { - type H = H; +impl<'a, F, T, H: Hasher> Query for (&'a mut Recorder, F) where F: FnOnce(&[u8]) -> T { type Item = T; fn decode(self, value: &[u8]) -> T { (self.1)(value) } - fn record(&mut self, hash: &::Out, data: &[u8], depth: u32) { + fn record(&mut self, hash: &H::Out, data: &[u8], depth: u32) { self.0.record(hash, data, depth) } } @@ -153,25 +145,24 @@ pub trait Trie { fn root(&self) -> &::Out; /// Is the trie empty? - fn is_empty(&self) -> bool { *self.root() == KECCAK_NULL_RLP } + fn is_empty(&self) -> bool { *self.root() == Self::H::HASHED_NULL_RLP } /// Does the trie contain a given key? - fn contains(&self, key: &[u8]) -> Result { - self.get(key).map(|x| x.is_some()) + fn contains(&self, key: &[u8]) -> Result::Out> { + self.get(key).map(|x|x.is_some() ) } /// What is the value of the given key in this trie? - fn get<'a, 'key>(&'a self, key: &'key [u8]) -> Result> where 'a: 'key { + fn get<'a, 'key>(&'a self, key: &'key [u8]) -> Result, ::Out> where 'a: 'key { self.get_with(key, DBValue::from_slice) } /// Search for the key with the given query parameter. See the docs of the `Query` /// trait for more details. - fn get_with<'a, 'key, Q: Query>(&'a self, key: &'key [u8], query: Q) - -> Result> where 'a: 'key; + fn get_with<'a, 'key, Q: Query>(&'a self, key: &'key [u8], query: Q) -> Result, ::Out> where 'a: 'key; /// Returns a depth-first iterator over the elements of trie. - fn iter<'a>(&'a self) -> Result + 'a>>; + fn iter<'a>(&'a self) -> Result> + 'a>, ::Out>; } /// A key-value datastore implemented as a database-backed modified Merkle tree. @@ -184,26 +175,26 @@ pub trait TrieMut { fn is_empty(&self) -> bool; /// Does the trie contain a given key? - fn contains(&self, key: &[u8]) -> Result { + fn contains(&self, key: &[u8]) -> Result::Out> { self.get(key).map(|x| x.is_some()) } /// What is the value of the given key in this trie? - fn get<'a, 'key>(&'a self, key: &'key [u8]) -> Result> where 'a: 'key; + fn get<'a, 'key>(&'a self, key: &'key [u8]) -> Result, ::Out> where 'a: 'key; /// Insert a `key`/`value` pair into the trie. An empty value is equivalent to removing /// `key` from the trie. Returns the old value associated with this key, if it existed. - fn insert(&mut self, key: &[u8], value: &[u8]) -> Result>; + fn insert(&mut self, key: &[u8], value: &[u8]) -> Result, ::Out>; /// Remove a `key` from the trie. Equivalent to making it equal to the empty /// value. Returns the old value associated with this key, if it existed. - fn remove(&mut self, key: &[u8]) -> Result>; + fn remove(&mut self, key: &[u8]) -> Result, ::Out>; } /// A trie iterator that also supports random access. -pub trait TrieIterator : Iterator { +pub trait TrieIterator: Iterator { /// Position the iterator on the first element with key > `key` - fn seek(&mut self, key: &[u8]) -> Result<()>; + fn seek(&mut self, key: &[u8]) -> Result<(), H::Out>; } /// Trie types @@ -236,6 +227,7 @@ pub enum TrieKinds<'db, H: Hasher + 'db> { /// A generic trie db. Generic(TrieDB<'db, H>), /// A secure trie db. +// Secure(TrieDB<'db, H>), Secure(SecTrieDB<'db, H>), /// A fat trie db. Fat(FatDB<'db, H>), @@ -251,8 +243,7 @@ macro_rules! wrapper { } } } - -impl<'db, H: Hasher> Trie for TrieKinds<'db, H> { +impl<'db, H: Hasher> Trie for TrieKinds<'db, H> where H::Out: rlp::Decodable + rlp::Encodable { type H = H; fn root(&self) -> &::Out { wrapper!(self, root,) @@ -262,29 +253,31 @@ impl<'db, H: Hasher> Trie for TrieKinds<'db, H> { wrapper!(self, is_empty,) } - fn contains(&self, key: &[u8]) -> Result { + fn contains(&self, key: &[u8]) -> Result::Out> { wrapper!(self, contains, key) } - fn get_with<'a, 'key, Q: Query>(&'a self, key: &'key [u8], query: Q) -> Result> + fn get_with<'a, 'key, Q: Query>(&'a self, key: &'key [u8], query: Q) -> Result, ::Out> where 'a: 'key { wrapper!(self, get_with, key, query) } - fn iter<'a>(&'a self) -> Result + 'a>> { + fn iter<'a>(&'a self) -> Result> + 'a>, ::Out> { wrapper!(self, iter,) } } -impl TrieFactory { +impl TrieFactory +where H::Out: rlp::Decodable + rlp::Encodable +{ /// Creates new factory. pub fn new(spec: TrieSpec) -> Self { - TrieFactory { spec } + TrieFactory { spec, marker: PhantomData } } /// Create new immutable instance of Trie. - pub fn readonly<'db>(&self, db: &'db HashDB, root: &'db H256) -> Result> { + pub fn readonly<'db>(&self, db: &'db HashDB, root: &'db H::Out) -> Result, H::Out> { match self.spec { TrieSpec::Generic => Ok(TrieKinds::Generic(TrieDB::new(db, root)?)), TrieSpec::Secure => Ok(TrieKinds::Secure(SecTrieDB::new(db, root)?)), @@ -293,23 +286,29 @@ impl TrieFactory { } /// Create new mutable instance of Trie. - pub fn create<'db>(&self, db: &'db mut HashDB, root: &'db mut H256) -> Box + 'db> { - match self.spec { - TrieSpec::Generic => Box::new(TrieDBMut::new(db, root)), - TrieSpec::Secure => Box::new(SecTrieDBMut::new(db, root)), - TrieSpec::Fat => Box::new(FatDBMut::new(db, root)), - } - } +// pub fn create<'db>(&self, db: &'db mut HashDB, root: &'db mut H::Out) -> Box + 'db> { +// match self.spec { +// TrieSpec::Generic => Box::new(TrieDBMut::new(db, root)), +// TrieSpec::Secure => Box::new(SecTrieDBMut::new(db, root)), +// TrieSpec::Fat => Box::new(FatDBMut::new(db, root)), +// } +// } /// Create new mutable instance of trie and check for errors. - pub fn from_existing<'db>(&self, db: &'db mut HashDB, root: &'db mut H256) -> Result + 'db>> { - match self.spec { - TrieSpec::Generic => Ok(Box::new(TrieDBMut::from_existing(db, root)?)), - TrieSpec::Secure => Ok(Box::new(SecTrieDBMut::from_existing(db, root)?)), - TrieSpec::Fat => Ok(Box::new(FatDBMut::from_existing(db, root)?)), - } - } +// pub fn from_existing<'db>(&self, db: &'db mut HashDB, root: &'db mut H::Out) -> Result + 'db>, H::Out> { +// match self.spec { +// TrieSpec::Generic => Ok(Box::new(TrieDBMut::from_existing(db, root)?)), +// TrieSpec::Secure => Ok(Box::new(SecTrieDBMut::from_existing(db, root)?)), +// TrieSpec::Fat => Ok(Box::new(FatDBMut::from_existing(db, root)?)), +// } +// } /// Returns true iff the trie DB is a fat DB (allows enumeration of keys). pub fn is_fat(&self) -> bool { self.spec == TrieSpec::Fat } } + +/* +fn decode_node(node: &'db [u8]) -> Node { + Node::decoded(node).expect("rlp read from db; qed") + } +*/ \ No newline at end of file diff --git a/util/patricia_trie/src/lookup.rs b/util/patricia_trie/src/lookup.rs index 5ea396acd20..d66cb3e20f8 100644 --- a/util/patricia_trie/src/lookup.rs +++ b/util/patricia_trie/src/lookup.rs @@ -18,13 +18,14 @@ use hashdb::{HashDB, Hasher}; use nibbleslice::NibbleSlice; -use ethereum_types::H256; +//use ethereum_types::H256; use super::{TrieError, Query}; use super::node::Node; +use rlp::Decodable; /// Trie lookup helper object. -pub struct Lookup<'a, H: Hasher + 'a, Q: Query> { +pub struct Lookup<'a, H: Hasher + 'a, Q: Query> { /// database to query from. pub db: &'a HashDB, /// Query object to record nodes and transform data. @@ -33,10 +34,10 @@ pub struct Lookup<'a, H: Hasher + 'a, Q: Query> { pub hash: H::Out, // TODO } -impl<'a, H: Hasher, Q: Query> Lookup<'a, H, Q> { +impl<'a, H: Hasher + 'a, Q: Query> Lookup<'a, H, Q> where H::Out: Decodable { /// Look up the given key. If the value is found, it will be passed to the given /// function to decode or copy. - pub fn look_up(mut self, mut key: NibbleSlice) -> super::Result> { + pub fn look_up(mut self, mut key: NibbleSlice) -> super::Result, H::Out> { let mut hash = self.hash; // this loop iterates through non-inline nodes. @@ -81,8 +82,8 @@ impl<'a, H: Hasher, Q: Query> Lookup<'a, H, Q> { } // check if new node data is inline or hash. - if let Some(h) = Node::try_decode_hash(&node_data) { - hash = as Hasher>::H::Out(h); // REVIEW: this is pretty horrible. Better way? + if let Some(h) = Node::try_decode_hash::(&node_data) { + hash = h; break } } diff --git a/util/patricia_trie/src/node.rs b/util/patricia_trie/src/node.rs index 0b99acded34..9bbea4e2d1a 100644 --- a/util/patricia_trie/src/node.rs +++ b/util/patricia_trie/src/node.rs @@ -14,12 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use ethereum_types::H256; use elastic_array::ElasticArray36; use nibbleslice::NibbleSlice; use nibblevec::NibbleVec; use bytes::*; -use rlp::{Rlp, RlpStream, Prototype, DecoderError}; +use rlp::{Rlp, RlpStream, Prototype, DecoderError, self}; use hashdb::DBValue; /// Partial node key type. @@ -35,7 +34,7 @@ pub enum Node<'a> { /// Extension node; has key slice and node data. Data may not be null. Extension(NibbleSlice<'a>, &'a [u8]), /// Branch node; has array of 16 child nodes (each possibly null) and an optional immediate node data. - Branch([&'a [u8]; 16], Option<&'a [u8]>) + Branch([&'a [u8]; 16], Option<&'a [u8]>), } impl<'a> Node<'a> { @@ -104,7 +103,9 @@ impl<'a> Node<'a> { } } - pub fn try_decode_hash(node_data: &[u8]) -> Option { + pub fn try_decode_hash(node_data: &[u8]) -> Option + where O: rlp::Decodable // REVIEW: this is not necessary but is perhaps useful when reading the code? Keep or leave out? + { let r = Rlp::new(node_data); if r.is_data() && r.size() == 32 { Some(r.as_val().expect("Hash is the correct size of 32 bytes; qed")) diff --git a/util/patricia_trie/src/recorder.rs b/util/patricia_trie/src/recorder.rs index f5c04ef2641..7add50152f6 100644 --- a/util/patricia_trie/src/recorder.rs +++ b/util/patricia_trie/src/recorder.rs @@ -16,8 +16,8 @@ //! Trie query recorder. -use keccak::keccak; -use ethereum_types::H256; +//use keccak::keccak; +//use ethereum_types::H256; use bytes::Bytes; use hashdb::Hasher; use std::marker::PhantomData; @@ -32,7 +32,7 @@ pub struct Record { pub data: Bytes, /// The hash of the data. - pub hash: ::Out, + pub hash: H::Out, marker: PhantomData, } @@ -69,7 +69,7 @@ impl Recorder { /// Record a visited node, given its hash, data, and depth. // pub fn record(&mut self, hash: &H256, data: &[u8], depth: u32) { pub fn record(&mut self, hash: &::Out, data: &[u8], depth: u32) { - debug_assert_eq!(keccak(data), *hash); + debug_assert_eq!(H::hash(data), *hash); if depth >= self.min_depth { self.nodes.push(Record { diff --git a/util/patricia_trie/src/sectriedb.rs b/util/patricia_trie/src/sectriedb.rs index 05c42058bdf..fde26792bfd 100644 --- a/util/patricia_trie/src/sectriedb.rs +++ b/util/patricia_trie/src/sectriedb.rs @@ -14,11 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use ethereum_types::H256; -use keccak::keccak; +//use ethereum_types::H256; +//use keccak::keccak; use hashdb::{HashDB, Hasher}; use super::triedb::TrieDB; use super::{Trie, TrieItem, TrieIterator, Query}; +use rlp::{Decodable, Encodable}; /// A `Trie` implementation which hashes keys and uses a generic `HashDB` backing database. /// @@ -27,13 +28,13 @@ pub struct SecTrieDB<'db, H: Hasher + 'db> { raw: TrieDB<'db, H> } -impl<'db, H: Hasher> SecTrieDB<'db, H> { +impl<'db, H: Hasher> SecTrieDB<'db, H> where H::Out: Decodable { /// Create a new trie with the backing database `db` and empty `root` /// /// Initialise to the state entailed by the genesis block. /// This guarantees the trie is built correctly. /// Returns an error if root does not exist. - pub fn new(db: &'db HashDB, root: &'db H256) -> super::Result { + pub fn new(db: &'db HashDB, root: &'db H::Out) -> super::Result { Ok(SecTrieDB { raw: TrieDB::new(db, root)? }) } @@ -48,22 +49,22 @@ impl<'db, H: Hasher> SecTrieDB<'db, H> { } } -impl<'db, H: Hasher> Trie for SecTrieDB<'db, H> { +impl<'db, H: Hasher> Trie for SecTrieDB<'db, H> where H::Out: Decodable + Encodable { type H = H; - fn root(&self) -> &::Out{ self.raw.root() } + fn root(&self) -> &::Out { self.raw.root() } - fn contains(&self, key: &[u8]) -> super::Result { - self.raw.contains(&keccak(key)) // TODO + fn contains(&self, key: &[u8]) -> super::Result::Out> { + self.raw.contains(&Self::H::hash(key).as_ref()) } - fn get_with<'a, 'key, Q: Query>(&'a self, key: &'key [u8], query: Q) -> super::Result> + fn get_with<'a, 'key, Q: Query>(&'a self, key: &'key [u8], query: Q) -> super::Result, ::Out> where 'a: 'key { - self.raw.get_with(&keccak(key), query) // TODO + self.raw.get_with(&Self::H::hash(key).as_ref(), query) } - fn iter<'a>(&'a self) -> super::Result + 'a>> { + fn iter<'a>(&'a self) -> super::Result> + 'a>, ::Out> { TrieDB::iter(&self.raw) } } diff --git a/util/patricia_trie/src/sectriedbmut.rs b/util/patricia_trie/src/sectriedbmut.rs index 4449395cce5..c981d9cc4f3 100644 --- a/util/patricia_trie/src/sectriedbmut.rs +++ b/util/patricia_trie/src/sectriedbmut.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use ethereum_types::H256; use keccak::keccak; use hashdb::{HashDB, DBValue, Hasher}; use super::triedbmut::TrieDBMut; @@ -31,14 +30,14 @@ impl<'db, H: Hasher> SecTrieDBMut<'db, H> { /// Create a new trie with the backing database `db` and empty `root` /// Initialise to the state entailed by the genesis block. /// This guarantees the trie is built correctly. - pub fn new(db: &'db mut HashDB, root: &'db mut H256) -> Self { + pub fn new(db: &'db mut HashDB, root: &'db mut H::Out) -> Self { SecTrieDBMut { raw: TrieDBMut::new(db, root) } } /// Create a new trie with the backing database `db` and `root`. /// /// Returns an error if root does not exist. - pub fn from_existing(db: &'db mut HashDB, root: &'db mut H256) -> super::Result { + pub fn from_existing(db: &'db mut HashDB, root: &'db mut H::Out) -> super::Result { Ok(SecTrieDBMut { raw: TrieDBMut::from_existing(db, root)? }) } @@ -60,21 +59,21 @@ impl<'db, H: Hasher> TrieMut for SecTrieDBMut<'db, H> { } fn contains(&self, key: &[u8]) -> super::Result { - self.raw.contains(&keccak(key)) + self.raw.contains(&Self::H::hash(key)) } fn get<'a, 'key>(&'a self, key: &'key [u8]) -> super::Result> where 'a: 'key { - self.raw.get(&keccak(key)) // TODO + self.raw.get(&Self::H::hash(key)) } fn insert(&mut self, key: &[u8], value: &[u8]) -> super::Result> { - self.raw.insert(&keccak(key), value) // TODO + self.raw.insert(&Self::H::hash(key), value) } fn remove(&mut self, key: &[u8]) -> super::Result> { - self.raw.remove(&keccak(key)) // TODO + self.raw.remove(&Self::H::hash(key)) } } diff --git a/util/patricia_trie/src/triedb.rs b/util/patricia_trie/src/triedb.rs index c34739d1c8a..8418fabfc41 100644 --- a/util/patricia_trie/src/triedb.rs +++ b/util/patricia_trie/src/triedb.rs @@ -20,8 +20,8 @@ use nibbleslice::NibbleSlice; use super::node::{Node, OwnedNode}; use super::lookup::Lookup; use super::{Trie, TrieItem, TrieError, TrieIterator, Query}; -use ethereum_types::H256; -use bytes::{ToPretty, Bytes}; +use bytes::Bytes; +use rlp::{Decodable, Encodable}; /// A `Trie` implementation using a generic `HashDB` backing database. /// @@ -56,10 +56,10 @@ pub struct TrieDB<'db, H: Hasher + 'db> { hash_count: usize, } -impl<'db, H: Hasher> TrieDB<'db, H> { +impl<'db, H: Hasher> TrieDB<'db, H> where H::Out: Decodable { /// Create a new trie with the backing database `db` and `root` /// Returns an error if `root` does not exist - pub fn new(db: &'db HashDB, root: &'db H256) -> super::Result { + pub fn new(db: &'db HashDB, root: &'db H::Out) -> super::Result { if !db.contains(root) { Err(Box::new(TrieError::InvalidStateRoot(*root))) } else { @@ -68,12 +68,10 @@ impl<'db, H: Hasher> TrieDB<'db, H> { } /// Get the backing database. - pub fn db(&'db self) -> &'db HashDB { - self.db - } + pub fn db(&'db self) -> &'db HashDB { self.db } /// Get the data of the root node. - fn root_data(&self) -> super::Result { + fn root_data(&self) -> super::Result { self.db .get(self.root) .ok_or_else(|| Box::new(TrieError::InvalidStateRoot(*self.root))) @@ -82,26 +80,22 @@ impl<'db, H: Hasher> TrieDB<'db, H> { /// Given some node-describing data `node`, return the actual node RLP. /// This could be a simple identity operation in the case that the node is sufficiently small, but /// may require a database lookup. - fn get_raw_or_lookup(&'db self, node: &'db [u8]) -> super::Result { - match Node::try_decode_hash(node) { + fn get_raw_or_lookup(&'db self, node: &'db [u8]) -> super::Result { + // REVIEW: is it better to parametrize on `H` or like this with `H::Out` (saves us from adding `use hashdb::Hasher`) + match Node::try_decode_hash::(node) { Some(key) => { self.db.get(&key).ok_or_else(|| Box::new(TrieError::IncompleteDatabase(key))) } None => Ok(DBValue::from_slice(node)) } } - - /// Create a node from raw rlp bytes, assumes valid rlp because encoded locally - fn decode_node(node: &'db [u8]) -> Node { - Node::decoded(node).expect("rlp read from db; qed") - } } -impl<'db, H: Hasher> Trie for TrieDB<'db, H> { +impl<'db, H: Hasher> Trie for TrieDB<'db, H> where H::Out: Decodable + Encodable { type H = H; fn root(&self) -> &::Out { self.root } - fn get_with<'a, 'key, Q: Query>(&'a self, key: &'key [u8], query: Q) -> super::Result> + fn get_with<'a, 'key, Q: Query>(&'a self, key: &'key [u8], query: Q) -> super::Result, H::Out> where 'a: 'key { Lookup { @@ -111,7 +105,7 @@ impl<'db, H: Hasher> Trie for TrieDB<'db, H> { }.look_up(NibbleSlice::new(key)) } - fn iter<'a>(&'a self) -> super::Result + 'a>> { + fn iter<'a>(&'a self) -> super::Result> + 'a>, H::Out> { TrieDBIterator::new(self).map(|iter| Box::new(iter) as Box<_>) } } @@ -122,7 +116,7 @@ struct TrieAwareDebugNode<'db, 'a, H: Hasher + 'db> { key: &'a[u8] } -impl<'db, 'a, H: Hasher> fmt::Debug for TrieAwareDebugNode<'db, 'a, H> { +impl<'db, 'a, H: Hasher> fmt::Debug for TrieAwareDebugNode<'db, 'a, H> where H::Out: Decodable { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if let Ok(node) = self.trie.get_raw_or_lookup(self.key) { match Node::decoded(&node) { @@ -135,7 +129,7 @@ impl<'db, 'a, H: Hasher> fmt::Debug for TrieAwareDebugNode<'db, 'a, H> { .field("item", &TrieAwareDebugNode{trie: self.trie, key: item}) .finish(), Ok(Node::Branch(ref nodes, ref value)) => { - let nodes: Vec = nodes.into_iter().map(|n| TrieAwareDebugNode{trie: self.trie, key: n} ).collect(); + let nodes: Vec> = nodes.into_iter().map(|n| TrieAwareDebugNode{trie: self.trie, key: n} ).collect(); f.debug_struct("Node::Branch") .field("nodes", &nodes) .field("value", &value) @@ -158,7 +152,7 @@ impl<'db, 'a, H: Hasher> fmt::Debug for TrieAwareDebugNode<'db, 'a, H> { } -impl<'db, H: Hasher> fmt::Debug for TrieDB<'db, H> { +impl<'db, H: Hasher> fmt::Debug for TrieDB<'db, H> where H::Out: Decodable { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let root_rlp = self.db.get(self.root).expect("Trie root not found!"); f.debug_struct("TrieDB") @@ -205,9 +199,9 @@ pub struct TrieDBIterator<'a, H: Hasher + 'a> { key_nibbles: Bytes, } -impl<'a, H: Hasher> TrieDBIterator<'a, H> { +impl<'a, H: Hasher> TrieDBIterator<'a, H> where H::Out: Decodable { /// Create a new iterator. - pub fn new(db: &'a TrieDB) -> super::Result> { + pub fn new(db: &'a TrieDB) -> super::Result, H::Out> { let mut r = TrieDBIterator { db: db, trail: vec![], @@ -218,10 +212,10 @@ impl<'a, H: Hasher> TrieDBIterator<'a, H> { Ok(r) } - fn seek<'key>(&mut self, mut node_data: DBValue, mut key: NibbleSlice<'key>) -> super::Result<()> { + fn seek<'key>(&mut self, mut node_data: DBValue, mut key: NibbleSlice<'key>) -> super::Result<(), H::Out> { loop { let (data, mid) = { - let node = TrieDB::decode_node(&node_data); + let node = Node::decoded(&node_data).expect("rlp read from db; qed"); match node { Node::Leaf(slice, _) => { if slice == key { @@ -282,9 +276,10 @@ impl<'a, H: Hasher> TrieDBIterator<'a, H> { } /// Descend into a payload. - fn descend(&mut self, d: &[u8]) -> super::Result<()> { - let node = TrieDB::decode_node(&self.db.get_raw_or_lookup(d)?).into(); - Ok(self.descend_into_node(node)) + fn descend(&mut self, d: &[u8]) -> super::Result<(), H::Out> { + let node_data = &self.db.get_raw_or_lookup(d)?; + let node = Node::decoded(&node_data).expect("rlp read from db; qed"); + Ok(self.descend_into_node(node.into())) } /// Descend into a payload. @@ -316,9 +311,9 @@ impl<'a, H: Hasher> TrieDBIterator<'a, H> { } } -impl<'a, H: Hasher> TrieIterator for TrieDBIterator<'a, H> { +impl<'a, H: Hasher> TrieIterator for TrieDBIterator<'a, H> where H::Out: Decodable { /// Position the iterator on the first element with key >= `key` - fn seek(&mut self, key: &[u8]) -> super::Result<()> { + fn seek(&mut self, key: &[u8]) -> super::Result<(), H::Out> { self.trail.clear(); self.key_nibbles.clear(); let root_rlp = self.db.root_data()?; @@ -326,16 +321,16 @@ impl<'a, H: Hasher> TrieIterator for TrieDBIterator<'a, H> { } } -impl<'a, H: Hasher> Iterator for TrieDBIterator<'a, H> { - type Item = TrieItem<'a>; + +impl<'a, H: Hasher> Iterator for TrieDBIterator<'a, H> where H::Out: Decodable { + type Item = TrieItem<'a, H>; fn next(&mut self) -> Option { - enum IterStep { + enum IterStep { Continue, PopTrail, - Descend(super::Result), + Descend(super::Result), } - loop { let iter_step = { self.trail.last_mut()?.increment(); @@ -356,7 +351,7 @@ impl<'a, H: Hasher> Iterator for TrieDBIterator<'a, H> { (Status::At, &OwnedNode::Leaf(_, ref v)) | (Status::At, &OwnedNode::Branch(_, Some(ref v))) => { return Some(Ok((self.key(), v.clone()))); }, - (Status::At, &OwnedNode::Extension(_, ref d)) => IterStep::Descend(self.db.get_raw_or_lookup(&*d)), + (Status::At, &OwnedNode::Extension(_, ref d)) => IterStep::Descend::(self.db.get_raw_or_lookup(&*d)), (Status::At, &OwnedNode::Branch(_, _)) => IterStep::Continue, (Status::AtChild(i), &OwnedNode::Branch(ref children, _)) if children[i].len() > 0 => { match i { @@ -364,7 +359,7 @@ impl<'a, H: Hasher> Iterator for TrieDBIterator<'a, H> { i => *self.key_nibbles.last_mut() .expect("pushed as 0; moves sequentially; removed afterwards; qed") = i as u8, } - IterStep::Descend(self.db.get_raw_or_lookup(&*children[i])) + IterStep::Descend::(self.db.get_raw_or_lookup(&*children[i])) }, (Status::AtChild(i), &OwnedNode::Branch(_, _)) => { if i == 0 { @@ -380,11 +375,23 @@ impl<'a, H: Hasher> Iterator for TrieDBIterator<'a, H> { IterStep::PopTrail => { self.trail.pop(); }, - IterStep::Descend(Ok(d)) => { - self.descend_into_node(TrieDB::decode_node(&d).into()) + IterStep::Descend::(Ok(d)) => { + let node = Node::decoded(&d).expect("rlp read from db; qed"); + self.descend_into_node(node.into()) }, - IterStep::Descend(Err(e)) => { - return Some(Err(e)) + IterStep::Descend::(Err(e)) => { +// return Some(Err(e)) // <–– REVIEW: This causes a compiler error I can't figure out: + /* + error[E0308]: mismatched types + --> util/patricia_trie/src/triedb.rs:404:22 + | + 404 | return Some(Err(e)) + | ^ expected type parameter, found associated type + | + = note: expected type `std::boxed::Box>` + found type `std::boxed::Box::Out>>` + */ + panic!("FIXME: this causes `expected type parameter, found associated type`") } IterStep::Continue => {}, } diff --git a/util/patricia_trie/src/triedbmut.rs b/util/patricia_trie/src/triedbmut.rs index d959b280ccc..4ee3f50a69d 100644 --- a/util/patricia_trie/src/triedbmut.rs +++ b/util/patricia_trie/src/triedbmut.rs @@ -24,15 +24,13 @@ use super::node::NodeKey; use hashdb::HashDB; use bytes::ToPretty; use nibbleslice::NibbleSlice; -use rlp::{Rlp, RlpStream}; -use hashdb::{Hasher, DBValue, KeccakHasher}; +use rlp::{Rlp, RlpStream, Encodable, Decodable}; +use hashdb::{Hasher, DBValue}; use std::collections::{HashSet, VecDeque}; use std::mem; use std::ops::Index; -use ethereum_types::H256; use elastic_array::ElasticArray1024; -use keccak::{KECCAK_NULL_RLP}; // For lookups into the Node storage buffer. // This is deliberately non-copyable. @@ -41,26 +39,26 @@ struct StorageHandle(usize); // Handles to nodes in the trie. #[derive(Debug)] -enum NodeHandle { +enum NodeHandle { /// Loaded into memory. InMemory(StorageHandle), /// Either a hash or an inline node - Hash(H256), + Hash(H::Out), } -impl From for NodeHandle { +impl From for NodeHandle { fn from(handle: StorageHandle) -> Self { NodeHandle::InMemory(handle) } } -impl From for NodeHandle { - fn from(hash: H256) -> Self { - NodeHandle::Hash(hash) - } -} +//impl From for NodeHandle { +// fn from(hash: H256) -> Self { +// NodeHandle::Hash(hash) +// } +//} -fn empty_children() -> Box<[Option; 16]> { +fn empty_children() -> Box<[Option>; 16]> { Box::new([ None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, @@ -69,7 +67,7 @@ fn empty_children() -> Box<[Option; 16]> { /// Node types in the Trie. #[derive(Debug)] -enum Node { +enum Node { /// Empty node. Empty, /// A leaf node contains the end of a key and a value. @@ -80,15 +78,15 @@ enum Node { /// The shared portion is encoded from a `NibbleSlice` meaning it contains /// a flag indicating it is an extension. /// The child node is always a branch. - Extension(NodeKey, NodeHandle), + Extension(NodeKey, NodeHandle), /// A branch has up to 16 children and an optional value. - Branch(Box<[Option; 16]>, Option) + Branch(Box<[Option>; 16]>, Option) } -impl Node { +impl Node where H::Out: Decodable { // load an inline node into memory or get the hash to do the lookup later. - fn inline_or_hash(node: &[u8], db: &HashDB, storage: &mut NodeStorage) -> NodeHandle { - RlpNode::try_decode_hash(&node) + fn inline_or_hash(node: &[u8], db: &HashDB, storage: &mut NodeStorage) -> NodeHandle { + RlpNode::try_decode_hash::(&node) .map(NodeHandle::Hash) .unwrap_or_else(|| { let child = Node::from_rlp(node, db, storage); @@ -97,7 +95,7 @@ impl Node { } // decode a node from rlp without getting its children. - fn from_rlp(rlp: &[u8], db: &HashDB, storage: &mut NodeStorage) -> Self { + fn from_rlp(rlp: &[u8], db: &HashDB, storage: &mut NodeStorage) -> Self { match RlpNode::decoded(rlp).expect("rlp read from db; qed") { RlpNode::Empty => Node::Empty, RlpNode::Leaf(k, v) => Node::Leaf(k.encoded(true), DBValue::from_slice(&v)), @@ -130,7 +128,7 @@ impl Node { // encode a node to RLP // TODO: parallelize fn into_rlp(self, mut child_cb: F) -> ElasticArray1024 - where F: FnMut(NodeHandle, &mut RlpStream) + where F: FnMut(NodeHandle, &mut RlpStream) { match self { Node::Empty => { @@ -172,25 +170,25 @@ impl Node { } // post-inspect action. -enum Action { +enum Action { // Replace a node with a new one. - Replace(Node), + Replace(Node), // Restore the original node. This trusts that the node is actually the original. - Restore(Node), + Restore(Node), // if it is a new node, just clears the storage. Delete, } // post-insert action. Same as action without delete -enum InsertAction { +enum InsertAction { // Replace a node with a new one. - Replace(Node), + Replace(Node), // Restore the original node. - Restore(Node), + Restore(Node), } -impl InsertAction { - fn into_action(self) -> Action { +impl InsertAction { + fn into_action(self) -> Action { match self { InsertAction::Replace(n) => Action::Replace(n), InsertAction::Restore(n) => Action::Restore(n), @@ -198,7 +196,7 @@ impl InsertAction { } // unwrap the node, disregarding replace or restore state. - fn unwrap_node(self) -> Node { + fn unwrap_node(self) -> Node { match self { InsertAction::Replace(n) | InsertAction::Restore(n) => n, } @@ -206,20 +204,20 @@ impl InsertAction { } // What kind of node is stored here. -enum Stored { +enum Stored { // A new node. - New(Node), + New(Node), // A cached node, loaded from the DB. - Cached(Node, H256), + Cached(Node, H::Out), } /// Compact and cache-friendly storage for Trie nodes. -struct NodeStorage { - nodes: Vec, +struct NodeStorage { + nodes: Vec>, free_indices: VecDeque, } -impl NodeStorage { +impl NodeStorage { /// Create a new storage. fn empty() -> Self { NodeStorage { @@ -229,7 +227,7 @@ impl NodeStorage { } /// Allocate a new node in the storage. - fn alloc(&mut self, stored: Stored) -> StorageHandle { + fn alloc(&mut self, stored: Stored) -> StorageHandle { if let Some(idx) = self.free_indices.pop_front() { self.nodes[idx] = stored; StorageHandle(idx) @@ -240,7 +238,7 @@ impl NodeStorage { } /// Remove a node from the storage, consuming the handle and returning the node. - fn destroy(&mut self, handle: StorageHandle) -> Stored { + fn destroy(&mut self, handle: StorageHandle) -> Stored { let idx = handle.0; self.free_indices.push_back(idx); @@ -248,10 +246,10 @@ impl NodeStorage { } } -impl<'a> Index<&'a StorageHandle> for NodeStorage { - type Output = Node; +impl<'a, H: Hasher> Index<&'a StorageHandle> for NodeStorage { + type Output = Node; - fn index(&self, handle: &'a StorageHandle) -> &Node { + fn index(&self, handle: &'a StorageHandle) -> &Node { match self.nodes[handle.0] { Stored::New(ref node) => node, Stored::Cached(ref node, _) => node, @@ -292,22 +290,22 @@ impl<'a> Index<&'a StorageHandle> for NodeStorage { /// assert!(!t.contains(b"foo").unwrap()); /// } /// ``` -pub struct TrieDBMut<'a, H: Hasher + 'a> { - storage: NodeStorage, +pub struct TrieDBMut<'a, H: Hasher + 'a> where H::Out: Decodable + Encodable { + storage: NodeStorage, db: &'a mut HashDB, - root: &'a mut H256, // TOOD - root_handle: NodeHandle, - death_row: HashSet, // TODO + root: &'a mut H::Out, + root_handle: NodeHandle, + death_row: HashSet, /// The number of hash operations this trie has performed. /// Note that none are performed until changes are committed. hash_count: usize, } -impl<'a, H: Hasher> TrieDBMut<'a, H> { +impl<'a, H: Hasher> TrieDBMut<'a, H> where H::Out: Decodable + Encodable { /// Create a new trie with backing database `db` and empty `root`. - pub fn new(db: &'a mut HashDB, root: &'a mut H256) -> Self { - *root = KECCAK_NULL_RLP; - let root_handle = NodeHandle::Hash(KECCAK_NULL_RLP); // TODO + pub fn new(db: &'a mut HashDB, root: &'a mut H::Out) -> Self { + *root = H::HASHED_NULL_RLP; + let root_handle = NodeHandle::Hash(H::HASHED_NULL_RLP); TrieDBMut { storage: NodeStorage::empty(), @@ -321,7 +319,7 @@ impl<'a, H: Hasher> TrieDBMut<'a, H> { /// Create a new trie with the backing database `db` and `root. /// Returns an error if `root` does not exist. - pub fn from_existing(db: &'a mut HashDB, root: &'a mut H256) -> super::Result { + pub fn from_existing(db: &'a mut HashDB, root: &'a mut H::Out) -> super::Result { if !db.contains(root) { return Err(Box::new(TrieError::InvalidStateRoot(*root))); } @@ -347,7 +345,7 @@ impl<'a, H: Hasher> TrieDBMut<'a, H> { } // cache a node by hash - fn cache(&mut self, hash: H256) -> super::Result { + fn cache(&mut self, hash: H::Out) -> super::Result { let node_rlp = self.db.get(&hash).ok_or_else(|| Box::new(TrieError::IncompleteDatabase(hash)))?; let node = Node::from_rlp(&node_rlp, &*self.db, &mut self.storage); Ok(self.storage.alloc(Stored::Cached(node, hash))) @@ -355,8 +353,8 @@ impl<'a, H: Hasher> TrieDBMut<'a, H> { // inspect a node, choosing either to replace, restore, or delete it. // if restored or replaced, returns the new node along with a flag of whether it was changed. - fn inspect(&mut self, stored: Stored, inspector: F) -> super::Result> - where F: FnOnce(&mut Self, Node) -> super::Result { + fn inspect(&mut self, stored: Stored, inspector: F) -> super::Result, bool)>, H::Out> + where F: FnOnce(&mut Self, Node) -> super::Result, H::Out> { Ok(match stored { Stored::New(node) => match inspector(self, node)? { Action::Restore(node) => Some((Stored::New(node), false)), @@ -378,7 +376,7 @@ impl<'a, H: Hasher> TrieDBMut<'a, H> { } // walk the trie, attempting to find the key's node. - fn lookup<'x, 'key>(&'x self, mut partial: NibbleSlice<'key>, handle: &NodeHandle) -> super::Result> + fn lookup<'x, 'key>(&'x self, mut partial: NibbleSlice<'key>, handle: &NodeHandle) -> super::Result, H::Out> where 'x: 'key { let mut handle = handle; @@ -426,9 +424,7 @@ impl<'a, H: Hasher> TrieDBMut<'a, H> { } /// insert a key, value pair into the trie, creating new nodes if necessary. - fn insert_at(&mut self, handle: NodeHandle, partial: NibbleSlice, value: DBValue, old_val: &mut Option) - -> super::Result<(StorageHandle, bool)> - { + fn insert_at(&mut self, handle: NodeHandle, partial: NibbleSlice, value: DBValue, old_val: &mut Option) -> super::Result<(StorageHandle, bool), H::Out> { let h = match handle { NodeHandle::InMemory(h) => h, NodeHandle::Hash(h) => self.cache(h)?, @@ -442,9 +438,7 @@ impl<'a, H: Hasher> TrieDBMut<'a, H> { } /// the insertion inspector. - fn insert_inspector(&mut self, node: Node, partial: NibbleSlice, value: DBValue, old_val: &mut Option) - -> super::Result - { + fn insert_inspector(&mut self, node: Node, partial: NibbleSlice, value: DBValue, old_val: &mut Option) -> super::Result, H::Out> { trace!(target: "trie", "augmented (partial: {:?}, value: {:?})", partial, value.pretty()); Ok(match node { @@ -605,9 +599,7 @@ impl<'a, H: Hasher> TrieDBMut<'a, H> { } /// Remove a node from the trie based on key. - fn remove_at(&mut self, handle: NodeHandle, partial: NibbleSlice, old_val: &mut Option) - -> super::Result> - { + fn remove_at(&mut self, handle: NodeHandle, partial: NibbleSlice, old_val: &mut Option) -> super::Result, H::Out> { let stored = match handle { NodeHandle::InMemory(h) => self.storage.destroy(h), NodeHandle::Hash(h) => { @@ -622,7 +614,7 @@ impl<'a, H: Hasher> TrieDBMut<'a, H> { } /// the removal inspector - fn remove_inspector(&mut self, node: Node, partial: NibbleSlice, old_val: &mut Option) -> super::Result { + fn remove_inspector(&mut self, node: Node, partial: NibbleSlice, old_val: &mut Option) -> super::Result, H::Out> { Ok(match (node, partial.is_empty()) { (Node::Empty, _) => Action::Delete, (Node::Branch(c, None), true) => Action::Restore(Node::Branch(c, None)), @@ -708,7 +700,7 @@ impl<'a, H: Hasher> TrieDBMut<'a, H> { /// _invalid state_ means: /// - Branch node where there is only a single entry; /// - Extension node followed by anything other than a Branch node. - fn fix(&mut self, node: Node) -> super::Result { + fn fix(&mut self, node: Node) -> super::Result, H::Out> { match node { Node::Branch(mut children, value) => { // if only a single value, transmute to leaf/extension and feed through fixed. @@ -845,7 +837,7 @@ impl<'a, H: Hasher> TrieDBMut<'a, H> { /// commit a node, hashing it, committing it to the db, /// and writing it to the rlp stream as necessary. - fn commit_node(&mut self, handle: NodeHandle, stream: &mut RlpStream) { + fn commit_node(&mut self, handle: NodeHandle, stream: &mut RlpStream) { match handle { NodeHandle::Hash(h) => stream.append(&h), NodeHandle::InMemory(h) => match self.storage.destroy(h) { @@ -865,7 +857,7 @@ impl<'a, H: Hasher> TrieDBMut<'a, H> { } // a hack to get the root node's handle - fn root_handle(&self) -> NodeHandle { + fn root_handle(&self) -> NodeHandle { match self.root_handle { NodeHandle::Hash(h) => NodeHandle::Hash(h), NodeHandle::InMemory(StorageHandle(x)) => NodeHandle::InMemory(StorageHandle(x)), @@ -873,7 +865,7 @@ impl<'a, H: Hasher> TrieDBMut<'a, H> { } } -impl<'a, H: Hasher> TrieMut for TrieDBMut<'a, H> { +impl<'a, H: Hasher> TrieMut for TrieDBMut<'a, H> where H::Out: Decodable + Encodable { type H = H; fn root(&mut self) -> &::Out { @@ -883,7 +875,7 @@ impl<'a, H: Hasher> TrieMut for TrieDBMut<'a, H> { fn is_empty(&self) -> bool { match self.root_handle { - NodeHandle::Hash(h) => h == KECCAK_NULL_RLP, // TODO + NodeHandle::Hash(h) => h == Self::H::HASHED_NULL_RLP, // TODO NodeHandle::InMemory(ref h) => match self.storage[h] { Node::Empty => true, _ => false, @@ -891,12 +883,12 @@ impl<'a, H: Hasher> TrieMut for TrieDBMut<'a, H> { } } - fn get<'x, 'key>(&'x self, key: &'key [u8]) -> super::Result> where 'x: 'key { + fn get<'x, 'key>(&'x self, key: &'key [u8]) -> super::Result, ::Out> where 'x: 'key { self.lookup(NibbleSlice::new(key), &self.root_handle) } - fn insert(&mut self, key: &[u8], value: &[u8]) -> super::Result> { + fn insert(&mut self, key: &[u8], value: &[u8]) -> super::Result, ::Out> { if value.is_empty() { return self.remove(key) } let mut old_val = None; @@ -917,7 +909,7 @@ impl<'a, H: Hasher> TrieMut for TrieDBMut<'a, H> { Ok(old_val) } - fn remove(&mut self, key: &[u8]) -> super::Result> { + fn remove(&mut self, key: &[u8]) -> super::Result, ::Out> { trace!(target: "trie", "remove: key={:?}", key.pretty()); let root_handle = self.root_handle(); @@ -931,8 +923,8 @@ impl<'a, H: Hasher> TrieMut for TrieDBMut<'a, H> { } None => { trace!(target: "trie", "remove: obliterated trie"); - self.root_handle = NodeHandle::Hash(KECCAK_NULL_RLP); - *self.root = KECCAK_NULL_RLP; + self.root_handle = NodeHandle::Hash(Self::H::HASHED_NULL_RLP); + *self.root = Self::H::HASHED_NULL_RLP; } } @@ -940,7 +932,7 @@ impl<'a, H: Hasher> TrieMut for TrieDBMut<'a, H> { } } -impl<'a, H: Hasher> Drop for TrieDBMut<'a, H> { +impl<'a, H: Hasher> Drop for TrieDBMut<'a, H> where H::Out: Decodable + Encodable { fn drop(&mut self) { self.commit(); }