reth_eth_wire/errors/
eth.rs

1//! Error handling for (`EthStream`)[`crate::EthStream`]
2
3use crate::{
4    errors::P2PStreamError, message::MessageError, version::ParseVersionError, DisconnectReason,
5};
6use alloy_chains::Chain;
7use alloy_primitives::B256;
8use reth_eth_wire_types::EthVersion;
9use reth_ethereum_forks::ValidationError;
10use reth_primitives_traits::{GotExpected, GotExpectedBoxed};
11use std::io;
12
13/// Errors when sending/receiving messages
14#[derive(thiserror::Error, Debug)]
15pub enum EthStreamError {
16    #[error(transparent)]
17    /// Error of the underlying P2P connection.
18    P2PStreamError(#[from] P2PStreamError),
19    #[error(transparent)]
20    /// Failed to parse peer's version.
21    ParseVersionError(#[from] ParseVersionError),
22    #[error(transparent)]
23    /// Failed Ethereum handshake.
24    EthHandshakeError(#[from] EthHandshakeError),
25    /// Thrown when decoding a message message failed.
26    #[error(transparent)]
27    InvalidMessage(#[from] MessageError),
28    #[error("message size ({0}) exceeds max length (10MB)")]
29    /// Received a message whose size exceeds the standard limit.
30    MessageTooBig(usize),
31    #[error("TransactionHashes invalid len of fields: hashes_len={hashes_len} types_len={types_len} sizes_len={sizes_len}")]
32    /// Received malformed transaction hashes message with discrepancies in field lengths.
33    TransactionHashesInvalidLenOfFields {
34        /// The number of transaction hashes.
35        hashes_len: usize,
36        /// The number of transaction types.
37        types_len: usize,
38        /// The number of transaction sizes.
39        sizes_len: usize,
40    },
41    /// Error when data is not received from peer for a prolonged period.
42    #[error("never received data from remote peer")]
43    StreamTimeout,
44}
45
46// === impl EthStreamError ===
47
48impl EthStreamError {
49    /// Returns the [`DisconnectReason`] if the error is a disconnect message
50    pub const fn as_disconnected(&self) -> Option<DisconnectReason> {
51        if let Self::P2PStreamError(err) = self {
52            err.as_disconnected()
53        } else {
54            None
55        }
56    }
57
58    /// Returns the [`io::Error`] if it was caused by IO
59    pub const fn as_io(&self) -> Option<&io::Error> {
60        if let Self::P2PStreamError(P2PStreamError::Io(io)) = self {
61            return Some(io)
62        }
63        None
64    }
65}
66
67impl From<io::Error> for EthStreamError {
68    fn from(err: io::Error) -> Self {
69        P2PStreamError::from(err).into()
70    }
71}
72
73/// Error  that can occur during the `eth` sub-protocol handshake.
74#[derive(thiserror::Error, Debug)]
75pub enum EthHandshakeError {
76    /// Status message received or sent outside of the handshake process.
77    #[error("status message can only be recv/sent in handshake")]
78    StatusNotInHandshake,
79    /// Receiving a non-status message during the handshake phase.
80    #[error("received non-status message when trying to handshake")]
81    NonStatusMessageInHandshake,
82    #[error("no response received when sending out handshake")]
83    /// No response received during the handshake process.
84    NoResponse,
85    #[error(transparent)]
86    /// Invalid fork data.
87    InvalidFork(#[from] ValidationError),
88    #[error("mismatched genesis in status message: {0}")]
89    /// Mismatch in the genesis block during status exchange.
90    MismatchedGenesis(GotExpectedBoxed<B256>),
91    #[error("mismatched protocol version in status message: {0}")]
92    /// Mismatched protocol versions in status messages.
93    MismatchedProtocolVersion(GotExpected<EthVersion>),
94    #[error("mismatched chain in status message: {0}")]
95    /// Mismatch in chain details in status messages.
96    MismatchedChain(GotExpected<Chain>),
97    #[error("total difficulty bitlen is too large: got {got}, maximum {maximum}")]
98    /// Excessively large total difficulty bit lengths.
99    TotalDifficultyBitLenTooLarge {
100        /// The actual bit length of the total difficulty.
101        got: usize,
102        /// The maximum allowed bit length for the total difficulty.
103        maximum: usize,
104    },
105}