diff --git a/src/block.rs b/src/block.rs index aefa1da2f..f30509698 100644 --- a/src/block.rs +++ b/src/block.rs @@ -111,7 +111,7 @@ impl<'engine> OpenBlock<'engine> { let env_info = self.env_info(); match self.block.state.apply(&env_info, self.engine, &t, true) { Ok(x) => { - self.block.archive_set.insert(h.unwrap_or_else(||t.sha3())); + self.block.archive_set.insert(h.unwrap_or_else(||t.hash())); self.block.archive.push(Entry { transaction: t, receipt: x.receipt }); Ok(&self.block.archive.last().unwrap().receipt) } @@ -122,15 +122,14 @@ impl<'engine> OpenBlock<'engine> { /// Turn this into a `ClosedBlock`. A BlockChain must be provided in order to figure out the uncles. pub fn close(self, uncles: Vec
, author: Address, extra_data: Bytes) -> ClosedBlock<'engine> { let mut s = self; - // populate rest of header. s.engine.on_close_block(&mut s.block); s.block.header.author = author; -// s.header.transactions_root = ...; + s.block.header.transactions_root = ordered_trie_root(s.block.archive.iter().map(|ref e| e.transaction.rlp_bytes()).collect()); let uncle_bytes = uncles.iter().fold(RlpStream::new_list(uncles.len()), |mut s, u| {s.append(&u.rlp(Seal::With)); s} ).out(); s.block.header.uncles_hash = uncle_bytes.sha3(); s.block.header.extra_data = extra_data; s.block.header.state_root = s.block.state.root().clone(); -// s.header.receipts_root = ...; + s.block.header.receipts_root = ordered_trie_root(s.block.archive.iter().map(|ref e| e.receipt.rlp_bytes()).collect()); s.block.header.log_bloom = s.block.archive.iter().fold(LogBloom::zero(), |mut b, e| {b |= &e.receipt.log_bloom; b}); s.block.header.gas_used = s.block.archive.last().map(|t| t.receipt.gas_used).unwrap_or(U256::from(0)); s.block.header.note_dirty(); @@ -175,12 +174,10 @@ impl IsBlock for SealedBlock { #[test] fn open_block() { use spec::*; - use ethereum::*; - let engine = new_morden().to_engine().unwrap(); + let engine = Spec::new_test().to_engine().unwrap(); let genesis_header = engine.spec().genesis_header(); let mut db = OverlayDB::new_temp(); engine.spec().ensure_db_good(&mut db); let b = OpenBlock::new(engine.deref(), db, &genesis_header, vec![genesis_header.hash()]); - let b = b.close(vec![], Address::zero(), vec![]); - assert_eq!(b.state().balance(&Address::zero()), U256::from_str("4563918244F40000").unwrap()); + let _ = b.close(vec![], Address::zero(), vec![]); } \ No newline at end of file diff --git a/src/header.rs b/src/header.rs index 56f03460e..a1153d880 100644 --- a/src/header.rs +++ b/src/header.rs @@ -27,7 +27,7 @@ pub struct Header { pub difficulty: U256, pub seal: Vec, - pub hash: RefCell>, //TODO: make this private + pub hash: RefCell>, } pub enum Seal { @@ -163,28 +163,6 @@ impl Encodable for Header { }) } } -/* -trait RlpStandard { - fn append(&self, s: &mut RlpStream); -} - -impl RlpStandard for Header { - fn append(&self, s: &mut RlpStream) { - s.append_list(13); - s.append(self.parent_hash); - s.append_raw(self.seal[0]); - s.append_standard(self.x); - } - fn populate(&mut self, s: &Rlp) { - } -} - -impl RlpStream { - fn append_standard(&mut self, o: &O) where O: RlpStandard { - o.append(self); - } -} -*/ #[cfg(test)] mod tests { diff --git a/src/receipt.rs b/src/receipt.rs index 6f91c14dc..5a188f93d 100644 --- a/src/receipt.rs +++ b/src/receipt.rs @@ -1,10 +1,47 @@ use util::*; use basic_types::LogBloom; +/// A single log's entry. +pub struct LogEntry { + pub address: Address, + pub topics: Vec, + pub data: Bytes, +} + +impl RlpStandard for LogEntry { + fn rlp_append(&self, s: &mut RlpStream) { + s.append_list(3); + s.append(&self.address); + s.append(&self.topics); + s.append(&self.data); + } +} + +impl LogEntry { + pub fn bloom(&self) -> LogBloom { + self.topics.iter().fold(LogBloom::from_bloomed(&self.address.sha3()), |b, t| b.with_bloomed(&t.sha3())) + } +} + /// Information describing execution of a transaction. pub struct Receipt { - // TODO pub state_root: H256, pub gas_used: U256, pub log_bloom: LogBloom, + pub logs: Vec, +} + +impl RlpStandard for Receipt { + fn rlp_append(&self, s: &mut RlpStream) { + s.append_list(4); + s.append(&self.state_root); + s.append(&self.gas_used); + s.append(&self.log_bloom); + // TODO: make work: + //s.append(&self.logs); + s.append_list(self.logs.len()); + for l in self.logs.iter() { + l.rlp_append(s); + } + } } diff --git a/src/transaction.rs b/src/transaction.rs index b54329422..d13a728bb 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -9,6 +9,8 @@ pub struct Transaction { to: Option
, value: U256, data: Bytes, + + hash: RefCell>, //TODO: make this private } impl Transaction { @@ -21,10 +23,36 @@ impl Transaction { pub fn is_message_call(&self) -> bool { !self.is_contract_creation() } +} - /// Get the hash of this transaction. - pub fn sha3(&self) -> H256 { - unimplemented!(); +impl RlpStandard for Transaction { + fn rlp_append(&self, s: &mut RlpStream) { + s.append_list(6); + s.append(&self.nonce); + s.append(&self.gas_price); + s.append(&self.gas); + s.append(&self.to); + s.append(&self.value); + s.append(&self.data); + } +} + +impl Transaction { + /// Get the hash of this header (sha3 of the RLP). + pub fn hash(&self) -> H256 { + let mut hash = self.hash.borrow_mut(); + match &mut *hash { + &mut Some(ref h) => h.clone(), + hash @ &mut None => { + *hash = Some(self.rlp_sha3()); + hash.as_ref().unwrap().clone() + } + } + } + + /// Note that some fields have changed. Resets the memoised hash. + pub fn note_dirty(&self) { + *self.hash.borrow_mut() = None; } } @@ -52,6 +80,7 @@ impl Decodable for Transaction { to: try!(Decodable::decode(&d[3])), value: try!(Decodable::decode(&d[4])), data: try!(Decodable::decode(&d[5])), + hash: RefCell::new(None) }; Ok(transaction)