Merge pull request #61 from gavofyork/ethash
More on OpenBlock::close; State::kill_account added
This commit is contained in:
commit
e807f36e83
7
src/basic_types.rs
Normal file
7
src/basic_types.rs
Normal file
@ -0,0 +1,7 @@
|
||||
use util::*;
|
||||
|
||||
/// Type for a 2048-bit log-bloom, as used by our blocks.
|
||||
pub type LogBloom = H2048;
|
||||
|
||||
/// Constant 2048-bit datum for 0. Often used as a default.
|
||||
pub static ZERO_LOGBLOOM: LogBloom = H2048([0x00; 256]);
|
43
src/block.rs
43
src/block.rs
@ -1,9 +1,5 @@
|
||||
use util::*;
|
||||
use transaction::*;
|
||||
use receipt::*;
|
||||
use common::*;
|
||||
use engine::*;
|
||||
use header::*;
|
||||
use env_info::*;
|
||||
use state::*;
|
||||
|
||||
/// A transaction/receipt execution entry.
|
||||
@ -71,7 +67,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 +101,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(),
|
||||
}
|
||||
}
|
||||
@ -123,8 +119,24 @@ impl<'engine> OpenBlock<'engine> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Turn this into a `ClosedBlock`. A BlockChain must be provided in order to figure ou the uncles.
|
||||
pub fn close(self, _uncles: Vec<Header>) -> ClosedBlock<'engine> { unimplemented!(); }
|
||||
/// Turn this into a `ClosedBlock`. A BlockChain must be provided in order to figure out the uncles.
|
||||
pub fn close(self, uncles: Vec<Header>, 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 = ...;
|
||||
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.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();
|
||||
|
||||
ClosedBlock::new(s, uncle_bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'engine> IsBlock for OpenBlock<'engine> {
|
||||
@ -132,6 +144,13 @@ impl<'engine> IsBlock for OpenBlock<'engine> {
|
||||
}
|
||||
|
||||
impl<'engine> ClosedBlock<'engine> {
|
||||
fn new<'a>(open_block: OpenBlock<'a>, uncles: Bytes) -> ClosedBlock<'a> {
|
||||
ClosedBlock {
|
||||
open_block: open_block,
|
||||
uncles: uncles,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the hash of the header without seal arguments.
|
||||
pub fn preseal_hash(&self) -> H256 { unimplemented!(); }
|
||||
|
||||
@ -155,11 +174,13 @@ impl IsBlock for SealedBlock {
|
||||
|
||||
#[test]
|
||||
fn open_block() {
|
||||
use super::*;
|
||||
use spec::*;
|
||||
let engine = Spec::new_test().to_engine().unwrap();
|
||||
use ethereum::*;
|
||||
let engine = new_morden().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());
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
pub use util::*;
|
||||
pub use basic_types::*;
|
||||
pub use env_info::*;
|
||||
pub use evm_schedule::*;
|
||||
pub use views::*;
|
||||
@ -6,3 +7,4 @@ pub use builtin::*;
|
||||
pub use header::*;
|
||||
pub use account::*;
|
||||
pub use transaction::*;
|
||||
pub use receipt::*;
|
||||
|
@ -23,24 +23,18 @@ impl Engine for Ethash {
|
||||
/// Apply the block reward on finalisation of the block.
|
||||
fn on_close_block(&self, block: &mut Block) {
|
||||
let a = block.header().author.clone();
|
||||
block.state_mut().add_balance(&a, &decode(&self.spec().engine_params.get("block_reward").unwrap()));
|
||||
block.state_mut().add_balance(&a, &decode(&self.spec().engine_params.get("blockReward").unwrap()));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: test for on_close_block.
|
||||
#[test]
|
||||
fn playpen() {
|
||||
fn on_close_block() {
|
||||
use super::*;
|
||||
use state::*;
|
||||
let engine = new_morden().to_engine().unwrap();
|
||||
let genesis_header = engine.spec().genesis_header();
|
||||
let mut db = OverlayDB::new_temp();
|
||||
engine.spec().ensure_db_good(&mut db);
|
||||
assert!(SecTrieDB::new(&db, &genesis_header.state_root).contains(&address_from_hex("102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c")));
|
||||
{
|
||||
let s = State::from_existing(db.clone(), genesis_header.state_root.clone(), engine.account_start_nonce());
|
||||
assert_eq!(s.balance(&address_from_hex("0000000000000000000000000000000000000001")), U256::from(1u64));
|
||||
}
|
||||
let b = OpenBlock::new(engine.deref(), db, &genesis_header, vec![genesis_header.hash()]);
|
||||
// let c = b.close();
|
||||
let b = b.close(vec![], Address::zero(), vec![]);
|
||||
assert_eq!(b.state().balance(&Address::zero()), U256::from_str("4563918244F40000").unwrap());
|
||||
}
|
@ -56,7 +56,7 @@ mod tests {
|
||||
let genesis = morden.genesis_block();
|
||||
assert_eq!(BlockView::new(&genesis).header_view().sha3(), H256::from_str("0cd786a2425d16f152c658316c423e6ce1181e15c3295826d7c9904cba9ce303").unwrap());
|
||||
|
||||
morden.to_engine();
|
||||
let _ = morden.to_engine();
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -67,6 +67,6 @@ mod tests {
|
||||
let genesis = frontier.genesis_block();
|
||||
assert_eq!(BlockView::new(&genesis).header_view().sha3(), H256::from_str("d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3").unwrap());
|
||||
|
||||
frontier.to_engine();
|
||||
let _ = frontier.to_engine();
|
||||
}
|
||||
}
|
@ -1,14 +1,5 @@
|
||||
use util::*;
|
||||
|
||||
/// Type for a 2048-bit log-bloom, as used by our blocks.
|
||||
pub type LogBloom = H2048;
|
||||
|
||||
/// Constant address for point 0. Often used as a default.
|
||||
pub static ZERO_ADDRESS: Address = Address([0x00; 20]);
|
||||
/// Constant 256-bit datum for 0. Often used as a default.
|
||||
pub static ZERO_H256: H256 = H256([0x00; 32]);
|
||||
/// Constant 2048-bit datum for 0. Often used as a default.
|
||||
pub static ZERO_LOGBLOOM: LogBloom = H2048([0x00; 256]);
|
||||
use basic_types::*;
|
||||
|
||||
/// A block header.
|
||||
///
|
||||
@ -39,6 +30,11 @@ pub struct Header {
|
||||
pub hash: RefCell<Option<H256>>, //TODO: make this private
|
||||
}
|
||||
|
||||
pub enum Seal {
|
||||
With,
|
||||
Without,
|
||||
}
|
||||
|
||||
impl Header {
|
||||
/// Create a new, default-valued, header.
|
||||
pub fn new() -> Header {
|
||||
@ -64,19 +60,54 @@ 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.rlp_sha3(Seal::With));
|
||||
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;
|
||||
}
|
||||
|
||||
// TODO: get hash without seal.
|
||||
|
||||
// TODO: make these functions traity
|
||||
pub fn stream_rlp(&self, s: &mut RlpStream, with_seal: Seal) {
|
||||
s.append_list(13 + match with_seal { Seal::With => self.seal.len(), _ => 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);
|
||||
match with_seal {
|
||||
Seal::With => for b in self.seal.iter() { s.append_raw(&b, 1); },
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rlp(&self, with_seal: Seal) -> Bytes {
|
||||
let mut s = RlpStream::new();
|
||||
self.stream_rlp(&mut s, with_seal);
|
||||
s.out()
|
||||
}
|
||||
|
||||
pub fn rlp_sha3(&self, with_seal: Seal) -> H256 { self.rlp(with_seal).sha3() }
|
||||
}
|
||||
|
||||
impl Decodable for Header {
|
||||
|
@ -1,5 +1,5 @@
|
||||
#![feature(cell_extras)]
|
||||
|
||||
#![feature(augmented_assignments)]
|
||||
//! Ethcore's ethereum implementation
|
||||
//!
|
||||
//! ### Rust version
|
||||
@ -85,6 +85,7 @@ extern crate evmjit;
|
||||
extern crate ethcore_util as util;
|
||||
|
||||
pub mod common;
|
||||
pub mod basic_types;
|
||||
pub mod env_info;
|
||||
pub mod engine;
|
||||
pub mod state;
|
||||
|
@ -1,8 +1,10 @@
|
||||
use util::*;
|
||||
use basic_types::LogBloom;
|
||||
|
||||
/// Information describing execution of a transaction.
|
||||
pub struct Receipt {
|
||||
// TODO
|
||||
pub state_root: H256,
|
||||
pub gas_used: U256,
|
||||
pub log_bloom: LogBloom,
|
||||
}
|
||||
|
56
src/state.rs
56
src/state.rs
@ -79,6 +79,11 @@ impl State {
|
||||
self.require_or_from(contract, false, || Account::new_contract(U256::from(0u8)), |r| r.reset_code());
|
||||
}
|
||||
|
||||
/// Remove an existing account.
|
||||
pub fn kill_account(&mut self, account: &Address) {
|
||||
self.cache.borrow_mut().insert(account.clone(), None);
|
||||
}
|
||||
|
||||
/// Get the balance of account `a`.
|
||||
pub fn balance(&self, a: &Address) -> U256 {
|
||||
self.get(a, false).as_ref().map(|account| account.balance().clone()).unwrap_or(U256::from(0u8))
|
||||
@ -228,12 +233,11 @@ use util::hash::*;
|
||||
use util::trie::*;
|
||||
use util::rlp::*;
|
||||
use util::uint::*;
|
||||
use std::str::FromStr;
|
||||
use account::*;
|
||||
|
||||
#[test]
|
||||
fn code_from_database() {
|
||||
let a = Address::from_str("0000000000000000000000000000000000000000").unwrap();
|
||||
let a = Address::zero();
|
||||
let (r, db) = {
|
||||
let mut s = State::new_temp();
|
||||
s.require_or_from(&a, false, ||Account::new_contract(U256::from(42u32)), |_|{});
|
||||
@ -250,7 +254,7 @@ fn code_from_database() {
|
||||
|
||||
#[test]
|
||||
fn storage_at_from_database() {
|
||||
let a = Address::from_str("0000000000000000000000000000000000000000").unwrap();
|
||||
let a = Address::zero();
|
||||
let (r, db) = {
|
||||
let mut s = State::new_temp();
|
||||
s.set_storage(&a, H256::from(&U256::from(01u64)), H256::from(&U256::from(69u64)));
|
||||
@ -264,7 +268,7 @@ fn storage_at_from_database() {
|
||||
|
||||
#[test]
|
||||
fn get_from_database() {
|
||||
let a = Address::from_str("0000000000000000000000000000000000000000").unwrap();
|
||||
let a = Address::zero();
|
||||
let (r, db) = {
|
||||
let mut s = State::new_temp();
|
||||
s.inc_nonce(&a);
|
||||
@ -279,11 +283,45 @@ fn get_from_database() {
|
||||
assert_eq!(s.nonce(&a), U256::from(1u64));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove() {
|
||||
let a = Address::zero();
|
||||
let mut s = State::new_temp();
|
||||
s.inc_nonce(&a);
|
||||
assert_eq!(s.nonce(&a), U256::from(1u64));
|
||||
s.kill_account(&a);
|
||||
assert_eq!(s.nonce(&a), U256::from(0u64));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_from_database() {
|
||||
let a = Address::zero();
|
||||
let (r, db) = {
|
||||
let mut s = State::new_temp();
|
||||
s.inc_nonce(&a);
|
||||
s.commit();
|
||||
assert_eq!(s.nonce(&a), U256::from(1u64));
|
||||
s.drop()
|
||||
};
|
||||
|
||||
let (r, db) = {
|
||||
let mut s = State::from_existing(db, r, U256::from(0u8));
|
||||
assert_eq!(s.nonce(&a), U256::from(1u64));
|
||||
s.kill_account(&a);
|
||||
s.commit();
|
||||
assert_eq!(s.nonce(&a), U256::from(0u64));
|
||||
s.drop()
|
||||
};
|
||||
|
||||
let s = State::from_existing(db, r, U256::from(0u8));
|
||||
assert_eq!(s.nonce(&a), U256::from(0u64));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn alter_balance() {
|
||||
let mut s = State::new_temp();
|
||||
let a = Address::from_str("0000000000000000000000000000000000000000").unwrap();
|
||||
let b = Address::from_str("0000000000000000000000000000000000000001").unwrap();
|
||||
let a = Address::zero();
|
||||
let b = address_from_u64(1u64);
|
||||
s.add_balance(&a, &U256::from(69u64));
|
||||
assert_eq!(s.balance(&a), U256::from(69u64));
|
||||
s.commit();
|
||||
@ -303,7 +341,7 @@ fn alter_balance() {
|
||||
#[test]
|
||||
fn alter_nonce() {
|
||||
let mut s = State::new_temp();
|
||||
let a = Address::from_str("0000000000000000000000000000000000000000").unwrap();
|
||||
let a = Address::zero();
|
||||
s.inc_nonce(&a);
|
||||
assert_eq!(s.nonce(&a), U256::from(1u64));
|
||||
s.inc_nonce(&a);
|
||||
@ -319,7 +357,7 @@ fn alter_nonce() {
|
||||
#[test]
|
||||
fn balance_nonce() {
|
||||
let mut s = State::new_temp();
|
||||
let a = Address::from_str("0000000000000000000000000000000000000000").unwrap();
|
||||
let a = Address::zero();
|
||||
assert_eq!(s.balance(&a), U256::from(0u64));
|
||||
assert_eq!(s.nonce(&a), U256::from(0u64));
|
||||
s.commit();
|
||||
@ -330,7 +368,7 @@ fn balance_nonce() {
|
||||
#[test]
|
||||
fn ensure_cached() {
|
||||
let mut s = State::new_temp();
|
||||
let a = Address::from_str("0000000000000000000000000000000000000000").unwrap();
|
||||
let a = Address::zero();
|
||||
s.require(&a, false);
|
||||
s.commit();
|
||||
assert_eq!(s.root().hex(), "0ce23f3c809de377b008a4a3ee94a0834aac8bec1f86e28ffe4fdb5a15b0c785");
|
||||
|
Loading…
Reference in New Issue
Block a user