@@ -428,8 +428,14 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
428
428
self . state . discard_checkpoint ( ) ;
429
429
output. write ( 0 , & builtin_out_buffer) ;
430
430
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 {
433
439
let mut trace_output = tracer. prepare_trace_output ( ) ;
434
440
if let Some ( out) = trace_output. as_mut ( ) {
435
441
* out = output. to_owned ( ) ;
@@ -722,6 +728,12 @@ mod tests {
722
728
machine
723
729
}
724
730
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
+
725
737
#[ test]
726
738
fn test_contract_address ( ) {
727
739
let address = Address :: from_str ( "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" ) . unwrap ( ) ;
@@ -813,6 +825,76 @@ mod tests {
813
825
assert_eq ! ( substate. contracts_created. len( ) , 0 ) ;
814
826
}
815
827
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
+
816
898
#[ test]
817
899
// Tracing is not suported in JIT
818
900
fn test_call_to_create ( ) {
0 commit comments