@@ -23,6 +23,7 @@ use crate::{
23
23
pool:: transactions:: PoolTransaction ,
24
24
util:: get_precompiles_for,
25
25
} ,
26
+ inject_precompiles,
26
27
mem:: {
27
28
inspector:: Inspector ,
28
29
storage:: { BlockchainStorage , InMemoryBlockStates , MinedBlockOutcome } ,
@@ -31,7 +32,7 @@ use crate::{
31
32
db:: DatabaseRef ,
32
33
primitives:: { AccountInfo , U256 as rU256} ,
33
34
} ,
34
- NodeConfig ,
35
+ NodeConfig , PrecompileFactory ,
35
36
} ;
36
37
use alloy_consensus:: { Header , Receipt , ReceiptWithBloom } ;
37
38
use alloy_primitives:: { keccak256, Address , Bytes , TxHash , B256 , U256 , U64 } ;
@@ -78,7 +79,10 @@ use foundry_evm::{
78
79
} ;
79
80
use futures:: channel:: mpsc:: { unbounded, UnboundedSender } ;
80
81
use parking_lot:: { Mutex , RwLock } ;
81
- use revm:: primitives:: { HashMap , ResultAndState } ;
82
+ use revm:: {
83
+ db:: WrapDatabaseRef ,
84
+ primitives:: { HashMap , ResultAndState } ,
85
+ } ;
82
86
use std:: {
83
87
collections:: BTreeMap ,
84
88
io:: { Read , Write } ,
@@ -168,6 +172,8 @@ pub struct Backend {
168
172
node_config : Arc < AsyncRwLock < NodeConfig > > ,
169
173
/// Slots in an epoch
170
174
slots_in_an_epoch : u64 ,
175
+ /// Precompiles to inject to the EVM.
176
+ precompile_factory : Option < Arc < dyn PrecompileFactory > > ,
171
177
}
172
178
173
179
impl Backend {
@@ -214,7 +220,10 @@ impl Backend {
214
220
Default :: default ( )
215
221
} ;
216
222
217
- let slots_in_an_epoch = node_config. read ( ) . await . slots_in_an_epoch ;
223
+ let ( slots_in_an_epoch, precompile_factory) = {
224
+ let cfg = node_config. read ( ) . await ;
225
+ ( cfg. slots_in_an_epoch , cfg. precompile_factory . clone ( ) )
226
+ } ;
218
227
219
228
let backend = Self {
220
229
db,
@@ -233,6 +242,7 @@ impl Backend {
233
242
transaction_block_keeper,
234
243
node_config,
235
244
slots_in_an_epoch,
245
+ precompile_factory,
236
246
} ;
237
247
238
248
if let Some ( interval_block_time) = automine_block_time {
@@ -800,6 +810,24 @@ impl Backend {
800
810
env
801
811
}
802
812
813
+ /// Creates an EVM instance with optionally injected precompiles.
814
+ fn new_evm_with_inspector_ref < DB , I > (
815
+ & self ,
816
+ db : DB ,
817
+ env : EnvWithHandlerCfg ,
818
+ inspector : I ,
819
+ ) -> revm:: Evm < ' _ , I , WrapDatabaseRef < DB > >
820
+ where
821
+ DB : revm:: DatabaseRef ,
822
+ I : revm:: Inspector < WrapDatabaseRef < DB > > ,
823
+ {
824
+ let mut evm = new_evm_with_inspector_ref ( db, env, inspector) ;
825
+ if let Some ( ref factory) = self . precompile_factory {
826
+ inject_precompiles ( & mut evm, factory. precompiles ( ) ) ;
827
+ }
828
+ evm
829
+ }
830
+
803
831
/// executes the transactions without writing to the underlying database
804
832
pub async fn inspect_tx (
805
833
& self ,
@@ -812,9 +840,8 @@ impl Backend {
812
840
env. tx = tx. pending_transaction . to_revm_tx_env ( ) ;
813
841
let db = self . db . read ( ) . await ;
814
842
let mut inspector = Inspector :: default ( ) ;
815
-
816
- let ResultAndState { result, state } =
817
- new_evm_with_inspector_ref ( & * db, env, & mut inspector) . transact ( ) ?;
843
+ let mut evm = self . new_evm_with_inspector_ref ( & * db, env, & mut inspector) ;
844
+ let ResultAndState { result, state } = evm. transact ( ) ?;
818
845
let ( exit_reason, gas_used, out, logs) = match result {
819
846
ExecutionResult :: Success { reason, gas_used, logs, output, .. } => {
820
847
( reason. into ( ) , gas_used, Some ( output) , Some ( logs) )
@@ -825,6 +852,7 @@ impl Backend {
825
852
ExecutionResult :: Halt { reason, gas_used } => ( reason. into ( ) , gas_used, None , None ) ,
826
853
} ;
827
854
855
+ drop ( evm) ;
828
856
inspector. print_logs ( ) ;
829
857
830
858
Ok ( ( exit_reason, out, gas_used, state, logs. unwrap_or_default ( ) ) )
@@ -865,6 +893,7 @@ impl Backend {
865
893
parent_hash : storage. best_hash ,
866
894
gas_used : 0 ,
867
895
enable_steps_tracing : self . enable_steps_tracing ,
896
+ precompile_factory : self . precompile_factory . clone ( ) ,
868
897
} ;
869
898
870
899
// create a new pending block
@@ -924,6 +953,7 @@ impl Backend {
924
953
parent_hash : best_hash,
925
954
gas_used : 0 ,
926
955
enable_steps_tracing : self . enable_steps_tracing ,
956
+ precompile_factory : self . precompile_factory . clone ( ) ,
927
957
} ;
928
958
let executed_tx = executor. execute ( ) ;
929
959
@@ -1123,8 +1153,8 @@ impl Backend {
1123
1153
let mut inspector = Inspector :: default ( ) ;
1124
1154
1125
1155
let env = self . build_call_env ( request, fee_details, block_env) ;
1126
- let ResultAndState { result , state } =
1127
- new_evm_with_inspector_ref ( state, env , & mut inspector ) . transact ( ) ?;
1156
+ let mut evm = self . new_evm_with_inspector_ref ( state, env , & mut inspector ) ;
1157
+ let ResultAndState { result , state } = evm . transact ( ) ?;
1128
1158
let ( exit_reason, gas_used, out) = match result {
1129
1159
ExecutionResult :: Success { reason, gas_used, output, .. } => {
1130
1160
( reason. into ( ) , gas_used, Some ( output) )
@@ -1134,6 +1164,7 @@ impl Backend {
1134
1164
}
1135
1165
ExecutionResult :: Halt { reason, gas_used } => ( reason. into ( ) , gas_used, None ) ,
1136
1166
} ;
1167
+ drop ( evm) ;
1137
1168
inspector. print_logs ( ) ;
1138
1169
Ok ( ( exit_reason, out, gas_used as u128 , state) )
1139
1170
}
@@ -1150,8 +1181,9 @@ impl Backend {
1150
1181
let block_number = block. number ;
1151
1182
1152
1183
let env = self . build_call_env ( request, fee_details, block) ;
1153
- let ResultAndState { result, state : _ } =
1154
- new_evm_with_inspector_ref ( state, env, & mut inspector) . transact ( ) ?;
1184
+ let mut evm = self . new_evm_with_inspector_ref ( state, env, & mut inspector) ;
1185
+ let ResultAndState { result, state : _ } = evm. transact ( ) ?;
1186
+
1155
1187
let ( exit_reason, gas_used, out) = match result {
1156
1188
ExecutionResult :: Success { reason, gas_used, output, .. } => {
1157
1189
( reason. into ( ) , gas_used, Some ( output) )
@@ -1161,6 +1193,8 @@ impl Backend {
1161
1193
}
1162
1194
ExecutionResult :: Halt { reason, gas_used } => ( reason. into ( ) , gas_used, None ) ,
1163
1195
} ;
1196
+
1197
+ drop ( evm) ;
1164
1198
let tracer = inspector. tracer . expect ( "tracer disappeared" ) ;
1165
1199
let return_value = out. as_ref ( ) . map ( |o| o. data ( ) . clone ( ) ) . unwrap_or_default ( ) ;
1166
1200
let res = tracer. into_geth_builder ( ) . geth_traces ( gas_used, return_value, opts) ;
@@ -1196,8 +1230,8 @@ impl Backend {
1196
1230
) ;
1197
1231
1198
1232
let env = self . build_call_env ( request, fee_details, block_env) ;
1199
- let ResultAndState { result , state : _ } =
1200
- new_evm_with_inspector_ref ( state, env , & mut inspector ) . transact ( ) ?;
1233
+ let mut evm = self . new_evm_with_inspector_ref ( state, env , & mut inspector ) ;
1234
+ let ResultAndState { result , state : _ } = evm . transact ( ) ?;
1201
1235
let ( exit_reason, gas_used, out) = match result {
1202
1236
ExecutionResult :: Success { reason, gas_used, output, .. } => {
1203
1237
( reason. into ( ) , gas_used, Some ( output) )
@@ -1207,6 +1241,7 @@ impl Backend {
1207
1241
}
1208
1242
ExecutionResult :: Halt { reason, gas_used } => ( reason. into ( ) , gas_used, None ) ,
1209
1243
} ;
1244
+ drop ( evm) ;
1210
1245
let access_list = inspector. access_list ( ) ;
1211
1246
Ok ( ( exit_reason, out, gas_used, access_list) )
1212
1247
}
0 commit comments