@@ -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) => {
@@ -95,7 +94,7 @@ impl SubmitTask {
95
94
} )
96
95
}
97
96
98
- /// Builds blob transaction and encodes the sidecar for it from the provided header and signature values
97
+ /// Encodes the sidecar and then builds the 4844 blob transaction from the provided header and signature values.
99
98
fn build_blob_tx (
100
99
& self ,
101
100
fills : Vec < FillPermit2 > ,
@@ -118,8 +117,9 @@ impl SubmitTask {
118
117
retry_count : usize ,
119
118
resp : & SignResponse ,
120
119
block : & BuiltBlock ,
120
+ block_env : & BlockEnv ,
121
121
) -> eyre:: Result < ControlFlow > {
122
- let tx = self . prepare_tx ( retry_count, resp, block) . await ?;
122
+ let tx = self . prepare_tx ( retry_count, resp, block, block_env ) . await ?;
123
123
124
124
self . send_transaction ( resp, tx) . await
125
125
}
@@ -131,9 +131,11 @@ impl SubmitTask {
131
131
retry_count : usize ,
132
132
resp : & SignResponse ,
133
133
block : & BuiltBlock ,
134
+ block_env : & BlockEnv ,
134
135
) -> Result < TransactionRequest , eyre:: Error > {
135
136
// Create the transaction request with the signature values
136
- let tx: TransactionRequest = self . new_tx_request ( retry_count, resp, block) . await ?;
137
+ let tx: TransactionRequest =
138
+ self . new_tx_request ( retry_count, resp, block, block_env) . await ?;
137
139
138
140
// Simulate the transaction with a call to the host provider and report any errors
139
141
if let Err ( err) = self . sim_with_call ( & tx) . await {
@@ -191,6 +193,7 @@ impl SubmitTask {
191
193
retry_count : usize ,
192
194
resp : & SignResponse ,
193
195
block : & BuiltBlock ,
196
+ block_env : & BlockEnv ,
194
197
) -> Result < TransactionRequest , eyre:: Error > {
195
198
// manually retrieve nonce
196
199
let nonce =
@@ -200,14 +203,8 @@ impl SubmitTask {
200
203
// Extract the signature components from the response
201
204
let ( v, r, s) = extract_signature_components ( & resp. sig ) ;
202
205
203
- // Calculate gas limits based on retry attempts
204
206
let ( max_fee_per_gas, max_priority_fee_per_gas, max_fee_per_blob_gas) =
205
- calculate_gas_limits (
206
- retry_count,
207
- BASE_FEE_PER_GAS ,
208
- BASE_MAX_PRIORITY_FEE_PER_GAS ,
209
- BASE_MAX_FEE_PER_BLOB_GAS ,
210
- ) ;
207
+ calculate_gas ( retry_count, block_env) ;
211
208
212
209
// Build the block header
213
210
let header: BlockHeader = BlockHeader {
@@ -289,6 +286,7 @@ impl SubmitTask {
289
286
& self ,
290
287
retry_count : usize ,
291
288
block : & BuiltBlock ,
289
+ block_env : & BlockEnv ,
292
290
) -> eyre:: Result < ControlFlow > {
293
291
info ! ( retry_count, txns = block. tx_count( ) , "handling inbound block" ) ;
294
292
let Ok ( sig_request) = self . construct_sig_request ( block) . await . inspect_err ( |e| {
@@ -305,13 +303,14 @@ impl SubmitTask {
305
303
306
304
let signed = self . quincey . get_signature ( & sig_request) . await ?;
307
305
308
- self . submit_transaction ( retry_count, & signed, block) . await
306
+ self . submit_transaction ( retry_count, & signed, block, block_env ) . await
309
307
}
310
308
311
309
/// Handles the retry logic for the inbound block.
312
310
async fn retrying_handle_inbound (
313
311
& self ,
314
312
block : & BuiltBlock ,
313
+ block_env : & BlockEnv ,
315
314
retry_limit : usize ,
316
315
) -> eyre:: Result < ControlFlow > {
317
316
let mut retries = 0 ;
@@ -325,7 +324,8 @@ impl SubmitTask {
325
324
let span = debug_span ! ( "SubmitTask::retrying_handle_inbound" , retries) ;
326
325
327
326
let inbound_result =
328
- match self . handle_inbound ( retries, block) . instrument ( span. clone ( ) ) . await {
327
+ match self . handle_inbound ( retries, block, block_env) . instrument ( span. clone ( ) ) . await
328
+ {
329
329
Ok ( control_flow) => control_flow,
330
330
Err ( err) => {
331
331
// Delay until next slot if we get a 403 error
@@ -403,66 +403,86 @@ impl SubmitTask {
403
403
/// Task future for the submit task
404
404
/// NB: This task assumes that the simulator will only send it blocks for
405
405
/// slots that it's assigned.
406
- async fn task_future ( self , mut inbound : mpsc:: UnboundedReceiver < BuiltBlock > ) {
406
+ async fn task_future ( self , mut inbound : mpsc:: UnboundedReceiver < SimResult > ) {
407
407
// Holds a reference to the last block we attempted to submit
408
408
let mut last_block_attempted: u64 = 0 ;
409
409
410
410
loop {
411
411
// Wait to receive a new block
412
- let Some ( block ) = inbound. recv ( ) . await else {
412
+ let Some ( result ) = inbound. recv ( ) . await else {
413
413
debug ! ( "upstream task gone" ) ;
414
414
break ;
415
415
} ;
416
- debug ! ( block_number = block. block_number( ) , ?block, "submit channel received block" ) ;
416
+
417
+ debug ! ( block_number = result. block. block_number( ) , "submit channel received block" ) ;
417
418
418
419
// Only attempt each block number once
419
- if block. block_number ( ) == last_block_attempted {
420
+ if result . block . block_number ( ) == last_block_attempted {
420
421
debug ! ( "block number is unchanged from last attempt - skipping" ) ;
421
422
continue ;
422
423
}
423
424
424
425
// This means we have encountered a new block, so reset the last block attempted
425
- last_block_attempted = block. block_number ( ) ;
426
+ last_block_attempted = result . block . block_number ( ) ;
426
427
debug ! ( last_block_attempted, "resetting last block attempted" ) ;
427
428
428
- if self . retrying_handle_inbound ( & block, 3 ) . await . is_err ( ) {
429
+ if self . retrying_handle_inbound ( & result . block , & result . env , 3 ) . await . is_err ( ) {
429
430
debug ! ( "error handling inbound block" ) ;
430
431
continue ;
431
432
} ;
432
433
}
433
434
}
434
435
435
436
/// Spawns the in progress block building task
436
- pub fn spawn ( self ) -> ( mpsc:: UnboundedSender < BuiltBlock > , JoinHandle < ( ) > ) {
437
- let ( sender, inbound) = mpsc:: unbounded_channel ( ) ;
437
+ pub fn spawn ( self ) -> ( mpsc:: UnboundedSender < SimResult > , JoinHandle < ( ) > ) {
438
+ let ( sender, inbound) = mpsc:: unbounded_channel :: < SimResult > ( ) ;
438
439
let handle = tokio:: spawn ( self . task_future ( inbound) ) ;
439
440
440
441
( sender, handle)
441
442
}
442
443
}
443
444
444
- // Returns gas parameters based on retry counts.
445
- fn calculate_gas_limits (
445
+ /// Calculates gas parameters based on the block environment and retry count.
446
+ fn calculate_gas ( retry_count : usize , block_env : & BlockEnv ) -> ( u128 , u128 , u128 ) {
447
+ if let Some ( blob_excess) = block_env. blob_excess_gas_and_price {
448
+ debug ! ( ?blob_excess, "using blob excess gas and price from block env" ) ;
449
+ let blob_basefee = blob_excess. blob_gasprice ;
450
+
451
+ let ( max_fee_per_gas, max_priority_fee_per_gas, max_fee_per_blob_gas) =
452
+ bump_gas_from_retries ( retry_count, block_env. basefee , blob_basefee) ;
453
+
454
+ ( max_fee_per_gas as u128 , max_priority_fee_per_gas as u128 , max_fee_per_blob_gas as u128 )
455
+ } else {
456
+ warn ! ( "no blob excess gas and price in block env, using defaults" ) ;
457
+ let ( max_fee_per_gas, max_priority_fee_per_gas, max_fee_per_blob_gas) =
458
+ bump_gas_from_retries ( retry_count, block_env. basefee , 500 ) ;
459
+
460
+ ( max_fee_per_gas as u128 , max_priority_fee_per_gas as u128 , max_fee_per_blob_gas)
461
+ }
462
+ }
463
+
464
+ /// Bumps the gas parameters based on the retry count, base fee, and blob base fee.
465
+ pub fn bump_gas_from_retries (
446
466
retry_count : usize ,
447
- base_max_fee_per_gas : u128 ,
448
- base_max_priority_fee_per_gas : u128 ,
449
- base_max_fee_per_blob_gas : u128 ,
450
- ) -> ( u128 , u128 , u128 ) {
451
- let bump_multiplier = 1150u128 . pow ( retry_count as u32 ) ; // 15% bump
452
- let blob_bump_multiplier = 2000u128 . pow ( retry_count as u32 ) ; // 100% bump (double each time) for blob gas
453
- let bump_divisor = 1000u128 . pow ( retry_count as u32 ) ;
454
-
455
- let max_fee_per_gas = base_max_fee_per_gas * bump_multiplier / bump_divisor;
456
- let max_priority_fee_per_gas = base_max_priority_fee_per_gas * bump_multiplier / bump_divisor;
457
- let max_fee_per_blob_gas = base_max_fee_per_blob_gas * blob_bump_multiplier / bump_divisor;
467
+ basefee : u64 ,
468
+ blob_basefee : u128 ,
469
+ ) -> ( u64 , u64 , u128 ) {
470
+ const PRIORITY_FEE_BASE : u64 = 2 * GWEI_TO_WEI ;
471
+ const BASE_MULTIPLIER : u64 = 2 ;
472
+ const BLOB_MULTIPLIER : u128 = 2 ;
473
+
474
+ // Increase priority fee by 20% per retry
475
+ let priority_fee =
476
+ PRIORITY_FEE_BASE * ( 12u64 . pow ( retry_count as u32 ) / 10u64 . pow ( retry_count as u32 ) ) ;
477
+
478
+ // Max fee includes basefee + priority + headroom (double basefee, etc.)
479
+ let max_fee_per_gas = basefee * BASE_MULTIPLIER + priority_fee;
480
+ let max_fee_per_blob_gas = blob_basefee * BLOB_MULTIPLIER * ( retry_count as u128 + 1 ) ;
458
481
459
482
debug ! (
460
483
retry_count,
461
- max_fee_per_gas,
462
- max_priority_fee_per_gas,
463
- max_fee_per_blob_gas,
464
- "calculated bumped gas parameters"
484
+ max_fee_per_gas, priority_fee, max_fee_per_blob_gas, "calculated bumped gas parameters"
465
485
) ;
466
486
467
- ( max_fee_per_gas, max_priority_fee_per_gas , max_fee_per_blob_gas)
487
+ ( max_fee_per_gas, priority_fee , max_fee_per_blob_gas)
468
488
}
0 commit comments