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, string::String};
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 {
35        /// The invalid block.
36        block: Box<SealedBlock<N::Block>>,
37        /// The validation error that caused the block to be rejected.
38        error: String,
39    },
40    /// A slow block was detected after persistence, with its timing statistics.
41    SlowBlock(SlowBlockInfo),
42}
43
44impl<N: NodePrimitives> ConsensusEngineEvent<N> {
45    /// Returns the canonical header if the event is a
46    /// [`ConsensusEngineEvent::CanonicalChainCommitted`].
47    pub const fn canonical_header(&self) -> Option<&SealedHeader<N::BlockHeader>> {
48        match self {
49            Self::CanonicalChainCommitted(header, _) => Some(header),
50            _ => None,
51        }
52    }
53}
54
55impl<N> Display for ConsensusEngineEvent<N>
56where
57    N: NodePrimitives<BlockHeader: BlockHeader>,
58{
59    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
60        match self {
61            Self::ForkchoiceUpdated(state, status) => {
62                write!(f, "ForkchoiceUpdated({state:?}, {status:?})")
63            }
64            Self::ForkBlockAdded(block, duration) => {
65                write!(f, "ForkBlockAdded({:?}, {duration:?})", block.recovered_block.num_hash())
66            }
67            Self::CanonicalBlockAdded(block, duration) => {
68                write!(
69                    f,
70                    "CanonicalBlockAdded({:?}, {duration:?})",
71                    block.recovered_block.num_hash()
72                )
73            }
74            Self::CanonicalChainCommitted(block, duration) => {
75                write!(f, "CanonicalChainCommitted({:?}, {duration:?})", block.num_hash())
76            }
77            Self::InvalidBlock { block, error } => {
78                write!(f, "InvalidBlock({:?}, {error})", block.num_hash())
79            }
80            Self::BlockReceived(num_hash) => {
81                write!(f, "BlockReceived({num_hash:?})")
82            }
83            Self::SlowBlock(info) => {
84                write!(
85                    f,
86                    "SlowBlock(block={}, total={:?})",
87                    info.stats.block_number, info.total_duration
88                )
89            }
90        }
91    }
92}
93
94/// Information about a slow block detected after execution or persistence.
95#[derive(Clone, Debug)]
96pub struct SlowBlockInfo {
97    /// The timing statistics for the slow block.
98    pub stats: Box<ExecutionTimingStats>,
99    /// The commit duration for the batch containing this block.
100    /// `None` when emitted immediately after execution (before persistence).
101    pub commit_duration: Option<Duration>,
102    /// The total duration (execution + `state_root` + commit).
103    /// Note: `state_read` is a subset of execution and is not added separately.
104    pub total_duration: Duration,
105}