11use crate :: DebugError ;
2- use reth:: rpc:: {
3- server_types:: eth:: EthApiError ,
4- types:: trace:: geth:: {
5- FourByteFrame , GethDebugBuiltInTracerType , GethDebugTracerConfig , GethDebugTracerType ,
6- GethDebugTracingOptions , GethTrace ,
2+ use reth:: {
3+ revm:: { DatabaseRef , context:: ContextTr } ,
4+ rpc:: {
5+ server_types:: eth:: EthApiError ,
6+ types:: {
7+ TransactionInfo ,
8+ trace:: geth:: {
9+ FourByteFrame , GethDebugBuiltInTracerType , GethDebugTracerConfig ,
10+ GethDebugTracerType , GethDebugTracingOptions , GethTrace ,
11+ } ,
12+ } ,
713 } ,
814} ;
915use revm_inspectors:: tracing:: { FourByteInspector , TracingInspector , TracingInspectorConfig } ;
10- use signet_evm:: EvmReady ;
16+ use signet_evm:: { EvmNeedsTx , EvmReady } ;
1117use trevm:: {
1218 helpers:: Ctx ,
1319 revm:: { Database , DatabaseCommit , Inspector } ,
1420} ;
1521
16- pub ( super ) fn trace < Db : Database , Insp : Inspector < Ctx < Db > > > (
22+ pub ( super ) fn trace < Db , Insp > (
1723 trevm : EvmReady < Db , Insp > ,
1824 config : & GethDebugTracingOptions ,
19- ) -> Result < GethTrace , DebugError > {
25+ tx_info : TransactionInfo ,
26+ ) -> Result < ( GethTrace , EvmNeedsTx < Db , Insp > ) , DebugError >
27+ where
28+ Db : Database + DatabaseCommit + DatabaseRef ,
29+ Insp : Inspector < Ctx < Db > > ,
30+ {
2031 let Some ( tracer) = & config. tracer else { todo ! ( ) } ;
2132
2233 let GethDebugTracerType :: BuiltInTracer ( built_in) = tracer else {
@@ -28,41 +39,133 @@ pub(super) fn trace<Db: Database, Insp: Inspector<Ctx<Db>>>(
2839 GethDebugBuiltInTracerType :: CallTracer => {
2940 trace_call ( & config. tracer_config , trevm) . map_err ( Into :: into)
3041 }
31- GethDebugBuiltInTracerType :: FlatCallTracer => todo ! ( ) ,
32- GethDebugBuiltInTracerType :: PreStateTracer => todo ! ( ) ,
33- GethDebugBuiltInTracerType :: NoopTracer => todo ! ( ) ,
42+ GethDebugBuiltInTracerType :: FlatCallTracer => {
43+ trace_flat_call ( & config. tracer_config , trevm, tx_info) . map_err ( Into :: into)
44+ }
45+ GethDebugBuiltInTracerType :: PreStateTracer => {
46+ trace_pre_state ( & config. tracer_config , trevm) . map_err ( Into :: into)
47+ }
48+ GethDebugBuiltInTracerType :: NoopTracer => Ok ( (
49+ Default :: default ( ) ,
50+ trevm
51+ . run ( )
52+ . map_err ( |err| EthApiError :: EvmCustom ( err. into_error ( ) . to_string ( ) ) ) ?
53+ . accept_state ( ) ,
54+ ) ) ,
3455 GethDebugBuiltInTracerType :: MuxTracer => todo ! ( ) ,
3556 }
3657}
3758
38- fn trace_four_byte < Db : Database + DatabaseCommit , Insp : Inspector < Ctx < Db > > > (
59+ /// Traces a call using [`GethDebugBuiltInTracerType::FourByteTracer`].
60+ fn trace_four_byte < Db , Insp > (
3961 trevm : EvmReady < Db , Insp > ,
40- ) -> Result < GethTrace , EthApiError > {
62+ ) -> Result < ( GethTrace , EvmNeedsTx < Db , Insp > ) , EthApiError >
63+ where
64+ Db : Database + DatabaseCommit ,
65+ Insp : Inspector < Ctx < Db > > ,
66+ {
4167 let mut four_byte = FourByteInspector :: default ( ) ;
4268
4369 let trevm = trevm. try_with_inspector ( & mut four_byte, |trevm| trevm. run ( ) ) ;
4470
4571 let trevm = trevm. map_err ( |e| EthApiError :: EvmCustom ( e. into_error ( ) . to_string ( ) ) ) ?;
4672
47- trevm. accept_state ( ) ;
48-
49- Ok ( FourByteFrame :: from ( four_byte) . into ( ) )
73+ Ok ( ( FourByteFrame :: from ( four_byte) . into ( ) , trevm. accept_state ( ) ) )
5074}
5175
52- fn trace_call < Db : Database , Insp : Inspector < Ctx < Db > > > (
76+ /// Traces a call using [`GethDebugBuiltInTracerType::CallTracer`].
77+ fn trace_call < Db , Insp > (
5378 tracer_config : & GethDebugTracerConfig ,
5479 trevm : EvmReady < Db , Insp > ,
55- ) -> Result < GethTrace , EthApiError > {
80+ ) -> Result < ( GethTrace , EvmNeedsTx < Db , Insp > ) , EthApiError >
81+ where
82+ Db : Database + DatabaseCommit ,
83+ Insp : Inspector < Ctx < Db > > ,
84+ {
5685 let call_config =
5786 tracer_config. clone ( ) . into_call_config ( ) . map_err ( |_| EthApiError :: InvalidTracerConfig ) ?;
87+
5888 let mut inspector =
5989 TracingInspector :: new ( TracingInspectorConfig :: from_geth_call_config ( & call_config) ) ;
6090
6191 let trevm = trevm. try_with_inspector ( & mut inspector, |trevm| trevm. run ( ) ) ;
6292
6393 let trevm = trevm. map_err ( |e| EthApiError :: EvmCustom ( e. into_error ( ) . to_string ( ) ) ) ?;
6494
65- inspector. set_transaction_gas_limit ( trevm. gas_limit ( ) ) ;
95+ let frame = inspector
96+ . with_transaction_gas_limit ( trevm. gas_limit ( ) )
97+ . into_geth_builder ( )
98+ . geth_call_traces ( call_config, trevm. gas_used ( ) ) ;
99+
100+ Ok ( ( frame. into ( ) , trevm. accept_state ( ) ) )
101+ }
102+
103+ /// Traces a call using [`GethDebugBuiltInTracerType::PreStateTracer`]
104+ fn trace_pre_state < Db , Insp > (
105+ tracer_config : & GethDebugTracerConfig ,
106+ trevm : EvmReady < Db , Insp > ,
107+ ) -> Result < ( GethTrace , EvmNeedsTx < Db , Insp > ) , EthApiError >
108+ where
109+ Db : Database + DatabaseCommit + DatabaseRef ,
110+ Insp : Inspector < Ctx < Db > > ,
111+ {
112+ let prestate_config = tracer_config
113+ . clone ( )
114+ . into_pre_state_config ( )
115+ . map_err ( |_| EthApiError :: InvalidTracerConfig ) ?;
116+
117+ let mut inspector =
118+ TracingInspector :: new ( TracingInspectorConfig :: from_geth_prestate_config ( & prestate_config) ) ;
119+
120+ let trevm = trevm. try_with_inspector ( & mut inspector, |trevm| trevm. run ( ) ) ;
121+
122+ let trevm = trevm. map_err ( |e| EthApiError :: EvmCustom ( e. into_error ( ) . to_string ( ) ) ) ?;
123+ let gas_limit = trevm. gas_limit ( ) ;
124+
125+ // NB: Normally we would call `trevm.accept_state()` here, but we need the
126+ // state after execution to be UNCOMMITED when we compute the prestate
127+ // diffs.
128+ let ( result, mut trevm) = trevm. take_result_and_state ( ) ;
129+
130+ let frame = inspector
131+ . with_transaction_gas_limit ( gas_limit)
132+ . into_geth_builder ( )
133+ . geth_prestate_traces ( & result, & prestate_config, trevm. inner_mut_unchecked ( ) . db_mut ( ) )
134+ . map_err ( |err| EthApiError :: EvmCustom ( err. to_string ( ) ) ) ?;
135+
136+ // This is equivalent to calling `trevm.accept_state()`.
137+ trevm. inner_mut_unchecked ( ) . db_mut ( ) . commit ( result. state ) ;
138+
139+ Ok ( ( frame. into ( ) , trevm) )
140+ }
141+
142+ fn trace_flat_call < Db , Insp > (
143+ tracer_config : & GethDebugTracerConfig ,
144+ trevm : EvmReady < Db , Insp > ,
145+ tx_info : TransactionInfo ,
146+ ) -> Result < ( GethTrace , EvmNeedsTx < Db , Insp > ) , EthApiError >
147+ where
148+ Db : Database + DatabaseCommit ,
149+ Insp : Inspector < Ctx < Db > > ,
150+ {
151+ let flat_call_config = tracer_config
152+ . clone ( )
153+ . into_flat_call_config ( )
154+ . map_err ( |_| EthApiError :: InvalidTracerConfig ) ?;
155+
156+ let mut inspector =
157+ TracingInspector :: new ( TracingInspectorConfig :: from_flat_call_config ( & flat_call_config) ) ;
158+
159+ let trevm = trevm. try_with_inspector ( & mut inspector, |trevm| trevm. run ( ) ) ;
160+
161+ let trevm = trevm. map_err ( |e| EthApiError :: EvmCustom ( e. into_error ( ) . to_string ( ) ) ) ?;
162+
163+ let frame = inspector
164+ . with_transaction_gas_limit ( trevm. gas_limit ( ) )
165+ . into_parity_builder ( )
166+ . into_localized_transaction_traces ( tx_info) ;
167+
168+ Ok ( ( frame. into ( ) , trevm. accept_state ( ) ) )
66169}
67170
68171// Some code in this file has been copied and modified from reth
0 commit comments