@@ -25,14 +25,13 @@ use signet_zenith::{
25
25
Zenith :: { self , IncorrectHostBlock } ,
26
26
} ;
27
27
use std:: time:: { Instant , UNIX_EPOCH } ;
28
- use tokio:: { sync:: mpsc, task:: JoinHandle } ;
28
+ use tokio:: {
29
+ sync:: mpsc:: { self } ,
30
+ task:: JoinHandle ,
31
+ } ;
32
+ use trevm:: revm:: context:: BlockEnv ;
29
33
30
- /// Base maximum fee per gas to use as a starting point for retry bumps
31
- pub const BASE_FEE_PER_GAS : u128 = 10 * GWEI_TO_WEI as u128 ;
32
- /// Base max priority fee per gas to use as a starting point for retry bumps
33
- pub const BASE_MAX_PRIORITY_FEE_PER_GAS : u128 = 2 * GWEI_TO_WEI as u128 ;
34
- /// Base maximum fee per blob gas to use as a starting point for retry bumps
35
- pub const BASE_MAX_FEE_PER_BLOB_GAS : u128 = GWEI_TO_WEI as u128 ;
34
+ use super :: block:: sim:: SimResult ;
36
35
37
36
macro_rules! spawn_provider_send {
38
37
( $provider: expr, $tx: expr) => {
@@ -222,7 +221,7 @@ impl SubmitTask {
222
221
} )
223
222
}
224
223
225
- /// Builds blob transaction and encodes the sidecar for it from the provided header and signature values
224
+ /// Encodes the sidecar and then builds the 4844 blob transaction from the provided header and signature values.
226
225
fn build_blob_tx (
227
226
& self ,
228
227
fills : Vec < FillPermit2 > ,
@@ -245,8 +244,9 @@ impl SubmitTask {
245
244
retry_count : usize ,
246
245
resp : & SignResponse ,
247
246
block : & BuiltBlock ,
247
+ block_env : & BlockEnv ,
248
248
) -> eyre:: Result < ControlFlow > {
249
- let tx = self . prepare_tx ( retry_count, resp, block) . await ?;
249
+ let tx = self . prepare_tx ( retry_count, resp, block, block_env ) . await ?;
250
250
251
251
self . send_transaction ( resp, tx) . await
252
252
}
@@ -258,9 +258,11 @@ impl SubmitTask {
258
258
retry_count : usize ,
259
259
resp : & SignResponse ,
260
260
block : & BuiltBlock ,
261
+ block_env : & BlockEnv ,
261
262
) -> Result < TransactionRequest , eyre:: Error > {
262
263
// Create the transaction request with the signature values
263
- let tx: TransactionRequest = self . new_tx_request ( retry_count, resp, block) . await ?;
264
+ let tx: TransactionRequest =
265
+ self . new_tx_request ( retry_count, resp, block, block_env) . await ?;
264
266
265
267
// Simulate the transaction with a call to the host provider and report any errors
266
268
if let Err ( err) = self . sim_with_call ( & tx) . await {
@@ -288,6 +290,7 @@ impl SubmitTask {
288
290
retry_count : usize ,
289
291
resp : & SignResponse ,
290
292
block : & BuiltBlock ,
293
+ block_env : & BlockEnv ,
291
294
) -> Result < TransactionRequest , eyre:: Error > {
292
295
// manually retrieve nonce
293
296
let nonce =
@@ -297,14 +300,8 @@ impl SubmitTask {
297
300
// Extract the signature components from the response
298
301
let ( v, r, s) = extract_signature_components ( & resp. sig ) ;
299
302
300
- // Calculate gas limits based on retry attempts
301
303
let ( max_fee_per_gas, max_priority_fee_per_gas, max_fee_per_blob_gas) =
302
- calculate_gas_limits (
303
- retry_count,
304
- BASE_FEE_PER_GAS ,
305
- BASE_MAX_PRIORITY_FEE_PER_GAS ,
306
- BASE_MAX_FEE_PER_BLOB_GAS ,
307
- ) ;
304
+ calculate_gas ( retry_count, block_env) ;
308
305
309
306
// Build the block header
310
307
let header: BlockHeader = BlockHeader {
@@ -386,6 +383,7 @@ impl SubmitTask {
386
383
& self ,
387
384
retry_count : usize ,
388
385
block : & BuiltBlock ,
386
+ block_env : & BlockEnv ,
389
387
) -> eyre:: Result < ControlFlow > {
390
388
info ! ( retry_count, txns = block. tx_count( ) , "handling inbound block" ) ;
391
389
let Ok ( sig_request) = self . construct_sig_request ( block) . await . inspect_err ( |e| {
@@ -402,13 +400,14 @@ impl SubmitTask {
402
400
403
401
let signed = self . quincey . get_signature ( & sig_request) . await ?;
404
402
405
- self . submit_transaction ( retry_count, & signed, block) . await
403
+ self . submit_transaction ( retry_count, & signed, block, block_env ) . await
406
404
}
407
405
408
406
/// Handles the retry logic for the inbound block.
409
407
async fn retrying_handle_inbound (
410
408
& self ,
411
409
block : & BuiltBlock ,
410
+ block_env : & BlockEnv ,
412
411
retry_limit : usize ,
413
412
) -> eyre:: Result < ControlFlow > {
414
413
let mut retries = 0 ;
@@ -422,7 +421,8 @@ impl SubmitTask {
422
421
let span = debug_span ! ( "SubmitTask::retrying_handle_inbound" , retries) ;
423
422
424
423
let inbound_result =
425
- match self . handle_inbound ( retries, block) . instrument ( span. clone ( ) ) . await {
424
+ match self . handle_inbound ( retries, block, block_env) . instrument ( span. clone ( ) ) . await
425
+ {
426
426
Ok ( control_flow) => control_flow,
427
427
Err ( err) => {
428
428
// Delay until next slot if we get a 403 error
@@ -500,66 +500,86 @@ impl SubmitTask {
500
500
/// Task future for the submit task
501
501
/// NB: This task assumes that the simulator will only send it blocks for
502
502
/// slots that it's assigned.
503
- async fn task_future ( self , mut inbound : mpsc:: UnboundedReceiver < BuiltBlock > ) {
503
+ async fn task_future ( self , mut inbound : mpsc:: UnboundedReceiver < SimResult > ) {
504
504
// Holds a reference to the last block we attempted to submit
505
505
let mut last_block_attempted: u64 = 0 ;
506
506
507
507
loop {
508
508
// Wait to receive a new block
509
- let Some ( block ) = inbound. recv ( ) . await else {
509
+ let Some ( result ) = inbound. recv ( ) . await else {
510
510
debug ! ( "upstream task gone" ) ;
511
511
break ;
512
512
} ;
513
- debug ! ( block_number = block. block_number( ) , ?block, "submit channel received block" ) ;
513
+
514
+ debug ! ( block_number = result. block. block_number( ) , "submit channel received block" ) ;
514
515
515
516
// Only attempt each block number once
516
- if block. block_number ( ) == last_block_attempted {
517
+ if result . block . block_number ( ) == last_block_attempted {
517
518
debug ! ( "block number is unchanged from last attempt - skipping" ) ;
518
519
continue ;
519
520
}
520
521
521
522
// This means we have encountered a new block, so reset the last block attempted
522
- last_block_attempted = block. block_number ( ) ;
523
+ last_block_attempted = result . block . block_number ( ) ;
523
524
debug ! ( last_block_attempted, "resetting last block attempted" ) ;
524
525
525
- if self . retrying_handle_inbound ( & block, 3 ) . await . is_err ( ) {
526
+ if self . retrying_handle_inbound ( & result . block , & result . env , 3 ) . await . is_err ( ) {
526
527
debug ! ( "error handling inbound block" ) ;
527
528
continue ;
528
529
} ;
529
530
}
530
531
}
531
532
532
533
/// Spawns the in progress block building task
533
- pub fn spawn ( self ) -> ( mpsc:: UnboundedSender < BuiltBlock > , JoinHandle < ( ) > ) {
534
- let ( sender, inbound) = mpsc:: unbounded_channel ( ) ;
534
+ pub fn spawn ( self ) -> ( mpsc:: UnboundedSender < SimResult > , JoinHandle < ( ) > ) {
535
+ let ( sender, inbound) = mpsc:: unbounded_channel :: < SimResult > ( ) ;
535
536
let handle = tokio:: spawn ( self . task_future ( inbound) ) ;
536
537
537
538
( sender, handle)
538
539
}
539
540
}
540
541
541
- // Returns gas parameters based on retry counts.
542
- fn calculate_gas_limits (
542
+ /// Calculates gas parameters based on the block environment and retry count.
543
+ fn calculate_gas ( retry_count : usize , block_env : & BlockEnv ) -> ( u128 , u128 , u128 ) {
544
+ if let Some ( blob_excess) = block_env. blob_excess_gas_and_price {
545
+ debug ! ( ?blob_excess, "using blob excess gas and price from block env" ) ;
546
+ let blob_basefee = blob_excess. blob_gasprice ;
547
+
548
+ let ( max_fee_per_gas, max_priority_fee_per_gas, max_fee_per_blob_gas) =
549
+ bump_gas_from_retries ( retry_count, block_env. basefee , blob_basefee) ;
550
+
551
+ ( max_fee_per_gas as u128 , max_priority_fee_per_gas as u128 , max_fee_per_blob_gas as u128 )
552
+ } else {
553
+ warn ! ( "no blob excess gas and price in block env, using defaults" ) ;
554
+ let ( max_fee_per_gas, max_priority_fee_per_gas, max_fee_per_blob_gas) =
555
+ bump_gas_from_retries ( retry_count, block_env. basefee , 500 ) ;
556
+
557
+ ( max_fee_per_gas as u128 , max_priority_fee_per_gas as u128 , max_fee_per_blob_gas)
558
+ }
559
+ }
560
+
561
+ /// Bumps the gas parameters based on the retry count, base fee, and blob base fee.
562
+ pub fn bump_gas_from_retries (
543
563
retry_count : usize ,
544
- base_max_fee_per_gas : u128 ,
545
- base_max_priority_fee_per_gas : u128 ,
546
- base_max_fee_per_blob_gas : u128 ,
547
- ) -> ( u128 , u128 , u128 ) {
548
- let bump_multiplier = 1150u128 . pow ( retry_count as u32 ) ; // 15% bump
549
- let blob_bump_multiplier = 2000u128 . pow ( retry_count as u32 ) ; // 100% bump (double each time) for blob gas
550
- let bump_divisor = 1000u128 . pow ( retry_count as u32 ) ;
551
-
552
- let max_fee_per_gas = base_max_fee_per_gas * bump_multiplier / bump_divisor;
553
- let max_priority_fee_per_gas = base_max_priority_fee_per_gas * bump_multiplier / bump_divisor;
554
- let max_fee_per_blob_gas = base_max_fee_per_blob_gas * blob_bump_multiplier / bump_divisor;
564
+ basefee : u64 ,
565
+ blob_basefee : u128 ,
566
+ ) -> ( u64 , u64 , u128 ) {
567
+ const PRIORITY_FEE_BASE : u64 = 2 * GWEI_TO_WEI ;
568
+ const BASE_MULTIPLIER : u64 = 2 ;
569
+ const BLOB_MULTIPLIER : u128 = 2 ;
570
+
571
+ // Increase priority fee by 20% per retry
572
+ let priority_fee =
573
+ PRIORITY_FEE_BASE * ( 12u64 . pow ( retry_count as u32 ) / 10u64 . pow ( retry_count as u32 ) ) ;
574
+
575
+ // Max fee includes basefee + priority + headroom (double basefee, etc.)
576
+ let max_fee_per_gas = basefee * BASE_MULTIPLIER + priority_fee;
577
+ let max_fee_per_blob_gas = blob_basefee * BLOB_MULTIPLIER * ( retry_count as u128 + 1 ) ;
555
578
556
579
debug ! (
557
580
retry_count,
558
- max_fee_per_gas,
559
- max_priority_fee_per_gas,
560
- max_fee_per_blob_gas,
561
- "calculated bumped gas parameters"
581
+ max_fee_per_gas, priority_fee, max_fee_per_blob_gas, "calculated bumped gas parameters"
562
582
) ;
563
583
564
- ( max_fee_per_gas, max_priority_fee_per_gas , max_fee_per_blob_gas)
584
+ ( max_fee_per_gas, priority_fee , max_fee_per_blob_gas)
565
585
}
0 commit comments