@@ -19,11 +19,9 @@ use alloy_primitives::{utils::format_ether, U256};
1919use mockall:: automock;
2020use reth_chainspec:: ChainSpec ;
2121use reth_primitives:: SealedBlock ;
22- use std:: {
23- sync:: { Arc , Mutex } ,
24- time:: Duration ,
25- } ;
26- use tokio:: time:: { sleep, Instant } ;
22+ use std:: sync:: { Arc , Mutex } ;
23+ use tokio:: sync:: Notify ;
24+ use tokio:: time:: Instant ;
2725use tokio_util:: sync:: CancellationToken ;
2826use tracing:: { debug, error, event, info_span, trace, warn, Instrument , Level } ;
2927
@@ -36,40 +34,45 @@ const SIM_ERROR_CATEGORY: &str = "submit_block_simulation";
3634const VALIDATION_ERROR_CATEGORY : & str = "validate_block_simulation" ;
3735
3836/// Contains the best block so far.
39- /// Building updates via compare_and_update while relay submitter polls via take_best_block
40- #[ derive( Debug , Clone ) ]
37+ /// Building updates via compare_and_update while relay submitter polls via take_best_block.
38+ /// A new block can be waited without polling via wait_for_change.
39+ #[ derive( Debug , Default ) ]
4140pub struct BestBlockCell {
42- val : Arc < Mutex < Option < Block > > > ,
43- }
44-
45- impl Default for BestBlockCell {
46- fn default ( ) -> Self {
47- Self {
48- val : Arc :: new ( Mutex :: new ( None ) ) ,
49- }
50- }
51- }
52-
53- impl BlockBuildingSink for BestBlockCell {
54- fn new_block ( & self , block : Block ) {
55- self . compare_and_update ( block) ;
56- }
41+ block : Mutex < Option < Block > > ,
42+ block_notify : Notify ,
5743}
5844
5945impl BestBlockCell {
6046 pub fn compare_and_update ( & self , block : Block ) {
61- let mut best_block = self . val . lock ( ) . unwrap ( ) ;
47+ let mut best_block = self . block . lock ( ) . unwrap ( ) ;
6248 let old_value = best_block
6349 . as_ref ( )
6450 . map ( |b| b. trace . bid_value )
6551 . unwrap_or_default ( ) ;
6652 if block. trace . bid_value > old_value {
6753 * best_block = Some ( block) ;
54+ self . block_notify . notify_one ( ) ;
6855 }
6956 }
7057
7158 pub fn take_best_block ( & self ) -> Option < Block > {
72- self . val . lock ( ) . unwrap ( ) . take ( )
59+ self . block . lock ( ) . unwrap ( ) . take ( )
60+ }
61+
62+ pub async fn wait_for_change ( & self ) {
63+ self . block_notify . notified ( ) . await
64+ }
65+ }
66+
67+ /// Adapts BestBlockCell to BlockBuildingSink by calling compare_and_update on new_block.
68+ #[ derive( Debug ) ]
69+ struct BestBlockCellToBlockBuildingSink {
70+ best_block_cell : Arc < BestBlockCell > ,
71+ }
72+
73+ impl BlockBuildingSink for BestBlockCellToBlockBuildingSink {
74+ fn new_block ( & self , block : Block ) {
75+ self . best_block_cell . compare_and_update ( block) ;
7376 }
7477}
7578
@@ -105,13 +108,8 @@ pub struct SubmissionConfig {
105108 pub optimistic_prevalidate_optimistic_blocks : bool ,
106109
107110 pub bid_observer : Box < dyn BidObserver + Send + Sync > ,
108- /// Delta relative to slot_time at which we start to submit blocks. Usually negative since we need to start submitting BEFORE the slot time.
109- pub slot_delta_to_start_submits : time:: Duration ,
110111}
111112
112- /// run_submit_to_relays_job waits at least MIN_TIME_BETWEEN_BLOCK_CHECK between new block polls to avoid 100% CPU
113- const MIN_TIME_BETWEEN_BLOCK_CHECK : Duration = Duration :: from_millis ( 5 ) ;
114-
115113/// Values from [`BuiltBlockTrace`]
116114struct BuiltBlockInfo {
117115 pub bid_value : U256 ,
@@ -130,7 +128,7 @@ struct BuiltBlockInfo {
130128/// returns the best bid made
131129#[ allow( clippy:: too_many_arguments) ]
132130async fn run_submit_to_relays_job (
133- best_bid : BestBlockCell ,
131+ best_bid : Arc < BestBlockCell > ,
134132 slot_data : MevBoostSlotData ,
135133 relays : Vec < MevBoostRelay > ,
136134 config : Arc < SubmissionConfig > ,
@@ -143,14 +141,6 @@ async fn run_submit_to_relays_job(
143141 slot_data. slot ( ) ,
144142 ) ;
145143 let mut res = None ;
146- // first, sleep to slot time - slot_delta_to_start_submits
147- {
148- let submit_start_time = slot_data. timestamp ( ) + config. slot_delta_to_start_submits ;
149- let sleep_duration = submit_start_time - time:: OffsetDateTime :: now_utc ( ) ;
150- if sleep_duration. is_positive ( ) {
151- sleep ( sleep_duration. try_into ( ) . unwrap ( ) ) . await ;
152- }
153- }
154144
155145 let ( normal_relays, optimistic_relays) = {
156146 let mut normal_relays = Vec :: new ( ) ;
@@ -166,18 +156,12 @@ async fn run_submit_to_relays_job(
166156 } ;
167157
168158 let mut last_bid_value = U256 :: from ( 0 ) ;
169- let mut last_submit_time = Instant :: now ( ) ;
170159 ' submit: loop {
171160 if cancel. is_cancelled ( ) {
172161 break ' submit res;
173162 }
174163
175- let time_since_submit = last_submit_time. elapsed ( ) ;
176- if time_since_submit < MIN_TIME_BETWEEN_BLOCK_CHECK {
177- sleep ( MIN_TIME_BETWEEN_BLOCK_CHECK - time_since_submit) . await ;
178- }
179- last_submit_time = Instant :: now ( ) ;
180-
164+ best_bid. wait_for_change ( ) . await ;
181165 let block = if let Some ( new_block) = best_bid. take_best_block ( ) {
182166 if new_block. trace . bid_value > last_bid_value {
183167 last_bid_value = new_block. trace . bid_value ;
@@ -348,26 +332,29 @@ async fn run_submit_to_relays_job(
348332}
349333
350334pub async fn run_submit_to_relays_job_and_metrics (
351- best_bid : BestBlockCell ,
335+ best_bid : Arc < BestBlockCell > ,
352336 slot_data : MevBoostSlotData ,
353337 relays : Vec < MevBoostRelay > ,
354338 config : Arc < SubmissionConfig > ,
355339 cancel : CancellationToken ,
356340 competition_bid_value_source : Arc < dyn BidValueSource + Send + Sync > ,
357341) {
358- let best_bid = run_submit_to_relays_job (
359- best_bid. clone ( ) ,
342+ let last_build_block_info = run_submit_to_relays_job (
343+ best_bid,
360344 slot_data,
361345 relays,
362346 config,
363347 cancel,
364348 competition_bid_value_source,
365349 )
366350 . await ;
367- if let Some ( best_bid ) = best_bid {
368- if best_bid . bid_value > best_bid . true_bid_value {
351+ if let Some ( last_build_block_info ) = last_build_block_info {
352+ if last_build_block_info . bid_value > last_build_block_info . true_bid_value {
369353 inc_subsidized_blocks ( false ) ;
370- add_subsidy_value ( best_bid. bid_value - best_bid. true_bid_value , false ) ;
354+ add_subsidy_value (
355+ last_build_block_info. bid_value - last_build_block_info. true_bid_value ,
356+ false ,
357+ ) ;
371358 }
372359 }
373360}
@@ -540,7 +527,7 @@ impl BuilderSinkFactory for RelaySubmitSinkFactory {
540527 competition_bid_value_source : Arc < dyn BidValueSource + Send + Sync > ,
541528 cancel : CancellationToken ,
542529 ) -> Box < dyn BlockBuildingSink > {
543- let best_bid = BestBlockCell :: default ( ) ;
530+ let best_block_cell = Arc :: new ( BestBlockCell :: default ( ) ) ;
544531
545532 let relays = slot_data
546533 . relays
@@ -553,13 +540,13 @@ impl BuilderSinkFactory for RelaySubmitSinkFactory {
553540 } )
554541 . collect ( ) ;
555542 tokio:: spawn ( run_submit_to_relays_job_and_metrics (
556- best_bid . clone ( ) ,
543+ best_block_cell . clone ( ) ,
557544 slot_data,
558545 relays,
559546 self . submission_config . clone ( ) ,
560547 cancel,
561548 competition_bid_value_source,
562549 ) ) ;
563- Box :: new ( best_bid )
550+ Box :: new ( BestBlockCellToBlockBuildingSink { best_block_cell } )
564551 }
565552}
0 commit comments