Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Trace other types of calls #1727

Merged
merged 5 commits into from
Jul 27, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions ethcore/src/action_params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
//! Evm input params.
use common::*;
use ethjson;
use types::executed::CallType;

/// Transaction value
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -58,7 +59,10 @@ pub struct ActionParams {
/// Code being executed.
pub code: Option<Bytes>,
/// Input data.
pub data: Option<Bytes>
pub data: Option<Bytes>,
/// Type of call
pub call_type: CallType,

}

impl Default for ActionParams {
Expand All @@ -73,23 +77,26 @@ impl Default for ActionParams {
gas_price: U256::zero(),
value: ActionValue::Transfer(U256::zero()),
code: None,
data: None
data: None,
call_type: CallType::None,
}
}
}

impl From<ethjson::vm::Transaction> for ActionParams {
fn from(t: ethjson::vm::Transaction) -> Self {
let address: Address = t.address.into();
ActionParams {
code_address: Address::new(),
address: t.address.into(),
address: address,
sender: t.sender.into(),
origin: t.origin.into(),
code: Some(t.code.into()),
data: Some(t.data.into()),
gas: t.gas.into(),
gas_price: t.gas_price.into(),
value: ActionValue::Transfer(t.value.into()),
call_type: match address.is_zero() { true => CallType::None, false => CallType::Call }, // TODO @debris is this correct?
}
}
}
17 changes: 10 additions & 7 deletions ethcore/src/evm/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

use util::common::*;
use evm::{self, Schedule};
use types::executed::CallType;
use env_info::*;

/// Result of externalities create function.
Expand Down Expand Up @@ -69,13 +70,15 @@ pub trait Ext {
/// and true if subcall was successfull.
#[cfg_attr(feature="dev", allow(too_many_arguments))]
fn call(&mut self,
gas: &U256,
sender_address: &Address,
receive_address: &Address,
value: Option<U256>,
data: &[u8],
code_address: &Address,
output: &mut [u8]) -> MessageCallResult;
gas: &U256,
sender_address: &Address,
receive_address: &Address,
value: Option<U256>,
data: &[u8],
code_address: &Address,
output: &mut [u8],
call_type: CallType
) -> MessageCallResult;

/// Returns code at given address
fn extcode(&self, address: &Address) -> Bytes;
Expand Down
11 changes: 6 additions & 5 deletions ethcore/src/evm/interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ use self::memory::Memory;

use std::marker::PhantomData;
use common::*;
use types::executed::CallType;
use super::instructions::{self, Instruction, InstructionInfo};
use evm::{self, MessageCallResult, ContractCreateResult, GasLeft, CostType};

Expand Down Expand Up @@ -311,16 +312,16 @@ impl<Cost: CostType> Interpreter<Cost> {
});

// Get sender & receive addresses, check if we have balance
let (sender_address, receive_address, has_balance) = match instruction {
let (sender_address, receive_address, has_balance, call_type) = match instruction {
instructions::CALL => {
let has_balance = ext.balance(&params.address) >= value.unwrap();
(&params.address, &code_address, has_balance)
(&params.address, &code_address, has_balance, CallType::Call)
},
instructions::CALLCODE => {
let has_balance = ext.balance(&params.address) >= value.unwrap();
(&params.address, &params.address, has_balance)
(&params.address, &params.address, has_balance, CallType::CallCode)
},
instructions::DELEGATECALL => (&params.sender, &params.address, true),
instructions::DELEGATECALL => (&params.sender, &params.address, true, CallType::DelegateCall),
_ => panic!(format!("Unexpected instruction {} in CALL branch.", instruction))
};

Expand All @@ -335,7 +336,7 @@ impl<Cost: CostType> Interpreter<Cost> {
// and we don't want to copy
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)
ext.call(&call_gas.as_u256(), sender_address, receive_address, value, input, &code_address, output, call_type)
};

