@@ -12,7 +12,7 @@ use alloy_rlp::Buf;
12
12
use std:: time:: { SystemTime , UNIX_EPOCH } ;
13
13
use std:: { sync:: OnceLock , time:: Duration } ;
14
14
use tokio:: { sync:: mpsc, task:: JoinHandle } ;
15
- use tracing:: Instrument ;
15
+ use tracing:: { debug , error , Instrument } ;
16
16
use zenith_types:: { encode_txns, Alloy2718Coder } ;
17
17
18
18
/// Ethereum's slot time in seconds.
@@ -71,7 +71,7 @@ impl InProgressBlock {
71
71
/// Ingest a bundle into the in-progress block.
72
72
/// Ignores Signed Orders for now.
73
73
pub fn ingest_bundle ( & mut self , bundle : Bundle ) {
74
- tracing :: trace !( bundle = %bundle. id, "ingesting bundle" ) ;
74
+ debug ! ( bundle = %bundle. id, "ingesting bundle" ) ;
75
75
76
76
let txs = bundle
77
77
. bundle
@@ -83,11 +83,9 @@ impl InProgressBlock {
83
83
84
84
if let Ok ( txs) = txs {
85
85
self . unseal ( ) ;
86
- // extend the transactions with the decoded transactions.
87
- // As this builder does not provide bundles landing "top of block", its fine to just extend.
88
86
self . transactions . extend ( txs) ;
89
87
} else {
90
- tracing :: error!( "failed to decode bundle. dropping" ) ;
88
+ error ! ( "failed to decode bundle. dropping" ) ;
91
89
}
92
90
}
93
91
@@ -155,12 +153,12 @@ impl BlockBuilder {
155
153
}
156
154
}
157
155
158
- async fn _get_bundles ( & mut self , in_progress : & mut InProgressBlock ) {
156
+ async fn get_bundles ( & mut self , in_progress : & mut InProgressBlock ) {
159
157
tracing:: trace!( "query bundles from cache" ) ;
160
158
let bundles = self . bundle_poller . check_bundle_cache ( ) . await ;
159
+ // OPTIMIZE: Sort bundles received from cache
161
160
match bundles {
162
161
Ok ( bundles) => {
163
- tracing:: trace!( "got bundles response" ) ;
164
162
for bundle in bundles {
165
163
in_progress. ingest_bundle ( bundle) ;
166
164
}
@@ -218,9 +216,7 @@ impl BlockBuilder {
218
216
// Build a block
219
217
let mut in_progress = InProgressBlock :: default ( ) ;
220
218
self . get_transactions ( & mut in_progress) . await ;
221
-
222
- // TODO: Implement bundle ingestion #later
223
- // self.get_bundles(&mut in_progress).await;
219
+ self . get_bundles ( & mut in_progress) . await ;
224
220
225
221
// Filter confirmed transactions from the block
226
222
self . filter_transactions ( & mut in_progress) . await ;
@@ -242,3 +238,71 @@ impl BlockBuilder {
242
238
)
243
239
}
244
240
}
241
+
242
+ #[ cfg( test) ]
243
+ mod tests {
244
+ use super :: * ;
245
+ use alloy:: primitives:: Address ;
246
+ use alloy:: {
247
+ eips:: eip2718:: Encodable2718 ,
248
+ network:: { EthereumWallet , TransactionBuilder } ,
249
+ rpc:: types:: { mev:: EthSendBundle , TransactionRequest } ,
250
+ signers:: local:: PrivateKeySigner ,
251
+ } ;
252
+ use zenith_types:: ZenithEthBundle ;
253
+
254
+ /// Create a mock bundle for testing with a single transaction
255
+ async fn create_mock_bundle ( wallet : & EthereumWallet ) -> Bundle {
256
+ let tx = TransactionRequest :: default ( )
257
+ . to ( Address :: ZERO )
258
+ . from ( wallet. default_signer ( ) . address ( ) )
259
+ . nonce ( 1 )
260
+ . max_fee_per_gas ( 2 )
261
+ . max_priority_fee_per_gas ( 3 )
262
+ . gas_limit ( 4 )
263
+ . build ( wallet)
264
+ . await
265
+ . unwrap ( )
266
+ . encoded_2718 ( ) ;
267
+
268
+ let eth_bundle = EthSendBundle {
269
+ txs : vec ! [ tx. into( ) ] ,
270
+ block_number : 1 ,
271
+ min_timestamp : Some ( u64:: MIN ) ,
272
+ max_timestamp : Some ( u64:: MAX ) ,
273
+ reverting_tx_hashes : vec ! [ ] ,
274
+ replacement_uuid : Some ( "replacement_uuid" . to_owned ( ) ) ,
275
+ } ;
276
+
277
+ let zenith_bundle = ZenithEthBundle { bundle : eth_bundle, host_fills : None } ;
278
+
279
+ Bundle { id : "mock_bundle" . to_owned ( ) , bundle : zenith_bundle }
280
+ }
281
+
282
+ #[ tokio:: test]
283
+ async fn test_ingest_bundle ( ) {
284
+ // Setup random creds
285
+ let signer = PrivateKeySigner :: random ( ) ;
286
+ let wallet = EthereumWallet :: from ( signer) ;
287
+
288
+ // Create an empty InProgressBlock and bundle
289
+ let mut in_progress_block = InProgressBlock :: new ( ) ;
290
+ let bundle = create_mock_bundle ( & wallet) . await ;
291
+
292
+ // Save previous hash for comparison
293
+ let prev_hash = in_progress_block. contents_hash ( ) ;
294
+
295
+ // Ingest the bundle
296
+ in_progress_block. ingest_bundle ( bundle) ;
297
+
298
+ // Assert hash is changed after ingest
299
+ assert_ne ! ( prev_hash, in_progress_block. contents_hash( ) , "Bundle should change block hash" ) ;
300
+
301
+ // Assert that the transaction was persisted into block
302
+ assert_eq ! ( in_progress_block. len( ) , 1 , "Bundle should be persisted" ) ;
303
+
304
+ // Assert that the block is properly sealed
305
+ let raw_encoding = in_progress_block. encode_raw ( ) ;
306
+ assert ! ( !raw_encoding. is_empty( ) , "Raw encoding should not be empty" ) ;
307
+ }
308
+ }
0 commit comments