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