return match call_result {
Expand Down
7 changes: 5 additions & 2 deletions ethcore/src/evm/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

use common::*;
use types::executed::CallType;
use evm::{self, Ext, Schedule, Factory, GasLeft, VMType, ContractCreateResult, MessageCallResult};
use std::fmt::Debug;

Expand All @@ -36,7 +37,7 @@ pub struct FakeCall {
receive_address: Option<Address>,
value: Option<U256>,
data: Bytes,
code_address: Option<Address>
code_address: Option<Address>,
}

/// Fake externalities test structure.
Expand Down Expand Up @@ -119,7 +120,9 @@ impl Ext for FakeExt {
value: Option<U256>,
data: &[u8],
code_address: &Address,
_output: &mut [u8]) -> MessageCallResult {
_output: &mut [u8],
_call_type: CallType
) -> MessageCallResult {

self.calls.insert(FakeCall {
call_type: FakeCallType::Call,
Expand Down
20 changes: 11 additions & 9 deletions ethcore/src/executive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use common::*;
use state::*;
use engine::*;
use types::executed::CallType;
use evm::{self, Ext, Factory, Finalize};
use externalities::*;
use substate::*;
Expand Down Expand Up @@ -173,6 +174,7 @@ impl<'a> Executive<'a> {
value: ActionValue::Transfer(t.value),
code: Some(t.data.clone()),
data: None,
call_type: CallType::None,
};
(self.create(params, &mut substate, &mut tracer, &mut vm_tracer), vec![])
},
Expand All @@ -187,6 +189,7 @@ impl<'a> Executive<'a> {
value: ActionValue::Transfer(t.value),
code: self.state.code(address),
data: Some(t.data.clone()),
call_type: CallType::Call,
};
// TODO: move output upstream
let mut out = vec![];
Expand Down Expand Up @@ -248,8 +251,6 @@ impl<'a> Executive<'a> {
}
trace!("Executive::call(params={:?}) self.env_info={:?}", params, self.info);

let delegate_call = params.code_address != params.address;

if self.engine.is_builtin(&params.code_address) {
// if destination is builtin, try to execute it

Expand All @@ -275,8 +276,7 @@ impl<'a> Executive<'a> {
cost,
trace_output,
self.depth,
vec![],
delegate_call
vec![]
);
}

Expand All @@ -285,7 +285,7 @@ impl<'a> Executive<'a> {
// just drain the whole gas
self.state.revert_snapshot();

tracer.trace_failed_call(trace_info, self.depth, vec![], delegate_call);
tracer.trace_failed_call(trace_info, self.depth, vec![]);

Err(evm::Error::OutOfGas)
}
Expand Down Expand Up @@ -318,10 +318,9 @@ impl<'a> Executive<'a> {
gas - gas_left,
trace_output,
self.depth,
traces,
delegate_call
traces
),
_ => tracer.trace_failed_call(trace_info, self.depth, traces, delegate_call),
_ => tracer.trace_failed_call(trace_info, self.depth, traces),
};

trace!(target: "executive", "substate={:?}; unconfirmed_substate={:?}\n", substate, unconfirmed_substate);
Expand All @@ -333,7 +332,7 @@ impl<'a> Executive<'a> {
// otherwise it's just a basic transaction, only do tracing, if necessary.
self.state.clear_snapshot();

tracer.trace_call(trace_info, U256::zero(), trace_output, self.depth, vec![], delegate_call);
tracer.trace_call(trace_info, U256::zero(), trace_output, self.depth, vec![]);
Ok(params.gas)
}
}
Expand Down Expand Up @@ -495,6 +494,7 @@ mod tests {
use trace::trace;
use trace::{Trace, Tracer, NoopTracer, ExecutiveTracer};
use trace::{VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, VMTracer, NoopVMTracer, ExecutiveVMTracer};
use types::executed::CallType;

#[test]
fn test_contract_address() {
Expand Down Expand Up @@ -628,6 +628,7 @@ mod tests {
params.gas = U256::from(100_000);
params.code = Some(code.clone());
params.value = ActionValue::Transfer(U256::from(100));
params.call_type = CallType::Call;
let mut state_result = get_temp_state();
let mut state = state_result.reference_mut();
state.add_balance(&sender, &U256::from(100));
Expand All @@ -653,6 +654,7 @@ mod tests {
value: 100.into(),
gas: 100000.into(),
input: vec![],
call_type: CallType::Call,
}),
result: trace::Res::Call(trace::CallResult {
gas_used: U256::from(55_248),
Expand Down
11 changes: 9 additions & 2 deletions ethcore/src/externalities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use engine::*;
use executive::*;
use evm::{self, Schedule, Ext, ContractCreateResult, MessageCallResult, Factory};
use substate::*;
use types::executed::CallType;
use trace::{Tracer, VMTracer};

/// Policy for handling output data on `RETURN` opcode.
Expand Down Expand Up @@ -148,6 +149,7 @@ impl<'a, T, V> Ext for Externalities<'a, T, V> where T: 'a + Tracer, V: 'a + VMT
value: ActionValue::Transfer(*value),
code: Some(code.to_vec()),
data: None,
call_type: CallType::None,
};

self.state.inc_nonce(&self.origin_info.address);
Expand All @@ -170,7 +172,8 @@ impl<'a, T, V> Ext for Externalities<'a, T, V> where T: 'a + Tracer, V: 'a + VMT
value: Option<U256>,
data: &[u8],
code_address: &Address,
output: &mut [u8]
output: &mut [u8],
call_type: CallType
) -> MessageCallResult {
trace!(target: "externalities", "call");

Expand All @@ -184,6 +187,7 @@ impl<'a, T, V> Ext for Externalities<'a, T, V> where T: 'a + Tracer, V: 'a + VMT
gas_price: self.origin_info.gas_price,
code: self.state.code(code_address),
data: Some(data.to_vec()),
call_type: call_type,
};

if let Some(value) = value {
Expand Down Expand Up @@ -303,6 +307,7 @@ mod tests {
use devtools::GuardedTempResult;
use super::*;
use trace::{NoopTracer, NoopVMTracer};
use types::executed::CallType;

fn get_test_origin() -> OriginInfo {
OriginInfo {
Expand Down Expand Up @@ -421,7 +426,9 @@ mod tests {
Some(U256::from_str("0000000000000000000000000000000000000000000000000000000000150000").unwrap()),
&[],
&Address::new(),
&mut output);
&mut output,
CallType::Call
);
}

#[test]
Expand Down
17 changes: 10 additions & 7 deletions ethcore/src/json_tests/executive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use evm;
use evm::{Schedule, Ext, Factory, Finalize, VMType, ContractCreateResult, MessageCallResult};
use externalities::*;
use substate::*;
use types::executed::CallType;
use tests::helpers::*;
use ethjson;
use trace::{Tracer, NoopTracer};
Expand Down Expand Up @@ -109,13 +110,15 @@ impl<'a, T, V> Ext for TestExt<'a, T, V> where T: Tracer, V: VMTracer {
}

fn call(&mut self,
gas: &U256,
_sender_address: &Address,
receive_address: &Address,
value: Option<U256>,
data: &[u8],
_code_address: &Address,
_output: &mut [u8]) -> MessageCallResult {
gas: &U256,
_sender_address: &Address,
receive_address: &Address,
value: Option<U256>,
data: &[u8],
_code_address: &Address,
_output: &mut [u8],
_call_type: CallType
) -> MessageCallResult {
self.callcreates.push(CallCreate {
data: data.to_vec(),
destination: Some(receive_address.clone()),
Expand Down
Loading