kona_engine/task_queue/tasks/finalize/
task.rs

1//! A task for finalizing an L2 block.
2
3use crate::{
4    EngineClient, EngineState, EngineTaskExt, FinalizeTaskError, SynchronizeTask,
5    state::EngineSyncStateUpdate,
6};
7use alloy_provider::Provider;
8use async_trait::async_trait;
9use kona_genesis::RollupConfig;
10use kona_protocol::L2BlockInfo;
11use std::{sync::Arc, time::Instant};
12
13/// The [`FinalizeTask`] fetches the [`L2BlockInfo`] at `block_number`, updates the [`EngineState`],
14/// and dispatches a forkchoice update to finalize the block.
15#[derive(Debug, Clone)]
16pub struct FinalizeTask {
17    /// The engine client.
18    pub client: Arc<EngineClient>,
19    /// The rollup config.
20    pub cfg: Arc<RollupConfig>,
21    /// The number of the L2 block to finalize.
22    pub block_number: u64,
23}
24
25impl FinalizeTask {
26    /// Creates a new [`SynchronizeTask`].
27    pub const fn new(client: Arc<EngineClient>, cfg: Arc<RollupConfig>, block_number: u64) -> Self {
28        Self { client, cfg, block_number }
29    }
30}
31
32#[async_trait]
33impl EngineTaskExt for FinalizeTask {
34    type Output = ();
35
36    type Error = FinalizeTaskError;
37
38    async fn execute(&self, state: &mut EngineState) -> Result<(), FinalizeTaskError> {
39        // Sanity check that the block that is being finalized is at least safe.
40        if state.sync_state.safe_head().block_info.number < self.block_number {
41            return Err(FinalizeTaskError::BlockNotSafe);
42        }
43
44        let block_fetch_start = Instant::now();
45        let block = self
46            .client
47            .l2_engine()
48            .get_block(self.block_number.into())
49            .full()
50            .await
51            .map_err(FinalizeTaskError::TransportError)?
52            .ok_or(FinalizeTaskError::BlockNotFound(self.block_number))?
53            .into_consensus();
54        let block_info = L2BlockInfo::from_block_and_genesis(&block, &self.client.cfg().genesis)
55            .map_err(FinalizeTaskError::FromBlock)?;
56        let block_fetch_duration = block_fetch_start.elapsed();
57
58        // Dispatch a forkchoice update.
59        let fcu_start = Instant::now();
60        SynchronizeTask::new(
61            self.client.clone(),
62            self.cfg.clone(),
63            EngineSyncStateUpdate { finalized_head: Some(block_info), ..Default::default() },
64        )
65        .execute(state)
66        .await?;
67        let fcu_duration = fcu_start.elapsed();
68
69        info!(
70            target: "engine",
71            hash = %block_info.block_info.hash,
72            number = block_info.block_info.number,
73            ?block_fetch_duration,
74            ?fcu_duration,
75            "Updated finalized head"
76        );
77
78        Ok(())
79    }
80}