Ensure Spec::ensure_db_good() places DB entries for code & storage.
This commit is contained in:
parent
7065c477a4
commit
387e3ec3fd
@ -149,11 +149,15 @@ impl Account {
|
||||
/// Provide a database to lookup `code_hash`. Should not be called if it is a contract without code.
|
||||
pub fn cache_code(&mut self, db: &HashDB) -> bool {
|
||||
// TODO: fill out self.code_cache;
|
||||
trace!("Account::cache_code: ic={}; self.code_hash={:?}, self.code_cache={}", self.is_cached(), self.code_hash, self.code_cache.pretty());
|
||||
self.is_cached() ||
|
||||
match self.code_hash {
|
||||
Some(ref h) => match db.lookup(h) {
|
||||
Some(x) => { self.code_cache = x.to_vec(); true },
|
||||
_ => false,
|
||||
_ => {
|
||||
warn!("Failed reverse lookup of {}", h);
|
||||
false
|
||||
},
|
||||
},
|
||||
_ => false,
|
||||
}
|
||||
|
@ -107,6 +107,11 @@ pub trait BlockProvider {
|
||||
fn genesis_hash(&self) -> H256 {
|
||||
self.block_hash(0).expect("Genesis hash should always exist")
|
||||
}
|
||||
|
||||
/// Returns the header of the genesis block.
|
||||
fn genesis_header(&self) -> Header {
|
||||
self.block_header(&self.genesis_hash()).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Hash, Eq, PartialEq, Clone)]
|
||||
|
@ -4,8 +4,10 @@ use blockchain::{BlockChain, BlockProvider, CacheSize};
|
||||
use views::BlockView;
|
||||
use error::*;
|
||||
use header::BlockNumber;
|
||||
use state::State;
|
||||
use spec::Spec;
|
||||
use engine::Engine;
|
||||
use views::HeaderView;
|
||||
use block_queue::{BlockQueue, BlockQueueInfo};
|
||||
use service::NetSyncMessage;
|
||||
use env_info::LastHashes;
|
||||
@ -98,6 +100,11 @@ pub trait BlockChainClient : Sync + Send {
|
||||
|
||||
/// Get blockchain information.
|
||||
fn chain_info(&self) -> BlockChainInfo;
|
||||
|
||||
/// Get the best block header.
|
||||
fn best_block_header(&self) -> Bytes {
|
||||
self.block_header(&self.chain_info().best_block_hash).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Debug, Eq, PartialEq)]
|
||||
@ -137,7 +144,9 @@ const HISTORY: u64 = 1000;
|
||||
impl Client {
|
||||
/// Create a new client with given spec and DB path.
|
||||
pub fn new(spec: Spec, path: &Path, message_channel: IoChannel<NetSyncMessage> ) -> Result<Arc<Client>, Error> {
|
||||
let chain = Arc::new(RwLock::new(BlockChain::new(&spec.genesis_block(), path)));
|
||||
let gb = spec.genesis_block();
|
||||
flushln!("Spec says genesis block is {}", gb.pretty());
|
||||
let chain = Arc::new(RwLock::new(BlockChain::new(&gb, path)));
|
||||
let mut opts = Options::new();
|
||||
opts.set_max_open_files(256);
|
||||
opts.create_if_missing(true);
|
||||
@ -168,6 +177,7 @@ impl Client {
|
||||
if engine.spec().ensure_db_good(&mut state_db) {
|
||||
state_db.commit(0, &engine.spec().genesis_header().hash(), None).expect("Error commiting genesis state to state DB");
|
||||
}
|
||||
flushln!("Client::new: commiting. Best root now: {}. contains: {}", chain.read().unwrap().genesis_header().state_root, state_db.contains(&chain.read().unwrap().genesis_header().state_root));
|
||||
Ok(Arc::new(Client {
|
||||
chain: chain,
|
||||
engine: engine.clone(),
|
||||
@ -261,6 +271,11 @@ impl Client {
|
||||
self.uncommited_states.write().unwrap().remove(hash);
|
||||
}
|
||||
|
||||
/// Get a copy of the best block's state.
|
||||
pub fn state(&self) -> State {
|
||||
State::from_existing(self.state_db.clone(), HeaderView::new(&self.best_block_header()).state_root(), self.engine.account_start_nonce())
|
||||
}
|
||||
|
||||
/// Get info on the cache.
|
||||
pub fn cache_info(&self) -> CacheSize {
|
||||
self.chain.read().unwrap().cache_size()
|
||||
|
@ -275,6 +275,8 @@ impl evm::Evm for Interpreter {
|
||||
code: &code
|
||||
};
|
||||
|
||||
flushln!("Executing: {:?}", params);
|
||||
|
||||
while reader.position < code.len() {
|
||||
let instruction = code[reader.position];
|
||||
reader.position += 1;
|
||||
@ -640,6 +642,7 @@ impl Interpreter {
|
||||
return Ok(InstructionResult::StopExecution);
|
||||
},
|
||||
instructions::SUICIDE => {
|
||||
flushln!("SUICIDE!");
|
||||
let address = stack.pop_back();
|
||||
ext.suicide(&u256_to_address(&address));
|
||||
return Ok(InstructionResult::StopExecution);
|
||||
|
@ -166,7 +166,6 @@ impl<'a> Executive<'a> {
|
||||
/// Modifies the substate and the output.
|
||||
/// Returns either gas_left or `evm::Error`.
|
||||
pub fn call(&mut self, params: ActionParams, substate: &mut Substate, mut output: BytesRef) -> evm::Result {
|
||||
println!("Calling executive. Sender: {}", params.sender);
|
||||
// backup used in case of running out of gas
|
||||
let backup = self.state.clone();
|
||||
|
||||
@ -174,7 +173,7 @@ impl<'a> Executive<'a> {
|
||||
if let ActionValue::Transfer(val) = params.value {
|
||||
self.state.transfer_balance(¶ms.sender, ¶ms.address, &val);
|
||||
}
|
||||
trace!("Executive::call(params={:?}) self.env_info={:?}", params, self.info);
|
||||
flushln!("Executive::call(params={:?}) self.env_info={:?}", params, self.info);
|
||||
|
||||
if self.engine.is_builtin(¶ms.code_address) {
|
||||
// if destination is builtin, try to execute it
|
||||
@ -261,17 +260,17 @@ impl<'a> Executive<'a> {
|
||||
let refund_value = gas_left * t.gas_price;
|
||||
let fees_value = gas_used * t.gas_price;
|
||||
|
||||
trace!("exec::finalize: t.gas={}, sstore_refunds={}, suicide_refunds={}, refunds_bound={}, gas_left_prerefund={}, refunded={}, gas_left={}, gas_used={}, refund_value={}, fees_value={}\n",
|
||||
flushln!("exec::finalize: t.gas={}, sstore_refunds={}, suicide_refunds={}, refunds_bound={}, gas_left_prerefund={}, refunded={}, gas_left={}, gas_used={}, refund_value={}, fees_value={}\n",
|
||||
t.gas, sstore_refunds, suicide_refunds, refunds_bound, gas_left_prerefund, refunded, gas_left, gas_used, refund_value, fees_value);
|
||||
|
||||
trace!("exec::finalize: Refunding refund_value={}, sender={}\n", refund_value, t.sender().unwrap());
|
||||
flushln!("exec::finalize: Refunding refund_value={}, sender={}\n", refund_value, t.sender().unwrap());
|
||||
self.state.add_balance(&t.sender().unwrap(), &refund_value);
|
||||
trace!("exec::finalize: Compensating author: fees_value={}, author={}\n", fees_value, &self.info.author);
|
||||
flushln!("exec::finalize: Compensating author: fees_value={}, author={}\n", fees_value, &self.info.author);
|
||||
self.state.add_balance(&self.info.author, &fees_value);
|
||||
|
||||
// perform suicides
|
||||
for address in &substate.suicides {
|
||||
trace!("Killing {}", address);
|
||||
flushln!("Killing {}", address);
|
||||
self.state.kill_account(address);
|
||||
}
|
||||
|
||||
|
@ -215,6 +215,7 @@ impl<'a> Ext for Externalities<'a> {
|
||||
fn suicide(&mut self, refund_address: &Address) {
|
||||
let address = self.origin_info.address.clone();
|
||||
let balance = self.balance(&address);
|
||||
flushln!("Suiciding {} -> {} (xfer: {})", address, refund_address, balance);
|
||||
self.state.transfer_balance(&address, refund_address, &balance);
|
||||
self.substate.suicides.insert(address);
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ impl PodAccount {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
/// Returns the RLP for this account.
|
||||
pub fn rlp(&self) -> Bytes {
|
||||
let mut stream = RlpStream::new_list(4);
|
||||
stream.append(&self.nonce);
|
||||
@ -40,6 +40,18 @@ impl PodAccount {
|
||||
stream.append(&self.code.sha3());
|
||||
stream.out()
|
||||
}
|
||||
|
||||
/// Place additional data into given hash DB.
|
||||
pub fn insert_additional(&self, db: &mut HashDB) {
|
||||
if !self.code.is_empty() {
|
||||
db.insert(&self.code);
|
||||
}
|
||||
let mut r = H256::new();
|
||||
let mut t = SecTrieDBMut::new(db, &mut r);
|
||||
for (k, v) in &self.storage {
|
||||
t.insert(k, &encode(&U256::from(v.as_slice())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for PodAccount {
|
||||
|
@ -261,7 +261,6 @@ 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) -> bool {
|
||||
if !db.contains(&self.state_root()) {
|
||||
info!("Populating genesis state...");
|
||||
let mut root = H256::new();
|
||||
{
|
||||
let mut t = SecTrieDBMut::new(db, &mut root);
|
||||
@ -269,8 +268,10 @@ impl Spec {
|
||||
t.insert(address.as_slice(), &account.rlp());
|
||||
}
|
||||
}
|
||||
for (_, account) in self.genesis_state.get().iter() {
|
||||
account.insert_additional(db);
|
||||
}
|
||||
assert!(db.contains(&self.state_root()));
|
||||
info!("Genesis state is ready");
|
||||
true
|
||||
} else { false }
|
||||
}
|
||||
|
@ -103,6 +103,7 @@ impl State {
|
||||
|
||||
/// Mutate storage of account `a` so that it is `value` for `key`.
|
||||
pub fn code(&self, a: &Address) -> Option<Bytes> {
|
||||
flushln!("Getting code at {}", a);
|
||||
self.get(a, true).as_ref().map_or(None, |a|a.code().map(|x|x.to_vec()))
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,8 @@ fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
||||
|
||||
let blocks: Vec<Bytes> = test["blocks"].as_array().unwrap().iter().map(|e| xjson!(&e["rlp"])).collect();
|
||||
let mut spec = ethereum::new_frontier_like_test();
|
||||
spec.set_genesis_state(PodState::from_json(test.find("pre").unwrap()));
|
||||
let s = PodState::from_json(test.find("pre").unwrap());
|
||||
spec.set_genesis_state(s);
|
||||
spec.overwrite_genesis(test.find("genesisBlockHeader").unwrap());
|
||||
assert!(spec.is_state_root_valid());
|
||||
|
||||
@ -56,7 +57,7 @@ declare_test!{BlockchainTests_bcInvalidHeaderTest, "BlockchainTests/bcInvalidHea
|
||||
declare_test!{ignore => BlockchainTests_bcInvalidRLPTest, "BlockchainTests/bcInvalidRLPTest"} // FAILS
|
||||
declare_test!{ignore => BlockchainTests_bcMultiChainTest, "BlockchainTests/bcMultiChainTest"} // FAILS
|
||||
declare_test!{BlockchainTests_bcRPC_API_Test, "BlockchainTests/bcRPC_API_Test"}
|
||||
declare_test!{ignore => BlockchainTests_bcStateTest, "BlockchainTests/bcStateTest"} // FAILS (Suicides, GasUsed)
|
||||
declare_test!{BlockchainTests_bcStateTest, "BlockchainTests/bcStateTest"} // FAILS (Suicides, GasUsed)
|
||||
declare_test!{BlockchainTests_bcTotalDifficultyTest, "BlockchainTests/bcTotalDifficultyTest"}
|
||||
declare_test!{ignore => BlockchainTests_bcUncleHeaderValiditiy, "BlockchainTests/bcUncleHeaderValiditiy"} // FAILS
|
||||
declare_test!{ignore => BlockchainTests_bcUncleTest, "BlockchainTests/bcUncleTest"} // FAILS
|
||||
|
@ -25,6 +25,12 @@ impl<'db> SecTrieDBMut<'db> {
|
||||
pub fn from_existing(db: &'db mut HashDB, root: &'db mut H256) -> Self {
|
||||
SecTrieDBMut { raw: TrieDBMut::from_existing(db, root) }
|
||||
}
|
||||
|
||||
/// Get the backing database.
|
||||
pub fn db(&'db self) -> &'db HashDB { self.raw.db() }
|
||||
|
||||
/// Get the backing database.
|
||||
pub fn db_mut(&'db mut self) -> &'db mut HashDB { self.raw.db_mut() }
|
||||
}
|
||||
|
||||
impl<'db> Trie for SecTrieDBMut<'db> {
|
||||
|
@ -87,6 +87,11 @@ impl<'db> TrieDBMut<'db> {
|
||||
self.db
|
||||
}
|
||||
|
||||
/// Get the backing database.
|
||||
pub fn db_mut(&'db mut self) -> &'db mut HashDB {
|
||||
self.db
|
||||
}
|
||||
|
||||
/// Determine all the keys in the backing database that belong to the trie.
|
||||
pub fn keys(&self) -> Vec<H256> {
|
||||
let mut ret: Vec<H256> = Vec::new();
|
||||
|
Loading…
Reference in New Issue
Block a user