executive call
This commit is contained in:
parent
f7e9816d33
commit
3e90859d9d
@ -1,4 +1,5 @@
|
||||
use std::collections::HashSet;
|
||||
use std::cmp;
|
||||
use util::hash::*;
|
||||
use util::uint::*;
|
||||
use util::rlp::*;
|
||||
@ -26,7 +27,7 @@ pub struct Substate {
|
||||
/// Any logs.
|
||||
logs: Vec<LogEntry>,
|
||||
/// Refund counter of SSTORE nonzero->zero.
|
||||
refunds: U256,
|
||||
refunds_count: U256,
|
||||
}
|
||||
|
||||
impl Substate {
|
||||
@ -35,7 +36,7 @@ impl Substate {
|
||||
Substate {
|
||||
suicides: HashSet::new(),
|
||||
logs: vec![],
|
||||
refunds: U256::zero(),
|
||||
refunds_count: U256::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,7 +44,7 @@ impl Substate {
|
||||
fn accrue(&mut self, s: Substate) {
|
||||
self.suicides.extend(s.suicides.into_iter());
|
||||
self.logs.extend(s.logs.into_iter());
|
||||
self.refunds = self.refunds + s.refunds;
|
||||
self.refunds_count = self.refunds_count + s.refunds_count;
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,6 +55,7 @@ pub enum ExecutiveResult {
|
||||
InternalError
|
||||
}
|
||||
|
||||
/// Message-call/contract-creation executor; useful for executing transactions.
|
||||
pub struct Executive<'a> {
|
||||
state: &'a mut State,
|
||||
info: &'a EnvInfo,
|
||||
@ -61,7 +63,6 @@ pub struct Executive<'a> {
|
||||
depth: usize,
|
||||
}
|
||||
|
||||
/// Message-call/contract-creation executor; useful for executing transactions.
|
||||
impl<'a> Executive<'a> {
|
||||
/// Creates new executive with depth equal 0.
|
||||
pub fn new(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine) -> Self {
|
||||
@ -126,21 +127,58 @@ impl<'a> Executive<'a> {
|
||||
};
|
||||
|
||||
// finalize here!
|
||||
e.finalize(substate);
|
||||
e.finalize(substate, U256::zero(), U256::zero());
|
||||
res
|
||||
}
|
||||
|
||||
/// Calls contract function with given contract params.
|
||||
/// *Note. It does not finalize the transaction (doesn't do refund).
|
||||
fn call(_e: &mut Executive<'a>, _p: &EvmParams, _s: &mut Substate) -> ExecutiveResult {
|
||||
//let _ext = Externalities::from_executive(e, &p);
|
||||
/// *Note. It does not finalize the transaction (doesn't do refunds, nor suicides).
|
||||
fn call(e: &mut Executive<'a>, params: &EvmParams, substate: &mut Substate) -> ExecutiveResult {
|
||||
// at first, transfer value to destination
|
||||
e.state.transfer_balance(¶ms.sender, ¶ms.address, ¶ms.value);
|
||||
|
||||
// if destination is builtin, try to execute it, or quickly return
|
||||
if e.engine.is_builtin(¶ms.address) {
|
||||
return match e.engine.cost_of_builtin(¶ms.address, ¶ms.data) > params.gas {
|
||||
true => ExecutiveResult::OutOfGas,
|
||||
false => {
|
||||
// TODO: substract gas for execution
|
||||
let mut out = vec![];
|
||||
e.engine.execute_builtin(¶ms.address, ¶ms.data, &mut out);
|
||||
ExecutiveResult::Ok
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// otherwise do `normal` execution if destination is a contract
|
||||
// TODO: is executing contract with no code different from not executing contract at all?
|
||||
// if yes, there is a logic issue here. mk
|
||||
if params.code.len() > 0 {
|
||||
return match {
|
||||
let mut ext = Externalities::new(e.state, e.info, e.engine, e.depth, params, substate);
|
||||
let evm = VmFactory::create();
|
||||
evm.exec(¶ms, &mut ext)
|
||||
} {
|
||||
EvmResult::Stop => ExecutiveResult::Ok,
|
||||
EvmResult::Return(_) => ExecutiveResult::Ok,
|
||||
EvmResult::Suicide => {
|
||||
substate.suicides.insert(params.address.clone());
|
||||
ExecutiveResult::Ok
|
||||
},
|
||||
EvmResult::OutOfGas => ExecutiveResult::OutOfGas,
|
||||
_err => ExecutiveResult::InternalError
|
||||
}
|
||||
}
|
||||
|
||||
ExecutiveResult::Ok
|
||||
}
|
||||
|
||||
/// Creates contract with given contract params.
|
||||
/// *Note. It does not finalize the transaction (doesn't do refund).
|
||||
/// *Note. It does not finalize the transaction (doesn't do refunds, nor suicides).
|
||||
fn create(e: &mut Executive<'a>, params: &EvmParams, substate: &mut Substate) -> ExecutiveResult {
|
||||
// at first create new contract
|
||||
e.state.new_contract(¶ms.address);
|
||||
// then transfer value to it
|
||||
e.state.transfer_balance(¶ms.sender, ¶ms.address, ¶ms.value);
|
||||
|
||||
match {
|
||||
@ -156,6 +194,7 @@ impl<'a> Executive<'a> {
|
||||
ExecutiveResult::Ok
|
||||
},
|
||||
EvmResult::Suicide => {
|
||||
substate.suicides.insert(params.address.clone());
|
||||
ExecutiveResult::Ok
|
||||
},
|
||||
EvmResult::OutOfGas => ExecutiveResult::OutOfGas,
|
||||
@ -163,8 +202,19 @@ impl<'a> Executive<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Finalizes the transaction (does refunds).
|
||||
fn finalize(&self, _substate: Substate) {
|
||||
/// Finalizes the transaction (does refunds and suicides).
|
||||
fn finalize(&self, substate: Substate, gas: U256, gas_used: U256) {
|
||||
let schedule = self.engine.evm_schedule(self.info);
|
||||
|
||||
// refunds from SSTORE nonzero -> zero
|
||||
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
|
||||
let refund = cmp::min(sstore_refunds + suicide_refunds, (gas - gas_used) / U256::from(2));
|
||||
|
||||
// perform suicides
|
||||
//self.state.
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,12 +240,6 @@ impl<'a> Externalities<'a> {
|
||||
substate: substate
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: figure out how to use this function
|
||||
// so the lifetime checker is satisfied
|
||||
//pub fn from_executive(e: &mut Executive<'a>, params: &EvmParams, substate: &mut Substate) -> Self {
|
||||
//Externalities::new(e.state, e.info, e.engine, e.depth, params)
|
||||
//}
|
||||
}
|
||||
|
||||
impl<'a> Ext for Externalities<'a> {
|
||||
@ -205,8 +249,8 @@ impl<'a> Ext for Externalities<'a> {
|
||||
|
||||
fn sstore(&mut self, key: H256, value: H256) {
|
||||
if value == H256::new() && self.state.storage_at(&self.params.address, &key) != H256::new() {
|
||||
//self.substate.refunds = self.substate.refunds + U256::from(self.engine.evm_schedule(self.info).sstore_refund_gas);
|
||||
self.substate.refunds = self.substate.refunds + U256::one();
|
||||
//self.substate.refunds_count = self.substate.refunds_count + U256::from(self.engine.evm_schedule(self.info).sstore_refund_gas);
|
||||
self.substate.refunds_count = self.substate.refunds_count + U256::one();
|
||||
}
|
||||
self.state.set_storage(&self.params.address, key, value)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user