@@ -25,7 +25,7 @@ use tracing::{Level, debug, error, instrument};
2525
2626use super :: {
2727 Config , ExecutionEngine , FinalizedBlockProvider , Marshal ,
28- fcu:: { ForkchoiceTargets , ForkchoiceTracker , Target } ,
28+ fcu:: { BlockForkchoice , FinalityPlan , ForkchoiceTargets , ForkchoiceTracker } ,
2929 ingress:: Message ,
3030} ;
3131use crate :: { consensus:: block:: Block , utils:: OptionFuture } ;
@@ -41,7 +41,6 @@ pub(crate) struct Actor<TContext, P, E, M = crate::alias::marshal::Mailbox> {
4141 marshal : M ,
4242
4343 epoch_strategy : FixedEpocher ,
44- floor : Height ,
4544
4645 forkchoice : ForkchoiceTracker ,
4746
@@ -71,22 +70,20 @@ where
7170 execution_engine,
7271 marshal,
7372 epoch_strategy,
74- floor,
7573 fcu_heartbeat_interval,
7674 } = config;
7775
7876 let finalized_header = execution_provider
7977 . finalized_header ( )
8078 . expect ( "failed reading finalized execution header" ) ;
81- let forkchoice = ForkchoiceTracker :: new ( Target :: from_header ( & finalized_header) ) ;
79+ let forkchoice = ForkchoiceTracker :: new ( & finalized_header) ;
8280
8381 Self {
8482 context : ContextCell :: new ( context) ,
8583
8684 mailbox,
8785 marshal,
8886 epoch_strategy,
89- floor,
9087 execution_provider,
9188 execution_engine,
9289
@@ -118,15 +115,15 @@ where
118115 result = & mut self . execution_task => {
119116 self . execution_task = OptionFuture :: none( ) ;
120117 match result {
121- ExecutionTaskResult :: Completed ( submitted_fcu) => {
118+ Ok ( submitted_fcu) => {
122119 if let Some ( submitted_fcu) = submitted_fcu {
123120 self . forkchoice. note_submitted( submitted_fcu) ;
124121 }
125122
126123 // Emits an event on error.
127124 let _: Result <_, _> = self . try_advance_floor( ) . await ;
128125 }
129- ExecutionTaskResult :: Fatal ( error) => {
126+ Err ( error) => {
130127 error!( %error, "execution task failed" ) ;
131128 break ;
132129 }
@@ -149,12 +146,10 @@ where
149146 if self . floor_candidate. is_none( ) {
150147 self . floor_candidate = Some ( height) ;
151148 }
152- self . forkchoice
153- . advance_head( Target :: from_finalization( round, digest) ) ;
149+ self . forkchoice. observe_certificate( round, digest) ;
154150 }
155151 Message :: Finalization { round, digest } => {
156- let candidate = Target :: from_finalization( round, digest) ;
157- self . forkchoice. advance_head( candidate) ;
152+ self . forkchoice. observe_certificate( round, digest) ;
158153 }
159154 }
160155 }
@@ -182,33 +177,19 @@ where
182177 return ;
183178 }
184179
185- let request = if let Some ( ( block, ack) ) = self . block_queue . pop_front ( ) {
186- let block_target = Target :: from_block ( & block) ;
187- let finality_anchor =
188- self . forkchoice
189- . advance_finalized ( block_target)
190- . then_some ( ForkchoiceTargets {
191- head : block_target,
192- finalized : block_target,
193- } ) ;
194- let latest_forkchoice = ( self . forkchoice . requires_update ( ) || heartbeat)
195- . then_some ( self . forkchoice . latest ( ) ) ;
196- ExecutionRequest :: Block {
197- block,
198- latest_forkchoice,
199- finality_anchor,
200- ack,
201- }
202- } else if self . forkchoice . requires_update ( ) || heartbeat {
203- ExecutionRequest :: Forkchoice ( self . forkchoice . latest ( ) )
180+ let execution_engine = self . execution_engine . clone ( ) ;
181+ let task = if let Some ( ( block, ack) ) = self . block_queue . pop_front ( ) {
182+ let forkchoice = self . forkchoice . plan_block ( & block, heartbeat) ;
183+ let context = self . context . child ( "execute_block" ) ;
184+ execute_block ( context, execution_engine, block, forkchoice, ack) . boxed ( )
185+ } else if let Some ( forkchoice) = self . forkchoice . plan_update ( heartbeat) {
186+ let context = self . context . child ( "execute_head_update" ) ;
187+ execute_head_update ( context, execution_engine, forkchoice) . boxed ( )
204188 } else {
205189 return ;
206190 } ;
207191
208- let context = self . context . child ( "execute_request" ) ;
209- let execution_engine = self . execution_engine . clone ( ) ;
210- self . execution_task
211- . replace ( execute_request ( context, execution_engine, request) . boxed ( ) ) ;
192+ self . execution_task . replace ( task) ;
212193 }
213194
214195 #[ instrument( skip_all, err( level = Level :: WARN ) ) ]
@@ -253,103 +234,73 @@ where
253234
254235 self . marshal . set_floor ( finalization) ;
255236
256- self . floor = floor_height;
257237 self . floor_candidate = None ;
258238
259239 Ok ( ( ) )
260240 }
261241}
262242
263- enum ExecutionRequest {
264- Forkchoice ( ForkchoiceTargets ) ,
265- Block {
266- /// A finalized block delivered by marshal for execution.
267- block : Block ,
268- /// The latest combined head and finalized targets, if an update is due.
269- latest_forkchoice : Option < ForkchoiceTargets > ,
270- /// The delivered block as both head and finalized when it advances finality.
271- finality_anchor : Option < ForkchoiceTargets > ,
272- /// Signals marshal after the payload and required forkchoice update complete.
273- ack : Exact ,
274- } ,
275- }
276-
277- enum ExecutionTaskResult {
278- Completed ( Option < ForkchoiceTargets > ) ,
279- Fatal ( Report ) ,
280- }
243+ type ExecutionTaskResult = eyre:: Result < Option < ForkchoiceTargets > > ;
281244
282245enum ForkchoiceOutcome {
283246 Valid ,
284247 Syncing ,
285248}
286249
287- async fn execute_request < TContext : Pacer , E : ExecutionEngine + ' static > (
250+ async fn execute_head_update < TContext : Pacer , E : ExecutionEngine + ' static > (
288251 context : TContext ,
289252 execution_engine : E ,
290- request : ExecutionRequest ,
253+ forkchoice : ForkchoiceTargets ,
291254) -> ExecutionTaskResult {
292- match request {
293- ExecutionRequest :: Forkchoice ( forkchoice) => {
294- let result = submit_forkchoice_update ( & context, & execution_engine, & forkchoice) . await ;
295- match result {
296- Ok ( ForkchoiceOutcome :: Valid | ForkchoiceOutcome :: Syncing ) => {
297- ExecutionTaskResult :: Completed ( Some ( forkchoice) )
298- }
299- Err ( error) => ExecutionTaskResult :: Fatal ( error) ,
300- }
255+ submit_forkchoice_update ( & context, & execution_engine, & forkchoice) . await ?;
256+ Ok ( Some ( forkchoice) )
257+ }
258+
259+ async fn execute_block < TContext : Pacer , E : ExecutionEngine + ' static > (
260+ context : TContext ,
261+ execution_engine : E ,
262+ block : Block ,
263+ forkchoice : BlockForkchoice ,
264+ ack : Exact ,
265+ ) -> ExecutionTaskResult {
266+ submit_new_payload ( & context, & execution_engine, block) . await ?;
267+
268+ let submitted = match forkchoice {
269+ BlockForkchoice :: Guide ( targets) => {
270+ submit_forkchoice_update ( & context, & execution_engine, & targets) . await ?;
271+ Some ( targets)
301272 }
302- ExecutionRequest :: Block {
303- block,
304- latest_forkchoice,
305- finality_anchor,
306- ack,
307- } => {
308- if let Err ( error) = submit_new_payload ( & context, & execution_engine, block) . await {
309- return ExecutionTaskResult :: Fatal ( error) ;
310- }
273+ BlockForkchoice :: Finalize ( plan) => {
274+ Some ( apply_finality ( & context, & execution_engine, plan) . await ?)
275+ }
276+ BlockForkchoice :: None => None ,
277+ } ;
311278
312- let submitted_fcu = match latest_forkchoice {
313- Some ( latest_forkchoice) => {
314- let result =
315- submit_forkchoice_update ( & context, & execution_engine, & latest_forkchoice)
316- . await ;
317- match result {
318- Ok ( ForkchoiceOutcome :: Valid ) => Some ( latest_forkchoice) ,
319- Ok ( ForkchoiceOutcome :: Syncing ) => match finality_anchor {
320- Some ( finality_anchor) => {
321- if let Err ( error) = submit_finality_anchor (
322- & context,
323- & execution_engine,
324- & finality_anchor,
325- )
326- . await
327- {
328- return ExecutionTaskResult :: Fatal ( error) ;
329- }
330- Some ( finality_anchor)
331- }
332- None => Some ( latest_forkchoice) ,
333- } ,
334- Err ( error) => return ExecutionTaskResult :: Fatal ( error) ,
335- }
336- }
337- None => None ,
338- } ;
279+ ack. acknowledge ( ) ;
280+ Ok ( submitted)
281+ }
339282
340- ack. acknowledge ( ) ;
341- ExecutionTaskResult :: Completed ( submitted_fcu)
283+ async fn apply_finality < TContext : Pacer , E : ExecutionEngine + ?Sized > (
284+ context : & TContext ,
285+ execution_engine : & E ,
286+ plan : FinalityPlan ,
287+ ) -> eyre:: Result < ForkchoiceTargets > {
288+ match submit_forkchoice_update ( context, execution_engine, & plan. preferred ) . await ? {
289+ ForkchoiceOutcome :: Valid => Ok ( plan. preferred ) ,
290+ ForkchoiceOutcome :: Syncing => {
291+ submit_until_valid ( context, execution_engine, & plan. anchor ) . await ?;
292+ Ok ( plan. anchor )
342293 }
343294 }
344295}
345296
346- async fn submit_finality_anchor < TContext : Pacer , E : ExecutionEngine + ?Sized > (
297+ async fn submit_until_valid < TContext : Pacer , E : ExecutionEngine + ?Sized > (
347298 context : & TContext ,
348299 execution_engine : & E ,
349- finality_anchor : & ForkchoiceTargets ,
300+ forkchoice : & ForkchoiceTargets ,
350301) -> eyre:: Result < ( ) > {
351302 loop {
352- let outcome = submit_forkchoice_update ( context, execution_engine, finality_anchor ) . await ?;
303+ let outcome = submit_forkchoice_update ( context, execution_engine, forkchoice ) . await ?;
353304 match outcome {
354305 ForkchoiceOutcome :: Valid => return Ok ( ( ) ) ,
355306 ForkchoiceOutcome :: Syncing => {
@@ -397,10 +348,8 @@ async fn submit_new_payload<TContext: Pacer, E: ExecutionEngine + ?Sized>(
397348#[ instrument(
398349 skip_all,
399350 fields(
400- head. round = ?forkchoice. head. round,
401- head. digest = %forkchoice. head. digest,
402- finalized. round = ?forkchoice. finalized. round,
403- finalized. digest = %forkchoice. finalized. digest,
351+ head. digest = %forkchoice. head,
352+ finalized. digest = %forkchoice. finalized,
404353 )
405354) ]
406355async fn submit_forkchoice_update < TContext : Pacer , E : ExecutionEngine + ?Sized > (
0 commit comments