Merge pull request #58 from gavofyork/ethash

Use reorganisation
This commit is contained in:
Arkadiy Paronyan 2016-01-09 13:05:03 +01:00
commit 6aa8c32621
18 changed files with 95 additions and 154 deletions

View File

@ -1,12 +1,4 @@
use std::collections::HashMap; use util::*;
use util::hash::*;
use util::sha3::*;
use util::hashdb::*;
use util::bytes::*;
use util::trie::*;
use util::rlp::*;
use util::uint::*;
use std::cell::*;
pub const SHA3_EMPTY: H256 = H256( [0xc5, 0xd2, 0x46, 0x01, 0x86, 0xf7, 0x23, 0x3c, 0x92, 0x7e, 0x7d, 0xb2, 0xdc, 0xc7, 0x03, 0xc0, 0xe5, 0x00, 0xb6, 0x53, 0xca, 0x82, 0x27, 0x3b, 0x7b, 0xfa, 0xd8, 0x04, 0x5d, 0x85, 0xa4, 0x70] ); pub const SHA3_EMPTY: H256 = H256( [0xc5, 0xd2, 0x46, 0x01, 0x86, 0xf7, 0x23, 0x3c, 0x92, 0x7e, 0x7d, 0xb2, 0xdc, 0xc7, 0x03, 0xc0, 0xe5, 0x00, 0xb6, 0x53, 0xca, 0x82, 0x27, 0x3b, 0x7b, 0xfa, 0xd8, 0x04, 0x5d, 0x85, 0xa4, 0x70] );
@ -66,7 +58,7 @@ impl Account {
} }
/// Create a new contract account. /// Create a new contract account.
/// NOTE: make sure you use `set_code` on this before `commit`ing. /// NOTE: make sure you use `init_code` on this before `commit`ing.
pub fn new_contract(balance: U256) -> Account { pub fn new_contract(balance: U256) -> Account {
Account { Account {
balance: balance, balance: balance,
@ -80,7 +72,7 @@ impl Account {
/// Set this account's code to the given code. /// Set this account's code to the given code.
/// NOTE: Account should have been created with `new_contract`. /// NOTE: Account should have been created with `new_contract`.
pub fn set_code(&mut self, code: Bytes) { pub fn init_code(&mut self, code: Bytes) {
assert!(self.code_hash.is_none()); assert!(self.code_hash.is_none());
self.code_cache = code; self.code_cache = code;
} }
@ -224,7 +216,7 @@ fn storage_at() {
let mut a = Account::new_contract(U256::from(69u8)); let mut a = Account::new_contract(U256::from(69u8));
a.set_storage(H256::from(&U256::from(0x00u64)), H256::from(&U256::from(0x1234u64))); a.set_storage(H256::from(&U256::from(0x00u64)), H256::from(&U256::from(0x1234u64)));
a.commit_storage(&mut db); a.commit_storage(&mut db);
a.set_code(vec![]); a.init_code(vec![]);
a.commit_code(&mut db); a.commit_code(&mut db);
a.rlp() a.rlp()
}; };
@ -241,7 +233,7 @@ fn note_code() {
let rlp = { let rlp = {
let mut a = Account::new_contract(U256::from(69u8)); let mut a = Account::new_contract(U256::from(69u8));
a.set_code(vec![0x55, 0x44, 0xffu8]); a.init_code(vec![0x55, 0x44, 0xffu8]);
a.commit_code(&mut db); a.commit_code(&mut db);
a.rlp() a.rlp()
}; };
@ -267,7 +259,7 @@ fn commit_storage() {
fn commit_code() { fn commit_code() {
let mut a = Account::new_contract(U256::from(69u8)); let mut a = Account::new_contract(U256::from(69u8));
let mut db = OverlayDB::new_temp(); let mut db = OverlayDB::new_temp();
a.set_code(vec![0x55, 0x44, 0xffu8]); a.init_code(vec![0x55, 0x44, 0xffu8]);
assert_eq!(a.code_hash(), SHA3_EMPTY); assert_eq!(a.code_hash(), SHA3_EMPTY);
a.commit_code(&mut db); a.commit_code(&mut db);
assert_eq!(a.code_hash().hex(), "af231e631776a517ca23125370d542873eca1fb4d613ed9b5d5335a46ae5b7eb"); assert_eq!(a.code_hash().hex(), "af231e631776a517ca23125370d542873eca1fb4d613ed9b5d5335a46ae5b7eb");

View File

@ -1,9 +1,4 @@
use std::collections::hash_set::*; use util::*;
use util::hash::*;
use util::bytes::*;
use util::uint::*;
use util::error::*;
use util::overlaydb::*;
use transaction::*; use transaction::*;
use receipt::*; use receipt::*;
use blockchain::*; use blockchain::*;

View File

@ -1,18 +1,7 @@
//! Fast access to blockchain data. //! Fast access to blockchain data.
use std::collections::HashMap; use util::*;
use std::cell::RefCell;
use std::path::Path;
use std::hash::Hash;
use rocksdb::{DB, WriteBatch, Writable}; use rocksdb::{DB, WriteBatch, Writable};
use heapsize::HeapSizeOf;
use util::hash::*;
use util::uint::*;
use util::rlp::*;
use util::hashdb::*;
use util::sha3::*;
use util::bytes::*;
use util::squeeze::*;
use header::*; use header::*;
use extras::*; use extras::*;
use transaction::*; use transaction::*;

View File

@ -1,12 +1,4 @@
use std::cmp::min; use util::*;
use std::fmt;
use util::uint::*;
use util::hash::*;
use util::sha3::*;
use util::bytes::*;
use rustc_serialize::json::Json;
use std::io::Write;
use util::crypto::*;
use crypto::sha2::Sha256; use crypto::sha2::Sha256;
use crypto::ripemd160::Ripemd160; use crypto::ripemd160::Ripemd160;
use crypto::digest::Digest; use crypto::digest::Digest;
@ -95,8 +87,8 @@ pub fn new_builtin_exec(name: &str) -> Option<Box<Fn(&[u8], &mut [u8])>> {
it.copy_raw(input); it.copy_raw(input);
if it.v == H256::from(&U256::from(27)) || it.v == H256::from(&U256::from(28)) { if it.v == H256::from(&U256::from(27)) || it.v == H256::from(&U256::from(28)) {
let s = Signature::from_rsv(&it.r, &it.s, it.v[31] - 27); let s = Signature::from_rsv(&it.r, &it.s, it.v[31] - 27);
if is_valid(&s) { if ec::is_valid(&s) {
match recover(&s, &it.hash) { match ec::recover(&s, &it.hash) {
Ok(p) => { Ok(p) => {
let r = p.as_slice().sha3(); let r = p.as_slice().sha3();
// NICE: optimise and separate out into populate-like function // NICE: optimise and separate out into populate-like function

9
src/common.rs Normal file
View File

@ -0,0 +1,9 @@
pub use util::*;
pub use env_info::*;
pub use evm_schedule::*;
pub use denominations::*;
pub use views::*;
pub use builtin::*;
pub use header::*;
pub use account::*;
pub use transaction::*;

View File

@ -1,4 +1,4 @@
use util::uint::*; use util::*;
#[inline] #[inline]
pub fn ether() -> U256 { U256::exp10(18) } pub fn ether() -> U256 { U256::exp10(18) }

View File

@ -1,16 +1,6 @@
use std::collections::hash_map::*; use common::*;
use util::bytes::*;
use util::hash::*;
use util::uint::*;
use util::rlp::*;
use util::semantic_version::*;
use util::error::*;
use header::Header;
use transaction::Transaction;
use block::Block; use block::Block;
use spec::Spec; use spec::Spec;
use evm_schedule::EvmSchedule;
use env_info::EnvInfo;
/// A consensus mechanism for the chain. Generally either proof-of-work or proof-of-stake-based. /// A consensus mechanism for the chain. Generally either proof-of-work or proof-of-stake-based.
/// Provides hooks into each of the major parts of block import. /// Provides hooks into each of the major parts of block import.

View File

@ -1,5 +1,4 @@
use util::uint::*; use util::*;
use util::hash::*;
/// Simple vector of hashes, should be at most 256 items large, can be smaller if being used /// Simple vector of hashes, should be at most 256 items large, can be smaller if being used
/// for a block whose number is less than 257. /// for a block whose number is less than 257.

View File

@ -1,10 +1,7 @@
//use util::error::*; use common::*;
use util::rlp::decode;
use engine::Engine;
use spec::Spec;
use block::*; use block::*;
use evm_schedule::EvmSchedule; use spec::*;
use env_info::EnvInfo; use engine::*;
/// Engine using Ethash proof-of-work consensus algorithm, suitable for Ethereum /// Engine using Ethash proof-of-work consensus algorithm, suitable for Ethereum
/// mainnet chains in the Olympic, Frontier and Homestead eras. /// mainnet chains in the Olympic, Frontier and Homestead eras.
@ -31,3 +28,13 @@ impl Engine for Ethash {
} }
// TODO: test for on_close_block. // TODO: test for on_close_block.
#[test]
fn playpen() {
use util::sha3::*;
use util::overlaydb::*;
let engine = Spec::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()]);
}

View File

@ -1,8 +1,5 @@
use heapsize::HeapSizeOf; use util::*;
use rocksdb::{DB, Writable}; use rocksdb::{DB, Writable};
use util::uint::*;
use util::hash::*;
use util::rlp::*;
/// Represents index of extra data in database /// Represents index of extra data in database
#[derive(Copy, Clone)] #[derive(Copy, Clone)]

View File

@ -1,14 +1,5 @@
use std::io::Read; use util::*;
use std::str::FromStr;
use std::collections::HashMap;
use rustc_serialize::base64::FromBase64;
use rustc_serialize::json::Json;
use rustc_serialize::hex::FromHex;
use flate2::read::GzDecoder; use flate2::read::GzDecoder;
use util::rlp::*;
use util::hash::*;
use util::uint::*;
use util::sha3::*;
use account::*; use account::*;
use header::*; use header::*;
@ -90,7 +81,8 @@ impl Genesis {
let mixhash = H256::from_str(&json["mixhash"].as_string().unwrap()[2..]).unwrap(); let mixhash = H256::from_str(&json["mixhash"].as_string().unwrap()[2..]).unwrap();
let nonce = H64::from_str(&json["nonce"].as_string().unwrap()[2..]).unwrap(); let nonce = H64::from_str(&json["nonce"].as_string().unwrap()[2..]).unwrap();
vec![encode(&mixhash), encode(&nonce)] vec![encode(&mixhash), encode(&nonce)]
} },
hash: RefCell::new(None),
}; };
(header, state) (header, state)

View File

@ -1,7 +1,4 @@
use util::hash::*; use util::*;
use util::bytes::*;
use util::uint::*;
use util::rlp::*;
/// Type for a 2048-bit log-bloom, as used by our blocks. /// Type for a 2048-bit log-bloom, as used by our blocks.
pub type LogBloom = H2048; pub type LogBloom = H2048;
@ -38,6 +35,8 @@ pub struct Header {
pub difficulty: U256, pub difficulty: U256,
pub seal: Vec<Bytes>, pub seal: Vec<Bytes>,
pub hash: RefCell<Option<H256>>, //TODO: make this private
} }
impl Header { impl Header {
@ -61,6 +60,21 @@ impl Header {
difficulty: ZERO_U256.clone(), difficulty: ZERO_U256.clone(),
seal: vec![], seal: vec![],
hash: RefCell::new(None),
}
}
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()
}
} }
} }
} }
@ -84,6 +98,7 @@ impl Decodable for Header {
timestamp: try!(Decodable::decode(&d[11])), timestamp: try!(Decodable::decode(&d[11])),
extra_data: try!(Decodable::decode(&d[12])), extra_data: try!(Decodable::decode(&d[12])),
seal: vec![], seal: vec![],
hash: RefCell::new(None),
}; };
for i in 13..d.len() { for i in 13..d.len() {

View File

@ -84,11 +84,7 @@ extern crate env_logger;
extern crate evmjit; extern crate evmjit;
extern crate ethcore_util as util; extern crate ethcore_util as util;
//use util::error::*; pub mod common;
pub use util::hash::*;
pub use util::uint::*;
pub use util::bytes::*;
pub mod env_info; pub mod env_info;
pub mod engine; pub mod engine;
pub mod state; pub mod state;

View File

@ -1,5 +1,4 @@
use util::hash::*; use util::*;
use util::uint::*;
/// Information describing execution of a transaction. /// Information describing execution of a transaction.
pub struct Receipt { pub struct Receipt {

View File

@ -1,25 +1,8 @@
use std::io::Read; use common::*;
use std::collections::HashMap;
use std::cell::*;
use std::str::FromStr;
use rustc_serialize::base64::FromBase64;
use rustc_serialize::json::Json;
use rustc_serialize::hex::FromHex;
use flate2::read::GzDecoder; use flate2::read::GzDecoder;
use util::uint::*; use engine::*;
use util::hash::*; use null_engine::*;
use util::bytes::*; use ethash::*;
use util::triehash::*;
use util::error::*;
use util::rlp::*;
use util::sha3::*;
use account::*;
use engine::Engine;
use builtin::Builtin;
use null_engine::NullEngine;
use ethash::Ethash;
use denominations::*;
use header::*;
/// Converts file from base64 gzipped bytes to json /// Converts file from base64 gzipped bytes to json
pub fn gzip64res_to_json(source: &[u8]) -> Json { pub fn gzip64res_to_json(source: &[u8]) -> Json {
@ -107,7 +90,7 @@ impl Spec {
Ref::map(self.state_root_memo.borrow(), |x|x.as_ref().unwrap()) Ref::map(self.state_root_memo.borrow(), |x|x.as_ref().unwrap())
} }
fn genesis_header(&self) -> Header { pub fn genesis_header(&self) -> Header {
Header { Header {
parent_hash: self.parent_hash.clone(), parent_hash: self.parent_hash.clone(),
timestamp: self.timestamp.clone(), timestamp: self.timestamp.clone(),
@ -129,8 +112,9 @@ impl Spec {
s.out() s.out()
}; };
let r = Rlp::new(&seal); let r = Rlp::new(&seal);
(0..self.seal_fields).map(|i| r.at(i).raw().to_vec()).collect() (0..self.seal_fields).map(|i| r.at(i).as_raw().to_vec()).collect()
}, },
hash: RefCell::new(None),
} }
} }
@ -342,6 +326,17 @@ impl Spec {
} }
} }
/// Ensure that the given state DB has the trie nodes in for the genesis state.
pub fn ensure_db_good(&self, db: &mut HashDB) {
if !db.contains(&self.state_root()) {
let mut root = H256::new();
let mut t = SecTrieDBMut::new(db, &mut root);
for (address, account) in self.genesis_state.iter() {
t.insert(address.as_slice(), &account.rlp());
}
}
}
/// Create a new Spec from a JSON UTF-8 data resource `data`. /// Create a new Spec from a JSON UTF-8 data resource `data`.
pub fn from_json_utf8(data: &[u8]) -> Spec { pub fn from_json_utf8(data: &[u8]) -> Spec {
Self::from_json_str(::std::str::from_utf8(data).unwrap()) Self::from_json_str(::std::str::from_utf8(data).unwrap())
@ -365,26 +360,16 @@ mod tests {
use std::str::FromStr; use std::str::FromStr;
use util::hash::*; use util::hash::*;
use util::sha3::*; use util::sha3::*;
use rustc_serialize::json::Json;
use views::*; use views::*;
use super::*; use super::*;
#[test] #[test]
fn morden_manual() { fn morden() {
let morden = Spec::new_morden_manual(); for morden in [Spec::new_morden(), Spec::new_morden_manual()].into_iter() {
assert_eq!(*morden.state_root(), H256::from_str("f3f4696bbf3b3b07775128eb7a3763279a394e382130f27c21e70233e04946a9").unwrap()); assert_eq!(*morden.state_root(), H256::from_str("f3f4696bbf3b3b07775128eb7a3763279a394e382130f27c21e70233e04946a9").unwrap());
let genesis = morden.genesis_block(); let genesis = morden.genesis_block();
assert_eq!(BlockView::new(&genesis).header_view().sha3(), H256::from_str("0cd786a2425d16f152c658316c423e6ce1181e15c3295826d7c9904cba9ce303").unwrap()); assert_eq!(BlockView::new(&genesis).header_view().sha3(), H256::from_str("0cd786a2425d16f152c658316c423e6ce1181e15c3295826d7c9904cba9ce303").unwrap());
} }
#[test]
fn morden() {
let morden = Spec::new_morden();
assert_eq!(*morden.state_root(), H256::from_str("f3f4696bbf3b3b07775128eb7a3763279a394e382130f27c21e70233e04946a9").unwrap());
let genesis = morden.genesis_block();
assert_eq!(BlockView::new(&genesis).header_view().sha3(), H256::from_str("0cd786a2425d16f152c658316c423e6ce1181e15c3295826d7c9904cba9ce303").unwrap());
} }
#[test] #[test]

View File

@ -1,14 +1,4 @@
use std::cell::*; use util::*;
use std::ops::*;
use std::collections::HashMap;
use util::hash::*;
use util::hashdb::*;
use util::overlaydb::*;
use util::trie::*;
use util::bytes::*;
use util::rlp::*;
use util::uint::*;
use util::error::*;
use account::Account; use account::Account;
use transaction::Transaction; use transaction::Transaction;
use receipt::Receipt; use receipt::Receipt;
@ -129,9 +119,10 @@ impl State {
self.require(a, false).set_storage(key, value); self.require(a, false).set_storage(key, value);
} }
/// Mutate storage of account `a` so that it is `value` for `key`. /// Initialise the code of account `a` so that it is `value` for `key`.
pub fn set_code(&mut self, a: &Address, code: Bytes) { /// NOTE: Account should have been created with `new_contract`.
self.require_or_from(a, true, || Account::new_contract(U256::from(0u8))).set_code(code); pub fn init_code(&mut self, a: &Address, code: Bytes) {
self.require_or_from(a, true, || Account::new_contract(U256::from(0u8))).init_code(code);
} }
/// Execute a given transaction. /// Execute a given transaction.
@ -238,7 +229,7 @@ fn code_from_database() {
let (r, db) = { let (r, db) = {
let mut s = State::new_temp(); let mut s = State::new_temp();
s.require_or_from(&a, false, ||Account::new_contract(U256::from(42u32))); s.require_or_from(&a, false, ||Account::new_contract(U256::from(42u32)));
s.set_code(&a, vec![1, 2, 3]); s.init_code(&a, vec![1, 2, 3]);
assert_eq!(s.code(&a), Some([1u8, 2, 3].to_vec())); assert_eq!(s.code(&a), Some([1u8, 2, 3].to_vec()));
s.commit(); s.commit();
assert_eq!(s.code(&a), Some([1u8, 2, 3].to_vec())); assert_eq!(s.code(&a), Some([1u8, 2, 3].to_vec()));

View File

@ -1,7 +1,4 @@
use util::hash::*; use util::*;
use util::bytes::*;
use util::uint::*;
use util::rlp::*;
/// A set of information describing an externally-originating message call /// A set of information describing an externally-originating message call
/// or contract creation operation. /// or contract creation operation.

View File

@ -1,9 +1,5 @@
//! Block oriented views onto rlp. //! Block oriented views onto rlp.
use util::bytes::*; use util::*;
use util::hash::*;
use util::uint::*;
use util::rlp::*;
use util::sha3::*;
use header::*; use header::*;
use transaction::*; use transaction::*;
@ -49,7 +45,7 @@ impl<'a> BlockView<'a> {
/// Return transaction hashes. /// Return transaction hashes.
pub fn transaction_hashes(&self) -> Vec<H256> { pub fn transaction_hashes(&self) -> Vec<H256> {
self.rlp.at(1).iter().map(|rlp| rlp.raw().sha3()).collect() self.rlp.at(1).iter().map(|rlp| rlp.as_raw().sha3()).collect()
} }
/// Return list of uncles of given block. /// Return list of uncles of given block.
@ -59,7 +55,7 @@ impl<'a> BlockView<'a> {
/// Return list of uncle hashes of given block. /// Return list of uncle hashes of given block.
pub fn uncle_hashes(&self) -> Vec<H256> { pub fn uncle_hashes(&self) -> Vec<H256> {
self.rlp.at(2).iter().map(|rlp| rlp.raw().sha3()).collect() self.rlp.at(2).iter().map(|rlp| rlp.as_raw().sha3()).collect()
} }
} }
@ -143,6 +139,6 @@ impl<'a> HeaderView<'a> {
impl<'a> Hashable for HeaderView<'a> { impl<'a> Hashable for HeaderView<'a> {
fn sha3(&self) -> H256 { fn sha3(&self) -> H256 {
self.rlp.raw().sha3() self.rlp.as_raw().sha3()
} }
} }