From 674c667114370eb2975765bef47362013d308f24 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 17 Dec 2015 12:43:50 +0100 Subject: [PATCH] Rename Trie to TrieMut in preparation for immutable trie. --- benches/trie.rs | 8 ++--- src/bytes.rs | 12 +++++++ src/hashdb.rs | 12 +++++-- src/trie.rs | 95 +++++++++++++++++++++++++++---------------------- 4 files changed, 78 insertions(+), 49 deletions(-) diff --git a/benches/trie.rs b/benches/trie.rs index 65df58309..8f1a2a42d 100644 --- a/benches/trie.rs +++ b/benches/trie.rs @@ -55,7 +55,7 @@ fn trie_insertions_six_high(b: &mut Bencher) { b.iter(||{ let mut memdb = MemoryDB::new(); let mut root = H256::new(); - let mut t = TrieDB::new(&mut memdb, &mut root); + let mut t = TrieDBMut::new(&mut memdb, &mut root); for i in d.iter() { t.insert(&i.0, &i.1); } @@ -90,7 +90,7 @@ fn trie_insertions_six_mid(b: &mut Bencher) { b.iter(||{ let mut memdb = MemoryDB::new(); let mut root = H256::new(); - let mut t = TrieDB::new(&mut memdb, &mut root); + let mut t = TrieDBMut::new(&mut memdb, &mut root); for i in d.iter() { t.insert(&i.0, &i.1); } @@ -127,7 +127,7 @@ fn trie_insertions_random_mid(b: &mut Bencher) { b.iter(||{ let mut memdb = MemoryDB::new(); let mut root = H256::new(); - let mut t = TrieDB::new(&mut memdb, &mut root); + let mut t = TrieDBMut::new(&mut memdb, &mut root); for i in d.iter() { t.insert(&i.0, &i.1); } @@ -164,7 +164,7 @@ fn trie_insertions_six_low(b: &mut Bencher) { b.iter(||{ let mut memdb = MemoryDB::new(); let mut root = H256::new(); - let mut t = TrieDB::new(&mut memdb, &mut root); + let mut t = TrieDBMut::new(&mut memdb, &mut root); for i in d.iter() { t.insert(&i.0, &i.1); } diff --git a/src/bytes.rs b/src/bytes.rs index e81cd8572..d188eb69b 100644 --- a/src/bytes.rs +++ b/src/bytes.rs @@ -54,8 +54,20 @@ impl<'a> fmt::Debug for PrettySlice<'a> { } } +impl<'a> fmt::Display for PrettySlice<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + for i in 0..self.0.len() { + try!(write!(f, "{:02x}", self.0[i])); + } + Ok(()) + } +} + pub trait ToPretty { fn pretty(&self) -> PrettySlice; + fn to_hex(&self) -> String { + format!("{}", self.pretty()) + } } impl<'a> ToPretty for &'a [u8] { diff --git a/src/hashdb.rs b/src/hashdb.rs index e63d031e5..0eebe9d9e 100644 --- a/src/hashdb.rs +++ b/src/hashdb.rs @@ -8,6 +8,8 @@ pub trait HashDB { /// Get the keys in the database together with number of underlying references. fn keys(&self) -> HashMap; + /// Deprecated. use `get`. + fn lookup(&self, key: &H256) -> Option<&[u8]>; // TODO: rename to get. /// Look up a given hash into the bytes that hash to it, returning None if the /// hash is not known. /// @@ -23,8 +25,10 @@ pub trait HashDB { /// assert_eq!(m.lookup(&hash).unwrap(), hello_bytes); /// } /// ``` - fn lookup(&self, key: &H256) -> Option<&[u8]>; + fn get(&self, key: &H256) -> Option<&[u8]> { self.lookup(key) } + /// Deprecated. Use `contains`. + fn exists(&self, key: &H256) -> bool; // TODO: rename to contains. /// Check for the existance of a hash-key. /// /// # Examples @@ -43,7 +47,7 @@ pub trait HashDB { /// assert!(!m.exists(&key)); /// } /// ``` - fn exists(&self, key: &H256) -> bool; + fn contains(&self, key: &H256) -> bool { self.exists(key) } /// Insert a datum item into the DB and return the datum's hash for a later lookup. Insertions /// are counted and the equivalent number of `kill()`s must be performed before the data @@ -66,6 +70,8 @@ pub trait HashDB { /// Like `insert()` , except you provide the key and the data is all moved. fn emplace(&mut self, key: H256, value: Bytes); + /// Deprecated - use `remove`. + fn kill(&mut self, key: &H256); // TODO: rename to remove. /// Remove a datum previously inserted. Insertions can be "owed" such that the same number of `insert()`s may /// happen without the data being eventually being inserted into the DB. /// @@ -87,5 +93,5 @@ pub trait HashDB { /// assert_eq!(m.lookup(key).unwrap(), d); /// } /// ``` - fn kill(&mut self, key: &H256); + fn remove(&mut self, key: &H256) { self.kill(key) } } diff --git a/src/trie.rs b/src/trie.rs index ad70a30a1..1716aa56f 100644 --- a/src/trie.rs +++ b/src/trie.rs @@ -27,8 +27,11 @@ pub trait Trie { fn contains(&self, key: &[u8]) -> bool; /// What is the value of the given key in this trie? - fn at<'a, 'key>(&'a self, key: &'key [u8]) -> Option<&'a [u8]> where 'a: 'key; + fn get<'a, 'key>(&'a self, key: &'key [u8]) -> Option<&'a [u8]> where 'a: 'key; +} +/// A key-value datastore implemented as a database-backed modified Merkle tree. +pub trait TrieMut: Trie { /// 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]); @@ -287,12 +290,12 @@ impl <'a>Node<'a> { /// fn main() { /// let mut memdb = MemoryDB::new(); /// let mut root = H256::new(); -/// let mut t = TrieDB::new(&mut memdb, &mut root); +/// let mut t = TrieDBMut::new(&mut memdb, &mut root); /// assert!(t.is_empty()); /// assert_eq!(*t.root(), SHA3_NULL_RLP); /// t.insert(b"foo", b"bar"); /// assert!(t.contains(b"foo")); -/// assert_eq!(t.at(b"foo").unwrap(), b"bar"); +/// assert_eq!(t.get(b"foo").unwrap(), b"bar"); /// assert!(t.db_items_remaining().is_empty()); /// t.remove(b"foo"); /// assert!(!t.contains(b"foo")); @@ -300,6 +303,12 @@ impl <'a>Node<'a> { /// } /// ``` pub struct TrieDB<'db> { + db: &'db HashDB, + root: &'db H256, + pub hash_count: usize, +} + +pub struct TrieDBMut<'db> { db: &'db mut HashDB, root: &'db mut H256, pub hash_count: usize, @@ -311,12 +320,12 @@ enum MaybeChanged<'a> { Changed(Bytes), } -impl<'db> TrieDB<'db> { +impl<'db> TrieDBMut<'db> { /// 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 { - let mut r = TrieDB{ + let mut r = TrieDBMut{ db: db, root: root, hash_count: 0 @@ -331,7 +340,7 @@ impl<'db> TrieDB<'db> { /// Panics, if `root` does not exist pub fn new_existing(db: &'db mut HashDB, root: &'db mut H256) -> Self { assert!(db.exists(root)); - TrieDB { + TrieDBMut { db: db, root: root, hash_count: 0 @@ -390,11 +399,11 @@ impl<'db> TrieDB<'db> { for d in journal.0.into_iter() { match d { Operation::Delete(h) => { - trace!("TrieDB::apply --- {:?}", &h); + trace!("TrieDBMut::apply --- {:?}", &h); self.db.kill(&h); }, Operation::New(h, d) => { - trace!("TrieDB::apply +++ {:?} -> {:?}", &h, d.pretty()); + trace!("TrieDBMut::apply +++ {:?} -> {:?}", &h, d.pretty()); self.db.emplace(h, d); self.hash_count += 1; } @@ -475,7 +484,7 @@ impl<'db> TrieDB<'db> { } /// Return optional data for a key given as a `NibbleSlice`. Returns `None` if no data exists. - fn get<'a, 'key>(&'a self, key: &NibbleSlice<'key>) -> Option<&'a [u8]> where 'a: 'key { + fn do_lookup<'a, 'key>(&'a self, key: &NibbleSlice<'key>) -> Option<&'a [u8]> where 'a: 'key { let root_rlp = self.db.lookup(&self.root).expect("Trie root not found!"); self.get_from_node(&root_rlp, key) } @@ -892,17 +901,19 @@ impl<'db> TrieDB<'db> { } } -impl<'db> Trie for TrieDB<'db> { +impl<'db> Trie for TrieDBMut<'db> { fn root(&self) -> &H256 { &self.root } fn contains(&self, key: &[u8]) -> bool { - self.at(key).is_some() + self.get(key).is_some() } - fn at<'a, 'key>(&'a self, key: &'key [u8]) -> Option<&'a [u8]> where 'a: 'key { - self.get(&NibbleSlice::new(key)) + fn get<'a, 'key>(&'a self, key: &'key [u8]) -> Option<&'a [u8]> where 'a: 'key { + self.do_lookup(&NibbleSlice::new(key)) } +} +impl<'db> TrieMut for TrieDBMut<'db> { fn insert(&mut self, key: &[u8], value: &[u8]) { match value.is_empty() { false => self.insert_ns(&NibbleSlice::new(key), value), @@ -915,7 +926,7 @@ impl<'db> Trie for TrieDB<'db> { } } -impl<'db> fmt::Debug for TrieDB<'db> { +impl<'db> fmt::Debug for TrieDBMut<'db> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(writeln!(f, "c={:?} [", self.hash_count)); let root_rlp = self.db.lookup(&self.root).expect("Trie root not found!"); @@ -960,8 +971,8 @@ mod tests { } } - fn populate_trie<'db>(db: &'db mut HashDB, root: &'db mut H256, v: &Vec<(Vec, Vec)>) -> TrieDB<'db> { - let mut t = TrieDB::new(db, root); + fn populate_trie<'db>(db: &'db mut HashDB, root: &'db mut H256, v: &Vec<(Vec, Vec)>) -> TrieDBMut<'db> { + let mut t = TrieDBMut::new(db, root); for i in 0..v.len() { let key: &[u8]= &v[i].0; let val: &[u8] = &v[i].1; @@ -970,7 +981,7 @@ mod tests { t } - fn unpopulate_trie<'a, 'db>(t: &mut TrieDB<'db>, v: &Vec<(Vec, Vec)>) { + fn unpopulate_trie<'a, 'db>(t: &mut TrieDBMut<'db>, v: &Vec<(Vec, Vec)>) { for i in v.iter() { let key: &[u8]= &i.0; t.remove(&key); @@ -1053,7 +1064,7 @@ mod tests { fn init() { let mut memdb = MemoryDB::new(); let mut root = H256::new(); - let t = TrieDB::new(&mut memdb, &mut root); + let t = TrieDBMut::new(&mut memdb, &mut root); assert_eq!(*t.root(), SHA3_NULL_RLP); assert!(t.is_empty()); } @@ -1062,7 +1073,7 @@ mod tests { fn insert_on_empty() { let mut memdb = MemoryDB::new(); let mut root = H256::new(); - let mut t = TrieDB::new(&mut memdb, &mut root); + let mut t = TrieDBMut::new(&mut memdb, &mut root); t.insert(&[0x01u8, 0x23], &[0x01u8, 0x23]); assert_eq!(*t.root(), trie_root(vec![ (vec![0x01u8, 0x23], vec![0x01u8, 0x23]) ])); } @@ -1073,14 +1084,14 @@ mod tests { let mut memdb = MemoryDB::new(); let mut root = H256::new(); - let mut t1 = TrieDB::new(&mut memdb, &mut root); + let mut t1 = TrieDBMut::new(&mut memdb, &mut root); t1.insert(&[0x01, 0x23], &big_value.to_vec()); t1.insert(&[0x01, 0x34], &big_value.to_vec()); trace!("keys remaining {:?}", t1.db_items_remaining()); assert!(t1.db_items_remaining().is_empty()); let mut memdb2 = MemoryDB::new(); let mut root2 = H256::new(); - let mut t2 = TrieDB::new(&mut memdb2, &mut root2); + let mut t2 = TrieDBMut::new(&mut memdb2, &mut root2); t2.insert(&[0x01], &big_value.to_vec()); t2.insert(&[0x01, 0x23], &big_value.to_vec()); t2.insert(&[0x01, 0x34], &big_value.to_vec()); @@ -1096,7 +1107,7 @@ mod tests { fn insert_replace_root() { let mut memdb = MemoryDB::new(); let mut root = H256::new(); - let mut t = TrieDB::new(&mut memdb, &mut root); + let mut t = TrieDBMut::new(&mut memdb, &mut root); t.insert(&[0x01u8, 0x23], &[0x01u8, 0x23]); t.insert(&[0x01u8, 0x23], &[0x23u8, 0x45]); assert_eq!(*t.root(), trie_root(vec![ (vec![0x01u8, 0x23], vec![0x23u8, 0x45]) ])); @@ -1106,7 +1117,7 @@ mod tests { fn insert_make_branch_root() { let mut memdb = MemoryDB::new(); let mut root = H256::new(); - let mut t = TrieDB::new(&mut memdb, &mut root); + let mut t = TrieDBMut::new(&mut memdb, &mut root); t.insert(&[0x01u8, 0x23], &[0x01u8, 0x23]); t.insert(&[0x11u8, 0x23], &[0x11u8, 0x23]); assert_eq!(*t.root(), trie_root(vec![ @@ -1119,7 +1130,7 @@ mod tests { fn insert_into_branch_root() { let mut memdb = MemoryDB::new(); let mut root = H256::new(); - let mut t = TrieDB::new(&mut memdb, &mut root); + let mut t = TrieDBMut::new(&mut memdb, &mut root); t.insert(&[0x01u8, 0x23], &[0x01u8, 0x23]); t.insert(&[0xf1u8, 0x23], &[0xf1u8, 0x23]); t.insert(&[0x81u8, 0x23], &[0x81u8, 0x23]); @@ -1134,7 +1145,7 @@ mod tests { fn insert_value_into_branch_root() { let mut memdb = MemoryDB::new(); let mut root = H256::new(); - let mut t = TrieDB::new(&mut memdb, &mut root); + let mut t = TrieDBMut::new(&mut memdb, &mut root); t.insert(&[0x01u8, 0x23], &[0x01u8, 0x23]); t.insert(&[], &[0x0]); assert_eq!(*t.root(), trie_root(vec![ @@ -1147,7 +1158,7 @@ mod tests { fn insert_split_leaf() { let mut memdb = MemoryDB::new(); let mut root = H256::new(); - let mut t = TrieDB::new(&mut memdb, &mut root); + let mut t = TrieDBMut::new(&mut memdb, &mut root); t.insert(&[0x01u8, 0x23], &[0x01u8, 0x23]); t.insert(&[0x01u8, 0x34], &[0x01u8, 0x34]); assert_eq!(*t.root(), trie_root(vec![ @@ -1160,7 +1171,7 @@ mod tests { fn insert_split_extenstion() { let mut memdb = MemoryDB::new(); let mut root = H256::new(); - let mut t = TrieDB::new(&mut memdb, &mut root); + let mut t = TrieDBMut::new(&mut memdb, &mut root); t.insert(&[0x01, 0x23, 0x45], &[0x01]); t.insert(&[0x01, 0xf3, 0x45], &[0x02]); t.insert(&[0x01, 0xf3, 0xf5], &[0x03]); @@ -1178,7 +1189,7 @@ mod tests { let mut memdb = MemoryDB::new(); let mut root = H256::new(); - let mut t = TrieDB::new(&mut memdb, &mut root); + let mut t = TrieDBMut::new(&mut memdb, &mut root); t.insert(&[0x01u8, 0x23], big_value0); t.insert(&[0x11u8, 0x23], big_value1); assert_eq!(*t.root(), trie_root(vec![ @@ -1193,7 +1204,7 @@ mod tests { let mut memdb = MemoryDB::new(); let mut root = H256::new(); - let mut t = TrieDB::new(&mut memdb, &mut root); + let mut t = TrieDBMut::new(&mut memdb, &mut root); t.insert(&[0x01u8, 0x23], big_value); t.insert(&[0x11u8, 0x23], big_value); assert_eq!(*t.root(), trie_root(vec![ @@ -1253,38 +1264,38 @@ mod tests { fn test_at_empty() { let mut memdb = MemoryDB::new(); let mut root = H256::new(); - let t = TrieDB::new(&mut memdb, &mut root); - assert_eq!(t.at(&[0x5]), None); + let t = TrieDBMut::new(&mut memdb, &mut root); + assert_eq!(t.get(&[0x5]), None); } #[test] fn test_at_one() { let mut memdb = MemoryDB::new(); let mut root = H256::new(); - let mut t = TrieDB::new(&mut memdb, &mut root); + let mut t = TrieDBMut::new(&mut memdb, &mut root); t.insert(&[0x01u8, 0x23], &[0x01u8, 0x23]); - assert_eq!(t.at(&[0x1, 0x23]).unwrap(), &[0x1u8, 0x23]); + assert_eq!(t.get(&[0x1, 0x23]).unwrap(), &[0x1u8, 0x23]); } #[test] fn test_at_three() { let mut memdb = MemoryDB::new(); let mut root = H256::new(); - let mut t = TrieDB::new(&mut memdb, &mut root); + let mut t = TrieDBMut::new(&mut memdb, &mut root); t.insert(&[0x01u8, 0x23], &[0x01u8, 0x23]); t.insert(&[0xf1u8, 0x23], &[0xf1u8, 0x23]); t.insert(&[0x81u8, 0x23], &[0x81u8, 0x23]); - assert_eq!(t.at(&[0x01, 0x23]).unwrap(), &[0x01u8, 0x23]); - assert_eq!(t.at(&[0xf1, 0x23]).unwrap(), &[0xf1u8, 0x23]); - assert_eq!(t.at(&[0x81, 0x23]).unwrap(), &[0x81u8, 0x23]); - assert_eq!(t.at(&[0x82, 0x23]), None); + assert_eq!(t.get(&[0x01, 0x23]).unwrap(), &[0x01u8, 0x23]); + assert_eq!(t.get(&[0xf1, 0x23]).unwrap(), &[0xf1u8, 0x23]); + assert_eq!(t.get(&[0x81, 0x23]).unwrap(), &[0x81u8, 0x23]); + assert_eq!(t.get(&[0x82, 0x23]), None); } #[test] fn test_print_trie() { let mut memdb = MemoryDB::new(); let mut root = H256::new(); - let mut t = TrieDB::new(&mut memdb, &mut root); + let mut t = TrieDBMut::new(&mut memdb, &mut root); t.insert(&[0x01u8, 0x23], &[0x01u8, 0x23]); t.insert(&[0x02u8, 0x23], &[0x01u8, 0x23]); t.insert(&[0xf1u8, 0x23], &[0xf1u8, 0x23]); @@ -1339,7 +1350,7 @@ mod tests { let mut memdb = MemoryDB::new(); let mut root = H256::new(); - let mut t = TrieDB::new(&mut memdb, &mut root); + let mut t = TrieDBMut::new(&mut memdb, &mut root); for operation in input.into_iter() { match operation { trie::Operation::Insert(key, value) => t.insert(&key, &value), @@ -1356,12 +1367,12 @@ mod tests { let mut root = H256::new(); let mut db = MemoryDB::new(); { - let mut t = TrieDB::new(&mut db, &mut root); + let mut t = TrieDBMut::new(&mut db, &mut root); t.insert(&[0x01u8, 0x23], &[0x01u8, 0x23]); } { - let _ = TrieDB::new_existing(&mut db, &mut root); + let _ = TrieDBMut::new_existing(&mut db, &mut root); } } }