From 0179cf54b7ea271a32a862eb9a4461563ac1f110 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 1 Dec 2015 12:10:36 +0100 Subject: [PATCH 1/4] Better logging, additional tests. --- src/trie.rs | 47 +++++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/src/trie.rs b/src/trie.rs index 9f0b209be..8dbf220ad 100644 --- a/src/trie.rs +++ b/src/trie.rs @@ -40,6 +40,7 @@ impl Diff { self.0.push(Operation::New(rlp_sha3, rlp)); } else { + trace!("new_node: inline node {:?}", &rlp); out.append_raw(&rlp, 1); } } @@ -67,13 +68,11 @@ pub struct TrieDB { } impl TrieDB { - pub fn new(db: T) -> Self where T: HashDB + 'static { TrieDB{ db: Box::new(db), root: H256::new() } } + pub fn new_boxed(db_box: Box) -> Self { let mut r = TrieDB{ db: db_box, root: H256::new() }; r.set_root_rlp(&NULL_RLP); r } - pub fn new_boxed(db_box: Box) -> Self { TrieDB{ db: db_box, root: H256::new() } } + pub fn new(db: T) -> Self where T: HashDB + 'static { Self::new_boxed(Box::new(db)) } - pub fn new_memory() -> Self { TrieDB{ db: Box::new(MemoryDB::new()), root: H256::new() } } - - pub fn init(&mut self) { self.set_root_rlp(&NULL_RLP); } + pub fn new_memory() -> Self { Self::new(MemoryDB::new()) } pub fn db(&self) -> &HashDB { self.db.as_ref() } @@ -84,6 +83,7 @@ impl TrieDB { } fn apply(&mut self, diff: Diff) { + trace!("applying {:?} changes", diff.0.len()); for d in diff.0.into_iter() { match d { Operation::Delete(h) => { @@ -99,11 +99,13 @@ impl TrieDB { } fn add(&mut self, key: &NibbleSlice, value: &[u8]) { + trace!("ADD: {:?} {:?}", key, value); // determine what the new root is, insert new nodes and remove old as necessary. let mut todo: Diff = Diff::new(); let root_rlp = self.augmented(self.db.lookup(&self.root).expect("Trie root not found!"), key, value, &mut todo); self.apply(todo); self.set_root_rlp(&root_rlp); + trace!("---"); } fn compose_leaf(partial: &NibbleSlice, value: &[u8]) -> Bytes { @@ -112,7 +114,7 @@ impl TrieDB { s.append(&partial.encoded(true)); s.append(&value); let r = s.out(); - trace!("output: -> {:?}", &r); + trace!("compose_leaf: -> {:?}", &r); r } @@ -122,7 +124,7 @@ impl TrieDB { s.append(&partial.encoded(is_leaf)); s.append_raw(raw_payload, 1); let r = s.out(); - println!("output: -> {:?}", &r); + println!("compose_raw: -> {:?}", &r); r } @@ -246,6 +248,7 @@ impl TrieDB { let old_rlp = Rlp::new(old); match old_rlp.prototype() { Prototype::List(17) => { + trace!("branch: ROUTE,AUGMENT"); // already have a branch. route and augment. self.augmented_into_branch(&old_rlp, partial, value, diff) }, @@ -297,6 +300,7 @@ impl TrieDB { } }, Prototype::Data(0) => { + trace!("empty: COMPOSE"); Self::compose_leaf(partial, value) }, _ => panic!("Invalid RLP for node."), @@ -326,7 +330,6 @@ impl Trie for TrieDB { #[cfg(test)] mod tests { - use memorydb::*; use triehash::*; use super::*; use env_logger; @@ -335,33 +338,45 @@ mod tests { fn playpen() { env_logger::init().unwrap(); - let mut t = TrieDB::new(MemoryDB::new()); - t.init(); + let mut t = TrieDB::new_memory(); t.insert(&[0x01u8, 0x23], &[0x01u8, 0x23]); + t.insert(&[0x11u8, 0x23], &[0x11u8, 0x23]); + assert_eq!(*t.root(), trie_root(vec![ + (vec![0x01u8, 0x23], vec![0x01u8, 0x23]), + (vec![0x11u8, 0x23], vec![0x11u8, 0x23]) + ])); } #[test] fn init() { - let mut t = TrieDB::new(MemoryDB::new()); - t.init(); + let t = TrieDB::new_memory(); assert_eq!(*t.root(), SHA3_NULL_RLP); assert!(t.is_empty()); } #[test] fn insert_on_empty() { - let mut t = TrieDB::new(MemoryDB::new()); - t.init(); + let mut t = TrieDB::new_memory(); t.insert(&[0x01u8, 0x23], &[0x01u8, 0x23]); assert_eq!(*t.root(), trie_root(vec![ (vec![0x01u8, 0x23], vec![0x01u8, 0x23]) ])); } #[test] fn insert_replace_root() { - let mut t = TrieDB::new(MemoryDB::new()); - t.init(); + let mut t = TrieDB::new_memory(); 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]) ])); } + + #[test] + fn insert_branch_root() { + let mut t = TrieDB::new_memory(); + t.insert(&[0x01u8, 0x23], &[0x01u8, 0x23]); + t.insert(&[0x11u8, 0x23], &[0x11u8, 0x23]); + assert_eq!(*t.root(), trie_root(vec![ + (vec![0x01u8, 0x23], vec![0x01u8, 0x23]), + (vec![0x11u8, 0x23], vec![0x11u8, 0x23]) + ])); + } } \ No newline at end of file From a90ef806a3a53a5d38610f9da1729e9a9223494e Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 1 Dec 2015 12:24:58 +0100 Subject: [PATCH 2/4] Broken triehash --- src/trie.rs | 15 +++++++++++++-- src/triehash.rs | 13 +++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/trie.rs b/src/trie.rs index 8dbf220ad..aad6db1cf 100644 --- a/src/trie.rs +++ b/src/trie.rs @@ -340,10 +340,21 @@ mod tests { let mut t = TrieDB::new_memory(); t.insert(&[0x01u8, 0x23], &[0x01u8, 0x23]); - t.insert(&[0x11u8, 0x23], &[0x11u8, 0x23]); + t.insert(&[0xf1u8, 0x23], &[0xf1u8, 0x23]); + t.insert(&[0x81u8, 0x23], &[0x81u8, 0x23]); + trace!("trieroot with 2 items: {:?}", trie_root(vec![ + (vec![0x01u8, 0x23], vec![0x01u8, 0x23]), + (vec![0xf1u8, 0x23], vec![0xf1u8, 0x23]), + ])); + trace!("trieroot with 3 items: {:?}", trie_root(vec![ + (vec![0x01u8, 0x23], vec![0x01u8, 0x23]), + (vec![0xf1u8, 0x23], vec![0xf1u8, 0x23]), + (vec![0x81u8, 0x23], vec![0x81u8, 0x23]), + ])); assert_eq!(*t.root(), trie_root(vec![ (vec![0x01u8, 0x23], vec![0x01u8, 0x23]), - (vec![0x11u8, 0x23], vec![0x11u8, 0x23]) + (vec![0xf1u8, 0x23], vec![0xf1u8, 0x23]), + (vec![0x81u8, 0x23], vec![0x81u8, 0x23]), ])); } diff --git a/src/triehash.rs b/src/triehash.rs index e26cc255f..56df87c55 100644 --- a/src/triehash.rs +++ b/src/triehash.rs @@ -319,6 +319,19 @@ mod tests { assert_eq!(trie_root(v), H256::from_str("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84").unwrap()); } + #[test] + fn broken() { + assert!(trie_root(vec![ + (vec![0x01u8, 0x23], vec![0x01u8, 0x23]), + (vec![0xf1u8, 0x23], vec![0xf1u8, 0x23]), + ]) != + trie_root(vec![ + (vec![0x01u8, 0x23], vec![0x01u8, 0x23]), + (vec![0xf1u8, 0x23], vec![0xf1u8, 0x23]), + (vec![0x81u8, 0x23], vec![0x81u8, 0x23]), + ])); + } + #[test] fn test_trie_root() { let v = vec![ From 6c21bc7b952b10f2935da02a75905a08aa6f8b32 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 1 Dec 2015 12:26:20 +0100 Subject: [PATCH 3/4] out of order test for trieroot --- src/triehash.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/triehash.rs b/src/triehash.rs index 56df87c55..8be23e210 100644 --- a/src/triehash.rs +++ b/src/triehash.rs @@ -320,11 +320,12 @@ mod tests { } #[test] - fn broken() { + fn out_of_order() { assert!(trie_root(vec![ (vec![0x01u8, 0x23], vec![0x01u8, 0x23]), + (vec![0x81u8, 0x23], vec![0x81u8, 0x23]), (vec![0xf1u8, 0x23], vec![0xf1u8, 0x23]), - ]) != + ]) == trie_root(vec![ (vec![0x01u8, 0x23], vec![0x01u8, 0x23]), (vec![0xf1u8, 0x23], vec![0xf1u8, 0x23]), From 9041f81cba0d457ce04f2fd8af594df5f2f33974 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 1 Dec 2015 12:57:08 +0100 Subject: [PATCH 4/4] Additional trie test and fix. --- src/trie.rs | 50 +++++++++++++++++++++++--------------------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/src/trie.rs b/src/trie.rs index aad6db1cf..5c716c947 100644 --- a/src/trie.rs +++ b/src/trie.rs @@ -213,22 +213,16 @@ impl TrieDB { let mut s = RlpStream::new_list(17); let index = if partial.is_empty() {16} else {partial.at(0) as usize}; for i in 0usize..17 { - if index == i { - // this is node to augment into... - if orig.at(i).is_empty() { - // easy - original had empty slot. - diff.new_node(Self::compose_leaf(&partial.mid(if i == 16 {0} else {1}), value), &mut s); - } else if i == 16 { - // leaf entry - just replace. - let new = Self::compose_leaf(&partial.mid(if i == 16 {0} else {1}), value); - diff.replace_node(&orig.at(i), new, &mut s); - } else { - // harder - original has something there already + match (index == i, i) { + (true, 16) => // leaf entry - just replace. + { s.append(&value); }, + (true, i) if orig.at(i).is_empty() => // easy - original had empty slot. + diff.new_node(Self::compose_leaf(&partial.mid(1), value), &mut s), + (true, i) => { // harder - original has something there already let new = self.augmented(orig.at(i).raw(), &partial.mid(1), value, diff); diff.replace_node(&orig.at(i), new, &mut s); } - } else { - s.append_raw(orig.at(i).raw(), 1); + (false, i) => { s.append_raw(orig.at(i).raw(), 1); }, } } s.out() @@ -340,21 +334,10 @@ mod tests { let mut t = TrieDB::new_memory(); t.insert(&[0x01u8, 0x23], &[0x01u8, 0x23]); - t.insert(&[0xf1u8, 0x23], &[0xf1u8, 0x23]); - t.insert(&[0x81u8, 0x23], &[0x81u8, 0x23]); - trace!("trieroot with 2 items: {:?}", trie_root(vec![ - (vec![0x01u8, 0x23], vec![0x01u8, 0x23]), - (vec![0xf1u8, 0x23], vec![0xf1u8, 0x23]), - ])); - trace!("trieroot with 3 items: {:?}", trie_root(vec![ - (vec![0x01u8, 0x23], vec![0x01u8, 0x23]), - (vec![0xf1u8, 0x23], vec![0xf1u8, 0x23]), - (vec![0x81u8, 0x23], vec![0x81u8, 0x23]), - ])); + t.insert(&[], &[0x0]); assert_eq!(*t.root(), trie_root(vec![ + (vec![], vec![0x0]), (vec![0x01u8, 0x23], vec![0x01u8, 0x23]), - (vec![0xf1u8, 0x23], vec![0xf1u8, 0x23]), - (vec![0x81u8, 0x23], vec![0x81u8, 0x23]), ])); } @@ -381,7 +364,7 @@ mod tests { } #[test] - fn insert_branch_root() { + fn insert_make_branch_root() { let mut t = TrieDB::new_memory(); t.insert(&[0x01u8, 0x23], &[0x01u8, 0x23]); t.insert(&[0x11u8, 0x23], &[0x11u8, 0x23]); @@ -390,4 +373,17 @@ mod tests { (vec![0x11u8, 0x23], vec![0x11u8, 0x23]) ])); } + + #[test] + fn insert_into_branch_root() { + let mut t = TrieDB::new_memory(); + t.insert(&[0x01u8, 0x23], &[0x01u8, 0x23]); + t.insert(&[0xf1u8, 0x23], &[0xf1u8, 0x23]); + t.insert(&[0x81u8, 0x23], &[0x81u8, 0x23]); + assert_eq!(*t.root(), trie_root(vec![ + (vec![0x01u8, 0x23], vec![0x01u8, 0x23]), + (vec![0x81u8, 0x23], vec![0x81u8, 0x23]), + (vec![0xf1u8, 0x23], vec![0xf1u8, 0x23]), + ])); + } } \ No newline at end of file