diff --git a/src/executive.rs b/src/executive.rs index 2a26dd3f0..6c2b29e3f 100644 --- a/src/executive.rs +++ b/src/executive.rs @@ -171,7 +171,7 @@ impl<'a> Executive<'a> { // at first, transfer value to destination self.state.transfer_balance(¶ms.sender, ¶ms.address, ¶ms.value); - debug!("Executive::call(params={:?}) self.env_info={:?}", params, self.info); + trace!("Executive::call(params={:?}) self.env_info={:?}", params, self.info); if self.engine.is_builtin(¶ms.code_address) { // if destination is builtin, try to execute it diff --git a/src/state.rs b/src/state.rs index fc4d6f817..a186d6cd6 100644 --- a/src/state.rs +++ b/src/state.rs @@ -150,10 +150,10 @@ impl State { let e = try!(Executive::new(self, env_info, engine).transact(t)); //println!("Executed: {:?}", e); - debug!("Applied transaction. Diff:\n{}\n", StateDiff::diff_pod(&old, &self.to_pod())); + trace!("Applied transaction. Diff:\n{}\n", StateDiff::diff_pod(&old, &self.to_pod())); self.commit(); let receipt = Receipt::new(self.root().clone(), e.cumulative_gas_used, e.logs); - debug!("Transaction receipt: {:?}", receipt); + trace!("Transaction receipt: {:?}", receipt); Ok(receipt) } diff --git a/src/views.rs b/src/views.rs index 6c616774d..a9c723ef2 100644 --- a/src/views.rs +++ b/src/views.rs @@ -61,6 +61,44 @@ impl<'a> Hashable for TransactionView<'a> { } } +/// View onto transaction rlp. +pub struct AccountView<'a> { + rlp: Rlp<'a> +} + +impl<'a> AccountView<'a> { + /// Creates new view onto block from raw bytes. + pub fn new(bytes: &'a [u8]) -> AccountView<'a> { + AccountView { + rlp: Rlp::new(bytes) + } + } + + /// Creates new view onto block from rlp. + pub fn new_from_rlp(rlp: Rlp<'a>) -> AccountView<'a> { + AccountView { + rlp: rlp + } + } + + /// Return reference to underlaying rlp. + pub fn rlp(&self) -> &Rlp<'a> { + &self.rlp + } + + /// Get the nonce field of the transaction. + pub fn nonce(&self) -> U256 { self.rlp.val_at(0) } + + /// Get the gas_price field of the transaction. + pub fn balance(&self) -> U256 { self.rlp.val_at(1) } + + /// Get the gas field of the transaction. + pub fn storage_root(&self) -> H256 { self.rlp.val_at(2) } + + /// Get the value field of the transaction. + pub fn code_hash(&self) -> H256 { self.rlp.val_at(3) } +} + /// View onto block rlp. pub struct BlockView<'a> { rlp: Rlp<'a> @@ -97,13 +135,13 @@ impl<'a> BlockView<'a> { } /// Return List of transactions in given block. - pub fn transaction_views(&self) -> Vec { - self.rlp.at(1).iter().map(|rlp| TransactionView::new_from_rlp(rlp)).collect() + pub fn transactions(&self) -> Vec { + self.rlp.val_at(1) } /// Return List of transactions in given block. - pub fn transactions(&self) -> Vec { - self.rlp.val_at(1) + pub fn transaction_views(&self) -> Vec { + self.rlp.at(1).iter().map(|rlp| TransactionView::new_from_rlp(rlp)).collect() } /// Return transaction hashes. @@ -116,6 +154,11 @@ impl<'a> BlockView<'a> { self.rlp.val_at(2) } + /// Return List of transactions in given block. + pub fn uncle_views(&self) -> Vec { + self.rlp.at(2).iter().map(|rlp| HeaderView::new_from_rlp(rlp)).collect() + } + /// Return list of uncle hashes of given block. pub fn uncle_hashes(&self) -> Vec { self.rlp.at(2).iter().map(|rlp| rlp.as_raw().sha3()).collect() diff --git a/util/src/hash.rs b/util/src/hash.rs index 3c90b841d..17057ef07 100644 --- a/util/src/hash.rs +++ b/util/src/hash.rs @@ -215,10 +215,14 @@ macro_rules! impl_hash { } impl fmt::Display for $from { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - for i in self.0[0..3].iter() { + for i in self.0[0..2].iter() { try!(write!(f, "{:02x}", i)); } - write!(f, "…{:02x}", self.0.last().unwrap()) + try!(write!(f, "…")); + for i in self.0[$size - 4..$size].iter() { + try!(write!(f, "{:02x}", i)); + } + Ok(()) } } @@ -544,7 +548,7 @@ mod tests { fn hash() { let h = H64([0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]); assert_eq!(H64::from_str("0123456789abcdef").unwrap(), h); - assert_eq!(format!("{}", h), "012345…ef"); + assert_eq!(format!("{}", h), "0123…89abcdef"); assert_eq!(format!("{:?}", h), "0123456789abcdef"); assert_eq!(h.hex(), "0123456789abcdef"); assert!(h == h); diff --git a/util/src/network/host.rs b/util/src/network/host.rs index 90cbfdaad..37b58f1f0 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -561,13 +561,13 @@ impl IoHandler> for Host where Messa let port = self.info.config.listen_address.port(); self.info.listen_port = port; -// self.add_node("enode://a9a921de2ff09a9a4d38b623c67b2d6b477a8e654ae95d874750cbbcb31b33296496a7b4421934e2629269e180823e52c15c2b19fc59592ec51ffe4f2de76ed7@127.0.0.1:30303"); - // GO bootnodes + self.add_node("enode://a9a921de2ff09a9a4d38b623c67b2d6b477a8e654ae95d874750cbbcb31b33296496a7b4421934e2629269e180823e52c15c2b19fc59592ec51ffe4f2de76ed7@127.0.0.1:30303"); +/* // GO bootnodes self.add_node("enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@52.16.188.185:30303"); // IE self.add_node("enode://de471bccee3d042261d52e9bff31458daecc406142b401d4cd848f677479f73104b9fdeb090af9583d3391b7f10cb2ba9e26865dd5fca4fcdc0fb1e3b723c786@54.94.239.50:30303"); // BR self.add_node("enode://1118980bf48b0a3640bdba04e0fe78b1add18e1cd99bf22d53daac1fd9972ad650df52176e7c7d89d1114cfef2bc23a2959aa54998a46afcf7d91809f0855082@52.74.57.123:30303"); // SG // ETH/DEV cpp-ethereum (poc-9.ethdev.com) - self.add_node("enode://979b7fa28feeb35a4741660a16076f1943202cb72b6af70d327f053e248bab9ba81760f39d0701ef1d8f89cc1fbd2cacba0710a12cd5314d5e0c9021aa3637f9@5.1.83.226:30303"); + self.add_node("enode://979b7fa28feeb35a4741660a16076f1943202cb72b6af70d327f053e248bab9ba81760f39d0701ef1d8f89cc1fbd2cacba0710a12cd5314d5e0c9021aa3637f9@5.1.83.226:30303");*/ } fn stream_hup<'s>(&'s mut self, io: &mut IoContext<'s, NetworkIoMessage>, stream: StreamToken) { diff --git a/util/src/nibbleslice.rs b/util/src/nibbleslice.rs index 6f4232945..b9028dff3 100644 --- a/util/src/nibbleslice.rs +++ b/util/src/nibbleslice.rs @@ -34,6 +34,22 @@ pub struct NibbleSlice<'a> { offset_encode_suffix: usize, } +pub struct NibbleSliceIterator<'a> { + p: &'a NibbleSlice<'a>, + i: usize, +} + +impl<'a> Iterator for NibbleSliceIterator<'a> { + type Item = u8; + fn next(&mut self) -> Option { + self.i += 1; + match self.i <= self.p.len() { + true => Some(self.p.at(self.i - 1)), + false => None, + } + } +} + impl<'a, 'view> NibbleSlice<'a> where 'a: 'view { /// Create a new nibble slice with the given byte-slice. pub fn new(data: &[u8]) -> NibbleSlice { NibbleSlice::new_offset(data, 0) } @@ -41,7 +57,7 @@ impl<'a, 'view> NibbleSlice<'a> where 'a: 'view { /// Create a new nibble slice with the given byte-slice with a nibble offset. pub fn new_offset(data: &'a [u8], offset: usize) -> NibbleSlice { NibbleSlice{data: data, offset: offset, data_encode_suffix: &b""[..], offset_encode_suffix: 0} } - /// + /// Create a composed nibble slice; one followed by the other. pub fn new_composed(a: &'a NibbleSlice, b: &'a NibbleSlice) -> NibbleSlice<'a> { NibbleSlice{data: a.data, offset: a.offset, data_encode_suffix: b.data, offset_encode_suffix: b.offset} } /*pub fn new_composed_bytes_offset(a: &NibbleSlice, b: &NibbleSlice) -> (Bytes, usize) { @@ -60,6 +76,10 @@ impl<'a, 'view> NibbleSlice<'a> where 'a: 'view { (r, a.len() + b.len()) }*/ + pub fn iter(&'a self) -> NibbleSliceIterator<'a> { + NibbleSliceIterator { p: self, i: 0 } + } + /// Create a new nibble slice from the given HPE encoded data (e.g. output of `encoded()`). pub fn from_encoded(data: &'a [u8]) -> (NibbleSlice, bool) { (Self::new_offset(data, if data[0] & 16 == 16 {1} else {2}), data[0] & 32 == 32) @@ -189,6 +209,14 @@ mod tests { } } + #[test] + fn iterator() { + let n = NibbleSlice::new(D); + let mut nibbles: Vec = vec![]; + nibbles.extend(n.iter()); + assert_eq!(nibbles, (0u8..6).collect::>()) + } + #[test] fn mid() { let n = NibbleSlice::new(D); diff --git a/util/src/overlaydb.rs b/util/src/overlaydb.rs index 929a492ef..1006cd28c 100644 --- a/util/src/overlaydb.rs +++ b/util/src/overlaydb.rs @@ -70,7 +70,9 @@ impl OverlayDB { let mut ret = 0u32; for i in self.overlay.drain().into_iter() { let (key, (value, rc)) = i; - if rc != 0 { + // until we figure out state trie pruning, only commit stuff when it has a strictly positive delkta of RCs - + // this prevents RCs being reduced to 0 where the DB would pretent that the node had been removed. + if rc > 0 { match self.payload(&key) { Some(x) => { let (back_value, back_rc) = x; diff --git a/util/src/trie/node.rs b/util/src/trie/node.rs index b5745b66f..b10b0e05e 100644 --- a/util/src/trie/node.rs +++ b/util/src/trie/node.rs @@ -5,7 +5,7 @@ use rlp::*; use super::journal::*; /// Type of node in the trie and essential information thereof. -#[derive(Eq, PartialEq, Debug)] +#[derive(Clone, Eq, PartialEq, Debug)] pub enum Node<'a> { Empty, Leaf(NibbleSlice<'a>, &'a[u8]), diff --git a/util/src/trie/triedb.rs b/util/src/trie/triedb.rs index bd34e710d..9e4cf36e2 100644 --- a/util/src/trie/triedb.rs +++ b/util/src/trie/triedb.rs @@ -42,7 +42,7 @@ impl<'db> TrieDB<'db> { /// Panics, if `root` does not exist pub fn new(db: &'db HashDB, root: &'db H256) -> Self { if !db.exists(root) { - flush(format!("Trie root not found {}", root)); + flushln!("TrieDB::new({}): Trie root not found!", root); panic!("Trie root not found!"); } TrieDB { @@ -109,7 +109,12 @@ impl<'db> TrieDB<'db> { /// Get the root node's RLP. fn root_node(&self) -> Node { - Node::decoded(self.db.lookup(&self.root).expect("Trie root not found!")) + Node::decoded(self.root_data()) + } + + /// Get the data of the root node. + fn root_data(&self) -> &[u8] { + self.db.lookup(&self.root).expect("Trie root not found!") } /// Get the root node as a `Node`. @@ -198,6 +203,122 @@ impl<'db> TrieDB<'db> { } } +#[derive(Clone, Eq, PartialEq)] +enum Status { + Entering, + At, + AtChild(usize), + Exiting, +} + +#[derive(Clone, Eq, PartialEq)] +struct Crumb<'a> { + node: Node<'a>, +// key: &'a[u8], + status: Status, +} + +impl<'a> Crumb<'a> { + /// Move on to next status in the node's sequence. + fn increment(&mut self) { + self.status = match (&self.status, &self.node) { + (_, &Node::Empty) => Status::Exiting, + (&Status::Entering, _) => Status::At, + (&Status::At, &Node::Branch(_, _)) => Status::AtChild(0), + (&Status::AtChild(x), &Node::Branch(_, _)) if x < 15 => Status::AtChild(x + 1), + _ => Status::Exiting, + } + } +} + +/// Iterator for going through all values in the trie. +#[derive(Clone)] +pub struct TrieDBIterator<'a> { + db: &'a TrieDB<'a>, + trail: Vec>, + key_nibbles: Bytes, +} + +impl<'a> TrieDBIterator<'a> { + /// Create a new iterator. + fn new(db: &'a TrieDB) -> TrieDBIterator<'a> { + let mut r = TrieDBIterator { + db: db, + trail: vec![], + key_nibbles: Vec::new(), + }; + r.descend(db.root_data()); + r + } + + /// Descend into a payload. + fn descend(&mut self, d: &'a [u8]) { + self.trail.push(Crumb { + status: Status::Entering, + node: self.db.get_node(d) + }); + match self.trail.last().unwrap().node { + Node::Leaf(n, _) | Node::Extension(n, _) => { self.key_nibbles.extend(n.iter()); }, + _ => {} + } + } + + /// Descend into a payload and get the next item. + fn descend_next(&mut self, d: &'a [u8]) -> Option<(Bytes, &'a [u8])> { self.descend(d); self.next() } + + /// The present key. + fn key(&self) -> Bytes { + // collapse the key_nibbles down to bytes. + self.key_nibbles.iter().step(2).zip(self.key_nibbles.iter().skip(1).step(2)).map(|(h, l)| h * 16 + l).collect() + } +} + +impl<'a> Iterator for TrieDBIterator<'a> { + type Item = (Bytes, &'a [u8]); + + fn next(&mut self) -> Option { + let b = match self.trail.last_mut() { + Some(ref mut b) => { b.increment(); b.clone() }, + None => return None + }; + match (b.status, b.node) { + (Status::Exiting, n) => { + match n { + Node::Leaf(n, _) | Node::Extension(n, _) => { + let l = self.key_nibbles.len(); + self.key_nibbles.truncate(l - n.len()); + }, + Node::Branch(_, _) => { self.key_nibbles.pop(); }, + _ => {} + } + self.trail.pop(); + self.next() + }, + (Status::At, Node::Leaf(_, v)) => Some((self.key(), v)), + (Status::At, Node::Extension(_, d)) => self.descend_next(d), + (Status::At, Node::Branch(_, Some(v))) => Some((self.key(), v)), + (Status::At, Node::Branch(_, _)) => self.next(), + (Status::AtChild(i), Node::Branch(children, _)) if children[i].len() > 0 => { + match i { + 0 => self.key_nibbles.push(0), + i => *self.key_nibbles.last_mut().unwrap() = i as u8, + } + self.descend_next(children[i]) + }, + (Status::AtChild(i), Node::Branch(_, _)) => { + if i == 0 { self.key_nibbles.push(0); } + self.next() + }, + _ => panic!() // Should never see Entering or AtChild without a Branch here. + } + } +} + +impl<'db> TrieDB<'db> { + /// Get all keys/values stored in the trie. + pub fn iter(&self) -> TrieDBIterator { TrieDBIterator::new(self) } +} + impl<'db> Trie for TrieDB<'db> { fn root(&self) -> &H256 { &self.root } @@ -218,3 +339,22 @@ impl<'db> fmt::Debug for TrieDB<'db> { writeln!(f, "]") } } + +#[test] +fn iterator() { + use memorydb::*; + use super::triedbmut::*; + + let d = vec![ &b"A"[..], &b"AA"[..], &b"AB"[..], &b"B"[..] ]; + + let mut memdb = MemoryDB::new(); + let mut root = H256::new(); + { + let mut t = TrieDBMut::new(&mut memdb, &mut root); + for x in &d { + t.insert(&x, &x); + } + } + assert_eq!(d.iter().map(|i|i.to_vec()).collect::>(), TrieDB::new(&memdb, &root).iter().map(|x|x.0).collect::>()); + assert_eq!(d, TrieDB::new(&memdb, &root).iter().map(|x|x.1).collect::>()); +} diff --git a/util/src/trie/triedbmut.rs b/util/src/trie/triedbmut.rs index 832b532f8..0f3dde4fb 100644 --- a/util/src/trie/triedbmut.rs +++ b/util/src/trie/triedbmut.rs @@ -65,8 +65,9 @@ impl<'db> TrieDBMut<'db> { r } - /// Create a new trie with the backing database `db` and `root` - /// Panics, if `root` does not exist + /// Create a new trie with the backing database `db` and `root`. + /// Panics, if `root` does not exist. + // TODO: return Result pub fn from_existing(db: &'db mut HashDB, root: &'db mut H256) -> Self { if !db.exists(root) { flush(format!("Trie root not found {}", root));