| 31 | type Error = FinalizeTaskError; |
| 32 | |
| 33 | async fn execute(&self, state: &mut EngineState) -> Result<(), FinalizeTaskError> { |
| 34 | // Monotonicity guard: BinaryHeap does not define ordering between same-variant tasks, |
| 35 | // so a stale FinalizeTask with a lower block number may be popped after a higher one |
| 36 | // has already been executed. Skip it to prevent finalized_head from regressing. |
| 37 | let finalized_head = state.sync_state.finalized_head().block_info.number; |
| 38 | if self.block_number < finalized_head { |
| 39 | debug!( |
| 40 | target: "engine", |
| 41 | block_number = self.block_number, |
| 42 | finalized_head, |
| 43 | "skipping stale finalize task" |
| 44 | ); |
| 45 | return Ok(()); |
| 46 | } |
| 47 | |
| 48 | // Sanity check that the block that is being finalized is at least safe. |
| 49 | if state.sync_state.safe_head().block_info.number < self.block_number { |
| 50 | return Err(FinalizeTaskError::BlockNotSafe); |
| 51 | } |
| 52 | |
| 53 | let block_fetch_start = Instant::now(); |
| 54 | let block = self |
| 55 | .client |
| 56 | .get_l2_block(self.block_number.into()) |
| 57 | .full() |
| 58 | .await |
| 59 | .map_err(FinalizeTaskError::TransportError)? |
| 60 | .ok_or(FinalizeTaskError::BlockNotFound(self.block_number))? |
| 61 | .into_consensus(); |
| 62 | let block_info = L2BlockInfo::from_block_and_genesis( |
| 63 | &block.map_transactions(|tx| tx.inner.inner.into_inner()), |
| 64 | &self.client.cfg().genesis, |
| 65 | ) |
| 66 | .map_err(FinalizeTaskError::FromBlock)?; |
| 67 | let block_fetch_duration = block_fetch_start.elapsed(); |
| 68 | |
| 69 | // Dispatch a forkchoice update. |
| 70 | let fcu_start = Instant::now(); |
| 71 | SynchronizeTask::new( |
| 72 | Arc::clone(&self.client), |
| 73 | Arc::clone(&self.cfg), |
| 74 | EngineSyncStateUpdate { finalized_head: Some(block_info), ..Default::default() }, |
| 75 | ) |
| 76 | .execute(state) |
| 77 | .await?; |
| 78 | let fcu_duration = fcu_start.elapsed(); |
| 79 | let total_duration = block_fetch_start.elapsed(); |
| 80 | Metrics::engine_finalize_duration_seconds().record(total_duration.as_secs_f64()); |
| 81 | |
| 82 | info!( |
| 83 | target: "engine", |
| 84 | hash = %block_info.block_info.hash, |
| 85 | number = block_info.block_info.number, |
| 86 | ?block_fetch_duration, |
| 87 | ?fcu_duration, |
| 88 | "Updated finalized head" |
| 89 | ); |
| 90 | |