diff --git a/src/account.rs b/src/account.rs new file mode 100644 index 000000000..49df9922b --- /dev/null +++ b/src/account.rs @@ -0,0 +1,25 @@ +use std::collections::HashMap; +use util::uint::*; +use util::hash::*; + +pub struct Account { + balance: U256, + code: Vec, + nonce: U256, + storage: HashMap +} + +impl Account { + pub fn balance(&self) -> &U256 { &self.balance } + pub fn code(&self) -> &[u8] { &self.code } + pub fn nonce(&self) -> &U256 { &self.nonce } + pub fn storage(&self) -> &HashMap { &self.storage } +} + +pub struct AccountMap { + accounts: HashMap +} + +impl AccountMap { + pub fn accounts(&self) -> &HashMap { &self.accounts } +} diff --git a/src/blockchain.rs b/src/blockchain.rs index 55a8248f7..63728ea2f 100644 --- a/src/blockchain.rs +++ b/src/blockchain.rs @@ -7,20 +7,23 @@ use blockheader::*; use block::*; use verifiedblock::*; use importroute::*; +use account::*; pub struct BlockChain { genesis_block: Vec, - genesis_hash: H256 + genesis_hash: H256, + genesis_state: AccountMap } impl BlockChain { - pub fn new(genesis_block: Vec) -> 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(); BlockChain { genesis_block: genesis_block, - genesis_hash: genesis_hash + genesis_hash: genesis_hash, + genesis_state: genesis_state } } @@ -32,7 +35,7 @@ impl BlockChain { } let mut block = Block::new(db.clone()); - // TODO: commit genesis state (accounts) to block.state + block.mutable_state().insert_accounts(&self.genesis_state); block.mutable_state().commit_db(); // TODO: set previous block // TODO: reset current diff --git a/src/lib.rs b/src/lib.rs index b6afb47f4..719578b66 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -76,6 +76,7 @@ extern crate ethcore_util as util; #[cfg(feature = "jit" )] extern crate evmjit; +pub mod account; pub mod block; pub mod blockchain; pub mod blockheader; diff --git a/src/state.rs b/src/state.rs index 3b2d4cf2c..c33474869 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,7 +1,12 @@ use util::hash::*; use util::hashdb::*; +use util::memorydb::*; use util::overlaydb::*; +use util::bytes::*; use util::trie::*; +use util::rlp::*; +use util::sha3::*; +use account::*; pub struct State { db: OverlayDB, @@ -45,4 +50,37 @@ impl State { pub fn commit_db(&mut self) { self.db.commit().expect("Number of kills exceeded number of inserts!"); } + + /// Commit accounts to TrieDB. This is simplified version of + /// cpp-ethereum's dev::eth::commit. + pub fn insert_accounts(&mut self, map: &AccountMap) { + let mut trie = TrieDB::new_existing(&mut self.db, &mut self.root); + + for (address, account) in map.accounts().iter() { + let mut stream = RlpStream::new_list(4); + stream.append(account.nonce()); + stream.append(account.balance()); + let mut root = H256::new(); + { + let mut db = MemoryDB::new(); + let mut t = TrieDB::new(&mut db, &mut root); + for (k, v) in account.storage().iter() { + // cast key and value to trait type, + // so we can call overloaded `to_bytes` method + let kas: &ToBytes = k; + let vas: &ToBytes = v; + t.insert(&kas.to_bytes(), &vas.to_bytes()); + } + } + stream.append(&root); + + let code_hash = account.code().sha3(); + stream.append(&code_hash); + + if account.code().len() > 0 { + trie.insert(&code_hash, account.code()); + } + trie.insert(address, &stream.out()); + } + } }