@@ -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
// TODO: ENG-1082 Implement fills
196
199
let fills = vec ! [ ] ;
@@ -203,14 +206,8 @@ impl SubmitTask {
203
206
// Extract the signature components from the response
204
207
let ( v, r, s) = extract_signature_components ( & resp. sig ) ;
205
208
206
- // Calculate gas limits based on retry attempts
207
209
let ( max_fee_per_gas, max_priority_fee_per_gas, max_fee_per_blob_gas) =
208
- calculate_gas_limits (
209
- retry_count,
210
- BASE_FEE_PER_GAS ,
211
- BASE_MAX_PRIORITY_FEE_PER_GAS ,
212
- BASE_MAX_FEE_PER_BLOB_GAS ,
213
- ) ;
210
+ calculate_gas ( retry_count, block_env) ;
214
211
215
212
// Build the block header
216
213
let header: BlockHeader = BlockHeader {
@@ -288,6 +285,7 @@ impl SubmitTask {
288
285
& self ,
289
286
retry_count : usize ,
290
287
block : & BuiltBlock ,
288
+ block_env : & BlockEnv ,
291
289
) -> eyre:: Result < ControlFlow > {
292
290
info ! ( retry_count, txns = block. tx_count( ) , "handling inbound block" ) ;
293
291
let Ok ( sig_request) = self . construct_sig_request ( block) . await . inspect_err ( |e| {
@@ -304,13 +302,14 @@ impl SubmitTask {
304
302
305
303
let signed = self . quincey . get_signature ( & sig_request) . await ?;
306
304
307
- self . submit_transaction ( retry_count, & signed, block) . await
305
+ self . submit_transaction ( retry_count, & signed, block, block_env ) . await
308
306
}
309
307
310
308
/// Handles the retry logic for the inbound block.
311
309
async fn retrying_handle_inbound (
312
310
& self ,
313
311
block : & BuiltBlock ,
312
+ block_env : & BlockEnv ,
314
313
retry_limit : usize ,
315
314
) -> eyre:: Result < ControlFlow > {
316
315
let mut retries = 0 ;
@@ -324,7 +323,8 @@ impl SubmitTask {
324
323
let span = debug_span ! ( "SubmitTask::retrying_handle_inbound" , retries) ;
325
324
326
325
let inbound_result =
327
- match self . handle_inbound ( retries, block) . instrument ( span. clone ( ) ) . await {
326
+ match self . handle_inbound ( retries, block, block_env) . instrument ( span. clone ( ) ) . await
327
+ {
328
328
Ok ( control_flow) => control_flow,
329
329
Err ( err) => {
330
330
// Delay until next slot if we get a 403 error
@@ -397,66 +397,86 @@ impl SubmitTask {
397
397
/// Task future for the submit task
398
398
/// NB: This task assumes that the simulator will only send it blocks for
399
399
/// slots that it's assigned.
400
- async fn task_future ( self , mut inbound : mpsc:: UnboundedReceiver < BuiltBlock > ) {
400
+ async fn task_future ( self , mut inbound : mpsc:: UnboundedReceiver < SimResult > ) {
401
401
// Holds a reference to the last block we attempted to submit
402
402
let mut last_block_attempted: u64 = 0 ;
403
403
404
404
loop {
405
405
// Wait to receive a new block
406
- let Some ( block ) = inbound. recv ( ) . await else {
406
+ let Some ( result ) = inbound. recv ( ) . await else {
407
407
debug ! ( "upstream task gone" ) ;
408
408
break ;
409
409
} ;
410
- debug ! ( block_number = block. block_number( ) , ?block, "submit channel received block" ) ;
410
+
411
+ debug ! ( block_number = result. block. block_number( ) , "submit channel received block" ) ;
411
412
412
413
// Only attempt each block number once
413
- if block. block_number ( ) == last_block_attempted {
414
+ if result . block . block_number ( ) == last_block_attempted {
414
415
debug ! ( "block number is unchanged from last attempt - skipping" ) ;
415
416
continue ;
416
417
}
417
418
418
419
// This means we have encountered a new block, so reset the last block attempted
419
- last_block_attempted = block. block_number ( ) ;
420
+ last_block_attempted = result . block . block_number ( ) ;
420
421
debug ! ( last_block_attempted, "resetting last block attempted" ) ;
421
422
422
- if self . retrying_handle_inbound ( & block, 3 ) . await . is_err ( ) {
423
+ if self . retrying_handle_inbound ( & result . block , & result . env , 3 ) . await . is_err ( ) {
423
424
debug ! ( "error handling inbound block" ) ;
424
425
continue ;
425
426
} ;
426
427
}
427
428
}
428
429
429
430
/// Spawns the in progress block building task
430
- pub fn spawn ( self ) -> ( mpsc:: UnboundedSender < BuiltBlock > , JoinHandle < ( ) > ) {
431
- let ( sender, inbound) = mpsc:: unbounded_channel ( ) ;
431
+ pub fn spawn ( self ) -> ( mpsc:: UnboundedSender < SimResult > , JoinHandle < ( ) > ) {
432
+ let ( sender, inbound) = mpsc:: unbounded_channel :: < SimResult > ( ) ;
432
433
let handle = tokio:: spawn ( self . task_future ( inbound) ) ;
433
434
434
435
( sender, handle)
435
436
}
436
437
}
437
438
438
- // Returns gas parameters based on retry counts.
439
- fn calculate_gas_limits (
439
+ /// Calculates gas parameters based on the block environment and retry count.
440
+ fn calculate_gas ( retry_count : usize , block_env : & BlockEnv ) -> ( u128 , u128 , u128 ) {
441
+ if let Some ( blob_excess) = block_env. blob_excess_gas_and_price {
442
+ debug ! ( ?blob_excess, "using blob excess gas and price from block env" ) ;
443
+ let blob_basefee = blob_excess. blob_gasprice ;
444
+
445
+ let ( max_fee_per_gas, max_priority_fee_per_gas, max_fee_per_blob_gas) =
446
+ bump_gas_from_retries ( retry_count, block_env. basefee , blob_basefee) ;
447
+
448
+ ( max_fee_per_gas as u128 , max_priority_fee_per_gas as u128 , max_fee_per_blob_gas as u128 )
449
+ } else {
450
+ warn ! ( "no blob excess gas and price in block env, using defaults" ) ;
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 , 500 ) ;
453
+
454
+ ( max_fee_per_gas as u128 , max_priority_fee_per_gas as u128 , max_fee_per_blob_gas)
455
+ }
456
+ }
457
+
458
+ /// Bumps the gas parameters based on the retry count, base fee, and blob base fee.
459
+ pub fn bump_gas_from_retries (
440
460
retry_count : usize ,
441
- base_max_fee_per_gas : u128 ,
442
- base_max_priority_fee_per_gas : u128 ,
443
- base_max_fee_per_blob_gas : u128 ,
444
- ) -> ( u128 , u128 , u128 ) {
445
- let bump_multiplier = 1150u128 . pow ( retry_count as u32 ) ; // 15% bump
446
- let blob_bump_multiplier = 2000u128 . pow ( retry_count as u32 ) ; // 100% bump (double each time) for blob gas
447
- let bump_divisor = 1000u128 . pow ( retry_count as u32 ) ;
448
-
449
- let max_fee_per_gas = base_max_fee_per_gas * bump_multiplier / bump_divisor;
450
- let max_priority_fee_per_gas = base_max_priority_fee_per_gas * bump_multiplier / bump_divisor;
451
- let max_fee_per_blob_gas = base_max_fee_per_blob_gas * blob_bump_multiplier / bump_divisor;
461
+ basefee : u64 ,
462
+ blob_basefee : u128 ,
463
+ ) -> ( u64 , u64 , u128 ) {
464
+ const PRIORITY_FEE_BASE : u64 = 2 * GWEI_TO_WEI ;
465
+ const BASE_MULTIPLIER : u64 = 2 ;
466
+ const BLOB_MULTIPLIER : u128 = 2 ;
467
+
468
+ // Increase priority fee by 20% per retry
469
+ let priority_fee =
470
+ PRIORITY_FEE_BASE * ( 12u64 . pow ( retry_count as u32 ) / 10u64 . pow ( retry_count as u32 ) ) ;
471
+
472
+ // Max fee includes basefee + priority + headroom (double basefee, etc.)
473
+ let max_fee_per_gas = basefee * BASE_MULTIPLIER + priority_fee;
474
+ let max_fee_per_blob_gas = blob_basefee * BLOB_MULTIPLIER * ( retry_count as u128 + 1 ) ;
452
475
453
476
debug ! (
454
477
retry_count,
455
- max_fee_per_gas,
456
- max_priority_fee_per_gas,
457
- max_fee_per_blob_gas,
458
- "calculated bumped gas parameters"
478
+ max_fee_per_gas, priority_fee, max_fee_per_blob_gas, "calculated bumped gas parameters"
459
479
) ;
460
480
461
- ( max_fee_per_gas, max_priority_fee_per_gas , max_fee_per_blob_gas)
481
+ ( max_fee_per_gas, priority_fee , max_fee_per_blob_gas)
462
482
}
0 commit comments