Avoid schedule copying in nested call/create (#9190)

* Avoid schedule copying in nested call/create

* Fix tests

* fix test: wrong Schedule used

* Fix private-tx test

* Fix jsontests compilation
This commit is contained in:
Wei Tang 2018-07-23 21:48:01 +08:00 committed by Tomasz Drwięga
parent d4f38d3894
commit 4848c384cd
12 changed files with 117 additions and 67 deletions

View File

@ -435,7 +435,9 @@ impl Provider where {
let (new_address, _) = ethcore_contract_address(engine.create_address_scheme(env_info.number), &sender, &nonce, &transaction.data);
Some(new_address)
});
let result = Executive::new(&mut state, &env_info, engine.machine()).transact_virtual(transaction, options)?;
let machine = engine.machine();
let schedule = machine.schedule(env_info.number);
let result = Executive::new(&mut state, &env_info, &machine, &schedule).transact_virtual(transaction, options)?;
let (encrypted_code, encrypted_storage) = match contract_address {
None => bail!(ErrorKind::ContractDoesNotExist),
Some(address) => {

View File

@ -616,7 +616,9 @@ impl Importer {
).expect("state known to be available for just-imported block; qed");
let options = TransactOptions::with_no_tracing().dont_check_nonce();
let res = Executive::new(&mut state, &env_info, self.engine.machine())
let machine = self.engine.machine();
let schedule = machine.schedule(env_info.number);
let res = Executive::new(&mut state, &env_info, &machine, &schedule)
.transact(&transaction, options);
let res = match res {
@ -1232,8 +1234,9 @@ impl Client {
.dont_check_nonce()
.save_output_from_contract();
let original_state = if state_diff { Some(state.clone()) } else { None };
let schedule = machine.schedule(env_info.number);
let mut ret = Executive::new(state, env_info, machine).transact_virtual(transaction, options)?;
let mut ret = Executive::new(state, env_info, &machine, &schedule).transact_virtual(transaction, options)?;
if let Some(original) = original_state {
ret.state_diff = Some(state.diff_from(original).map_err(ExecutionError::from)?);
@ -1486,7 +1489,9 @@ impl Call for Client {
let tx = tx.fake_sign(sender);
let mut clone = state.clone();
Ok(Executive::new(&mut clone, &env_info, self.engine.machine())
let machine = self.engine.machine();
let schedule = machine.schedule(env_info.number);
Ok(Executive::new(&mut clone, &env_info, &machine, &schedule)
.transact_virtual(&tx, options())
.map(|r| r.exception.is_none())
.unwrap_or(false))

View File

@ -184,7 +184,9 @@ impl<'a> EvmTestClient<'a> {
};
let mut substate = state::Substate::new();
let mut output = vec![];
let mut executive = executive::Executive::new(&mut self.state, &info, self.spec.engine.machine());
let machine = self.spec.engine.machine();
let schedule = machine.schedule(info.number);
let mut executive = executive::Executive::new(&mut self.state, &info, &machine, &schedule);
executive.call(
params,
&mut substate,

View File

@ -21,11 +21,11 @@ use hash::keccak;
use ethereum_types::{H256, U256, U512, Address};
use bytes::{Bytes, BytesRef};
use state::{Backend as StateBackend, State, Substate, CleanupMode};
use machine::EthereumMachine as Machine;
use error::ExecutionError;
use machine::EthereumMachine as Machine;
use evm::{CallType, Finalize, FinalizationResult};
use vm::{
self, Ext, EnvInfo, CreateContractAddress, ReturnData, CleanDustMode, ActionParams,
self, EnvInfo, CreateContractAddress, ReturnData, CleanDustMode, ActionParams,
ActionValue, Schedule,
};
use externalities::*;
@ -167,28 +167,31 @@ pub struct Executive<'a, B: 'a> {
state: &'a mut State<B>,
info: &'a EnvInfo,
machine: &'a Machine,
schedule: &'a Schedule,
depth: usize,
static_flag: bool,
}
impl<'a, B: 'a + StateBackend> Executive<'a, B> {
/// Basic constructor.
pub fn new(state: &'a mut State<B>, info: &'a EnvInfo, machine: &'a Machine) -> Self {
pub fn new(state: &'a mut State<B>, info: &'a EnvInfo, machine: &'a Machine, schedule: &'a Schedule) -> Self {
Executive {
state: state,
info: info,
machine: machine,
schedule: schedule,
depth: 0,
static_flag: false,
}
}
/// Populates executive from parent properties. Increments executive depth.
pub fn from_parent(state: &'a mut State<B>, info: &'a EnvInfo, machine: &'a Machine, parent_depth: usize, static_flag: bool) -> Self {
pub fn from_parent(state: &'a mut State<B>, info: &'a EnvInfo, machine: &'a Machine, schedule: &'a Schedule, parent_depth: usize, static_flag: bool) -> Self {
Executive {
state: state,
info: info,
machine: machine,
schedule: schedule,
depth: parent_depth + 1,
static_flag: static_flag,
}
@ -205,7 +208,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
static_call: bool,
) -> Externalities<'any, T, V, B> where T: Tracer, V: VMTracer {
let is_static = self.static_flag || static_call;
Externalities::new(self.state, self.info, self.machine, self.depth, origin_info, substate, output, tracer, vm_tracer, is_static)
Externalities::new(self.state, self.info, self.machine, self.schedule, self.depth, origin_info, substate, output, tracer, vm_tracer, is_static)
}
/// This function should be used to execute transaction.
@ -244,7 +247,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
let sender = t.sender();
let nonce = self.state.nonce(&sender)?;
let schedule = self.machine.schedule(self.info.number);
let schedule = self.schedule;
let base_gas_required = U256::from(t.gas_required(&schedule));
if t.gas < base_gas_required {
@ -336,7 +339,6 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
fn exec_vm<T, V>(
&mut self,
schedule: Schedule,
params: ActionParams,
unconfirmed_substate: &mut Substate,
output_policy: OutputPolicy,
@ -350,19 +352,22 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
// Ordinary execution - keep VM in same thread
if self.depth != depth_threshold {
let vm_factory = self.state.vm_factory();
let wasm = self.schedule.wasm.is_some();
trace!(target: "executive", "ext.schedule.have_delegate_call: {}", self.schedule.have_delegate_call);
let mut ext = self.as_externalities(OriginInfo::from(&params), unconfirmed_substate, output_policy, tracer, vm_tracer, static_call);
trace!(target: "executive", "ext.schedule.have_delegate_call: {}", ext.schedule().have_delegate_call);
let mut vm = vm_factory.create(&params, &schedule);
let mut vm = vm_factory.create(&params, wasm);
return vm.exec(params, &mut ext).finalize(ext);
}
// Start in new thread with stack size needed up to max depth
crossbeam::scope(|scope| {
let vm_factory = self.state.vm_factory();
let max_depth = self.schedule.max_depth;
let wasm = self.schedule.wasm.is_some();
let mut ext = self.as_externalities(OriginInfo::from(&params), unconfirmed_substate, output_policy, tracer, vm_tracer, static_call);
scope.builder().stack_size(::std::cmp::max(schedule.max_depth.saturating_sub(depth_threshold) * STACK_SIZE_PER_DEPTH, local_stack_size)).spawn(move || {
let mut vm = vm_factory.create(&params, &schedule);
scope.builder().stack_size(::std::cmp::max(max_depth.saturating_sub(depth_threshold) * STACK_SIZE_PER_DEPTH, local_stack_size)).spawn(move || {
let mut vm = vm_factory.create(&params, wasm);
vm.exec(params, &mut ext).finalize(ext)
}).expect("Sub-thread creation cannot fail; the host might run out of resources; qed")
}).join()
@ -392,7 +397,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
// backup used in case of running out of gas
self.state.checkpoint();
let schedule = self.machine.schedule(self.info.number);
let schedule = self.schedule;
// at first, transfer value to destination
if let ActionValue::Transfer(val) = params.value {
@ -479,7 +484,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
let mut subvmtracer = vm_tracer.prepare_subtrace(params.code.as_ref().expect("scope is conditional on params.code.is_some(); qed"));
let res = {
self.exec_vm(schedule, params, &mut unconfirmed_substate, OutputPolicy::Return(output, trace_output.as_mut()), &mut subtracer, &mut subvmtracer)
self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::Return(output, trace_output.as_mut()), &mut subtracer, &mut subvmtracer)
};
vm_tracer.done_subtrace(subvmtracer);
@ -552,7 +557,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
let mut unconfirmed_substate = Substate::new();
// create contract and transfer value to it if necessary
let schedule = self.machine.schedule(self.info.number);
let schedule = self.schedule;
let nonce_offset = if schedule.no_empty {1} else {0}.into();
let prev_bal = self.state.balance(&params.address)?;
if let ActionValue::Transfer(val) = params.value {
@ -571,7 +576,6 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
let mut subvmtracer = vm_tracer.prepare_subtrace(params.code.as_ref().expect("two ways into create (Externalities::create and Executive::transact_with_tracer); both place `Some(...)` `code` in `params`; qed"));
let res = self.exec_vm(
schedule,
params,
&mut unconfirmed_substate,
OutputPolicy::InitContract(output.as_mut().or(trace_output.as_mut())),
@ -607,7 +611,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
trace: Vec<T>,
vm_trace: Option<V>
) -> Result<Executed<T, V>, ExecutionError> {
let schedule = self.machine.schedule(self.info.number);
let schedule = self.schedule;
// refunds from SSTORE nonzero -> zero
let sstore_refunds = U256::from(schedule.sstore_refund_gas) * substate.sstore_clears_count;
@ -756,10 +760,11 @@ mod tests {
state.add_balance(&sender, &U256::from(0x100u64), CleanupMode::NoEmpty).unwrap();
let info = EnvInfo::default();
let machine = make_frontier_machine(0);
let schedule = machine.schedule(info.number);
let mut substate = Substate::new();
let FinalizationResult { gas_left, .. } = {
let mut ex = Executive::new(&mut state, &info, &machine);
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap()
};
@ -813,10 +818,11 @@ mod tests {
state.add_balance(&sender, &U256::from(100), CleanupMode::NoEmpty).unwrap();
let info = EnvInfo::default();
let machine = make_frontier_machine(0);
let schedule = machine.schedule(info.number);
let mut substate = Substate::new();
let FinalizationResult { gas_left, .. } = {
let mut ex = Executive::new(&mut state, &info, &machine);
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap()
};
@ -855,11 +861,12 @@ mod tests {
state.add_balance(&sender, &U256::from(100), CleanupMode::NoEmpty).unwrap();
let info = EnvInfo::default();
let machine = make_byzantium_machine(5);
let schedule = machine.schedule(info.number);
let mut substate = Substate::new();
let mut tracer = ExecutiveTracer::default();
let mut vm_tracer = ExecutiveVMTracer::toplevel();
let mut ex = Executive::new(&mut state, &info, &machine);
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
let output = BytesRef::Fixed(&mut[0u8;0]);
ex.call(params, &mut substate, output, &mut tracer, &mut vm_tracer).unwrap();
@ -939,12 +946,13 @@ mod tests {
state.add_balance(&sender, &U256::from(100), CleanupMode::NoEmpty).unwrap();
let info = EnvInfo::default();
let machine = make_frontier_machine(5);
let schedule = machine.schedule(info.number);
let mut substate = Substate::new();
let mut tracer = ExecutiveTracer::default();
let mut vm_tracer = ExecutiveVMTracer::toplevel();
let FinalizationResult { gas_left, .. } = {
let mut ex = Executive::new(&mut state, &info, &machine);
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
let output = BytesRef::Fixed(&mut[0u8;0]);
ex.call(params, &mut substate, output, &mut tracer, &mut vm_tracer).unwrap()
};
@ -1055,12 +1063,13 @@ mod tests {
state.add_balance(&sender, &U256::from(100), CleanupMode::NoEmpty).unwrap();
let info = EnvInfo::default();
let machine = ::ethereum::new_byzantium_test_machine();
let schedule = machine.schedule(info.number);
let mut substate = Substate::new();
let mut tracer = ExecutiveTracer::default();
let mut vm_tracer = ExecutiveVMTracer::toplevel();
let FinalizationResult { gas_left, .. } = {
let mut ex = Executive::new(&mut state, &info, &machine);
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
let output = BytesRef::Fixed(&mut[0u8;0]);
ex.call(params, &mut substate, output, &mut tracer, &mut vm_tracer).unwrap()
};
@ -1127,12 +1136,13 @@ mod tests {
state.add_balance(&sender, &U256::from(100), CleanupMode::NoEmpty).unwrap();
let info = EnvInfo::default();
let machine = make_frontier_machine(5);
let schedule = machine.schedule(info.number);
let mut substate = Substate::new();
let mut tracer = ExecutiveTracer::default();
let mut vm_tracer = ExecutiveVMTracer::toplevel();
let FinalizationResult { gas_left, .. } = {
let mut ex = Executive::new(&mut state, &info, &machine);
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
ex.create(params.clone(), &mut substate, &mut None, &mut tracer, &mut vm_tracer).unwrap()
};
@ -1214,10 +1224,11 @@ mod tests {
state.add_balance(&sender, &U256::from(100), CleanupMode::NoEmpty).unwrap();
let info = EnvInfo::default();
let machine = make_frontier_machine(0);
let schedule = machine.schedule(info.number);
let mut substate = Substate::new();
let FinalizationResult { gas_left, .. } = {
let mut ex = Executive::new(&mut state, &info, &machine);
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap()
};
@ -1265,10 +1276,11 @@ mod tests {
state.add_balance(&sender, &U256::from(100), CleanupMode::NoEmpty).unwrap();
let info = EnvInfo::default();
let machine = make_frontier_machine(1024);
let schedule = machine.schedule(info.number);
let mut substate = Substate::new();
{
let mut ex = Executive::new(&mut state, &info, &machine);
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap();
}
@ -1325,10 +1337,11 @@ mod tests {
let info = EnvInfo::default();
let machine = make_frontier_machine(0);
let schedule = machine.schedule(info.number);
let mut substate = Substate::new();
let FinalizationResult { gas_left, .. } = {
let mut ex = Executive::new(&mut state, &info, &machine);
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
ex.call(params, &mut substate, BytesRef::Fixed(&mut []), &mut NoopTracer, &mut NoopVMTracer).unwrap()
};
@ -1369,10 +1382,11 @@ mod tests {
state.init_code(&address, code).unwrap();
let info = EnvInfo::default();
let machine = make_frontier_machine(0);
let schedule = machine.schedule(info.number);
let mut substate = Substate::new();
let FinalizationResult { gas_left, .. } = {
let mut ex = Executive::new(&mut state, &info, &machine);
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
ex.call(params, &mut substate, BytesRef::Fixed(&mut []), &mut NoopTracer, &mut NoopVMTracer).unwrap()
};
@ -1402,9 +1416,10 @@ mod tests {
let mut info = EnvInfo::default();
info.gas_limit = U256::from(100_000);
let machine = make_frontier_machine(0);
let schedule = machine.schedule(info.number);
let executed = {
let mut ex = Executive::new(&mut state, &info, &machine);
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
let opts = TransactOptions::with_no_tracing();
ex.transact(&t, opts).unwrap()
};
@ -1439,9 +1454,10 @@ mod tests {
let mut info = EnvInfo::default();
info.gas_limit = U256::from(100_000);
let machine = make_frontier_machine(0);
let schedule = machine.schedule(info.number);
let res = {
let mut ex = Executive::new(&mut state, &info, &machine);
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
let opts = TransactOptions::with_no_tracing();
ex.transact(&t, opts)
};
@ -1472,9 +1488,10 @@ mod tests {
info.gas_used = U256::from(20_000);
info.gas_limit = U256::from(100_000);
let machine = make_frontier_machine(0);
let schedule = machine.schedule(info.number);
let res = {
let mut ex = Executive::new(&mut state, &info, &machine);
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
let opts = TransactOptions::with_no_tracing();
ex.transact(&t, opts)
};
@ -1505,9 +1522,10 @@ mod tests {
let mut info = EnvInfo::default();
info.gas_limit = U256::from(100_000);
let machine = make_frontier_machine(0);
let schedule = machine.schedule(info.number);
let res = {
let mut ex = Executive::new(&mut state, &info, &machine);
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
let opts = TransactOptions::with_no_tracing();
ex.transact(&t, opts)
};
@ -1538,10 +1556,11 @@ mod tests {
state.add_balance(&sender, &U256::from_str("152d02c7e14af6800000").unwrap(), CleanupMode::NoEmpty).unwrap();
let info = EnvInfo::default();
let machine = make_frontier_machine(0);
let schedule = machine.schedule(info.number);
let mut substate = Substate::new();
let result = {
let mut ex = Executive::new(&mut state, &info, &machine);
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer)
};
@ -1571,11 +1590,12 @@ mod tests {
params.value = ActionValue::Transfer(U256::zero());
let info = EnvInfo::default();
let machine = ::ethereum::new_byzantium_test_machine();
let schedule = machine.schedule(info.number);
let mut substate = Substate::new();
let mut output = [0u8; 14];
let FinalizationResult { gas_left: result, .. } = {
let mut ex = Executive::new(&mut state, &info, &machine);
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
ex.call(params, &mut substate, BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer).unwrap()
};
@ -1618,7 +1638,8 @@ mod tests {
let mut output = [0u8; 20];
let FinalizationResult { gas_left: result, .. } = {
let mut ex = Executive::new(&mut state, &info, &machine);
let schedule = machine.schedule(info.number);
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
ex.call(params.clone(), &mut Substate::new(), BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer).unwrap()
};
@ -1631,7 +1652,8 @@ mod tests {
let mut output = [0u8; 20];
let FinalizationResult { gas_left: result, .. } = {
let mut ex = Executive::new(&mut state, &info, &machine);
let schedule = machine.schedule(info.number);
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
ex.call(params, &mut Substate::new(), BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer).unwrap()
};

View File

@ -66,11 +66,11 @@ impl OriginInfo {
pub struct Externalities<'a, T: 'a, V: 'a, B: 'a> {
state: &'a mut State<B>,
env_info: &'a EnvInfo,
machine: &'a Machine,
depth: usize,
origin_info: OriginInfo,
substate: &'a mut Substate,
schedule: Schedule,
machine: &'a Machine,
schedule: &'a Schedule,
output: OutputPolicy<'a, 'a>,
tracer: &'a mut T,
vm_tracer: &'a mut V,
@ -81,9 +81,11 @@ impl<'a, T: 'a, V: 'a, B: 'a> Externalities<'a, T, V, B>
where T: Tracer, V: VMTracer, B: StateBackend
{
/// Basic `Externalities` constructor.
pub fn new(state: &'a mut State<B>,
pub fn new(
state: &'a mut State<B>,
env_info: &'a EnvInfo,
machine: &'a Machine,
schedule: &'a Schedule,
depth: usize,
origin_info: OriginInfo,
substate: &'a mut Substate,
@ -95,11 +97,11 @@ impl<'a, T: 'a, V: 'a, B: 'a> Externalities<'a, T, V, B>
Externalities {
state: state,
env_info: env_info,
machine: machine,
depth: depth,
origin_info: origin_info,
substate: substate,
schedule: machine.schedule(env_info.number),
machine: machine,
schedule: schedule,
output: output,
tracer: tracer,
vm_tracer: vm_tracer,
@ -170,7 +172,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
};
let mut output = H256::new();
let mut ex = Executive::new(self.state, self.env_info, self.machine);
let mut ex = Executive::new(self.state, self.env_info, self.machine, self.schedule);
let r = ex.call(params, self.substate, BytesRef::Fixed(&mut output), self.tracer, self.vm_tracer);
trace!("ext: blockhash contract({}) -> {:?}({}) self.env_info.number={}\n", number, r, output, self.env_info.number);
output
@ -226,7 +228,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
}
}
}
let mut ex = Executive::from_parent(self.state, self.env_info, self.machine, self.depth, self.static_flag);
let mut ex = Executive::from_parent(self.state, self.env_info, self.machine, self.schedule, self.depth, self.static_flag);
// TODO: handle internal error separately
match ex.create(params, self.substate, &mut None, self.tracer, self.vm_tracer) {
@ -280,7 +282,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
params.value = ActionValue::Transfer(value);
}
let mut ex = Executive::from_parent(self.state, self.env_info, self.machine, self.depth, self.static_flag);
let mut ex = Executive::from_parent(self.state, self.env_info, self.machine, self.schedule, self.depth, self.static_flag);
match ex.call(params, self.substate, BytesRef::Fixed(output), self.tracer, self.vm_tracer) {
Ok(FinalizationResult{ gas_left, return_data, apply_state: true }) => MessageCallResult::Success(gas_left, return_data),
@ -440,6 +442,7 @@ mod tests {
struct TestSetup {
state: State<::state_db::StateDB>,
machine: ::machine::EthereumMachine,
schedule: Schedule,
sub_state: Substate,
env_info: EnvInfo
}
@ -452,11 +455,15 @@ mod tests {
impl TestSetup {
fn new() -> Self {
let machine = ::spec::Spec::new_test_machine();
let env_info = get_test_env_info();
let schedule = machine.schedule(env_info.number);
TestSetup {
state: get_temp_state(),
machine: ::spec::Spec::new_test_machine(),
schedule: schedule,
machine: machine,
sub_state: Substate::new(),
env_info: get_test_env_info()
env_info: env_info,
}
}
}
@ -468,7 +475,7 @@ mod tests {
let mut tracer = NoopTracer;
let mut vm_tracer = NoopVMTracer;
let ext = Externalities::new(state, &setup.env_info, &setup.machine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
let ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
assert_eq!(ext.env_info().number, 100);
}
@ -480,7 +487,7 @@ mod tests {
let mut tracer = NoopTracer;
let mut vm_tracer = NoopVMTracer;
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
let hash = ext.blockhash(&"0000000000000000000000000000000000000000000000000000000000120000".parse::<U256>().unwrap());
@ -504,7 +511,7 @@ mod tests {
let mut tracer = NoopTracer;
let mut vm_tracer = NoopVMTracer;
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
let hash = ext.blockhash(&"0000000000000000000000000000000000000000000000000000000000120000".parse::<U256>().unwrap());
@ -519,7 +526,7 @@ mod tests {
let mut tracer = NoopTracer;
let mut vm_tracer = NoopVMTracer;
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
let mut output = vec![];
@ -547,7 +554,7 @@ mod tests {
let mut vm_tracer = NoopVMTracer;
{
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
ext.log(log_topics, &log_data).unwrap();
}
@ -564,7 +571,7 @@ mod tests {
let mut vm_tracer = NoopVMTracer;
{
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
ext.suicide(refund_account).unwrap();
}

View File

@ -18,7 +18,7 @@ use trie::TrieFactory;
use ethtrie::RlpCodec;
use account_db::Factory as AccountFactory;
use evm::{Factory as EvmFactory, VMType};
use vm::{Vm, ActionParams, Schedule};
use vm::{Vm, ActionParams};
use wasm::WasmInterpreter;
use keccak_hasher::KeccakHasher;
@ -31,8 +31,8 @@ pub struct VmFactory {
}
impl VmFactory {
pub fn create(&self, params: &ActionParams, schedule: &Schedule) -> Box<Vm> {
if schedule.wasm.is_some() && params.code.as_ref().map_or(false, |code| code.len() > 4 && &code[0..4] == WASM_MAGIC_NUMBER) {
pub fn create(&self, params: &ActionParams, wasm: bool) -> Box<Vm> {
if wasm && params.code.as_ref().map_or(false, |code| code.len() > 4 && &code[0..4] == WASM_MAGIC_NUMBER) {
Box::new(WasmInterpreter)
} else {
self.evm.create(&params.gas)

View File

@ -86,6 +86,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> TestExt<'a, T, V, B>
state: &'a mut State<B>,
info: &'a EnvInfo,
machine: &'a Machine,
schedule: &'a Schedule,
depth: usize,
origin_info: OriginInfo,
substate: &'a mut Substate,
@ -97,7 +98,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> TestExt<'a, T, V, B>
let static_call = false;
Ok(TestExt {
nonce: state.nonce(&address)?,
ext: Externalities::new(state, info, machine, depth, origin_info, substate, output, tracer, vm_tracer, static_call),
ext: Externalities::new(state, info, machine, schedule, depth, origin_info, substate, output, tracer, vm_tracer, static_call),
callcreates: vec![],
sender: address,
})
@ -245,7 +246,7 @@ fn do_json_test_for<H: FnMut(&str, HookType)>(vm_type: &VMType, json_data: &[u8]
let out_of_gas = vm.out_of_gas();
let mut state = get_temp_state();
state.populate_from(From::from(vm.pre_state.clone()));
let info = From::from(vm.env);
let info: EnvInfo = From::from(vm.env);
let machine = {
let mut machine = ::ethereum::new_frontier_test_machine();
machine.set_schedule_creation_rules(Box::new(move |s, _| s.max_depth = 1));
@ -262,10 +263,12 @@ fn do_json_test_for<H: FnMut(&str, HookType)>(vm_type: &VMType, json_data: &[u8]
// execute
let (res, callcreates) = {
let schedule = machine.schedule(info.number);
let mut ex = try_fail!(TestExt::new(
&mut state,
&info,
&machine,
&schedule,
0,
OriginInfo::from(&params),
&mut substate,
@ -274,7 +277,7 @@ fn do_json_test_for<H: FnMut(&str, HookType)>(vm_type: &VMType, json_data: &[u8]
&mut tracer,
&mut vm_tracer,
));
let mut evm = vm_factory.create(&params, &machine.schedule(0u64.into()));
let mut evm = vm_factory.create(&params, schedule.wasm.is_some());
let res = evm.exec(params, &mut ex);
// a return in finalize will not alter callcreates
let callcreates = ex.callcreates.clone();

View File

@ -145,7 +145,8 @@ impl EthereumMachine {
call_type: CallType::Call,
params_type: ParamsType::Separate,
};
let mut ex = Executive::new(&mut state, &env_info, self);
let schedule = self.schedule(env_info.number);
let mut ex = Executive::new(&mut state, &env_info, self, &schedule);
let mut substate = Substate::new();
let mut output = Vec::new();
if let Err(e) = ex.call(params, &mut substate, BytesRef::Flexible(&mut output), &mut NoopTracer, &mut NoopVMTracer) {

View File

@ -631,7 +631,9 @@ impl Spec {
let mut substate = Substate::new();
{
let mut exec = Executive::new(&mut state, &env_info, self.engine.machine());
let machine = self.engine.machine();
let schedule = machine.schedule(env_info.number);
let mut exec = Executive::new(&mut state, &env_info, &machine, &schedule);
if let Err(e) = exec.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer) {
warn!(target: "spec", "Genesis constructor execution at {} failed: {}.", address, e);
}

View File

@ -745,7 +745,8 @@ impl<B: Backend> State<B> {
fn execute<T, V>(&mut self, env_info: &EnvInfo, machine: &Machine, t: &SignedTransaction, options: TransactOptions<T, V>, virt: bool)
-> Result<Executed<T::Output, V::Output>, ExecutionError> where T: trace::Tracer, V: trace::VMTracer,
{
let mut e = Executive::new(self, env_info, machine);
let schedule = machine.schedule(env_info.number);
let mut e = Executive::new(self, env_info, machine, &schedule);
match virt {
true => e.transact_virtual(t, options),

View File

@ -373,8 +373,11 @@ fn transaction_proof() {
factories.accountdb = ::account_db::Factory::Plain; // raw state values, no mangled keys.
let root = *client.best_block_header().state_root();
let machine = test_spec.engine.machine();
let env_info = client.latest_env_info();
let schedule = machine.schedule(env_info.number);
let mut state = State::from_existing(backend, root, 0.into(), factories.clone()).unwrap();
Executive::new(&mut state, &client.latest_env_info(), test_spec.engine.machine())
Executive::new(&mut state, &env_info, &machine, &schedule)
.transact(&transaction, TransactOptions::with_no_tracing().dont_check_nonce()).unwrap();
assert_eq!(state.balance(&Address::default()).unwrap(), 5.into());

View File

@ -62,7 +62,8 @@ fn test_blockhash_eip210(factory: Factory) {
call_type: CallType::Call,
params_type: ParamsType::Separate,
};
let mut ex = Executive::new(&mut state, &env_info, &machine);
let schedule = machine.schedule(env_info.number);
let mut ex = Executive::new(&mut state, &env_info, &machine, &schedule);
let mut substate = Substate::new();
let mut output = [];
if let Err(e) = ex.call(params, &mut substate, BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer) {
@ -85,7 +86,8 @@ fn test_blockhash_eip210(factory: Factory) {
call_type: CallType::Call,
params_type: ParamsType::Separate,
};
let mut ex = Executive::new(&mut state, &env_info, &machine);
let schedule = machine.schedule(env_info.number);
let mut ex = Executive::new(&mut state, &env_info, &machine, &schedule);
let mut substate = Substate::new();
let mut output = H256::new();
if let Err(e) = ex.call(params, &mut substate, BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer) {