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:
parent
d4f38d3894
commit
4848c384cd
@ -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) => {
|
||||
|
@ -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))
|
||||
|
@ -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,
|
||||
|
@ -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(¶ms), 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(¶ms, &schedule);
|
||||
let mut vm = vm_factory.create(¶ms, 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(¶ms), 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(¶ms, &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(¶ms, 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(¶ms.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()
|
||||
};
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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(¶ms.gas)
|
||||
|
@ -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(¶ms),
|
||||
&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(¶ms, &machine.schedule(0u64.into()));
|
||||
let mut evm = vm_factory.create(¶ms, schedule.wasm.is_some());
|
||||
let res = evm.exec(params, &mut ex);
|
||||
// a return in finalize will not alter callcreates
|
||||
let callcreates = ex.callcreates.clone();
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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());
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user