11use crate :: { SignetCallBundle , SignetCallBundleResponse } ;
22use alloy:: { consensus:: TxEnvelope , primitives:: U256 } ;
33use signet_evm:: OrderDetector ;
4- use signet_types:: { MarketContext , MarketError } ;
54use std:: fmt:: Debug ;
5+ use tracing:: { debug_span, instrument, Level } ;
66use trevm:: {
77 revm:: { primitives:: EVMError , Database , DatabaseCommit } ,
88 trevm_bail, trevm_ensure, unwrap_or_trevm_err, BundleDriver , BundleError ,
99} ;
1010
11- /// Errors that can occur when running a bundle on the Signet EVM.
12- #[ derive( thiserror:: Error ) ]
13- pub enum SignetBundleError < Db : Database > {
14- /// A primitive [`BundleError`] error ocurred.
15- #[ error( transparent) ]
16- BundleError ( #[ from] BundleError < Db > ) ,
17- /// A [`MarketError`] ocurred.
18- #[ error( transparent) ]
19- MarketError ( #[ from] MarketError ) ,
20- }
21-
22- impl < Db : Database > Debug for SignetBundleError < Db > {
23- fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
24- match self {
25- SignetBundleError :: BundleError ( e) => write ! ( f, "BundleError({:?})" , e) ,
26- SignetBundleError :: MarketError ( e) => write ! ( f, "MarketError({:?})" , e) ,
27- }
28- }
29- }
30-
31- impl < Db : Database > From < EVMError < Db :: Error > > for SignetBundleError < Db > {
32- fn from ( e : EVMError < Db :: Error > ) -> Self {
33- SignetBundleError :: BundleError ( BundleError :: EVMError { inner : e } )
34- }
35- }
36-
37- impl < Db : Database > SignetBundleError < Db > {
38- /// Instantiate a new [`SignetBundleError`] from a [`Database::Error`].
39- pub const fn evm_db ( e : Db :: Error ) -> Self {
40- SignetBundleError :: BundleError ( BundleError :: EVMError { inner : EVMError :: Database ( e) } )
41- }
42- }
43-
4411/// A bundle driver for the Signet EVM.
12+ ///
13+ /// This type allows for the simulation of a [`SignetCallBundle`], outputting
14+ /// the results of the simulation in a [`SignetCallBundleResponse`].
4515#[ derive( Debug ) ]
4616pub struct SignetBundleDriver < ' a > {
4717 /// The bundle to drive.
4818 bundle : & ' a SignetCallBundle ,
4919 /// The accumulated results of the bundle, if applicable.
5020 response : SignetCallBundleResponse ,
51- /// The market context.
52- context : MarketContext ,
53- /// The host chain id.
54- host_chain_id : u64 ,
21+ }
22+
23+ impl < ' a > From < & ' a SignetCallBundle > for SignetBundleDriver < ' a > {
24+ fn from ( bundle : & ' a SignetCallBundle ) -> Self {
25+ Self :: new ( bundle)
26+ }
5527}
5628
5729impl < ' a > SignetBundleDriver < ' a > {
5830 /// Create a new bundle driver with the given bundle and response.
59- pub fn new ( bundle : & ' a SignetCallBundle , host_chain_id : u64 ) -> Self {
60- let context = bundle. make_context ( host_chain_id) ;
61- Self { bundle, response : Default :: default ( ) , context, host_chain_id }
31+ pub fn new ( bundle : & ' a SignetCallBundle ) -> Self {
32+ Self { bundle, response : Default :: default ( ) }
6233 }
6334}
6435
@@ -73,55 +44,32 @@ impl SignetBundleDriver<'_> {
7344 & self . response
7445 }
7546
76- /// Get a reference to the market context.
77- pub const fn context ( & self ) -> & MarketContext {
78- & self . context
79- }
80-
8147 /// Take the response from the bundle driver. This consumes
8248 pub fn into_response ( self ) -> SignetCallBundleResponse {
8349 self . response
8450 }
8551
86- /// Clear the driver, resetting the response and the market context. This
87- /// reset the driver, allowing for resimulation of the same bundle.
88- ///
89- /// The returned context contains the amount of overfill, i.e. the amount
90- /// that was filled, but not required by the orders in the bundle.
91- pub fn clear ( & mut self ) -> ( SignetCallBundleResponse , MarketContext ) {
92- let r = std:: mem:: take ( & mut self . response ) ;
93- let context = self . bundle . make_context ( self . host_chain_id ) ;
94- let c = std:: mem:: replace ( & mut self . context , context) ;
95- ( r, c)
52+ /// Clear the driver, resetting the response.
53+ pub fn clear ( & mut self ) -> SignetCallBundleResponse {
54+ std:: mem:: take ( & mut self . response )
9655 }
9756
98- /// Check the market context , accept the result, accumulate the transaction
57+ /// Check the aggregate fills , accept the result, accumulate the transaction
9958 /// details into the response.
100- fn check_market_and_accept < ' a , Db : Database + DatabaseCommit , I > (
59+ fn accept_and_accumulate < ' a , Db : Database + DatabaseCommit , I > (
10160 & mut self ,
102- mut trevm : signet_evm:: EvmTransacted < ' a , Db , I > ,
61+ trevm : signet_evm:: EvmTransacted < ' a , Db , I > ,
10362 tx : & TxEnvelope ,
10463 pre_sim_coinbase_balance : & mut U256 ,
10564 basefee : U256 ,
10665 ) -> signet_evm:: DriveBundleResult < ' a , Db , Self , I > {
10766 let coinbase = trevm. inner ( ) . block ( ) . coinbase ;
10867
109- // Taking these clears the context for reuse.
110- let ( aggregate, market_context) =
111- trevm. inner_mut_unchecked ( ) . context . external . take_aggregate ( ) ;
112-
113- // We check the market context here, and if it fails, we discard the
114- // transaction outcome and push a failure receipt.
115- if let Err ( err) = self . context . checked_remove_ru_tx_events ( & aggregate, & market_context) {
116- tracing:: debug!( %err, "Discarding transaction outcome due to market error" ) ;
117- return Err ( trevm. errored ( SignetBundleError :: MarketError ( err) ) ) ;
118- }
119-
12068 let ( execution_result, mut trevm) = trevm. accept ( ) ;
12169
12270 // Get the post simulation coinbase balance
12371 let post_sim_coinbase_balance = unwrap_or_trevm_err ! (
124- trevm. try_read_balance( coinbase) . map_err( SignetBundleError :: evm_db ) ,
72+ trevm. try_read_balance( coinbase) . map_err( EVMError :: Database ) . map_err ( BundleError :: from ) ,
12573 trevm
12674 ) ;
12775
@@ -143,10 +91,11 @@ impl SignetBundleDriver<'_> {
14391
14492// [`BundleDriver`] Implementation for [`SignetCallBundle`].
14593// This is useful mainly for the `signet_simBundle` endpoint,
146- // which is used to simulate a signet bundle while respecting market context .
94+ // which is used to simulate a signet bundle while respecting aggregate fills .
14795impl < I > BundleDriver < OrderDetector < I > > for SignetBundleDriver < ' _ > {
148- type Error < Db : Database + DatabaseCommit > = SignetBundleError < Db > ;
96+ type Error < Db : Database + DatabaseCommit > = BundleError < Db > ;
14997
98+ #[ instrument( skip_all, level = Level :: DEBUG ) ]
15099 fn run_bundle < ' a , Db : Database + DatabaseCommit > (
151100 & mut self ,
152101 trevm : signet_evm:: EvmNeedsTx < ' a , Db , I > ,
@@ -155,56 +104,63 @@ impl<I> BundleDriver<OrderDetector<I>> for SignetBundleDriver<'_> {
155104 let bundle = & self . bundle . bundle ;
156105
157106 // Ensure that the bundle has transactions
158- trevm_ensure ! ( !bundle. txs. is_empty( ) , trevm, BundleError :: BundleEmpty . into ( ) ) ;
107+ trevm_ensure ! ( !bundle. txs. is_empty( ) , trevm, BundleError :: BundleEmpty ) ;
159108
160109 // Check if the block we're in is valid for this bundle. Both must match
161110 trevm_ensure ! (
162- trevm. inner ( ) . block ( ) . number . to:: <u64 >( ) == bundle. block_number,
111+ trevm. block_number ( ) . to:: <u64 >( ) == bundle. block_number,
163112 trevm,
164- BundleError :: BlockNumberMismatch . into ( )
113+ BundleError :: BlockNumberMismatch
165114 ) ;
115+ // Set the state block number this simulation was based on
116+ self . response . state_block_number = trevm. block_number ( ) . to :: < u64 > ( ) ;
166117
167118 // Check if the state block number is valid (not 0, and not a tag)
168119 trevm_ensure ! (
169120 bundle. state_block_number. is_number( )
170121 && bundle. state_block_number. as_number( ) . unwrap_or_default( ) != 0 ,
171122 trevm,
172- BundleError :: BlockNumberMismatch . into ( )
123+ BundleError :: BlockNumberMismatch
173124 ) ;
174125
175126 // Decode and validate the transactions in the bundle
176127 let txs = unwrap_or_trevm_err ! ( self . bundle. decode_and_validate_txs( ) , trevm) ;
177128
178129 trevm. try_with_block ( self . bundle , |mut trevm| {
179130 // Get the coinbase and basefee from the block
180- let coinbase = trevm. inner ( ) . block ( ) . coinbase ;
181- let basefee = trevm. inner ( ) . block ( ) . basefee ;
182-
183- // Set the state block number this simulation was based on
184- self . response . state_block_number = trevm. inner ( ) . block ( ) . number . to :: < u64 > ( ) ;
131+ // NB: Do not move these outside the `try_with_block` closure, as
132+ // they may be rewritten by the bundle
133+ let coinbase = trevm. block ( ) . coinbase ;
134+ let basefee = trevm. block ( ) . basefee ;
185135
186136 // Cache the pre simulation coinbase balance, so we can use it to calculate the coinbase diff after every tx simulated.
187137 let initial_coinbase_balance = unwrap_or_trevm_err ! (
188- trevm. try_read_balance( coinbase) . map_err( SignetBundleError :: evm_db) ,
138+ trevm
139+ . try_read_balance( coinbase)
140+ . map_err( EVMError :: Database )
141+ . map_err( BundleError :: from) ,
189142 trevm
190143 ) ;
191144
192145 // Stack vars to keep track of the coinbase balance across txs.
193146 let mut pre_sim_coinbase_balance = initial_coinbase_balance;
194147
195- for tx in txs. iter ( ) {
148+ let span = debug_span ! ( "bundle loop" , count = txs. len( ) ) . entered ( ) ;
149+ for ( idx, tx) in txs. iter ( ) . enumerate ( ) {
150+ let _span = debug_span ! ( "tx loop" , tx = %tx. tx_hash( ) , idx) . entered ( ) ;
196151 let run_result = trevm. run_tx ( tx) ;
197152
198153 let transacted_trevm = run_result. map_err ( |e| e. map_err ( Into :: into) ) ?;
199154
200155 // Set the trevm instance to the committed one
201- trevm = self . check_market_and_accept (
156+ trevm = self . accept_and_accumulate (
202157 transacted_trevm,
203158 tx,
204159 & mut pre_sim_coinbase_balance,
205160 basefee,
206161 ) ?;
207162 }
163+ drop ( span) ;
208164
209165 // Accumulate the total results
210166 self . response . coinbase_diff =
@@ -218,6 +174,11 @@ impl<I> BundleDriver<OrderDetector<I>> for SignetBundleDriver<'_> {
218174 . unwrap_or_default ( ) ;
219175 self . response . bundle_hash = self . bundle . bundle_hash ( ) ;
220176
177+ // Taking these clears the order detector
178+ let ( orders, fills) = trevm. inner_mut_unchecked ( ) . context . external . take_aggregates ( ) ;
179+ self . response . orders = orders;
180+ self . response . fills = fills;
181+
221182 // return the final state
222183 Ok ( trevm)
223184 } )
0 commit comments