From 2eead090d52b6e5abcff405fdb04fd2f50caa894 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 15 Jan 2016 18:56:28 +0100 Subject: [PATCH] Fix executive. Syncs to 62509. --- src/evm/ext.rs | 4 ++-- src/evm/jit.rs | 4 ++-- src/evm/tests.rs | 4 ++-- src/executive.rs | 50 +++++++++++++++++++----------------------- src/externalities.rs | 10 ++++++--- src/state.rs | 8 +++++++ src/substate.rs | 1 + src/tests/executive.rs | 8 +++---- 8 files changed, 49 insertions(+), 40 deletions(-) diff --git a/src/evm/ext.rs b/src/evm/ext.rs index ca06b5086..d74f847d7 100644 --- a/src/evm/ext.rs +++ b/src/evm/ext.rs @@ -8,10 +8,10 @@ use env_info::*; pub trait Ext { /// Returns a value for given key. - fn sload(&self, key: &H256) -> H256; + fn storage_at(&self, key: &H256) -> H256; /// Stores a value for given key. - fn sstore(&mut self, key: H256, value: H256); + fn set_storage_at(&mut self, key: H256, value: H256); /// Returns address balance. fn balance(&self, address: &Address) -> U256; diff --git a/src/evm/jit.rs b/src/evm/jit.rs index 19a28de6f..122947d32 100644 --- a/src/evm/jit.rs +++ b/src/evm/jit.rs @@ -175,14 +175,14 @@ impl<'a> evmjit::Ext for ExtAdapter<'a> { fn sload(&self, index: *const evmjit::I256, out_value: *mut evmjit::I256) { unsafe { let i = H256::from_jit(&*index); - let o = self.ext.sload(&i); + let o = self.ext.storage_at(&i); *out_value = o.into_jit(); } } fn sstore(&mut self, index: *const evmjit::I256, value: *const evmjit::I256) { unsafe { - self.ext.sstore(H256::from_jit(&*index), H256::from_jit(&*value)); + self.ext.set_storage_at(H256::from_jit(&*index), H256::from_jit(&*value)); } } diff --git a/src/evm/tests.rs b/src/evm/tests.rs index 3ed56bc39..f43881424 100644 --- a/src/evm/tests.rs +++ b/src/evm/tests.rs @@ -26,11 +26,11 @@ impl FakeExt { } impl Ext for FakeExt { - fn sload(&self, key: &H256) -> H256 { + fn storage_at(&self, key: &H256) -> H256 { self.store.get(key).unwrap_or(&H256::new()).clone() } - fn sstore(&mut self, key: H256, value: H256) { + fn set_storage_at(&mut self, key: H256, value: H256) { self.store.insert(key, value); } diff --git a/src/executive.rs b/src/executive.rs index 8252b9221..bab431ed9 100644 --- a/src/executive.rs +++ b/src/executive.rs @@ -201,7 +201,11 @@ impl<'a> Executive<'a> { let evm = Factory::create(); evm.exec(¶ms, &mut ext) }; + +// flush(format!("exec: sstore-clears={}\n", unconfirmed_substate.refunds_count)); +// flush(format!("exec: substate={:?}; unconfirmed_substate={:?}\n", substate, unconfirmed_substate)); self.enact_result(&res, substate, unconfirmed_substate, backup); +// flush(format!("exec: new substate={:?}\n", substate)); res } else { // otherwise, nothing @@ -242,51 +246,43 @@ impl<'a> Executive<'a> { let sstore_refunds = U256::from(schedule.sstore_refund_gas) * substate.refunds_count; // refunds from contract suicides let suicide_refunds = U256::from(schedule.suicide_refund_gas) * U256::from(substate.suicides.len()); + let refunds_bound = sstore_refunds + suicide_refunds; // real ammount to refund - let gas_left = match &result { &Ok(x) => x, _ => x!(0) }; - let refund = cmp::min(sstore_refunds + suicide_refunds, (t.gas - gas_left) / U256::from(2)) + gas_left; - let refund_value = refund * t.gas_price; - trace!("Refunding sender: sstore0s: {}, suicides: {}, gas_left: {}, refund: {}, refund_value: {}, sender: {}", sstore_refunds, suicide_refunds, gas_left, refund, refund_value, t.sender().unwrap()); + let gas_left_prerefund = match &result { &Ok(x) => x, _ => x!(0) }; + let refunded = cmp::min(refunds_bound, (t.gas - gas_left_prerefund) / U256::from(2)); + let gas_left = gas_left_prerefund + refunded; + + let gas_used = t.gas - gas_left; + let refund_value = gas_left * t.gas_price; + let fees_value = gas_used * t.gas_price; + + flush(format!("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)); + + flush(format!("exec::finalize: Refunding sender={}\n", t.sender().unwrap())); self.state.add_balance(&t.sender().unwrap(), &refund_value); - - // fees earned by author - let fees = t.gas - refund; - let fees_value = fees * t.gas_price; - let author = &self.info.author; - self.state.add_balance(author, &fees_value); - trace!("Compensating author: fees: {}, fees_value: {}, author: {}", fees, fees_value, author); + flush(format!("exec::finalize: Compensating author: fees_value: {}, author: {}", fees_value, &self.info.author)); + self.state.add_balance(&self.info.author, &fees_value); // perform suicides for address in substate.suicides.iter() { - trace!("Killing {}", address); +// trace!("Killing {}", address); self.state.kill_account(address); } - let gas_used = t.gas - gas_left; - match result { Err(evm::Error::Internal) => Err(ExecutionError::Internal), - Ok(_) => { + _ => { Ok(Executed { gas: t.gas, gas_used: gas_used, - refunded: refund, + refunded: refunded, cumulative_gas_used: self.info.gas_used + gas_used, logs: substate.logs, - contracts_created: substate.contracts_created + contracts_created: substate.contracts_created, }) }, - _err => { - Ok(Executed { - gas: t.gas, - gas_used: t.gas, - refunded: U256::zero(), - cumulative_gas_used: self.info.gas_used + t.gas, - logs: vec![], - contracts_created: vec![] - }) - } } } diff --git a/src/externalities.rs b/src/externalities.rs index f5a72288a..28d27ffbc 100644 --- a/src/externalities.rs +++ b/src/externalities.rs @@ -60,15 +60,19 @@ impl<'a> Externalities<'a> { } impl<'a> Ext for Externalities<'a> { - fn sload(&self, key: &H256) -> H256 { + fn storage_at(&self, key: &H256) -> H256 { +// flush(format!("ext: storage_at({}, {}) == {}\n", self.params.address, key, U256::from(self.state.storage_at(&self.params.address, key).as_slice()))); self.state.storage_at(&self.params.address, key) } - fn sstore(&mut self, key: H256, value: H256) { + fn set_storage_at(&mut self, key: H256, value: H256) { + let old = self.state.storage_at(&self.params.address, &key); // if SSTORE nonzero -> zero, increment refund count - if value == H256::new() && self.state.storage_at(&self.params.address, &key) != H256::new() { + if value.is_zero() && !old.is_zero() { +// flush(format!("ext: additional refund. {} -> {}\n", self.substate.refunds_count, self.substate.refunds_count + x!(1))); self.substate.refunds_count = self.substate.refunds_count + U256::one(); } +// flush(format!("ext: set_storage_at({}, {}): {} -> {}\n", self.params.address, key, U256::from(old.as_slice()), U256::from(value.as_slice()))); self.state.set_storage(&self.params.address, key, value) } diff --git a/src/state.rs b/src/state.rs index 55a16b0ae..0c1a2e731 100644 --- a/src/state.rs +++ b/src/state.rs @@ -3,6 +3,7 @@ use engine::Engine; use executive::Executive; use pod_account::*; use pod_state::*; +use state_diff::*; pub type ApplyResult = Result; @@ -106,11 +107,13 @@ impl State { /// Add `incr` to the balance of account `a`. pub fn add_balance(&mut self, a: &Address, incr: &U256) { + flush(format!("state: add_balance({}, {})\n", a, incr)); self.require(a, false).add_balance(incr) } /// Subtract `decr` from the balance of account `a`. pub fn sub_balance(&mut self, a: &Address, decr: &U256) { + flush(format!("state: sub_balance({}, {})\n", a, decr)); self.require(a, false).sub_balance(decr) } @@ -139,8 +142,13 @@ impl State { /// Execute a given transaction. /// This will change the state accordingly. pub fn apply(&mut self, env_info: &EnvInfo, engine: &Engine, t: &Transaction) -> ApplyResult { + + let old = self.to_pod(); + let e = try!(Executive::new(self, env_info, engine).transact(t)); //println!("Executed: {:?}", e); + + flush(format!("Applied transaction. Diff:\n{}\n", StateDiff::diff_pod(&old, &self.to_pod()))); self.commit(); let receipt = Receipt::new(self.root().clone(), e.cumulative_gas_used, e.logs); debug!("Transaction receipt: {:?}", receipt); diff --git a/src/substate.rs b/src/substate.rs index f85427745..b227afacc 100644 --- a/src/substate.rs +++ b/src/substate.rs @@ -2,6 +2,7 @@ use common::*; /// State changes which should be applied in finalize, /// after transaction is fully executed. +#[derive(Debug)] pub struct Substate { /// Any accounts that have suicided. pub suicides: HashSet
, diff --git a/src/tests/executive.rs b/src/tests/executive.rs index 3e0eae4b5..8b53e65bb 100644 --- a/src/tests/executive.rs +++ b/src/tests/executive.rs @@ -57,12 +57,12 @@ impl<'a> TestExt<'a> { } impl<'a> Ext for TestExt<'a> { - fn sload(&self, key: &H256) -> H256 { - self.ext.sload(key) + fn storage_at(&self, key: &H256) -> H256 { + self.ext.storage_at(key) } - fn sstore(&mut self, key: H256, value: H256) { - self.ext.sstore(key, value) + fn set_storage_at(&mut self, key: H256, value: H256) { + self.ext.set_storage_at(key, value) } fn balance(&self, address: &Address) -> U256 {