1
1
use crate :: {
2
2
db:: { StateAcc , TryStateAcc } ,
3
3
driver:: DriveBlockResult ,
4
- helpers:: { Ctx , Evm } ,
4
+ helpers:: { Ctx , Evm , Instruction } ,
5
5
Block , BlockDriver , BundleDriver , Cfg , ChainDriver , DriveBundleResult , DriveChainResult ,
6
6
ErroredState , EvmErrored , EvmExtUnchecked , EvmNeedsBlock , EvmNeedsCfg , EvmNeedsTx , EvmReady ,
7
7
EvmTransacted , HasBlock , HasCfg , HasTx , NeedsCfg , NeedsTx , TransactedState , Tx ,
@@ -12,13 +12,15 @@ use alloy::{
12
12
} ;
13
13
use core:: { convert:: Infallible , fmt} ;
14
14
use revm:: {
15
+ bytecode:: opcode:: DIFFICULTY ,
15
16
context:: {
16
17
result:: { EVMError , ExecutionResult , InvalidTransaction , ResultAndState } ,
17
18
Block as _, BlockEnv , Cfg as _, ContextSetters , ContextTr , Transaction as _, TxEnv ,
18
19
} ,
19
20
database:: { states:: bundle_state:: BundleRetention , BundleState , TryDatabaseCommit } ,
21
+ handler:: EthPrecompiles ,
20
22
inspector:: NoOpInspector ,
21
- interpreter:: gas:: calculate_initial_tx_gas_for_tx,
23
+ interpreter:: { gas:: calculate_initial_tx_gas_for_tx, instructions :: block_info } ,
22
24
primitives:: { hardfork:: SpecId , TxKind } ,
23
25
state:: { AccountInfo , Bytecode , EvmState } ,
24
26
Database , DatabaseCommit , DatabaseRef , InspectEvm , Inspector ,
@@ -183,6 +185,81 @@ where
183
185
Ok ( self )
184
186
}
185
187
}
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
+ }
186
263
}
187
264
188
265
// Fallible DB Reads with &mut self
0 commit comments