Remove pass-by-reference return data value from executive (#9211)
* Remove pass-by-reference return data value from executive * Fix tests * Fix a missing test output * typo: wasm_activation_test * Tracing change in output * json_tests: fix compile * typo: 0..32 -> ..32 to keep it consistent with other occurance * Fix tests
This commit is contained in:
parent
9c595aff95
commit
ff716e7799
@ -45,7 +45,7 @@ impl Finalize for Result<GasLeft> {
|
|||||||
fn finalize<E: Ext>(self, ext: E) -> Result<FinalizationResult> {
|
fn finalize<E: Ext>(self, ext: E) -> Result<FinalizationResult> {
|
||||||
match self {
|
match self {
|
||||||
Ok(GasLeft::Known(gas_left)) => Ok(FinalizationResult { gas_left: gas_left, apply_state: true, return_data: ReturnData::empty() }),
|
Ok(GasLeft::Known(gas_left)) => Ok(FinalizationResult { gas_left: gas_left, apply_state: true, return_data: ReturnData::empty() }),
|
||||||
Ok(GasLeft::NeedsReturn {gas_left, data, apply_state}) => ext.ret(&gas_left, &data, apply_state).map(|gas_left| FinalizationResult {
|
Ok(GasLeft::NeedsReturn { gas_left, data, apply_state }) => ext.ret(&gas_left, &data, apply_state).map(|gas_left| FinalizationResult {
|
||||||
gas_left: gas_left,
|
gas_left: gas_left,
|
||||||
apply_state: apply_state,
|
apply_state: apply_state,
|
||||||
return_data: data,
|
return_data: data,
|
||||||
|
@ -523,20 +523,25 @@ impl<Cost: CostType> Interpreter<Cost> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let call_result = {
|
let call_result = {
|
||||||
// we need to write and read from memory in the same time
|
let input = self.mem.read_slice(in_off, in_size);
|
||||||
// and we don't want to copy
|
ext.call(&call_gas.as_u256(), sender_address, receive_address, value, input, &code_address, call_type)
|
||||||
let input = unsafe { ::std::mem::transmute(self.mem.read_slice(in_off, in_size)) };
|
|
||||||
let output = self.mem.writeable_slice(out_off, out_size);
|
|
||||||
ext.call(&call_gas.as_u256(), sender_address, receive_address, value, input, &code_address, output, call_type)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let output = self.mem.writeable_slice(out_off, out_size);
|
||||||
|
|
||||||
return match call_result {
|
return match call_result {
|
||||||
MessageCallResult::Success(gas_left, data) => {
|
MessageCallResult::Success(gas_left, data) => {
|
||||||
|
let len = cmp::min(output.len(), data.len());
|
||||||
|
(&mut output[..len]).copy_from_slice(&data[..len]);
|
||||||
|
|
||||||
self.stack.push(U256::one());
|
self.stack.push(U256::one());
|
||||||
self.return_data = data;
|
self.return_data = data;
|
||||||
Ok(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater than current one")))
|
Ok(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater than current one")))
|
||||||
},
|
},
|
||||||
MessageCallResult::Reverted(gas_left, data) => {
|
MessageCallResult::Reverted(gas_left, data) => {
|
||||||
|
let len = cmp::min(output.len(), data.len());
|
||||||
|
(&mut output[..len]).copy_from_slice(&data[..len]);
|
||||||
|
|
||||||
self.stack.push(U256::zero());
|
self.stack.push(U256::zero());
|
||||||
self.return_data = data;
|
self.return_data = data;
|
||||||
Ok(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater than current one")))
|
Ok(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater than current one")))
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use ethereum_types::{H256, U256, H160};
|
use ethereum_types::{H256, U256, H160};
|
||||||
use {factory, journaldb, trie, kvdb_memorydb, bytes};
|
use {factory, journaldb, trie, kvdb_memorydb};
|
||||||
use kvdb::{self, KeyValueDB};
|
use kvdb::{self, KeyValueDB};
|
||||||
use {state, state_db, client, executive, trace, transaction, db, spec, pod_state, log_entry, receipt};
|
use {state, state_db, client, executive, trace, transaction, db, spec, pod_state, log_entry, receipt};
|
||||||
use factory::Factories;
|
use factory::Factories;
|
||||||
@ -183,14 +183,12 @@ impl<'a> EvmTestClient<'a> {
|
|||||||
gas_limit: *genesis.gas_limit(),
|
gas_limit: *genesis.gas_limit(),
|
||||||
};
|
};
|
||||||
let mut substate = state::Substate::new();
|
let mut substate = state::Substate::new();
|
||||||
let mut output = vec![];
|
|
||||||
let machine = self.spec.engine.machine();
|
let machine = self.spec.engine.machine();
|
||||||
let schedule = machine.schedule(info.number);
|
let schedule = machine.schedule(info.number);
|
||||||
let mut executive = executive::Executive::new(&mut self.state, &info, &machine, &schedule);
|
let mut executive = executive::Executive::new(&mut self.state, &info, &machine, &schedule);
|
||||||
executive.call(
|
executive.call(
|
||||||
params,
|
params,
|
||||||
&mut substate,
|
&mut substate,
|
||||||
bytes::BytesRef::Flexible(&mut output),
|
|
||||||
tracer,
|
tracer,
|
||||||
vm_tracer,
|
vm_tracer,
|
||||||
).map_err(EvmTestError::Evm)
|
).map_err(EvmTestError::Evm)
|
||||||
|
@ -204,7 +204,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
|||||||
&'any mut self,
|
&'any mut self,
|
||||||
origin_info: OriginInfo,
|
origin_info: OriginInfo,
|
||||||
substate: &'any mut Substate,
|
substate: &'any mut Substate,
|
||||||
output: OutputPolicy<'any, 'any>,
|
output: OutputPolicy,
|
||||||
tracer: &'any mut T,
|
tracer: &'any mut T,
|
||||||
vm_tracer: &'any mut V,
|
vm_tracer: &'any mut V,
|
||||||
static_call: bool,
|
static_call: bool,
|
||||||
@ -312,8 +312,12 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
|||||||
call_type: CallType::None,
|
call_type: CallType::None,
|
||||||
params_type: vm::ParamsType::Embedded,
|
params_type: vm::ParamsType::Embedded,
|
||||||
};
|
};
|
||||||
let mut out = if output_from_create { Some(vec![]) } else { None };
|
let res = self.create(params, &mut substate, &mut tracer, &mut vm_tracer);
|
||||||
(self.create(params, &mut substate, &mut out, &mut tracer, &mut vm_tracer), out.unwrap_or_else(Vec::new))
|
let out = match &res {
|
||||||
|
Ok(res) if output_from_create => res.return_data.to_vec(),
|
||||||
|
_ => Vec::new(),
|
||||||
|
};
|
||||||
|
(res, out)
|
||||||
},
|
},
|
||||||
Action::Call(ref address) => {
|
Action::Call(ref address) => {
|
||||||
let params = ActionParams {
|
let params = ActionParams {
|
||||||
@ -330,8 +334,12 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
|||||||
call_type: CallType::Call,
|
call_type: CallType::Call,
|
||||||
params_type: vm::ParamsType::Separate,
|
params_type: vm::ParamsType::Separate,
|
||||||
};
|
};
|
||||||
let mut out = vec![];
|
let res = self.call(params, &mut substate, &mut tracer, &mut vm_tracer);
|
||||||
(self.call(params, &mut substate, BytesRef::Flexible(&mut out), &mut tracer, &mut vm_tracer), out)
|
let out = match &res {
|
||||||
|
Ok(res) => res.return_data.to_vec(),
|
||||||
|
_ => Vec::new(),
|
||||||
|
};
|
||||||
|
(res, out)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -382,7 +390,6 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
params: ActionParams,
|
params: ActionParams,
|
||||||
substate: &mut Substate,
|
substate: &mut Substate,
|
||||||
mut output: BytesRef,
|
|
||||||
tracer: &mut T,
|
tracer: &mut T,
|
||||||
vm_tracer: &mut V
|
vm_tracer: &mut V
|
||||||
) -> vm::Result<FinalizationResult> where T: Tracer, V: VMTracer {
|
) -> vm::Result<FinalizationResult> where T: Tracer, V: VMTracer {
|
||||||
@ -432,7 +439,6 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
|||||||
Err(evm_err)
|
Err(evm_err)
|
||||||
} else {
|
} else {
|
||||||
self.state.discard_checkpoint();
|
self.state.discard_checkpoint();
|
||||||
output.write(0, &builtin_out_buffer);
|
|
||||||
|
|
||||||
// Trace only top level calls and calls with balance transfer to builtins. The reason why we don't
|
// Trace only top level calls and calls with balance transfer to builtins. The reason why we don't
|
||||||
// trace all internal calls to builtin contracts is that memcpy (IDENTITY) is a heavily used
|
// trace all internal calls to builtin contracts is that memcpy (IDENTITY) is a heavily used
|
||||||
@ -444,7 +450,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
|||||||
if self.depth == 0 || is_transferred {
|
if self.depth == 0 || is_transferred {
|
||||||
let mut trace_output = tracer.prepare_trace_output();
|
let mut trace_output = tracer.prepare_trace_output();
|
||||||
if let Some(out) = trace_output.as_mut() {
|
if let Some(out) = trace_output.as_mut() {
|
||||||
*out = output.to_owned();
|
*out = builtin_out_buffer.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
tracer.trace_call(
|
tracer.trace_call(
|
||||||
@ -485,7 +491,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 mut subvmtracer = vm_tracer.prepare_subtrace(params.code.as_ref().expect("scope is conditional on params.code.is_some(); qed"));
|
||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::Return(output, trace_output.as_mut()), &mut subtracer, &mut subvmtracer)
|
self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::Return, &mut subtracer, &mut subvmtracer)
|
||||||
};
|
};
|
||||||
|
|
||||||
vm_tracer.done_subtrace(subvmtracer);
|
vm_tracer.done_subtrace(subvmtracer);
|
||||||
@ -494,12 +500,15 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
|||||||
|
|
||||||
let traces = subtracer.drain();
|
let traces = subtracer.drain();
|
||||||
match res {
|
match res {
|
||||||
Ok(ref res) if res.apply_state => tracer.trace_call(
|
Ok(ref res) if res.apply_state => {
|
||||||
|
trace_output.as_mut().map(|d| *d = res.return_data.to_vec());
|
||||||
|
tracer.trace_call(
|
||||||
trace_info,
|
trace_info,
|
||||||
gas - res.gas_left,
|
gas - res.gas_left,
|
||||||
trace_output,
|
trace_output,
|
||||||
traces
|
traces
|
||||||
),
|
);
|
||||||
|
},
|
||||||
Ok(_) => tracer.trace_failed_call(trace_info, traces, vm::Error::Reverted.into()),
|
Ok(_) => tracer.trace_failed_call(trace_info, traces, vm::Error::Reverted.into()),
|
||||||
Err(ref e) => tracer.trace_failed_call(trace_info, traces, e.into()),
|
Err(ref e) => tracer.trace_failed_call(trace_info, traces, e.into()),
|
||||||
};
|
};
|
||||||
@ -530,7 +539,6 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
params: ActionParams,
|
params: ActionParams,
|
||||||
substate: &mut Substate,
|
substate: &mut Substate,
|
||||||
output: &mut Option<Bytes>,
|
|
||||||
tracer: &mut T,
|
tracer: &mut T,
|
||||||
vm_tracer: &mut V,
|
vm_tracer: &mut V,
|
||||||
) -> vm::Result<FinalizationResult> where T: Tracer, V: VMTracer {
|
) -> vm::Result<FinalizationResult> where T: Tracer, V: VMTracer {
|
||||||
@ -579,7 +587,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
|||||||
let res = self.exec_vm(
|
let res = self.exec_vm(
|
||||||
params,
|
params,
|
||||||
&mut unconfirmed_substate,
|
&mut unconfirmed_substate,
|
||||||
OutputPolicy::InitContract(output.as_mut().or(trace_output.as_mut())),
|
OutputPolicy::InitContract,
|
||||||
&mut subtracer,
|
&mut subtracer,
|
||||||
&mut subvmtracer
|
&mut subvmtracer
|
||||||
);
|
);
|
||||||
@ -587,13 +595,16 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
|||||||
vm_tracer.done_subtrace(subvmtracer);
|
vm_tracer.done_subtrace(subvmtracer);
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
Ok(ref res) if res.apply_state => tracer.trace_create(
|
Ok(ref res) if res.apply_state => {
|
||||||
|
trace_output.as_mut().map(|trace| *trace = res.return_data.to_vec());
|
||||||
|
tracer.trace_create(
|
||||||
trace_info,
|
trace_info,
|
||||||
gas - res.gas_left,
|
gas - res.gas_left,
|
||||||
trace_output.map(|data| output.as_ref().map(|out| out.to_vec()).unwrap_or(data)),
|
trace_output,
|
||||||
created,
|
created,
|
||||||
subtracer.drain()
|
subtracer.drain()
|
||||||
),
|
);
|
||||||
|
}
|
||||||
Ok(_) => tracer.trace_failed_create(trace_info, subtracer.drain(), vm::Error::Reverted.into()),
|
Ok(_) => tracer.trace_failed_create(trace_info, subtracer.drain(), vm::Error::Reverted.into()),
|
||||||
Err(ref e) => tracer.trace_failed_create(trace_info, subtracer.drain(), e.into())
|
Err(ref e) => tracer.trace_failed_create(trace_info, subtracer.drain(), e.into())
|
||||||
};
|
};
|
||||||
@ -715,7 +726,6 @@ mod tests {
|
|||||||
use ethkey::{Generator, Random};
|
use ethkey::{Generator, Random};
|
||||||
use super::*;
|
use super::*;
|
||||||
use ethereum_types::{H256, U256, U512, Address};
|
use ethereum_types::{H256, U256, U512, Address};
|
||||||
use bytes::BytesRef;
|
|
||||||
use vm::{ActionParams, ActionValue, CallType, EnvInfo, CreateContractAddress};
|
use vm::{ActionParams, ActionValue, CallType, EnvInfo, CreateContractAddress};
|
||||||
use evm::{Factory, VMType};
|
use evm::{Factory, VMType};
|
||||||
use error::ExecutionError;
|
use error::ExecutionError;
|
||||||
@ -766,7 +776,7 @@ mod tests {
|
|||||||
|
|
||||||
let FinalizationResult { gas_left, .. } = {
|
let FinalizationResult { gas_left, .. } = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||||
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(79_975));
|
assert_eq!(gas_left, U256::from(79_975));
|
||||||
@ -824,7 +834,7 @@ mod tests {
|
|||||||
|
|
||||||
let FinalizationResult { gas_left, .. } = {
|
let FinalizationResult { gas_left, .. } = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||||
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(62_976));
|
assert_eq!(gas_left, U256::from(62_976));
|
||||||
@ -868,8 +878,7 @@ mod tests {
|
|||||||
let mut vm_tracer = ExecutiveVMTracer::toplevel();
|
let mut vm_tracer = ExecutiveVMTracer::toplevel();
|
||||||
|
|
||||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||||
let output = BytesRef::Fixed(&mut[0u8;0]);
|
ex.call(params, &mut substate, &mut tracer, &mut vm_tracer).unwrap();
|
||||||
ex.call(params, &mut substate, output, &mut tracer, &mut vm_tracer).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(tracer.drain(), vec![FlatTrace {
|
assert_eq!(tracer.drain(), vec![FlatTrace {
|
||||||
action: trace::Action::Call(trace::Call {
|
action: trace::Action::Call(trace::Call {
|
||||||
@ -896,7 +905,7 @@ mod tests {
|
|||||||
call_type: CallType::Call
|
call_type: CallType::Call
|
||||||
}), result: trace::Res::Call(trace::CallResult {
|
}), result: trace::Res::Call(trace::CallResult {
|
||||||
gas_used: 600.into(),
|
gas_used: 600.into(),
|
||||||
output: vec![]
|
output: vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 17, 133, 165, 197, 233, 252, 84, 97, 40, 8, 151, 126, 232, 245, 72, 178, 37, 141, 49]
|
||||||
}),
|
}),
|
||||||
subtraces: 0,
|
subtraces: 0,
|
||||||
trace_address: vec![0].into_iter().collect(),
|
trace_address: vec![0].into_iter().collect(),
|
||||||
@ -954,8 +963,7 @@ mod tests {
|
|||||||
|
|
||||||
let FinalizationResult { gas_left, .. } = {
|
let FinalizationResult { gas_left, .. } = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||||
let output = BytesRef::Fixed(&mut[0u8;0]);
|
ex.call(params, &mut substate, &mut tracer, &mut vm_tracer).unwrap()
|
||||||
ex.call(params, &mut substate, output, &mut tracer, &mut vm_tracer).unwrap()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(44_752));
|
assert_eq!(gas_left, U256::from(44_752));
|
||||||
@ -1071,8 +1079,7 @@ mod tests {
|
|||||||
|
|
||||||
let FinalizationResult { gas_left, .. } = {
|
let FinalizationResult { gas_left, .. } = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||||
let output = BytesRef::Fixed(&mut[0u8;0]);
|
ex.call(params, &mut substate, &mut tracer, &mut vm_tracer).unwrap()
|
||||||
ex.call(params, &mut substate, output, &mut tracer, &mut vm_tracer).unwrap()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(62967));
|
assert_eq!(gas_left, U256::from(62967));
|
||||||
@ -1144,7 +1151,7 @@ mod tests {
|
|||||||
|
|
||||||
let FinalizationResult { gas_left, .. } = {
|
let FinalizationResult { gas_left, .. } = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||||
ex.create(params.clone(), &mut substate, &mut None, &mut tracer, &mut vm_tracer).unwrap()
|
ex.create(params.clone(), &mut substate, &mut tracer, &mut vm_tracer).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(96_776));
|
assert_eq!(gas_left, U256::from(96_776));
|
||||||
@ -1230,7 +1237,7 @@ mod tests {
|
|||||||
|
|
||||||
let FinalizationResult { gas_left, .. } = {
|
let FinalizationResult { gas_left, .. } = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||||
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(62_976));
|
assert_eq!(gas_left, U256::from(62_976));
|
||||||
@ -1282,7 +1289,7 @@ mod tests {
|
|||||||
|
|
||||||
{
|
{
|
||||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||||
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap();
|
ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(substate.contracts_created.len(), 1);
|
assert_eq!(substate.contracts_created.len(), 1);
|
||||||
@ -1343,7 +1350,7 @@ mod tests {
|
|||||||
|
|
||||||
let FinalizationResult { gas_left, .. } = {
|
let FinalizationResult { gas_left, .. } = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||||
ex.call(params, &mut substate, BytesRef::Fixed(&mut []), &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
ex.call(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(73_237));
|
assert_eq!(gas_left, U256::from(73_237));
|
||||||
@ -1388,7 +1395,7 @@ mod tests {
|
|||||||
|
|
||||||
let FinalizationResult { gas_left, .. } = {
|
let FinalizationResult { gas_left, .. } = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||||
ex.call(params, &mut substate, BytesRef::Fixed(&mut []), &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
ex.call(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(gas_left, U256::from(59_870));
|
assert_eq!(gas_left, U256::from(59_870));
|
||||||
@ -1562,7 +1569,7 @@ mod tests {
|
|||||||
|
|
||||||
let result = {
|
let result = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||||
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer)
|
ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer)
|
||||||
};
|
};
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
@ -1595,10 +1602,11 @@ mod tests {
|
|||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new();
|
||||||
|
|
||||||
let mut output = [0u8; 14];
|
let mut output = [0u8; 14];
|
||||||
let FinalizationResult { gas_left: result, .. } = {
|
let FinalizationResult { gas_left: result, return_data, .. } = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||||
ex.call(params, &mut substate, BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
ex.call(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
||||||
};
|
};
|
||||||
|
(&mut output).copy_from_slice(&return_data[..(cmp::min(14, return_data.len()))]);
|
||||||
|
|
||||||
assert_eq!(result, U256::from(1));
|
assert_eq!(result, U256::from(1));
|
||||||
assert_eq!(output[..], returns[..]);
|
assert_eq!(output[..], returns[..]);
|
||||||
@ -1638,11 +1646,12 @@ mod tests {
|
|||||||
let machine = ::ethereum::new_kovan_wasm_test_machine();
|
let machine = ::ethereum::new_kovan_wasm_test_machine();
|
||||||
|
|
||||||
let mut output = [0u8; 20];
|
let mut output = [0u8; 20];
|
||||||
let FinalizationResult { gas_left: result, .. } = {
|
let FinalizationResult { gas_left: result, return_data, .. } = {
|
||||||
let schedule = machine.schedule(info.number);
|
let schedule = machine.schedule(info.number);
|
||||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
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()
|
ex.call(params.clone(), &mut Substate::new(), &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
||||||
};
|
};
|
||||||
|
(&mut output).copy_from_slice(&return_data[..(cmp::min(20, return_data.len()))]);
|
||||||
|
|
||||||
assert_eq!(result, U256::from(18433));
|
assert_eq!(result, U256::from(18433));
|
||||||
// Transaction successfully returned sender
|
// Transaction successfully returned sender
|
||||||
@ -1652,11 +1661,12 @@ mod tests {
|
|||||||
info.number = 1;
|
info.number = 1;
|
||||||
|
|
||||||
let mut output = [0u8; 20];
|
let mut output = [0u8; 20];
|
||||||
let FinalizationResult { gas_left: result, .. } = {
|
let FinalizationResult { gas_left: result, return_data, .. } = {
|
||||||
let schedule = machine.schedule(info.number);
|
let schedule = machine.schedule(info.number);
|
||||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
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()
|
ex.call(params, &mut Substate::new(), &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
||||||
};
|
};
|
||||||
|
(&mut output[..((cmp::min(20, return_data.len())))]).copy_from_slice(&return_data[..(cmp::min(20, return_data.len()))]);
|
||||||
|
|
||||||
assert_eq!(result, U256::from(20025));
|
assert_eq!(result, U256::from(20025));
|
||||||
// Since transaction errored due to wasm was not activated, result is just empty
|
// Since transaction errored due to wasm was not activated, result is just empty
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use ethereum_types::{H256, U256, Address};
|
use ethereum_types::{H256, U256, Address};
|
||||||
use bytes::{Bytes, BytesRef};
|
use bytes::Bytes;
|
||||||
use state::{Backend as StateBackend, State, Substate, CleanupMode};
|
use state::{Backend as StateBackend, State, Substate, CleanupMode};
|
||||||
use machine::EthereumMachine as Machine;
|
use machine::EthereumMachine as Machine;
|
||||||
use executive::*;
|
use executive::*;
|
||||||
@ -32,12 +32,12 @@ use transaction::UNSIGNED_SENDER;
|
|||||||
use trace::{Tracer, VMTracer};
|
use trace::{Tracer, VMTracer};
|
||||||
|
|
||||||
/// Policy for handling output data on `RETURN` opcode.
|
/// Policy for handling output data on `RETURN` opcode.
|
||||||
pub enum OutputPolicy<'a, 'b> {
|
pub enum OutputPolicy {
|
||||||
/// Return reference to fixed sized output.
|
/// Return reference to fixed sized output.
|
||||||
/// Used for message calls.
|
/// Used for message calls.
|
||||||
Return(BytesRef<'a>, Option<&'b mut Bytes>),
|
Return,
|
||||||
/// Init new contract as soon as `RETURN` is called.
|
/// Init new contract as soon as `RETURN` is called.
|
||||||
InitContract(Option<&'b mut Bytes>),
|
InitContract,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transaction properties that externalities need to know about.
|
/// Transaction properties that externalities need to know about.
|
||||||
@ -71,7 +71,7 @@ pub struct Externalities<'a, T: 'a, V: 'a, B: 'a> {
|
|||||||
substate: &'a mut Substate,
|
substate: &'a mut Substate,
|
||||||
machine: &'a Machine,
|
machine: &'a Machine,
|
||||||
schedule: &'a Schedule,
|
schedule: &'a Schedule,
|
||||||
output: OutputPolicy<'a, 'a>,
|
output: OutputPolicy,
|
||||||
tracer: &'a mut T,
|
tracer: &'a mut T,
|
||||||
vm_tracer: &'a mut V,
|
vm_tracer: &'a mut V,
|
||||||
static_flag: bool,
|
static_flag: bool,
|
||||||
@ -89,7 +89,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Externalities<'a, T, V, B>
|
|||||||
depth: usize,
|
depth: usize,
|
||||||
origin_info: OriginInfo,
|
origin_info: OriginInfo,
|
||||||
substate: &'a mut Substate,
|
substate: &'a mut Substate,
|
||||||
output: OutputPolicy<'a, 'a>,
|
output: OutputPolicy,
|
||||||
tracer: &'a mut T,
|
tracer: &'a mut T,
|
||||||
vm_tracer: &'a mut V,
|
vm_tracer: &'a mut V,
|
||||||
static_flag: bool,
|
static_flag: bool,
|
||||||
@ -171,9 +171,12 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
|||||||
params_type: vm::ParamsType::Separate,
|
params_type: vm::ParamsType::Separate,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut output = H256::new();
|
|
||||||
let mut ex = Executive::new(self.state, self.env_info, self.machine, self.schedule);
|
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);
|
let r = ex.call(params, self.substate, self.tracer, self.vm_tracer);
|
||||||
|
let output = match &r {
|
||||||
|
Ok(ref r) => H256::from(&r.return_data[..32]),
|
||||||
|
_ => H256::new(),
|
||||||
|
};
|
||||||
trace!("ext: blockhash contract({}) -> {:?}({}) self.env_info.number={}\n", number, r, output, self.env_info.number);
|
trace!("ext: blockhash contract({}) -> {:?}({}) self.env_info.number={}\n", number, r, output, self.env_info.number);
|
||||||
output
|
output
|
||||||
} else {
|
} else {
|
||||||
@ -194,7 +197,13 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create(&mut self, gas: &U256, value: &U256, code: &[u8], address_scheme: CreateContractAddress) -> ContractCreateResult {
|
fn create(
|
||||||
|
&mut self,
|
||||||
|
gas: &U256,
|
||||||
|
value: &U256,
|
||||||
|
code: &[u8],
|
||||||
|
address_scheme: CreateContractAddress
|
||||||
|
) -> ContractCreateResult {
|
||||||
// create new contract address
|
// create new contract address
|
||||||
let (address, code_hash) = match self.state.nonce(&self.origin_info.address) {
|
let (address, code_hash) = match self.state.nonce(&self.origin_info.address) {
|
||||||
Ok(nonce) => contract_address(address_scheme, &self.origin_info.address, &nonce, &code),
|
Ok(nonce) => contract_address(address_scheme, &self.origin_info.address, &nonce, &code),
|
||||||
@ -231,7 +240,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.schedule, 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
|
// TODO: handle internal error separately
|
||||||
match ex.create(params, self.substate, &mut None, self.tracer, self.vm_tracer) {
|
match ex.create(params, self.substate, self.tracer, self.vm_tracer) {
|
||||||
Ok(FinalizationResult{ gas_left, apply_state: true, .. }) => {
|
Ok(FinalizationResult{ gas_left, apply_state: true, .. }) => {
|
||||||
self.substate.contracts_created.push(address.clone());
|
self.substate.contracts_created.push(address.clone());
|
||||||
ContractCreateResult::Created(address, gas_left)
|
ContractCreateResult::Created(address, gas_left)
|
||||||
@ -243,14 +252,14 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self,
|
fn call(
|
||||||
|
&mut self,
|
||||||
gas: &U256,
|
gas: &U256,
|
||||||
sender_address: &Address,
|
sender_address: &Address,
|
||||||
receive_address: &Address,
|
receive_address: &Address,
|
||||||
value: Option<U256>,
|
value: Option<U256>,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
code_address: &Address,
|
code_address: &Address,
|
||||||
output: &mut [u8],
|
|
||||||
call_type: CallType
|
call_type: CallType
|
||||||
) -> MessageCallResult {
|
) -> MessageCallResult {
|
||||||
trace!(target: "externalities", "call");
|
trace!(target: "externalities", "call");
|
||||||
@ -284,7 +293,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.schedule, 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) {
|
match ex.call(params, self.substate, self.tracer, self.vm_tracer) {
|
||||||
Ok(FinalizationResult{ gas_left, return_data, apply_state: true }) => MessageCallResult::Success(gas_left, return_data),
|
Ok(FinalizationResult{ gas_left, return_data, apply_state: true }) => MessageCallResult::Success(gas_left, return_data),
|
||||||
Ok(FinalizationResult{ gas_left, return_data, apply_state: false }) => MessageCallResult::Reverted(gas_left, return_data),
|
Ok(FinalizationResult{ gas_left, return_data, apply_state: false }) => MessageCallResult::Reverted(gas_left, return_data),
|
||||||
_ => MessageCallResult::Failed
|
_ => MessageCallResult::Failed
|
||||||
@ -303,27 +312,13 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
|||||||
Ok(self.state.code_size(address)?)
|
Ok(self.state.code_size(address)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ret(mut self, gas: &U256, data: &ReturnData, apply_state: bool) -> vm::Result<U256>
|
fn ret(self, gas: &U256, data: &ReturnData, apply_state: bool) -> vm::Result<U256>
|
||||||
where Self: Sized {
|
where Self: Sized {
|
||||||
let handle_copy = |to: &mut Option<&mut Bytes>| {
|
|
||||||
to.as_mut().map(|b| **b = data.to_vec());
|
|
||||||
};
|
|
||||||
match self.output {
|
match self.output {
|
||||||
OutputPolicy::Return(BytesRef::Fixed(ref mut slice), ref mut copy) => {
|
OutputPolicy::Return => {
|
||||||
handle_copy(copy);
|
|
||||||
|
|
||||||
let len = cmp::min(slice.len(), data.len());
|
|
||||||
(&mut slice[..len]).copy_from_slice(&data[..len]);
|
|
||||||
Ok(*gas)
|
Ok(*gas)
|
||||||
},
|
},
|
||||||
OutputPolicy::Return(BytesRef::Flexible(ref mut vec), ref mut copy) => {
|
OutputPolicy::InitContract if apply_state => {
|
||||||
handle_copy(copy);
|
|
||||||
|
|
||||||
vec.clear();
|
|
||||||
vec.extend_from_slice(&*data);
|
|
||||||
Ok(*gas)
|
|
||||||
},
|
|
||||||
OutputPolicy::InitContract(ref mut copy) if apply_state => {
|
|
||||||
let return_cost = U256::from(data.len()) * U256::from(self.schedule.create_data_gas);
|
let return_cost = U256::from(data.len()) * U256::from(self.schedule.create_data_gas);
|
||||||
if return_cost > *gas || data.len() > self.schedule.create_data_limit {
|
if return_cost > *gas || data.len() > self.schedule.create_data_limit {
|
||||||
return match self.schedule.exceptional_failed_code_deposit {
|
return match self.schedule.exceptional_failed_code_deposit {
|
||||||
@ -331,11 +326,10 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
|||||||
false => Ok(*gas)
|
false => Ok(*gas)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
handle_copy(copy);
|
|
||||||
self.state.init_code(&self.origin_info.address, data.to_vec())?;
|
self.state.init_code(&self.origin_info.address, data.to_vec())?;
|
||||||
Ok(*gas - return_cost)
|
Ok(*gas - return_cost)
|
||||||
},
|
},
|
||||||
OutputPolicy::InitContract(_) => {
|
OutputPolicy::InitContract => {
|
||||||
Ok(*gas)
|
Ok(*gas)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -479,7 +473,7 @@ mod tests {
|
|||||||
let mut tracer = NoopTracer;
|
let mut tracer = NoopTracer;
|
||||||
let mut vm_tracer = NoopVMTracer;
|
let mut vm_tracer = NoopVMTracer;
|
||||||
|
|
||||||
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);
|
let ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||||
|
|
||||||
assert_eq!(ext.env_info().number, 100);
|
assert_eq!(ext.env_info().number, 100);
|
||||||
}
|
}
|
||||||
@ -491,7 +485,7 @@ mod tests {
|
|||||||
let mut tracer = NoopTracer;
|
let mut tracer = NoopTracer;
|
||||||
let mut vm_tracer = NoopVMTracer;
|
let mut vm_tracer = NoopVMTracer;
|
||||||
|
|
||||||
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 ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||||
|
|
||||||
let hash = ext.blockhash(&"0000000000000000000000000000000000000000000000000000000000120000".parse::<U256>().unwrap());
|
let hash = ext.blockhash(&"0000000000000000000000000000000000000000000000000000000000120000".parse::<U256>().unwrap());
|
||||||
|
|
||||||
@ -515,7 +509,7 @@ mod tests {
|
|||||||
let mut tracer = NoopTracer;
|
let mut tracer = NoopTracer;
|
||||||
let mut vm_tracer = NoopVMTracer;
|
let mut vm_tracer = NoopVMTracer;
|
||||||
|
|
||||||
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 ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||||
|
|
||||||
let hash = ext.blockhash(&"0000000000000000000000000000000000000000000000000000000000120000".parse::<U256>().unwrap());
|
let hash = ext.blockhash(&"0000000000000000000000000000000000000000000000000000000000120000".parse::<U256>().unwrap());
|
||||||
|
|
||||||
@ -530,9 +524,7 @@ mod tests {
|
|||||||
let mut tracer = NoopTracer;
|
let mut tracer = NoopTracer;
|
||||||
let mut vm_tracer = NoopVMTracer;
|
let mut vm_tracer = NoopVMTracer;
|
||||||
|
|
||||||
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 ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||||
|
|
||||||
let mut output = vec![];
|
|
||||||
|
|
||||||
// this should panic because we have no balance on any account
|
// this should panic because we have no balance on any account
|
||||||
ext.call(
|
ext.call(
|
||||||
@ -542,7 +534,6 @@ mod tests {
|
|||||||
Some("0000000000000000000000000000000000000000000000000000000000150000".parse::<U256>().unwrap()),
|
Some("0000000000000000000000000000000000000000000000000000000000150000".parse::<U256>().unwrap()),
|
||||||
&[],
|
&[],
|
||||||
&Address::new(),
|
&Address::new(),
|
||||||
&mut output,
|
|
||||||
CallType::Call
|
CallType::Call
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -558,7 +549,7 @@ mod tests {
|
|||||||
let mut vm_tracer = NoopVMTracer;
|
let mut vm_tracer = NoopVMTracer;
|
||||||
|
|
||||||
{
|
{
|
||||||
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 ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||||
ext.log(log_topics, &log_data).unwrap();
|
ext.log(log_topics, &log_data).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -575,7 +566,7 @@ mod tests {
|
|||||||
let mut vm_tracer = NoopVMTracer;
|
let mut vm_tracer = NoopVMTracer;
|
||||||
|
|
||||||
{
|
{
|
||||||
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 ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||||
ext.suicide(refund_account).unwrap();
|
ext.suicide(refund_account).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -592,7 +583,7 @@ mod tests {
|
|||||||
let mut vm_tracer = NoopVMTracer;
|
let mut vm_tracer = NoopVMTracer;
|
||||||
|
|
||||||
let address = {
|
let address = {
|
||||||
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 ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||||
match ext.create(&U256::max_value(), &U256::zero(), &[], CreateContractAddress::FromSenderAndNonce) {
|
match ext.create(&U256::max_value(), &U256::zero(), &[], CreateContractAddress::FromSenderAndNonce) {
|
||||||
ContractCreateResult::Created(address, _) => address,
|
ContractCreateResult::Created(address, _) => address,
|
||||||
_ => panic!("Test create failed; expected Created, got Failed/Reverted."),
|
_ => panic!("Test create failed; expected Created, got Failed/Reverted."),
|
||||||
@ -612,7 +603,7 @@ mod tests {
|
|||||||
let mut vm_tracer = NoopVMTracer;
|
let mut vm_tracer = NoopVMTracer;
|
||||||
|
|
||||||
let address = {
|
let address = {
|
||||||
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 ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||||
|
|
||||||
match ext.create(&U256::max_value(), &U256::zero(), &[], CreateContractAddress::FromSenderSaltAndCodeHash(H256::default())) {
|
match ext.create(&U256::max_value(), &U256::zero(), &[], CreateContractAddress::FromSenderSaltAndCodeHash(H256::default())) {
|
||||||
ContractCreateResult::Created(address, _) => address,
|
ContractCreateResult::Created(address, _) => address,
|
||||||
|
@ -30,7 +30,7 @@ use test_helpers::get_temp_state;
|
|||||||
use ethjson;
|
use ethjson;
|
||||||
use trace::{Tracer, NoopTracer};
|
use trace::{Tracer, NoopTracer};
|
||||||
use trace::{VMTracer, NoopVMTracer};
|
use trace::{VMTracer, NoopVMTracer};
|
||||||
use bytes::{Bytes, BytesRef};
|
use bytes::Bytes;
|
||||||
use ethtrie;
|
use ethtrie;
|
||||||
use rlp::RlpStream;
|
use rlp::RlpStream;
|
||||||
use hash::keccak;
|
use hash::keccak;
|
||||||
@ -90,7 +90,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> TestExt<'a, T, V, B>
|
|||||||
depth: usize,
|
depth: usize,
|
||||||
origin_info: OriginInfo,
|
origin_info: OriginInfo,
|
||||||
substate: &'a mut Substate,
|
substate: &'a mut Substate,
|
||||||
output: OutputPolicy<'a, 'a>,
|
output: OutputPolicy,
|
||||||
address: Address,
|
address: Address,
|
||||||
tracer: &'a mut T,
|
tracer: &'a mut T,
|
||||||
vm_tracer: &'a mut V,
|
vm_tracer: &'a mut V,
|
||||||
@ -154,7 +154,6 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B>
|
|||||||
value: Option<U256>,
|
value: Option<U256>,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
_code_address: &Address,
|
_code_address: &Address,
|
||||||
_output: &mut [u8],
|
|
||||||
_call_type: CallType
|
_call_type: CallType
|
||||||
) -> MessageCallResult {
|
) -> MessageCallResult {
|
||||||
self.callcreates.push(CallCreate {
|
self.callcreates.push(CallCreate {
|
||||||
@ -262,7 +261,6 @@ fn do_json_test_for<H: FnMut(&str, HookType)>(vm_type: &VMType, json_data: &[u8]
|
|||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new();
|
||||||
let mut tracer = NoopTracer;
|
let mut tracer = NoopTracer;
|
||||||
let mut vm_tracer = NoopVMTracer;
|
let mut vm_tracer = NoopVMTracer;
|
||||||
let mut output = vec![];
|
|
||||||
let vm_factory = state.vm_factory();
|
let vm_factory = state.vm_factory();
|
||||||
|
|
||||||
// execute
|
// execute
|
||||||
@ -276,7 +274,7 @@ fn do_json_test_for<H: FnMut(&str, HookType)>(vm_type: &VMType, json_data: &[u8]
|
|||||||
0,
|
0,
|
||||||
OriginInfo::from(¶ms),
|
OriginInfo::from(¶ms),
|
||||||
&mut substate,
|
&mut substate,
|
||||||
OutputPolicy::Return(BytesRef::Flexible(&mut output), None),
|
OutputPolicy::Return,
|
||||||
params.address.clone(),
|
params.address.clone(),
|
||||||
&mut tracer,
|
&mut tracer,
|
||||||
&mut vm_tracer,
|
&mut vm_tracer,
|
||||||
@ -288,6 +286,11 @@ fn do_json_test_for<H: FnMut(&str, HookType)>(vm_type: &VMType, json_data: &[u8]
|
|||||||
(res.finalize(ex), callcreates)
|
(res.finalize(ex), callcreates)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let output = match &res {
|
||||||
|
Ok(res) => res.return_data.to_vec(),
|
||||||
|
Err(_) => Vec::new(),
|
||||||
|
};
|
||||||
|
|
||||||
let log_hash = {
|
let log_hash = {
|
||||||
let mut rlp = RlpStream::new_list(substate.logs.len());
|
let mut rlp = RlpStream::new_list(substate.logs.len());
|
||||||
for l in &substate.logs {
|
for l in &substate.logs {
|
||||||
|
@ -33,7 +33,6 @@ use transaction::{self, SYSTEM_ADDRESS, UnverifiedTransaction, SignedTransaction
|
|||||||
use tx_filter::TransactionFilter;
|
use tx_filter::TransactionFilter;
|
||||||
|
|
||||||
use ethereum_types::{U256, Address};
|
use ethereum_types::{U256, Address};
|
||||||
use bytes::BytesRef;
|
|
||||||
use rlp::Rlp;
|
use rlp::Rlp;
|
||||||
use vm::{CallType, ActionParams, ActionValue, ParamsType};
|
use vm::{CallType, ActionParams, ActionValue, ParamsType};
|
||||||
use vm::{EnvInfo, Schedule, CreateContractAddress};
|
use vm::{EnvInfo, Schedule, CreateContractAddress};
|
||||||
@ -148,10 +147,14 @@ impl EthereumMachine {
|
|||||||
let schedule = self.schedule(env_info.number);
|
let schedule = self.schedule(env_info.number);
|
||||||
let mut ex = Executive::new(&mut state, &env_info, self, &schedule);
|
let mut ex = Executive::new(&mut state, &env_info, self, &schedule);
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new();
|
||||||
let mut output = Vec::new();
|
let res = ex.call(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer);
|
||||||
if let Err(e) = ex.call(params, &mut substate, BytesRef::Flexible(&mut output), &mut NoopTracer, &mut NoopVMTracer) {
|
let output = match res {
|
||||||
|
Ok(res) => res.return_data.to_vec(),
|
||||||
|
Err(e) => {
|
||||||
warn!("Encountered error on making system call: {}", e);
|
warn!("Encountered error on making system call: {}", e);
|
||||||
|
Vec::new()
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Ok(output)
|
Ok(output)
|
||||||
}
|
}
|
||||||
|
@ -655,7 +655,7 @@ impl Spec {
|
|||||||
let machine = self.engine.machine();
|
let machine = self.engine.machine();
|
||||||
let schedule = machine.schedule(env_info.number);
|
let schedule = machine.schedule(env_info.number);
|
||||||
let mut exec = Executive::new(&mut state, &env_info, &machine, &schedule);
|
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) {
|
if let Err(e) = exec.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer) {
|
||||||
warn!(target: "spec", "Genesis constructor execution at {} failed: {}.", address, e);
|
warn!(target: "spec", "Genesis constructor execution at {} failed: {}.", address, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,6 @@ use transaction::SYSTEM_ADDRESS;
|
|||||||
use rustc_hex::FromHex;
|
use rustc_hex::FromHex;
|
||||||
|
|
||||||
use ethereum_types::{H256, Address};
|
use ethereum_types::{H256, Address};
|
||||||
use bytes::BytesRef;
|
|
||||||
|
|
||||||
evm_test!{test_blockhash_eip210: test_blockhash_eip210_int}
|
evm_test!{test_blockhash_eip210: test_blockhash_eip210_int}
|
||||||
fn test_blockhash_eip210(factory: Factory) {
|
fn test_blockhash_eip210(factory: Factory) {
|
||||||
@ -65,8 +64,7 @@ fn test_blockhash_eip210(factory: Factory) {
|
|||||||
let schedule = machine.schedule(env_info.number);
|
let schedule = machine.schedule(env_info.number);
|
||||||
let mut ex = Executive::new(&mut state, &env_info, &machine, &schedule);
|
let mut ex = Executive::new(&mut state, &env_info, &machine, &schedule);
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new();
|
||||||
let mut output = [];
|
if let Err(e) = ex.call(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer) {
|
||||||
if let Err(e) = ex.call(params, &mut substate, BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer) {
|
|
||||||
panic!("Encountered error on updating last hashes: {}", e);
|
panic!("Encountered error on updating last hashes: {}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,9 +87,12 @@ fn test_blockhash_eip210(factory: Factory) {
|
|||||||
let schedule = machine.schedule(env_info.number);
|
let schedule = machine.schedule(env_info.number);
|
||||||
let mut ex = Executive::new(&mut state, &env_info, &machine, &schedule);
|
let mut ex = Executive::new(&mut state, &env_info, &machine, &schedule);
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new();
|
||||||
let mut output = H256::new();
|
let res = ex.call(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer);
|
||||||
if let Err(e) = ex.call(params, &mut substate, BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer) {
|
let output = match res {
|
||||||
|
Ok(res) => H256::from(&res.return_data[..32]),
|
||||||
|
Err(e) => {
|
||||||
panic!("Encountered error on getting last hash: {}", e);
|
panic!("Encountered error on getting last hash: {}", e);
|
||||||
}
|
},
|
||||||
|
};
|
||||||
assert_eq!(output, 255.into());
|
assert_eq!(output, 255.into());
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,6 @@ pub trait Ext {
|
|||||||
value: Option<U256>,
|
value: Option<U256>,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
code_address: &Address,
|
code_address: &Address,
|
||||||
output: &mut [u8],
|
|
||||||
call_type: CallType
|
call_type: CallType
|
||||||
) -> MessageCallResult;
|
) -> MessageCallResult;
|
||||||
|
|
||||||
|
@ -155,7 +155,6 @@ impl Ext for FakeExt {
|
|||||||
value: Option<U256>,
|
value: Option<U256>,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
code_address: &Address,
|
code_address: &Address,
|
||||||
_output: &mut [u8],
|
|
||||||
_call_type: CallType
|
_call_type: CallType
|
||||||
) -> MessageCallResult {
|
) -> MessageCallResult {
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use std::cmp;
|
||||||
use ethereum_types::{U256, H256, Address};
|
use ethereum_types::{U256, H256, Address};
|
||||||
use vm::{self, CallType};
|
use vm::{self, CallType};
|
||||||
use wasmi::{self, MemoryRef, RuntimeArgs, RuntimeValue, Error as InterpreterError, Trap, TrapKind};
|
use wasmi::{self, MemoryRef, RuntimeArgs, RuntimeValue, Error as InterpreterError, Trap, TrapKind};
|
||||||
@ -447,12 +448,14 @@ impl<'a> Runtime<'a> {
|
|||||||
val,
|
val,
|
||||||
&payload,
|
&payload,
|
||||||
&address,
|
&address,
|
||||||
&mut result[..],
|
|
||||||
call_type,
|
call_type,
|
||||||
);
|
);
|
||||||
|
|
||||||
match call_result {
|
match call_result {
|
||||||
vm::MessageCallResult::Success(gas_left, _) => {
|
vm::MessageCallResult::Success(gas_left, data) => {
|
||||||
|
let len = cmp::min(result.len(), data.len());
|
||||||
|
(&mut result[..len]).copy_from_slice(&data[..len]);
|
||||||
|
|
||||||
// cannot overflow, before making call gas_counter was incremented with gas, and gas_left < gas
|
// cannot overflow, before making call gas_counter was incremented with gas, and gas_left < gas
|
||||||
self.gas_counter = self.gas_counter -
|
self.gas_counter = self.gas_counter -
|
||||||
gas_left.low_u64() * self.ext.schedule().wasm().opcodes_div as u64
|
gas_left.low_u64() * self.ext.schedule().wasm().opcodes_div as u64
|
||||||
@ -461,7 +464,10 @@ impl<'a> Runtime<'a> {
|
|||||||
self.memory.set(result_ptr, &result)?;
|
self.memory.set(result_ptr, &result)?;
|
||||||
Ok(0i32.into())
|
Ok(0i32.into())
|
||||||
},
|
},
|
||||||
vm::MessageCallResult::Reverted(gas_left, _) => {
|
vm::MessageCallResult::Reverted(gas_left, data) => {
|
||||||
|
let len = cmp::min(result.len(), data.len());
|
||||||
|
(&mut result[..len]).copy_from_slice(&data[..len]);
|
||||||
|
|
||||||
// cannot overflow, before making call gas_counter was incremented with gas, and gas_left < gas
|
// cannot overflow, before making call gas_counter was incremented with gas, and gas_left < gas
|
||||||
self.gas_counter = self.gas_counter -
|
self.gas_counter = self.gas_counter -
|
||||||
gas_left.low_u64() * self.ext.schedule().wasm().opcodes_div as u64
|
gas_left.low_u64() * self.ext.schedule().wasm().opcodes_div as u64
|
||||||
|
Loading…
Reference in New Issue
Block a user