diff --git a/src/account.rs b/src/account.rs index 7b5bd1908..657f1d23b 100644 --- a/src/account.rs +++ b/src/account.rs @@ -1,12 +1,4 @@ -use std::collections::HashMap; -use util::hash::*; -use util::sha3::*; -use util::hashdb::*; -use util::bytes::*; -use util::trie::*; -use util::rlp::*; -use util::uint::*; -use std::cell::*; +use util::*; 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. - /// 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 { Account { balance: balance, @@ -80,7 +72,7 @@ impl Account { /// Set this account's code to the given code. /// 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()); self.code_cache = code; } @@ -224,7 +216,7 @@ fn storage_at() { let mut a = Account::new_contract(U256::from(69u8)); a.set_storage(H256::from(&U256::from(0x00u64)), H256::from(&U256::from(0x1234u64))); a.commit_storage(&mut db); - a.set_code(vec![]); + a.init_code(vec![]); a.commit_code(&mut db); a.rlp() }; @@ -241,7 +233,7 @@ fn note_code() { let rlp = { 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.rlp() }; @@ -267,7 +259,7 @@ fn commit_storage() { fn commit_code() { let mut a = Account::new_contract(U256::from(69u8)); 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); a.commit_code(&mut db); assert_eq!(a.code_hash().hex(), "af231e631776a517ca23125370d542873eca1fb4d613ed9b5d5335a46ae5b7eb"); diff --git a/src/block.rs b/src/block.rs index b1ebece79..ae05cc94d 100644 --- a/src/block.rs +++ b/src/block.rs @@ -1,9 +1,4 @@ -use std::collections::hash_set::*; -use util::hash::*; -use util::bytes::*; -use util::uint::*; -use util::error::*; -use util::overlaydb::*; +use util::*; use transaction::*; use receipt::*; use blockchain::*; diff --git a/src/blockchain.rs b/src/blockchain.rs index df729787a..399a8b330 100644 --- a/src/blockchain.rs +++ b/src/blockchain.rs @@ -1,18 +1,7 @@ //! Fast access to blockchain data. -use std::collections::HashMap; -use std::cell::RefCell; -use std::path::Path; -use std::hash::Hash; +use util::*; 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 extras::*; use transaction::*; diff --git a/src/builtin.rs b/src/builtin.rs index ade5aa8d2..7f8f0690b 100644 --- a/src/builtin.rs +++ b/src/builtin.rs @@ -1,12 +1,4 @@ -use std::cmp::min; -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 util::*; use crypto::sha2::Sha256; use crypto::ripemd160::Ripemd160; use crypto::digest::Digest; @@ -95,8 +87,8 @@ pub fn new_builtin_exec(name: &str) -> Option> { it.copy_raw(input); 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); - if is_valid(&s) { - match recover(&s, &it.hash) { + if ec::is_valid(&s) { + match ec::recover(&s, &it.hash) { Ok(p) => { let r = p.as_slice().sha3(); // NICE: optimise and separate out into populate-like function diff --git a/src/common.rs b/src/common.rs new file mode 100644 index 000000000..bc6371abf --- /dev/null +++ b/src/common.rs @@ -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::*; diff --git a/src/denominations.rs b/src/denominations.rs index 183e89f26..a23c94b4c 100644 --- a/src/denominations.rs +++ b/src/denominations.rs @@ -1,4 +1,4 @@ -use util::uint::*; +use util::*; #[inline] pub fn ether() -> U256 { U256::exp10(18) } diff --git a/src/engine.rs b/src/engine.rs index aec721818..318c5a6b4 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -1,16 +1,6 @@ -use std::collections::hash_map::*; -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 common::*; use block::Block; 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. /// Provides hooks into each of the major parts of block import. diff --git a/src/env_info.rs b/src/env_info.rs index dec8069ac..919db314d 100644 --- a/src/env_info.rs +++ b/src/env_info.rs @@ -1,5 +1,4 @@ -use util::uint::*; -use util::hash::*; +use util::*; /// 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. diff --git a/src/ethash.rs b/src/ethash.rs index f2d1320c5..219d0f870 100644 --- a/src/ethash.rs +++ b/src/ethash.rs @@ -1,10 +1,7 @@ -//use util::error::*; -use util::rlp::decode; -use engine::Engine; -use spec::Spec; +use common::*; use block::*; -use evm_schedule::EvmSchedule; -use env_info::EnvInfo; +use spec::*; +use engine::*; /// Engine using Ethash proof-of-work consensus algorithm, suitable for Ethereum /// mainnet chains in the Olympic, Frontier and Homestead eras. @@ -31,3 +28,13 @@ impl Engine for Ethash { } // 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()]); +} \ No newline at end of file diff --git a/src/extras.rs b/src/extras.rs index 93144dda7..39ce814c8 100644 --- a/src/extras.rs +++ b/src/extras.rs @@ -1,8 +1,5 @@ -use heapsize::HeapSizeOf; +use util::*; use rocksdb::{DB, Writable}; -use util::uint::*; -use util::hash::*; -use util::rlp::*; /// Represents index of extra data in database #[derive(Copy, Clone)] diff --git a/src/genesis.rs b/src/genesis.rs index 63a0caf81..aa6897573 100644 --- a/src/genesis.rs +++ b/src/genesis.rs @@ -1,14 +1,5 @@ -use std::io::Read; -use std::str::FromStr; -use std::collections::HashMap; -use rustc_serialize::base64::FromBase64; -use rustc_serialize::json::Json; -use rustc_serialize::hex::FromHex; +use util::*; use flate2::read::GzDecoder; -use util::rlp::*; -use util::hash::*; -use util::uint::*; -use util::sha3::*; use account::*; use header::*; @@ -90,7 +81,8 @@ impl Genesis { let mixhash = H256::from_str(&json["mixhash"].as_string().unwrap()[2..]).unwrap(); let nonce = H64::from_str(&json["nonce"].as_string().unwrap()[2..]).unwrap(); vec![encode(&mixhash), encode(&nonce)] - } + }, + hash: RefCell::new(None), }; (header, state) diff --git a/src/header.rs b/src/header.rs index ab84d5c58..80d91eb20 100644 --- a/src/header.rs +++ b/src/header.rs @@ -1,7 +1,4 @@ -use util::hash::*; -use util::bytes::*; -use util::uint::*; -use util::rlp::*; +use util::*; /// Type for a 2048-bit log-bloom, as used by our blocks. pub type LogBloom = H2048; @@ -38,6 +35,8 @@ pub struct Header { pub difficulty: U256, pub seal: Vec, + + pub hash: RefCell>, //TODO: make this private } impl Header { @@ -61,6 +60,21 @@ impl Header { difficulty: ZERO_U256.clone(), 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])), extra_data: try!(Decodable::decode(&d[12])), seal: vec![], + hash: RefCell::new(None), }; for i in 13..d.len() { diff --git a/src/lib.rs b/src/lib.rs index 054947ebe..9c2bd2d1d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -84,11 +84,7 @@ extern crate env_logger; extern crate evmjit; extern crate ethcore_util as util; -//use util::error::*; -pub use util::hash::*; -pub use util::uint::*; -pub use util::bytes::*; - +pub mod common; pub mod env_info; pub mod engine; pub mod state; diff --git a/src/receipt.rs b/src/receipt.rs index 481b6eda0..fb72e2e18 100644 --- a/src/receipt.rs +++ b/src/receipt.rs @@ -1,5 +1,4 @@ -use util::hash::*; -use util::uint::*; +use util::*; /// Information describing execution of a transaction. pub struct Receipt { diff --git a/src/spec.rs b/src/spec.rs index eee653966..a3fafa60f 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -1,25 +1,8 @@ -use std::io::Read; -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 common::*; use flate2::read::GzDecoder; -use util::uint::*; -use util::hash::*; -use util::bytes::*; -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::*; +use engine::*; +use null_engine::*; +use ethash::*; /// Converts file from base64 gzipped bytes to 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()) } - fn genesis_header(&self) -> Header { + pub fn genesis_header(&self) -> Header { Header { parent_hash: self.parent_hash.clone(), timestamp: self.timestamp.clone(), @@ -129,8 +112,9 @@ impl Spec { s.out() }; 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`. pub fn from_json_utf8(data: &[u8]) -> Spec { Self::from_json_str(::std::str::from_utf8(data).unwrap()) @@ -365,26 +360,16 @@ mod tests { use std::str::FromStr; use util::hash::*; use util::sha3::*; - use rustc_serialize::json::Json; use views::*; use super::*; - #[test] - fn morden_manual() { - let morden = Spec::new_morden_manual(); - - 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] 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()); + for morden in [Spec::new_morden(), Spec::new_morden_manual()].into_iter() { + 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] diff --git a/src/state.rs b/src/state.rs index 019dc0426..80c8276fc 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,14 +1,4 @@ -use std::cell::*; -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 util::*; use account::Account; use transaction::Transaction; use receipt::Receipt; @@ -129,9 +119,10 @@ impl State { self.require(a, false).set_storage(key, value); } - /// Mutate storage of account `a` so that it is `value` for `key`. - pub fn set_code(&mut self, a: &Address, code: Bytes) { - self.require_or_from(a, true, || Account::new_contract(U256::from(0u8))).set_code(code); + /// Initialise the code of account `a` so that it is `value` for `key`. + /// NOTE: Account should have been created with `new_contract`. + 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. @@ -238,7 +229,7 @@ fn code_from_database() { let (r, db) = { let mut s = State::new_temp(); 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())); s.commit(); assert_eq!(s.code(&a), Some([1u8, 2, 3].to_vec())); diff --git a/src/transaction.rs b/src/transaction.rs index d24448c93..b54329422 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -1,7 +1,4 @@ -use util::hash::*; -use util::bytes::*; -use util::uint::*; -use util::rlp::*; +use util::*; /// A set of information describing an externally-originating message call /// or contract creation operation. diff --git a/src/views.rs b/src/views.rs index e8425cc17..e66a46178 100644 --- a/src/views.rs +++ b/src/views.rs @@ -1,9 +1,5 @@ //! Block oriented views onto rlp. -use util::bytes::*; -use util::hash::*; -use util::uint::*; -use util::rlp::*; -use util::sha3::*; +use util::*; use header::*; use transaction::*; @@ -49,7 +45,7 @@ impl<'a> BlockView<'a> { /// Return transaction hashes. pub fn transaction_hashes(&self) -> Vec { - 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. @@ -59,7 +55,7 @@ impl<'a> BlockView<'a> { /// Return list of uncle hashes of given block. pub fn uncle_hashes(&self) -> Vec { - 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> { fn sha3(&self) -> H256 { - self.rlp.raw().sha3() + self.rlp.as_raw().sha3() } }