11use crate :: {
22 db:: { StateAcc , TryStateAcc } ,
33 driver:: DriveBlockResult ,
4- helpers:: { Ctx , Evm } ,
4+ helpers:: { Ctx , Evm , Instruction } ,
55 Block , BlockDriver , BundleDriver , Cfg , ChainDriver , DriveBundleResult , DriveChainResult ,
66 ErroredState , EvmErrored , EvmExtUnchecked , EvmNeedsBlock , EvmNeedsCfg , EvmNeedsTx , EvmReady ,
77 EvmTransacted , HasBlock , HasCfg , HasTx , NeedsCfg , NeedsTx , TransactedState , Tx ,
@@ -12,13 +12,15 @@ use alloy::{
1212} ;
1313use core:: { convert:: Infallible , fmt} ;
1414use revm:: {
15+ bytecode:: opcode:: DIFFICULTY ,
1516 context:: {
1617 result:: { EVMError , ExecutionResult , InvalidTransaction , ResultAndState } ,
1718 Block as _, BlockEnv , Cfg as _, ContextSetters , ContextTr , Transaction as _, TxEnv ,
1819 } ,
1920 database:: { states:: bundle_state:: BundleRetention , BundleState , TryDatabaseCommit } ,
21+ handler:: EthPrecompiles ,
2022 inspector:: NoOpInspector ,
21- interpreter:: gas:: calculate_initial_tx_gas_for_tx,
23+ interpreter:: { gas:: calculate_initial_tx_gas_for_tx, instructions :: block_info } ,
2224 primitives:: { hardfork:: SpecId , TxKind } ,
2325 state:: { AccountInfo , Bytecode , EvmState } ,
2426 Database , DatabaseCommit , DatabaseRef , InspectEvm , Inspector ,
@@ -183,6 +185,81 @@ where
183185 Ok ( self )
184186 }
185187 }
188+
189+ /// Overide an opcode with a custom handler. Returns the previous
190+ /// instruction handler for the opcode.
191+ pub fn override_opcode ( & mut self , opcode : u8 , handler : Instruction < Db > ) -> Instruction < Db > {
192+ std:: mem:: replace ( & mut self . inner . instruction . instruction_table [ opcode as usize ] , handler)
193+ }
194+
195+ /// Disable an opcode by replacing it with unknown opcode behavior. This is
196+ /// a shortcut for [`Self::override_opcode`] with [`crate::helpers::forbidden`].
197+ pub fn disable_opcode ( & mut self , opcode : u8 ) -> Instruction < Db > {
198+ self . override_opcode ( opcode, crate :: helpers:: forbidden)
199+ }
200+
201+ /// Run some closure with an opcode override, then restore the previous
202+ /// setting.
203+ pub fn with_opcode_override < F , NewState > (
204+ mut self ,
205+ opcode : u8 ,
206+ handler : Instruction < Db > ,
207+ f : F ,
208+ ) -> Trevm < Db , Insp , NewState >
209+ where
210+ F : FnOnce ( Self ) -> Trevm < Db , Insp , NewState > ,
211+ {
212+ let old = self . override_opcode ( opcode, handler) ;
213+ self . inner . instruction . insert_instruction ( opcode, handler) ;
214+ let mut this = f ( self ) ;
215+ this. override_opcode ( opcode, old) ;
216+ this
217+ }
218+
219+ /// Disable the prevrandao opcode, by replacing it with unknown opcode
220+ /// behavior. This is useful for block simulation, where the prevrandao
221+ /// opcode may produce incorrect results.
222+ pub fn disable_prevrandao ( & mut self ) -> Instruction < Db > {
223+ self . disable_opcode ( DIFFICULTY )
224+ }
225+
226+ /// Enable the prevrandao opcode. If the prevrandao opcode was not
227+ /// previously disabled or replaced, this will have no effect on behavior.
228+ pub fn enable_prevrandao ( & mut self ) -> Instruction < Db > {
229+ self . override_opcode ( DIFFICULTY , block_info:: difficulty)
230+ }
231+
232+ /// Run some code with the prevrandao opcode disabled, then restore the
233+ /// previous setting. This is useful for block simulation, where the
234+ /// prevrandao opcode may produce incorrect results.
235+ pub fn without_prevrandao < F , NewState > ( self , f : F ) -> Trevm < Db , Insp , NewState >
236+ where
237+ F : FnOnce ( Self ) -> Trevm < Db , Insp , NewState > ,
238+ {
239+ self . with_opcode_override ( DIFFICULTY , crate :: helpers:: forbidden, f)
240+ }
241+
242+ /// Set the precompiles for the EVM. This will replace the current
243+ /// precompiles with the provided ones.
244+ pub fn override_precompiles ( & mut self , precompiles : EthPrecompiles ) -> EthPrecompiles {
245+ std:: mem:: replace ( & mut self . inner . precompiles , precompiles)
246+ }
247+
248+ /// Run a closure with a different set of precompiles, then restore the
249+ /// previous setting.
250+ pub fn with_precompiles < F , NewState > (
251+ mut self ,
252+ precompiles : EthPrecompiles ,
253+ f : F ,
254+ ) -> Trevm < Db , Insp , NewState >
255+ where
256+ F : FnOnce ( Self ) -> Trevm < Db , Insp , NewState > ,
257+ {
258+ let old = self . override_precompiles ( precompiles) ;
259+ let mut this = f ( self ) ;
260+ this. override_precompiles ( old) ;
261+ this
262+ }
186263}
187264
188265// Fallible DB Reads with &mut self
0 commit comments