11use auto_impl:: auto_impl;
22use context:: { Database , Journal , JournalEntry } ;
3+ use handler:: FrameResult ;
34use interpreter:: {
4- interpreter:: EthInterpreter , CallInputs , CallOutcome , CreateInputs , CreateOutcome , Interpreter ,
5- InterpreterTypes ,
5+ interpreter:: EthInterpreter , CallInputs , CallOutcome , CreateInputs , CreateOutcome , FrameInput ,
6+ Interpreter , InterpreterTypes ,
67} ;
78use primitives:: { Address , Log , U256 } ;
89use state:: EvmState ;
@@ -14,7 +15,8 @@ use state::EvmState;
1415/// Object that is implemented this trait is used in `InspectorHandler` to trace the EVM execution.
1516/// And API that allow calling the inspector can be found in [`crate::InspectEvm`] and [`crate::InspectCommitEvm`].
1617#[ auto_impl( & mut , Box ) ]
17- pub trait Inspector < CTX , INTR : InterpreterTypes = EthInterpreter > {
18+ pub trait Inspector < CTX , INTR : InterpreterTypes = EthInterpreter , FI = FrameInput , FR = FrameResult >
19+ {
1820 /// Called before the interpreter is initialized.
1921 ///
2022 /// If `interp.bytecode.set_action` is set the execution of the interpreter is skipped.
@@ -64,6 +66,29 @@ pub trait Inspector<CTX, INTR: InterpreterTypes = EthInterpreter> {
6466 self . log ( context, log) ;
6567 }
6668
69+ /// Called before call/create dispatch. Called with a mutable reference to
70+ /// the frame input, allowing mutations of the input before the variant-specific
71+ /// hooks (`call`/`create`) are called.
72+ ///
73+ /// Returning `Some(FrameResult)` will skip execution of the frame entirely,
74+ /// and also skips calling `call()`/`create()`. `frame_end` will still be called.
75+ #[ inline]
76+ fn frame_start ( & mut self , context : & mut CTX , frame_input : & mut FI ) -> Option < FR > {
77+ let _ = context;
78+ let _ = frame_input;
79+ None
80+ }
81+
82+ /// Called after `call_end()`/`create_end()` variant-specific hooks complete.
83+ ///
84+ /// Allows transformation of the final result regardless of frame kind.
85+ #[ inline]
86+ fn frame_end ( & mut self , context : & mut CTX , frame_input : & FI , frame_result : & mut FR ) {
87+ let _ = context;
88+ let _ = frame_input;
89+ let _ = frame_result;
90+ }
91+
6792 /// Called whenever a call to a contract is about to start.
6893 ///
6994 /// Returning `CallOutcome` will override the result of the call.
@@ -122,10 +147,10 @@ pub trait Inspector<CTX, INTR: InterpreterTypes = EthInterpreter> {
122147 }
123148}
124149
125- impl < CTX , INTR : InterpreterTypes , L , R > Inspector < CTX , INTR > for ( L , R )
150+ impl < CTX , INTR : InterpreterTypes , FI , FR , L , R > Inspector < CTX , INTR , FI , FR > for ( L , R )
126151where
127- L : Inspector < CTX , INTR > ,
128- R : Inspector < CTX , INTR > ,
152+ L : Inspector < CTX , INTR , FI , FR > ,
153+ R : Inspector < CTX , INTR , FI , FR > ,
129154{
130155 fn initialize_interp ( & mut self , interp : & mut Interpreter < INTR > , context : & mut CTX ) {
131156 self . 0 . initialize_interp ( interp, context) ;
@@ -152,6 +177,17 @@ where
152177 self . 1 . log_full ( interp, context, log) ;
153178 }
154179
180+ fn frame_start ( & mut self , context : & mut CTX , frame_input : & mut FI ) -> Option < FR > {
181+ let first = self . 0 . frame_start ( context, frame_input) ;
182+ let second = self . 1 . frame_start ( context, frame_input) ;
183+ first. or ( second)
184+ }
185+
186+ fn frame_end ( & mut self , context : & mut CTX , frame_input : & FI , frame_result : & mut FR ) {
187+ self . 0 . frame_end ( context, frame_input, frame_result) ;
188+ self . 1 . frame_end ( context, frame_input, frame_result) ;
189+ }
190+
155191 fn call ( & mut self , context : & mut CTX , inputs : & mut CallInputs ) -> Option < CallOutcome > {
156192 let first = self . 0 . call ( context, inputs) ;
157193 let second = self . 1 . call ( context, inputs) ;
0 commit comments