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

Commit 7a00d97

Browse files
sorpaas5chdn
authored andcommitted
Trace precompiled contracts when the transfer value is not zero (#8486)
* Trace precompiled contracts when the transfer value is not zero * Add tests for precompiled CALL tracing * Use byzantium test machine for the new test * Add notes in comments on why we don't trace all precompileds * Use is_transferred instead of transferred
1 parent ac3de4c commit 7a00d97

File tree

1 file changed

+84
-2
lines changed

1 file changed

+84
-2
lines changed

ethcore/src/executive.rs

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -428,8 +428,14 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
428428
self.state.discard_checkpoint();
429429
output.write(0, &builtin_out_buffer);
430430

431-
// trace only top level calls to builtins to avoid DDoS attacks
432-
if self.depth == 0 {
431+
// Trace only top level calls and calls with balance transfer to builtins. The reason why we don't
432+
// trace all internal calls to builtin contracts is that memcpy (IDENTITY) is a heavily used
433+
// function.
434+
let is_transferred = match params.value {
435+
ActionValue::Transfer(value) => value != U256::zero(),
436+
ActionValue::Apparent(_) => false,
437+
};
438+
if self.depth == 0 || is_transferred {
433439
let mut trace_output = tracer.prepare_trace_output();
434440
if let Some(out) = trace_output.as_mut() {
435441
*out = output.to_owned();
@@ -722,6 +728,12 @@ mod tests {
722728
machine
723729
}
724730

731+
fn make_byzantium_machine(max_depth: usize) -> EthereumMachine {
732+
let mut machine = ::ethereum::new_byzantium_test_machine();
733+
machine.set_schedule_creation_rules(Box::new(move |s, _| s.max_depth = max_depth));
734+
machine
735+
}
736+
725737
#[test]
726738
fn test_contract_address() {
727739
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
@@ -813,6 +825,76 @@ mod tests {
813825
assert_eq!(substate.contracts_created.len(), 0);
814826
}
815827

828+
#[test]
829+
fn test_call_to_precompiled_tracing() {
830+
// code:
831+
//
832+
// 60 00 - push 00 out size
833+
// 60 00 - push 00 out offset
834+
// 60 00 - push 00 in size
835+
// 60 00 - push 00 in offset
836+
// 60 01 - push 01 value
837+
// 60 03 - push 03 to
838+
// 61 ffff - push fff gas
839+
// f1 - CALL
840+
841+
let code = "60006000600060006001600361fffff1".from_hex().unwrap();
842+
let sender = Address::from_str("4444444444444444444444444444444444444444").unwrap();
843+
let address = Address::from_str("5555555555555555555555555555555555555555").unwrap();
844+
845+
let mut params = ActionParams::default();
846+
params.address = address.clone();
847+
params.code_address = address.clone();
848+
params.sender = sender.clone();
849+
params.origin = sender.clone();
850+
params.gas = U256::from(100_000);
851+
params.code = Some(Arc::new(code));
852+
params.value = ActionValue::Transfer(U256::from(100));
853+
params.call_type = CallType::Call;
854+
let mut state = get_temp_state();
855+
state.add_balance(&sender, &U256::from(100), CleanupMode::NoEmpty).unwrap();
856+
let info = EnvInfo::default();
857+
let machine = make_byzantium_machine(5);
858+
let mut substate = Substate::new();
859+
let mut tracer = ExecutiveTracer::default();
860+
let mut vm_tracer = ExecutiveVMTracer::toplevel();
861+
862+
let mut ex = Executive::new(&mut state, &info, &machine);
863+
let output = BytesRef::Fixed(&mut[0u8;0]);
864+
ex.call(params, &mut substate, output, &mut tracer, &mut vm_tracer).unwrap();
865+
866+
assert_eq!(tracer.drain(), vec![FlatTrace {
867+
action: trace::Action::Call(trace::Call {
868+
from: "4444444444444444444444444444444444444444".into(),
869+
to: "5555555555555555555555555555555555555555".into(),
870+
value: 100.into(),
871+
gas: 100_000.into(),
872+
input: vec![],
873+
call_type: CallType::Call
874+
}),
875+
result: trace::Res::Call(trace::CallResult {
876+
gas_used: 33021.into(),
877+
output: vec![]
878+
}),
879+
subtraces: 1,
880+
trace_address: Default::default()
881+
}, FlatTrace {
882+
action: trace::Action::Call(trace::Call {
883+
from: "5555555555555555555555555555555555555555".into(),
884+
to: "0000000000000000000000000000000000000003".into(),
885+
value: 1.into(),
886+
gas: 66560.into(),
887+
input: vec![],
888+
call_type: CallType::Call
889+
}), result: trace::Res::Call(trace::CallResult {
890+
gas_used: 600.into(),
891+
output: vec![]
892+
}),
893+
subtraces: 0,
894+
trace_address: vec![0].into_iter().collect(),
895+
}]);
896+
}
897+
816898
#[test]
817899
// Tracing is not suported in JIT
818900
fn test_call_to_create() {

0 commit comments

Comments
 (0)