diff --git a/src/account.rs b/src/account.rs index 5999d8dd5..83b840191 100644 --- a/src/account.rs +++ b/src/account.rs @@ -25,16 +25,3 @@ impl Account { pub fn storage(&self) -> &HashMap { &self.storage } } -pub struct AccountMap { - accounts: HashMap -} - -impl AccountMap { - pub fn new(accounts: HashMap) -> AccountMap { - AccountMap { - accounts: accounts - } - } - - pub fn accounts(&self) -> &HashMap { &self.accounts } -} diff --git a/src/blockchain.rs b/src/blockchain.rs index 63728ea2f..4982afc4c 100644 --- a/src/blockchain.rs +++ b/src/blockchain.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use util::hash::*; use util::rlp::*; use util::hashdb::*; @@ -8,25 +9,53 @@ use block::*; use verifiedblock::*; use importroute::*; use account::*; +use genesis::*; pub struct BlockChain { genesis_block: Vec, + genesis_header: Vec, genesis_hash: H256, - genesis_state: AccountMap + genesis_state: HashMap } impl BlockChain { - pub fn new(genesis_block: Vec, genesis_state: AccountMap) -> BlockChain { - // consider creating `GenesisView` for genesis block RLP - let genesis_hash = BlockView::new(&genesis_block).parent_hash().sha3(); + /// Create new instance of blockchain from given Genesis + /// + /// ```rust + /// extern crate ethcore_util as util; + /// extern crate ethcore; + /// use std::str::FromStr; + /// use ethcore::genesis::*; + /// use ethcore::blockchain::*; + /// use util::hash::*; + /// + /// fn main() { + /// let genesis = Genesis::new_frontier(); + /// let bc = BlockChain::new(genesis); + /// let genesis_hash = "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"; + /// assert_eq!(bc.genesis_hash(), &H256::from_str(genesis_hash).unwrap()); + /// } + /// ``` + pub fn new(genesis: Genesis) -> BlockChain { + let (genesis_block, genesis_state) = genesis.drain(); + + let (genesis_header, genesis_hash) = { + let rlp = Rlp::new(&genesis_block).at(0); + (rlp.raw().to_vec(), BlockView::new_from_rlp(rlp).sha3()) + }; BlockChain { genesis_block: genesis_block, + genesis_header: genesis_header, genesis_hash: genesis_hash, genesis_state: genesis_state } } + pub fn genesis_hash(&self) -> &H256 { + &self.genesis_hash + } + pub fn genesis_block(&self, db: &OverlayDB) -> Block { let root = BlockView::new(&self.genesis_block).state_root(); diff --git a/src/blockheader.rs b/src/blockheader.rs index bfa81ed46..8d454c440 100644 --- a/src/blockheader.rs +++ b/src/blockheader.rs @@ -15,6 +15,12 @@ impl<'a> BlockView<'a> { } } + pub fn new_from_rlp(rlp: Rlp<'a>) -> BlockView<'a> { + BlockView { + rlp: rlp + } + } + pub fn parent_hash(&self) -> H256 { self.rlp.val_at(0) } pub fn uncles_hash(&self) -> H256 { self.rlp.val_at(1) } pub fn coinbase(&self) -> Address { self.rlp.val_at(2) } @@ -33,7 +39,7 @@ impl<'a> BlockView<'a> { impl<'a> sha3::Hashable for BlockView<'a> { fn sha3(&self) -> H256 { - self.rlp.data().sha3() + self.rlp.raw().sha3() } } diff --git a/src/genesis.rs b/src/genesis.rs index d4397218f..64889ce27 100644 --- a/src/genesis.rs +++ b/src/genesis.rs @@ -3,6 +3,7 @@ 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 util::rlp::*; use util::hash::*; @@ -24,7 +25,7 @@ fn base_to_json(source: &[u8]) -> Json { pub struct Genesis { block: Vec, - state: AccountMap + state: HashMap } impl Genesis { @@ -45,7 +46,7 @@ impl Genesis { let difficulty = U256::from_str(&json["difficulty"].as_string().unwrap()[2..]).unwrap(); let gas_limit = U256::from_str(&json["gasLimit"].as_string().unwrap()[2..]).unwrap(); let timestamp = U256::from_str(&json["timestamp"].as_string().unwrap()[2..]).unwrap(); - let extra_data: Vec = From::from(&json["extraData"].as_string().unwrap()[2..]); + let extra_data: Vec = json["extraData"].as_string().unwrap()[2..].from_hex().unwrap(); let nonce = H64::from_str(&json["nonce"].as_string().unwrap()[2..]).unwrap(); let log_bloom = H2048::new(); @@ -80,24 +81,32 @@ impl Genesis { stream.append_raw(&empty_list, 1); stream.append_raw(&empty_list, 1); - let mut map = HashMap::new(); + let mut state = HashMap::new(); let accounts = json["alloc"].as_object().expect("Missing genesis state"); for (address, acc) in accounts.iter() { let addr = Address::from_str(address).unwrap(); let o = acc.as_object().unwrap(); let balance = U256::from_dec_str(o["balance"].as_string().unwrap()).unwrap(); - map.insert(addr, Account::new_with_balance(balance)); + state.insert(addr, Account::new_with_balance(balance)); } Genesis { block: stream.out(), - state: AccountMap::new(map) + state: state } } + + pub fn drain(self) -> (Vec, HashMap) { + (self.block, self.state) + } } #[test] fn test_genesis() { - let g = Genesis::new_default(); + use blockheader::*; + let g = Genesis::new_frontier(); + let view = BlockView::new_from_rlp(Rlp::new(&g.block).at(0)); + let genesis_hash = H256::from_str("d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3").unwrap(); + assert_eq!(view.sha3(), genesis_hash); } diff --git a/src/state.rs b/src/state.rs index 81b0d2c85..46c45415f 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use util::hash::*; use util::hashdb::*; use util::memorydb::*; @@ -58,10 +59,10 @@ impl State { /// Commit accounts to TrieDB. This is simplified version of /// cpp-ethereum's dev::eth::commit. - pub fn insert_accounts(&mut self, map: &AccountMap) { + pub fn insert_accounts(&mut self, accounts: &HashMap) { let mut trie = TrieDB::new_existing(&mut self.db, &mut self.root); - for (address, account) in map.accounts().iter() { + for (address, account) in accounts.iter() { let mut stream = RlpStream::new_list(4); stream.append(account.nonce()); stream.append(account.balance());