From 3f5bd90b2bb81fec2bdb910b3d3bb87a372180d4 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 1 Dec 2015 17:43:24 +0100 Subject: [PATCH 1/2] Easier debugging output for nibbleslice. --- src/nibbleslice.rs | 12 +++++++- src/trie.rs | 72 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 79 insertions(+), 5 deletions(-) diff --git a/src/nibbleslice.rs b/src/nibbleslice.rs index 7569046ad..716963bab 100644 --- a/src/nibbleslice.rs +++ b/src/nibbleslice.rs @@ -1,5 +1,6 @@ //! Nibble-orientated view onto byte-slice, allowing nibble-precision offsets. use std::cmp::*; +use std::fmt; use bytes::*; /// Nibble-orientated view onto byte-slice, allowing nibble-precision offsets. @@ -25,7 +26,7 @@ use bytes::*; /// assert_eq!(n2.mid(3).common_prefix(&n1), 3); /// } /// ``` -#[derive(Debug, Copy, Clone, Eq, Ord)] +#[derive(Copy, Clone, Eq, Ord)] pub struct NibbleSlice<'a> { data: &'a [u8], offset: usize, @@ -122,6 +123,15 @@ impl<'a> PartialOrd for NibbleSlice<'a> { } } +impl<'a> fmt::Debug for NibbleSlice<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + for i in 0..self.len() { + try!(write!(f, "{:01x}", i)); + } + Ok(()) + } +} + #[cfg(test)] mod tests { use super::NibbleSlice; diff --git a/src/trie.rs b/src/trie.rs index 5c716c947..d4f2d2f70 100644 --- a/src/trie.rs +++ b/src/trie.rs @@ -332,12 +332,14 @@ mod tests { fn playpen() { env_logger::init().unwrap(); + let big_value = b"00000000000000000000000000000000"; + let mut t = TrieDB::new_memory(); - t.insert(&[0x01u8, 0x23], &[0x01u8, 0x23]); - t.insert(&[], &[0x0]); + t.insert(&[0x01u8, 0x23], big_value); + t.insert(&[0x11u8, 0x23], big_value); assert_eq!(*t.root(), trie_root(vec![ - (vec![], vec![0x0]), - (vec![0x01u8, 0x23], vec![0x01u8, 0x23]), + (vec![0x01u8, 0x23], big_value.to_vec()), + (vec![0x11u8, 0x23], big_value.to_vec()) ])); } @@ -386,4 +388,66 @@ mod tests { (vec![0xf1u8, 0x23], vec![0xf1u8, 0x23]), ])); } + + #[test] + fn insert_value_into_branch_root() { + let mut t = TrieDB::new_memory(); + t.insert(&[0x01u8, 0x23], &[0x01u8, 0x23]); + t.insert(&[], &[0x0]); + assert_eq!(*t.root(), trie_root(vec![ + (vec![], vec![0x0]), + (vec![0x01u8, 0x23], vec![0x01u8, 0x23]), + ])); + } + + #[test] + fn insert_split_leaf() { + let mut t = TrieDB::new_memory(); + t.insert(&[0x01u8, 0x23], &[0x01u8, 0x23]); + t.insert(&[0x01u8, 0x34], &[0x01u8, 0x34]); + assert_eq!(*t.root(), trie_root(vec![ + (vec![0x01u8, 0x23], vec![0x01u8, 0x23]), + (vec![0x01u8, 0x34], vec![0x01u8, 0x34]), + ])); + } + + #[test] + fn insert_split_extenstion() { + let mut t = TrieDB::new_memory(); + t.insert(&[0x01, 0x23, 0x45], &[0x01]); + t.insert(&[0x01, 0xf3, 0x45], &[0x02]); + t.insert(&[0x01, 0xf3, 0xf5], &[0x03]); + assert_eq!(*t.root(), trie_root(vec![ + (vec![0x01, 0x23, 0x45], vec![0x01]), + (vec![0x01, 0xf3, 0x45], vec![0x02]), + (vec![0x01, 0xf3, 0xf5], vec![0x03]), + ])); + } + + #[test] + fn insert_big_value() { + let big_value0 = b"00000000000000000000000000000000"; + let big_value1 = b"11111111111111111111111111111111"; + + let mut t = TrieDB::new_memory(); + t.insert(&[0x01u8, 0x23], big_value0); + t.insert(&[0x11u8, 0x23], big_value1); + assert_eq!(*t.root(), trie_root(vec![ + (vec![0x01u8, 0x23], big_value0.to_vec()), + (vec![0x11u8, 0x23], big_value1.to_vec()) + ])); + } + + #[test] + fn insert_duplicate_value() { + let big_value = b"00000000000000000000000000000000"; + + let mut t = TrieDB::new_memory(); + t.insert(&[0x01u8, 0x23], big_value); + t.insert(&[0x11u8, 0x23], big_value); + assert_eq!(*t.root(), trie_root(vec![ + (vec![0x01u8, 0x23], big_value.to_vec()), + (vec![0x11u8, 0x23], big_value.to_vec()) + ])); + } } \ No newline at end of file From 7f6efa9a8ffe737747703a73c0f795ae87db71c6 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 1 Dec 2015 18:25:18 +0100 Subject: [PATCH 2/2] pretty (hex) printing. --- src/bytes.rs | 32 ++++++++++++++++++++++++++++++++ src/trie.rs | 26 +++++++++++++------------- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/src/bytes.rs b/src/bytes.rs index e17ccca9a..a01fda3ee 100644 --- a/src/bytes.rs +++ b/src/bytes.rs @@ -40,6 +40,38 @@ use std::error::Error as StdError; use uint::{U128, U256}; use hash::FixedHash; +pub struct PrettySlice<'a> (&'a [u8]); + +impl<'a> fmt::Debug 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; +} + +impl<'a> ToPretty for &'a [u8] { + fn pretty(&self) -> PrettySlice { + PrettySlice(self) + } +} + +impl<'a> ToPretty for &'a Bytes { + fn pretty(&self) -> PrettySlice { + PrettySlice(self.bytes()) + } +} +impl ToPretty for Bytes { + fn pretty(&self) -> PrettySlice { + PrettySlice(self.bytes()) + } +} + /// Vector of bytes pub type Bytes = Vec; diff --git a/src/trie.rs b/src/trie.rs index bd64be127..1645d9750 100644 --- a/src/trie.rs +++ b/src/trie.rs @@ -115,7 +115,7 @@ impl Diff { self.0.push(Operation::New(rlp_sha3, rlp)); } else { - trace!("new_node: inline node {:?}", &rlp); + trace!("new_node: inline node {:?}", rlp.pretty()); out.append_raw(&rlp, 1); } } @@ -154,7 +154,7 @@ impl TrieDB { fn set_root_rlp(&mut self, root_data: &[u8]) { self.db.kill(&self.root); self.root = self.db.insert(root_data); - trace!("set_root_rlp {:?} {:?}", root_data, self.root); + trace!("set_root_rlp {:?} {:?}", root_data.pretty(), self.root); } fn apply(&mut self, diff: Diff) { @@ -166,7 +166,7 @@ impl TrieDB { self.db.kill(&h); }, Operation::New(h, d) => { - trace!("TrieDB::apply +++ {:?} -> {:?}", &h, &d); + trace!("TrieDB::apply +++ {:?} -> {:?}", &h, d.pretty()); self.db.emplace(h, d); } } @@ -200,32 +200,32 @@ impl TrieDB { } fn add(&mut self, key: &NibbleSlice, value: &[u8]) { - trace!("ADD: {:?} {:?}", key, value); + trace!("ADD: {:?} {:?}", key, value.pretty()); // 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!("---"); + trace!("/"); } fn compose_leaf(partial: &NibbleSlice, value: &[u8]) -> Bytes { - trace!("compose_leaf {:?} {:?} ({:?})", partial, value, partial.encoded(true)); + trace!("compose_leaf {:?} {:?} ({:?})", partial, value.pretty(), partial.encoded(true).pretty()); let mut s = RlpStream::new_list(2); s.append(&partial.encoded(true)); s.append(&value); let r = s.out(); - trace!("compose_leaf: -> {:?}", &r); + trace!("compose_leaf: -> {:?}", r.pretty()); r } fn compose_raw(partial: &NibbleSlice, raw_payload: &[u8], is_leaf: bool) -> Bytes { - println!("compose_raw {:?} {:?} {:?} ({:?})", partial, raw_payload, is_leaf, partial.encoded(is_leaf)); + println!("compose_raw {:?} {:?} {:?} ({:?})", partial, raw_payload.pretty(), is_leaf, partial.encoded(is_leaf)); let mut s = RlpStream::new_list(2); s.append(&partial.encoded(is_leaf)); s.append_raw(raw_payload, 1); let r = s.out(); - println!("compose_raw: -> {:?}", &r); + println!("compose_raw: -> {:?}", r.pretty()); r } @@ -237,18 +237,18 @@ impl TrieDB { /// the trie. fn take_node<'a, 'rlp_view>(&'a self, rlp: &'rlp_view Rlp<'a>, diff: &mut Diff) -> &'a [u8] where 'a: 'rlp_view { if rlp.is_list() { - trace!("take_node {:?} (inline)", rlp.raw()); + trace!("take_node {:?} (inline)", rlp.raw().pretty()); rlp.raw() } else if rlp.is_data() && rlp.size() == 32 { let h = H256::decode(rlp); let r = self.db.lookup(&h).expect("Trie root not found!"); - trace!("take_node {:?} (indirect for {:?})", rlp.raw(), r); + trace!("take_node {:?} (indirect for {:?})", rlp.raw().pretty(), r); diff.delete_node_sha3(h); r } else { - trace!("take_node {:?} (???)", rlp.raw()); + trace!("take_node {:?} (???)", rlp.raw().pretty()); panic!("Empty or invalid node given?"); } } @@ -339,7 +339,7 @@ impl TrieDB { /// /// **This operation will not insert the new node now destroy the original.** fn augmented(&self, old: &[u8], partial: &NibbleSlice, value: &[u8], diff: &mut Diff) -> Bytes { - trace!("augmented ({:?}, {:?}, {:?})", old, partial, value); + trace!("augmented ({:?}, {:?}, {:?})", old.pretty(), partial, value.pretty()); // already have an extension. either fast_forward, cleve or transmute_to_branch. let old_rlp = Rlp::new(old); match old_rlp.prototype() {