Resumable EVM and heap-allocated callstack (#9360)

* Add new Vm trappable interface

* Exec/Resume interface

* Basic implementation of CallCreateExecutive

* Implement resume_call and resume_create for executive

* Move convertion to call/create result to separate function

* Implement consume that converts resumable to non-resumable

* Use consume for Executive::call/create

* Resumable EVM

* Implement tracing mode without needing subtracers

* Implement vmtracer so it doesn't require extra structs for subtracing

* Use the new tracing mode in executive

* Fix most of the linting errors for cargo build

* Add the concept of stack_depth

* Add back crossbeam

* Fix some test compile

* Fix prefix address test

* Fix evm crate tests

* Fix wasm crate test compile

* Fix wasm runner compile

* Fix jsontests compile

* Fix evmbin compile

* Fix an issue with create nonce and better vm tracing interface

* Fix linting

* Fix evmbin compile

* Fix unconfirmed_substate and static_flag

* Fix an issue in create address logic

* Fix top-level tracing

* Handle builtin tracing

* Fix suicide and reward tracing index stack

* Fix an issue where trap conflicts with tracing

* Fix an issue in parent step vm tracing

* Fix revert tracing

* Fix evmbin tests

* Remove params clone

* Fix TODO proofs

* Fix jsontests compile

* Fix evmbin merge issue

* Fix wasm merge issue

* Fix wasm test

* Fix ethcore merge warnings

* Fix evmbin compile

* Better expect messages and add some trace::skip_one asserts
This commit is contained in:
Wei Tang
2018-10-02 22:33:19 +08:00
committed by GitHub
parent 61ec361182
commit 1e9aebbc86
24 changed files with 1465 additions and 804 deletions

View File

@@ -88,7 +88,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> TestExt<'a, T, V, B>
machine: &'a Machine,
schedule: &'a Schedule,
depth: usize,
origin_info: OriginInfo,
origin_info: &'a OriginInfo,
substate: &'a mut Substate,
output: OutputPolicy,
address: Address,
@@ -98,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, schedule, depth, origin_info, substate, output, tracer, vm_tracer, static_call),
ext: Externalities::new(state, info, machine, schedule, depth, 0, origin_info, substate, output, tracer, vm_tracer, static_call),
callcreates: vec![],
sender: address,
})
@@ -140,7 +140,14 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B>
self.ext.blockhash(number)
}
fn create(&mut self, gas: &U256, value: &U256, code: &[u8], address: CreateContractAddress) -> ContractCreateResult {
fn create(
&mut self,
gas: &U256,
value: &U256,
code: &[u8],
address: CreateContractAddress,
_trap: bool
) -> Result<ContractCreateResult, vm::TrapKind> {
self.callcreates.push(CallCreate {
data: code.to_vec(),
destination: None,
@@ -148,25 +155,27 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B>
value: *value
});
let contract_address = contract_address(address, &self.sender, &self.nonce, &code).0;
ContractCreateResult::Created(contract_address, *gas)
Ok(ContractCreateResult::Created(contract_address, *gas))
}
fn call(&mut self,
fn call(
&mut self,
gas: &U256,
_sender_address: &Address,
receive_address: &Address,
value: Option<U256>,
data: &[u8],
_code_address: &Address,
_call_type: CallType
) -> MessageCallResult {
_call_type: CallType,
_trap: bool
) -> Result<MessageCallResult, vm::TrapKind> {
self.callcreates.push(CallCreate {
data: data.to_vec(),
destination: Some(receive_address.clone()),
gas_limit: *gas,
value: value.unwrap()
});
MessageCallResult::Success(*gas, ReturnData::empty())
Ok(MessageCallResult::Success(*gas, ReturnData::empty()))
}
fn extcode(&self, address: &Address) -> vm::Result<Option<Arc<Bytes>>> {
@@ -270,6 +279,7 @@ fn do_json_test_for<H: FnMut(&str, HookType)>(vm_type: &VMType, json_data: &[u8]
let mut tracer = NoopTracer;
let mut vm_tracer = NoopVMTracer;
let vm_factory = state.vm_factory();
let origin_info = OriginInfo::from(&params);
// execute
let (res, callcreates) = {
@@ -280,7 +290,7 @@ fn do_json_test_for<H: FnMut(&str, HookType)>(vm_type: &VMType, json_data: &[u8]
&machine,
&schedule,
0,
OriginInfo::from(&params),
&origin_info,
&mut substate,
OutputPolicy::Return,
params.address.clone(),
@@ -288,7 +298,7 @@ fn do_json_test_for<H: FnMut(&str, HookType)>(vm_type: &VMType, json_data: &[u8]
&mut vm_tracer,
));
let mut evm = vm_factory.create(params, &schedule, 0);
let res = evm.exec(&mut ex);
let res = evm.exec(&mut ex).ok().expect("TestExt never trap; resume error never happens; qed");
// a return in finalize will not alter callcreates
let callcreates = ex.callcreates.clone();
(res.finalize(ex), callcreates)