From 8b5b493f7de742f32c949e1f6e1a38307474b8c1 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 9 Jan 2016 18:58:04 +0100 Subject: [PATCH] Sketch of how OpenBlock::close() might look. --- src/block.rs | 32 ++++++++++++++++++++++++++++--- src/header.rs | 53 ++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 77 insertions(+), 8 deletions(-) diff --git a/src/block.rs b/src/block.rs index 6ed97f6a7..15546f665 100644 --- a/src/block.rs +++ b/src/block.rs @@ -71,7 +71,7 @@ pub struct OpenBlock<'engine> { /// There is no function available to push a transaction. If you want that you'll need to `reopen()` it. pub struct ClosedBlock<'engine> { open_block: OpenBlock<'engine>, - _uncles: Vec
, + uncles: Bytes, } /// A block that has a valid seal. @@ -105,7 +105,7 @@ impl<'engine> OpenBlock<'engine> { timestamp: self.block.header.timestamp.clone(), difficulty: self.block.header.difficulty.clone(), last_hashes: self.last_hashes.clone(), - gas_used: if let Some(ref t) = self.block.archive.last() {t.receipt.gas_used} else {U256::from(0)}, + gas_used: self.block.archive.last().map(|t| t.receipt.gas_used).unwrap_or(U256::from(0)), gas_limit: self.block.header.gas_limit.clone(), } } @@ -124,7 +124,26 @@ 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
) -> ClosedBlock<'engine> { unimplemented!(); } + pub fn close(self, uncles: Vec
, author: Address, extra_data: Bytes) -> ClosedBlock<'engine> { + // TODO: populate rest of header. + self.engine.on_close_block(...); + self.header.author = author; + //self.header.transactions_root = ...; + let s = RlpStream::new_list(uncles.len()); + for u in uncles.iter() { + s.append(u.rlp()) + } + let uncle_bytes = u.out(); + self.header.uncles_hash = uncle_bytes.sha3(); + self.header.extra_data = extra_data; + self.header.state_root = self.state.root().clone(); + //self.header.receipts_root = ...; + //self.header.log_bloom = ...; // will need to amalgamate. + self.header.gas_used = self.block.archive.last().map(|t| t.receipt.gas_used).unwrap_or(U256::from(0)); + self.header.note_dirty(); + + ClosedBlock::new(self, uncle_bytes) + } } impl<'engine> IsBlock for OpenBlock<'engine> { @@ -132,6 +151,13 @@ impl<'engine> IsBlock for OpenBlock<'engine> { } impl<'engine> ClosedBlock<'engine> { + fn new(open_block: OpenBlock, uncles: Bytes) -> Self { + Self { + open_block: open_block, + uncles: uncles, + } + } + /// Get the hash of the header without seal arguments. pub fn preseal_hash(&self) -> H256 { unimplemented!(); } diff --git a/src/header.rs b/src/header.rs index 80d91eb20..85655d6e0 100644 --- a/src/header.rs +++ b/src/header.rs @@ -39,6 +39,13 @@ pub struct Header { pub hash: RefCell>, //TODO: make this private } +enum SealInclusion { + WithSeal, + WithoutSeal, +} + +pub use SealInclusion::*; + impl Header { /// Create a new, default-valued, header. pub fn new() -> Header { @@ -64,19 +71,55 @@ impl Header { } } + /// 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 => { - let mut stream = RlpStream::new(); - stream.append(self); - let h = stream.as_raw().sha3(); - *hash = Some(h.clone()); - h.clone() + *hash = Some(self.hash(WithSeal)); + hash.unwrap().clone() } } } + + /// Note that some fields have changed. Resets the memoised hash. + pub fn note_dirty(&self) { + *self.hash.borrow_mut() = None; + } + + // TODO: get hash without seal. + + // TODO: make these functions traity + pub fn stream_rlp(&self, s: &mut RlpStream, with_seal: SealInclusion) { + s.append_list(13 + if with_seal == WithSeal {self.seal.len()} else {0}) + s.append(&self.parent_hash); + s.append(&self.uncles_hash); + s.append(&self.author); + s.append(&self.state_root); + s.append(&self.transactions_root); + s.append(&self.receipts_root); + s.append(&self.log_bloom); + s.append(&self.difficulty); + s.append(&self.number); + s.append(&self.gas_limit); + s.append(&self.gas_used); + s.append(&self.timestamp); + s.append(&self.extra_data); + if with_seal == WithSeal { + for b in self.seal.iter() { + e.append_raw(&b); + } + } + } + + pub rlp(&self, with_seal: SealInclusion) -> Bytes { + let s = RlpStream::new(); + self.stream_rlp(&mut s, with_seal); + s.out() + } + + pub hash(&self, with_seal: SealInclusion) -> H256 { self.rlp().sha3() } } impl Decodable for Header {