reverting the execution state when out of gas
This commit is contained in:
parent
65bce7862a
commit
3f725ce89d
@ -65,8 +65,6 @@ pub struct Executed {
|
|||||||
///
|
///
|
||||||
/// where `tn` is current transaction.
|
/// where `tn` is current transaction.
|
||||||
pub cumulative_gas_used: U256,
|
pub cumulative_gas_used: U256,
|
||||||
/// Transaction output.
|
|
||||||
pub output: Bytes,
|
|
||||||
/// Vector of logs generated by transaction.
|
/// Vector of logs generated by transaction.
|
||||||
pub logs: Vec<LogEntry>
|
pub logs: Vec<LogEntry>
|
||||||
}
|
}
|
||||||
@ -78,7 +76,6 @@ impl Executed {
|
|||||||
gas_used: U256::zero(),
|
gas_used: U256::zero(),
|
||||||
refunded: U256::zero(),
|
refunded: U256::zero(),
|
||||||
cumulative_gas_used: U256::zero(),
|
cumulative_gas_used: U256::zero(),
|
||||||
output: vec![],
|
|
||||||
logs: vec![]
|
logs: vec![]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -168,6 +165,8 @@ impl<'a> Executive<'a> {
|
|||||||
self.state.inc_nonce(&sender);
|
self.state.inc_nonce(&sender);
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new();
|
||||||
|
|
||||||
|
let backup = self.state.clone();
|
||||||
|
|
||||||
let res = match t.action() {
|
let res = match t.action() {
|
||||||
&Action::Create => {
|
&Action::Create => {
|
||||||
let params = EvmParams {
|
let params = EvmParams {
|
||||||
@ -198,9 +197,7 @@ impl<'a> Executive<'a> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// finalize here!
|
// finalize here!
|
||||||
self.finalize(substate, &sender, U256::zero(), U256::zero(), t.gas_price);
|
self.finalize(t, substate, backup, res)
|
||||||
//res
|
|
||||||
Ok(Executed::new())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calls contract function with given contract params.
|
/// Calls contract function with given contract params.
|
||||||
@ -247,27 +244,41 @@ impl<'a> Executive<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Finalizes the transaction (does refunds and suicides).
|
/// Finalizes the transaction (does refunds and suicides).
|
||||||
fn finalize(&mut self, substate: Substate, sender: &Address, gas: U256, gas_left: U256, gas_price: U256) {
|
fn finalize(&mut self, t: &Transaction, substate: Substate, backup: State, result: EvmResult) -> ExecutionResult {
|
||||||
let schedule = self.engine.evm_schedule(self.info);
|
match result {
|
||||||
|
Err(EvmError::Internal) => Err(ExecutionError::Internal),
|
||||||
|
Err(EvmError::OutOfGas) => {
|
||||||
|
let executed = Executed::new();
|
||||||
|
*self.state = backup;
|
||||||
|
Ok(executed)
|
||||||
|
},
|
||||||
|
Ok(gas_left) => {
|
||||||
|
let executed = Executed::new();
|
||||||
|
|
||||||
// refunds from SSTORE nonzero -> zero
|
let schedule = self.engine.evm_schedule(self.info);
|
||||||
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());
|
|
||||||
|
|
||||||
// real ammount to refund
|
// refunds from SSTORE nonzero -> zero
|
||||||
let refund = cmp::min(sstore_refunds + suicide_refunds, (gas - gas_left) / U256::from(2)) + gas_left;
|
let sstore_refunds = U256::from(schedule.sstore_refund_gas) * substate.refunds_count;
|
||||||
let refund_value = refund * gas_price;
|
// refunds from contract suicides
|
||||||
self.state.add_balance(sender, &refund_value);
|
let suicide_refunds = U256::from(schedule.suicide_refund_gas) * U256::from(substate.suicides.len());
|
||||||
|
|
||||||
// fees earned by author
|
|
||||||
let fees = (gas - refund) * gas_price;
|
|
||||||
let author = &self.info.author;
|
|
||||||
self.state.add_balance(author, &fees);
|
|
||||||
|
|
||||||
// perform suicides
|
// real ammount to refund
|
||||||
for address in substate.suicides.iter() {
|
let refund = cmp::min(sstore_refunds + suicide_refunds, (t.gas - gas_left) / U256::from(2)) + gas_left;
|
||||||
self.state.kill_account(address);
|
let refund_value = refund * t.gas_price;
|
||||||
|
self.state.add_balance(&t.sender(), &refund_value);
|
||||||
|
|
||||||
|
// fees earned by author
|
||||||
|
let fees = (t.gas - refund) * t.gas_price;
|
||||||
|
let author = &self.info.author;
|
||||||
|
self.state.add_balance(author, &fees);
|
||||||
|
|
||||||
|
// perform suicides
|
||||||
|
for address in substate.suicides.iter() {
|
||||||
|
self.state.kill_account(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(executed)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -392,7 +403,7 @@ impl<'a> Ext for Externalities<'a> {
|
|||||||
return Err(EvmError::OutOfGas)
|
return Err(EvmError::OutOfGas)
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut gas = gas - gas_cost;
|
let gas = gas - gas_cost;
|
||||||
|
|
||||||
//println!("depth: {:?}", self.depth);
|
//println!("depth: {:?}", self.depth);
|
||||||
// if balance is insufficient or we are to deep, return
|
// if balance is insufficient or we are to deep, return
|
||||||
|
@ -6,6 +6,7 @@ use util::bytes::*;
|
|||||||
use evm_schedule::*;
|
use evm_schedule::*;
|
||||||
use evm::EvmError;
|
use evm::EvmError;
|
||||||
|
|
||||||
|
// TODO: replace all u64 with u256
|
||||||
pub trait Ext {
|
pub trait Ext {
|
||||||
/// Returns a value for given key.
|
/// Returns a value for given key.
|
||||||
fn sload(&self, key: &H256) -> H256;
|
fn sload(&self, key: &H256) -> H256;
|
||||||
|
@ -159,6 +159,10 @@ impl IntoJit<evmjit::RuntimeDataHandle> for RuntimeData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Externalities adapter. Maps callbacks from evmjit to externalities trait.
|
||||||
|
///
|
||||||
|
/// Evmjit doesn't have to know about children execution failures.
|
||||||
|
/// This adapter 'catches' them and moves upstream.
|
||||||
struct ExtAdapter<'a> {
|
struct ExtAdapter<'a> {
|
||||||
ext: &'a mut evm::Ext,
|
ext: &'a mut evm::Ext,
|
||||||
err: &'a mut Option<evm::EvmError>
|
err: &'a mut Option<evm::EvmError>
|
||||||
|
Loading…
Reference in New Issue
Block a user