Sketch of how OpenBlock::close() might look.

This commit is contained in:
Gav Wood 2016-01-09 18:58:04 +01:00
parent 71670e6277
commit 8b5b493f7d
2 changed files with 77 additions and 8 deletions

View File

@ -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<Header>,
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<Header>) -> ClosedBlock<'engine> { unimplemented!(); }
pub fn close(self, uncles: Vec<Header>, 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!(); }

View File

@ -39,6 +39,13 @@ pub struct Header {
pub hash: RefCell<Option<H256>>, //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 {