@@ -2,16 +2,14 @@ use crate::tasks::block::InProgressBlock;
2
2
use alloy:: consensus:: TxEnvelope ;
3
3
use alloy:: primitives:: U256 ;
4
4
use eyre:: Result ;
5
- use revm:: { db:: CacheDB , primitives:: { address, Account , CfgEnv , ExecutionResult } , DatabaseRef } ;
6
- use std:: { convert:: Infallible , sync:: Arc } ;
5
+ use std:: sync:: Arc ;
7
6
use tokio:: { select, sync:: mpsc:: UnboundedReceiver , task:: JoinSet } ;
8
7
use trevm:: {
9
- db:: sync:: { ConcurrentState , ConcurrentStateInfo } ,
10
- revm:: {
11
- primitives:: { EVMError , ResultAndState } ,
12
- Database , DatabaseCommit , EvmBuilder ,
13
- } ,
14
- BlockDriver , Cfg , DbConnect , EvmFactory , NoopBlock , TrevmBuilder , Tx ,
8
+ db:: sync:: { ConcurrentState , ConcurrentStateInfo } , helpers:: Ctx , revm:: {
9
+ context:: {
10
+ result:: { EVMError , ExecutionResult , ResultAndState } , CfgEnv
11
+ } , inspector:: inspectors:: GasInspector , primitives:: address, state:: Account , Database , DatabaseCommit , DatabaseRef , Inspector
12
+ } , BlockDriver , Cfg , DbConnect , EvmFactory , NoopBlock , Trevm , TrevmBuilder , TrevmBuilderError , Tx
15
13
} ;
16
14
17
15
/// Tracks the EVM state, score, and result of an EVM execution.
@@ -29,47 +27,43 @@ pub struct Best<T, S: PartialOrd + Ord = U256> {
29
27
30
28
/// Binds a database and an extension together.
31
29
#[ derive( Debug , Clone ) ]
32
- pub struct SimulatorFactory < Db , Ext > {
30
+ pub struct SimulatorFactory < Db , Insp > {
33
31
/// The database state the execution is carried out on.
34
32
pub db : Db ,
35
- /// The extension, if any, provided to the trevm instance.
36
- pub ext : Ext ,
33
+ /// The inspector
34
+ pub inspector : Insp ,
37
35
}
38
36
39
37
/// SimResult is an [`Option`] type that holds a tuple of a transaction and its associated
40
38
/// state as a [`Db`] type updates if it was successfully executed.
41
- type SimResult < Db > = Option < ( Best < TxEnvelope > , ConcurrentState < Arc < ConcurrentState < Db > > > ) > ;
39
+ type SimResult < Db > = Result < Option < ( Best < TxEnvelope > , ConcurrentState < Arc < ConcurrentState < Db > > > ) > > ;
42
40
43
- impl < Db , Ext > SimulatorFactory < Db , Ext >
41
+ impl < Db , Insp > SimulatorFactory < Db , Insp >
44
42
where
45
- Ext : Send + Sync + Clone + ' static ,
43
+ Insp : Inspector < Ctx < ConcurrentState < Db > > > + Send + Sync + Clone + ' static ,
46
44
Db : Database + DatabaseRef + DatabaseCommit + Send + Sync + Clone + ' static ,
47
45
{
48
46
/// Creates a new Simulator factory out of the database and extension.
49
- pub const fn new ( db : Db , ext : Ext ) -> Self {
50
- Self { db, ext }
47
+ pub const fn new ( db : Db , inspector : Insp ) -> Self {
48
+ Self { db, inspector }
51
49
}
52
50
53
51
/// Spawns a trevm simulator that runs until `deadline` is hit.
54
52
/// * Spawn does not guarantee that a thread is finished before the deadline.
55
53
/// * This is intentional, so that it can maximize simulation time before the deadline.
56
54
/// * This function always returns whatever the latest finished in progress block is.
57
- pub fn spawn < T , F > (
55
+ pub fn spawn < F > (
58
56
self ,
59
57
mut inbound_tx : UnboundedReceiver < TxEnvelope > ,
60
58
evaluator : Arc < F > ,
61
59
deadline : tokio:: time:: Instant ,
62
60
) -> tokio:: task:: JoinHandle < InProgressBlock >
63
61
where
64
- T : Tx ,
65
62
F : Fn ( & ResultAndState ) -> U256 + Send + Sync + ' static ,
66
63
{
67
64
tokio:: spawn ( async move {
68
- // Spawn a join set to track all simulation threads
69
65
let mut join_set = JoinSet :: new ( ) ;
70
-
71
66
let mut best: Option < Best < TxEnvelope > > = None ;
72
-
73
67
let mut block = InProgressBlock :: new ( ) ;
74
68
75
69
let sleep = tokio:: time:: sleep_until ( deadline) ;
@@ -84,13 +78,13 @@ where
84
78
// Setup the simulation environment
85
79
let sim = self . clone( ) ;
86
80
let eval = evaluator. clone( ) ;
87
- let mut parent_db = Arc :: new( sim. connect( ) . unwrap( ) ) ;
81
+ let db = self . connect( ) . expect( "must connect db" ) ;
82
+ let mut parent_db = Arc :: new( db) ;
88
83
89
- // Kick off the work in a new thread
90
84
join_set. spawn( async move {
91
85
let result = sim. simulate_tx( inbound_tx, eval, parent_db. child( ) ) ;
92
86
93
- if let Some ( ( best, db) ) = result {
87
+ if let Ok ( Some ( ( best, db) ) ) = result {
94
88
if let Ok ( ( ) ) = parent_db. merge_child( db) {
95
89
tracing:: debug!( "merging updated simulation state" ) ;
96
90
return Some ( best)
@@ -141,34 +135,22 @@ where
141
135
F : Fn ( & ResultAndState ) -> U256 + Send + Sync + ' static ,
142
136
Db : Database + DatabaseRef + DatabaseCommit + Send + Sync + Clone + ' static ,
143
137
{
144
- let trevm_instance = EvmBuilder :: default ( ) . with_db ( db) . build_trevm ( ) ;
138
+ let t = TrevmBuilder :: new ( ) . with_db ( db) . with_insp ( self . inspector . clone ( ) ) . build_trevm ( ) ? ;
145
139
146
- let result = trevm_instance
147
- . fill_cfg ( & PecorinoCfg )
148
- . fill_block ( & NoopBlock )
149
- . fill_tx ( & tx) // Use as_ref() to get &SimTxEnvelope from Arc
150
- . run ( ) ;
140
+ let result = t. fill_cfg ( & PecorinoCfg ) . fill_block ( & NoopBlock ) . fill_tx ( & tx) . run ( ) ;
151
141
152
142
match result {
153
143
Ok ( t) => {
154
- // log and evaluate simulation results
155
- tracing:: info!( tx_hash = ?tx. clone( ) . tx_hash( ) , "transaction simulated" ) ;
156
144
let result = t. result_and_state ( ) . clone ( ) ;
157
- tracing :: debug! ( gas_used = & result . result . gas_used ( ) , "gas consumed" ) ;
145
+ let db = t . into_db ( ) ;
158
146
let score = evaluator ( & result) ;
159
- tracing :: debug! ( score = ? score, "transaction evaluated" ) ;
147
+ let best = Best { tx : Arc :: new ( tx ) , result , score } ;
160
148
161
- // accept results
162
- let t = t. accept ( ) ;
163
- let db = t. 1 . into_db ( ) ;
164
-
165
- // return the updated db with the candidate applied to its state
166
- Some ( ( Best { tx : Arc :: new ( tx) , result, score } , db) )
149
+ Ok ( Some ( ( best, db) ) )
167
150
}
168
- Err ( e) => {
169
- // if this transaction fails to run, log the error and return None
170
- tracing:: error!( err = ?e. as_transaction_error( ) , "failed to simulate tx" ) ;
171
- None
151
+ Err ( terr) => {
152
+ tracing:: error!( err = ?terr. error( ) , "transaction simulation error" ) ;
153
+ Ok ( None )
172
154
}
173
155
}
174
156
}
@@ -178,7 +160,7 @@ where
178
160
& self ,
179
161
_bundle : Arc < Vec < T > > ,
180
162
_evaluator : Arc < F > ,
181
- _trevm_instance : trevm :: EvmNeedsCfg < ' _ , ( ) , ConcurrentState < CacheDB < Arc < Db > > > > ,
163
+ _db : ConcurrentState < Arc < ConcurrentState < Db > > > ,
182
164
) -> Option < Best < Vec < T > > >
183
165
where
184
166
T : Tx + Send + Sync + ' static ,
@@ -188,52 +170,59 @@ where
188
170
}
189
171
}
190
172
191
- /// Wraps a Db into an EvmFactory compatible [`Database`]
192
- impl < ' a , Db , Ext > DbConnect < ' a > for SimulatorFactory < Db , Ext >
173
+ impl < Db , Insp > DbConnect for SimulatorFactory < Db , Insp >
193
174
where
194
175
Db : Database + DatabaseRef + DatabaseCommit + Sync + Send + Clone + ' static ,
195
- Ext : Sync + Clone ,
176
+ Insp : Inspector < Ctx < ConcurrentState < Db > > > + Sync + Send + Clone ,
196
177
{
197
178
type Database = ConcurrentState < Db > ;
198
- type Error = Infallible ;
179
+ type Error = TrevmBuilderError ;
199
180
200
- fn connect ( & ' a self ) -> Result < Self :: Database , Self :: Error > {
181
+ fn connect ( & self ) -> Result < Self :: Database , Self :: Error > {
201
182
let inner = ConcurrentState :: new ( self . db . clone ( ) , ConcurrentStateInfo :: default ( ) ) ;
202
183
Ok ( inner)
203
184
}
204
185
}
205
186
206
187
/// Makes a SimulatorFactory capable of creating and configuring trevm instances
207
- impl < ' a , Db , Ext > EvmFactory < ' a > for SimulatorFactory < Db , Ext >
188
+ impl < Db , Insp > EvmFactory for SimulatorFactory < Db , Insp >
208
189
where
209
190
Db : Database + DatabaseRef + DatabaseCommit + Sync + Send + Clone + ' static ,
210
- Ext : Sync + Clone ,
191
+ Insp : Inspector < Ctx < ConcurrentState < Db > > > + Sync + Send + Clone ,
211
192
{
212
- type Ext = ( ) ;
193
+ type Insp = Insp ;
213
194
214
- /// Create makes a [`ConcurrentState`] database by calling connect
215
- fn create ( & ' a self ) -> Result < trevm:: EvmNeedsCfg < ' a , Self :: Ext , Self :: Database > , Self :: Error > {
195
+ fn create (
196
+ & self ,
197
+ ) -> std:: result:: Result < trevm:: EvmNeedsCfg < Self :: Database , Self :: Insp > , Self :: Error > {
216
198
let db = self . connect ( ) ?;
217
- let trevm = trevm:: revm:: EvmBuilder :: default ( ) . with_db ( db) . build_trevm ( ) ;
218
- Ok ( trevm)
199
+ let result =
200
+ TrevmBuilder :: new ( ) . with_db ( db) . with_insp ( self . inspector . clone ( ) ) . build_trevm ( ) ;
201
+ match result {
202
+ Ok ( t) => Ok ( t) ,
203
+ Err ( e) => Err ( e. into ( ) ) ,
204
+ }
219
205
}
220
206
}
221
207
222
- /// A trait for extracting transactions from
223
- pub trait BlockExtractor < Ext , Db : Database + DatabaseCommit > : Send + Sync + ' static {
208
+ pub trait BlockExtractor < Insp , Db >
209
+ where
210
+ Db : Database + DatabaseCommit ,
211
+ Insp : Inspector < Ctx < Db > > ,
212
+ {
224
213
/// BlockDriver runs the transactions over the provided trevm instance.
225
- type Driver : BlockDriver < Ext , Error < Db > : core:: error:: Error > ;
214
+ type Driver : BlockDriver < Insp , Error < Db > : core:: error:: Error > ;
226
215
227
216
/// Instantiate an configure a new [`trevm`] instance.
228
- fn trevm ( & self , db : Db ) -> trevm:: EvmNeedsBlock < ' static , Ext , Db > ;
217
+ fn trevm ( & self , db : Db ) -> trevm:: EvmNeedsBlock < Db , Insp > ;
229
218
230
219
/// Extracts transactions from the source.
231
220
///
232
221
/// Extraction is infallible. Worst case it should return a no-op driver.
233
222
fn extract ( & mut self , bytes : & [ u8 ] ) -> Self :: Driver ;
234
223
}
235
224
236
- impl < Ext > BlockDriver < Ext > for InProgressBlock {
225
+ impl < Insp > BlockDriver < Insp > for InProgressBlock {
237
226
type Block = NoopBlock ;
238
227
239
228
type Error < Db : Database + DatabaseCommit > = Error < Db > ;
@@ -244,10 +233,13 @@ impl<Ext> BlockDriver<Ext> for InProgressBlock {
244
233
245
234
/// Loops through the transactions in the block and runs them, accepting the state at the end
246
235
/// if it was successful and returning and erroring out otherwise.
247
- fn run_txns < ' a , Db : Database + DatabaseCommit > (
236
+ fn run_txns < Db : Database + DatabaseCommit > (
248
237
& mut self ,
249
- mut trevm : trevm:: EvmNeedsTx < ' a , Ext , Db > ,
250
- ) -> trevm:: RunTxResult < ' a , Ext , Db , Self > {
238
+ mut trevm : trevm:: EvmNeedsTx < Db , Insp > ,
239
+ ) -> trevm:: RunTxResult < Db , Insp , Self >
240
+ where
241
+ Insp : Inspector < Ctx < Db > > ,
242
+ {
251
243
for tx in self . transactions ( ) . iter ( ) {
252
244
if tx. recover_signer ( ) . is_ok ( ) {
253
245
let sender = tx. recover_signer ( ) . unwrap ( ) ;
@@ -272,8 +264,11 @@ impl<Ext> BlockDriver<Ext> for InProgressBlock {
272
264
273
265
fn post_block < Db : Database + DatabaseCommit > (
274
266
& mut self ,
275
- _trevm : & trevm:: EvmNeedsBlock < ' _ , Ext , Db > ,
276
- ) -> Result < ( ) , Self :: Error < Db > > {
267
+ _trevm : & trevm:: EvmNeedsBlock < Db , Insp > ,
268
+ ) -> Result < ( ) , Self :: Error < Db > >
269
+ where
270
+ Insp : Inspector < Ctx < Db > > ,
271
+ {
277
272
Ok ( ( ) )
278
273
}
279
274
}
@@ -330,4 +325,4 @@ pub fn eval_fn(state: &ResultAndState) -> U256 {
330
325
tracing:: info!( balance = ?target_account. info. balance, "target account balance" ) ;
331
326
332
327
target_account. info . balance
333
- }
328
+ }
0 commit comments