Skip to main content

reth_engine_primitives/
event.rs

1//! Events emitted by the beacon consensus engine.
2
3use crate::ForkchoiceStatus;
4use alloc::boxed::Box;
5use alloy_consensus::BlockHeader;
6use alloy_eips::BlockNumHash;
7use alloy_rpc_types_engine::ForkchoiceState;
8use core::{
9    fmt::{Display, Formatter, Result},
10    time::Duration,
11};
12use reth_chain_state::{ExecutedBlock, ExecutionTimingStats};
13use reth_ethereum_primitives::EthPrimitives;
14use reth_primitives_traits::{NodePrimitives, SealedBlock, SealedHeader};
15
16/// Type alias for backwards compat
17#[deprecated(note = "Use ConsensusEngineEvent instead")]
18pub type BeaconConsensusEngineEvent<N> = ConsensusEngineEvent<N>;
19
20/// Events emitted by the consensus engine.
21#[derive(Clone, Debug)]
22pub enum ConsensusEngineEvent<N: NodePrimitives = EthPrimitives> {
23    /// The fork choice state was updated, and the current fork choice status
24    ForkchoiceUpdated(ForkchoiceState, ForkchoiceStatus),
25    /// A block was added to the fork chain.
26    ForkBlockAdded(ExecutedBlock<N>, Duration),
27    /// A new block was received from the consensus engine
28    BlockReceived(BlockNumHash),
29    /// A block was added to the canonical chain, and the elapsed time validating the block
30    CanonicalBlockAdded(ExecutedBlock<N>, Duration),
31    /// A canonical chain was committed, and the elapsed time committing the data
32    CanonicalChainCommitted(Box<SealedHeader<N::BlockHeader>>, Duration),
33    /// The consensus engine processed an invalid block.
34    InvalidBlock(Box<SealedBlock<N::Block>>),
35    /// A slow block was detected after persistence, with its timing statistics.
36    SlowBlock(SlowBlockInfo),
37}
38
39impl<N: NodePrimitives> ConsensusEngineEvent<N> {
40    /// Returns the canonical header if the event is a
41    /// [`ConsensusEngineEvent::CanonicalChainCommitted`].
42    pub const fn canonical_header(&self) -> Option<&SealedHeader<N::BlockHeader>> {
43        match self {
44            Self::CanonicalChainCommitted(header, _) => Some(header),
45            _ => None,
46        }
47    }
48}
49
50impl<N> Display for ConsensusEngineEvent<N>
51where
52    N: NodePrimitives<BlockHeader: BlockHeader>,
53{
54    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
55        match self {
56            Self::ForkchoiceUpdated(state, status) => {
57                write!(f, "ForkchoiceUpdated({state:?}, {status:?})")
58            }
59            Self::ForkBlockAdded(block, duration) => {
60                write!(f, "ForkBlockAdded({:?}, {duration:?})", block.recovered_block.num_hash())
61            }
62            Self::CanonicalBlockAdded(block, duration) => {
63                write!(
64                    f,
65                    "CanonicalBlockAdded({:?}, {duration:?})",
66                    block.recovered_block.num_hash()
67                )
68            }
69            Self::CanonicalChainCommitted(block, duration) => {
70                write!(f, "CanonicalChainCommitted({:?}, {duration:?})", block.num_hash())
71            }
72            Self::InvalidBlock(block) => {
73                write!(f, "InvalidBlock({:?})", block.num_hash())
74            }
75            Self::BlockReceived(num_hash) => {
76                write!(f, "BlockReceived({num_hash:?})")
77            }
78            Self::SlowBlock(info) => {
79                write!(
80                    f,
81                    "SlowBlock(block={}, total={:?})",
82                    info.stats.block_number, info.total_duration
83                )
84            }
85        }
86    }
87}
88
89/// Information about a slow block detected after execution or persistence.
90#[derive(Clone, Debug)]
91pub struct SlowBlockInfo {
92    /// The timing statistics for the slow block.
93    pub stats: Box<ExecutionTimingStats>,
94    /// The commit duration for the batch containing this block.
95    /// `None` when emitted immediately after execution (before persistence).
96    pub commit_duration: Option<Duration>,
97    /// The total duration (execution + `state_root` + commit).
98    /// Note: `state_read` is a subset of execution and is not added separately.
99    pub total_duration: Duration,
100}