Output stored for calls.
This commit is contained in:
parent
bd7cd68c32
commit
7d93fa2533
@ -104,7 +104,7 @@ impl<'a> Executive<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Creates `Externalities` from `Executive`.
|
/// Creates `Externalities` from `Executive`.
|
||||||
pub fn as_externalities<'_>(&'_ mut self, origin_info: OriginInfo, substate: &'_ mut Substate, output: OutputPolicy<'_>) -> Externalities {
|
pub fn as_externalities<'_>(&'_ mut self, origin_info: OriginInfo, substate: &'_ mut Substate, output: OutputPolicy<'_, '_>) -> Externalities {
|
||||||
Externalities::new(self.state, self.info, self.engine, self.depth, origin_info, substate, output)
|
Externalities::new(self.state, self.info, self.engine, self.depth, origin_info, substate, output)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,15 +249,17 @@ impl<'a> Executive<'a> {
|
|||||||
|
|
||||||
// part of substate that may be reverted
|
// part of substate that may be reverted
|
||||||
let mut unconfirmed_substate = Substate::new(substate.subtraces.is_some());
|
let mut unconfirmed_substate = Substate::new(substate.subtraces.is_some());
|
||||||
|
|
||||||
let mut trace_info = substate.subtraces.as_ref().map(|_| (TraceAction::from_call(¶ms), self.depth));
|
let mut trace_info = substate.subtraces.as_ref().map(|_| (TraceAction::from_call(¶ms), self.depth));
|
||||||
|
let mut trace_output = trace_info.as_ref().map(|_| vec![]);
|
||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::Return(output))
|
self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::Return(output, trace_output.as_mut()))
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some((TraceAction::Call(ref mut c), _)) = trace_info {
|
if let Some((TraceAction::Call(ref mut c), _)) = trace_info {
|
||||||
c.result = res.as_ref().ok().map(|gas_left| (c.gas - *gas_left, vec![]));
|
if let Some(output) = trace_output {
|
||||||
|
c.result = res.as_ref().ok().map(|gas_left| (c.gas - *gas_left, output));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!("exec: sstore-clears={}\n", unconfirmed_substate.sstore_clears_count);
|
trace!("exec: sstore-clears={}\n", unconfirmed_substate.sstore_clears_count);
|
||||||
|
@ -23,12 +23,12 @@ use evm::{self, Schedule, Ext, ContractCreateResult, MessageCallResult};
|
|||||||
use substate::*;
|
use substate::*;
|
||||||
|
|
||||||
/// Policy for handling output data on `RETURN` opcode.
|
/// Policy for handling output data on `RETURN` opcode.
|
||||||
pub enum OutputPolicy<'a> {
|
pub enum OutputPolicy<'a, 'b> {
|
||||||
/// Return reference to fixed sized output.
|
/// Return reference to fixed sized output.
|
||||||
/// Used for message calls.
|
/// Used for message calls.
|
||||||
Return(BytesRef<'a>),
|
Return(BytesRef<'a>, Option<&'b mut Bytes>),
|
||||||
/// Init new contract as soon as `RETURN` is called.
|
/// Init new contract as soon as `RETURN` is called.
|
||||||
InitContract
|
InitContract,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transaction properties that externalities need to know about.
|
/// Transaction properties that externalities need to know about.
|
||||||
@ -62,18 +62,19 @@ pub struct Externalities<'a> {
|
|||||||
origin_info: OriginInfo,
|
origin_info: OriginInfo,
|
||||||
substate: &'a mut Substate,
|
substate: &'a mut Substate,
|
||||||
schedule: Schedule,
|
schedule: Schedule,
|
||||||
output: OutputPolicy<'a>
|
output: OutputPolicy<'a, 'a>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Externalities<'a> {
|
impl<'a> Externalities<'a> {
|
||||||
/// Basic `Externalities` constructor.
|
/// Basic `Externalities` constructor.
|
||||||
pub fn new(state: &'a mut State,
|
pub fn new(state: &'a mut State,
|
||||||
env_info: &'a EnvInfo,
|
env_info: &'a EnvInfo,
|
||||||
engine: &'a Engine,
|
engine: &'a Engine,
|
||||||
depth: usize,
|
depth: usize,
|
||||||
origin_info: OriginInfo,
|
origin_info: OriginInfo,
|
||||||
substate: &'a mut Substate,
|
substate: &'a mut Substate,
|
||||||
output: OutputPolicy<'a>) -> Self {
|
output: OutputPolicy<'a, 'a>
|
||||||
|
) -> Self {
|
||||||
Externalities {
|
Externalities {
|
||||||
state: state,
|
state: state,
|
||||||
env_info: env_info,
|
env_info: env_info,
|
||||||
@ -190,20 +191,29 @@ impl<'a> Ext for Externalities<'a> {
|
|||||||
|
|
||||||
#[cfg_attr(feature="dev", allow(match_ref_pats))]
|
#[cfg_attr(feature="dev", allow(match_ref_pats))]
|
||||||
fn ret(&mut self, gas: &U256, data: &[u8]) -> Result<U256, evm::Error> {
|
fn ret(&mut self, gas: &U256, data: &[u8]) -> Result<U256, evm::Error> {
|
||||||
match &mut self.output {
|
let handle_copy = |to: &mut Option<&mut Bytes>| {
|
||||||
&mut OutputPolicy::Return(BytesRef::Fixed(ref mut slice)) => unsafe {
|
to.as_mut().map(|b| **b = data.to_owned());
|
||||||
|
};
|
||||||
|
match self.output {
|
||||||
|
OutputPolicy::Return(BytesRef::Fixed(ref mut slice), ref mut copy) => {
|
||||||
|
handle_copy(copy);
|
||||||
let len = cmp::min(slice.len(), data.len());
|
let len = cmp::min(slice.len(), data.len());
|
||||||
ptr::copy(data.as_ptr(), slice.as_mut_ptr(), len);
|
unsafe {
|
||||||
|
ptr::copy(data.as_ptr(), slice.as_mut_ptr(), len);
|
||||||
|
}
|
||||||
Ok(*gas)
|
Ok(*gas)
|
||||||
},
|
},
|
||||||
&mut OutputPolicy::Return(BytesRef::Flexible(ref mut vec)) => unsafe {
|
OutputPolicy::Return(BytesRef::Flexible(ref mut vec), ref mut copy) => {
|
||||||
|
handle_copy(copy);
|
||||||
vec.clear();
|
vec.clear();
|
||||||
vec.reserve(data.len());
|
vec.reserve(data.len());
|
||||||
ptr::copy(data.as_ptr(), vec.as_mut_ptr(), data.len());
|
unsafe {
|
||||||
vec.set_len(data.len());
|
ptr::copy(data.as_ptr(), vec.as_mut_ptr(), data.len());
|
||||||
|
vec.set_len(data.len());
|
||||||
|
}
|
||||||
Ok(*gas)
|
Ok(*gas)
|
||||||
},
|
},
|
||||||
&mut OutputPolicy::InitContract => {
|
OutputPolicy::InitContract => {
|
||||||
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 {
|
if return_cost > *gas {
|
||||||
return match self.schedule.exceptional_failed_code_deposit {
|
return match self.schedule.exceptional_failed_code_deposit {
|
||||||
|
@ -239,7 +239,7 @@ fn do_json_test_for(vm: &VMType, json_data: &[u8]) -> Vec<String> {
|
|||||||
0,
|
0,
|
||||||
OriginInfo::from(¶ms),
|
OriginInfo::from(¶ms),
|
||||||
&mut substate,
|
&mut substate,
|
||||||
OutputPolicy::Return(BytesRef::Flexible(&mut output)),
|
OutputPolicy::Return(&mut BytesRef::Flexible(&mut output)),
|
||||||
params.address.clone()
|
params.address.clone()
|
||||||
);
|
);
|
||||||
let evm = engine.vm_factory().create();
|
let evm = engine.vm_factory().create();
|
||||||
|
Loading…
Reference in New Issue
Block a user