reth_eth_wire/errors/
eth.rs1use 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#[derive(thiserror::Error, Debug)]
15pub enum EthStreamError {
16 #[error(transparent)]
17 P2PStreamError(#[from] P2PStreamError),
19 #[error(transparent)]
20 ParseVersionError(#[from] ParseVersionError),
22 #[error(transparent)]
23 EthHandshakeError(#[from] EthHandshakeError),
25 #[error(transparent)]
27 InvalidMessage(#[from] MessageError),
28 #[error("message size ({0}) exceeds max length (10MB)")]
29 MessageTooBig(usize),
31 #[error(
32 "TransactionHashes invalid len of fields: hashes_len={hashes_len} types_len={types_len} sizes_len={sizes_len}"
33 )]
34 TransactionHashesInvalidLenOfFields {
36 hashes_len: usize,
38 types_len: usize,
40 sizes_len: usize,
42 },
43 #[error("never received data from remote peer")]
45 StreamTimeout,
46 #[error("Received unknown ETH message ID: 0x{message_id:X}")]
48 UnsupportedMessage {
49 message_id: u8,
51 },
52}
53
54impl EthStreamError {
57 pub const fn as_disconnected(&self) -> Option<DisconnectReason> {
59 if let Self::P2PStreamError(err) = self {
60 err.as_disconnected()
61 } else {
62 None
63 }
64 }
65
66 pub const fn is_protocol_breach(&self) -> bool {
71 matches!(
72 self,
73 Self::InvalidMessage(_) |
74 Self::MessageTooBig(_) |
75 Self::TransactionHashesInvalidLenOfFields { .. } |
76 Self::UnsupportedMessage { .. } |
77 Self::P2PStreamError(
78 P2PStreamError::Rlp(_) |
79 P2PStreamError::Snap(_) |
80 P2PStreamError::MessageTooBig { .. } |
81 P2PStreamError::UnknownReservedMessageId(_) |
82 P2PStreamError::EmptyProtocolMessage |
83 P2PStreamError::UnknownDisconnectReason(_)
84 )
85 )
86 }
87
88 pub const fn as_io(&self) -> Option<&io::Error> {
90 if let Self::P2PStreamError(P2PStreamError::Io(io)) = self {
91 return Some(io)
92 }
93 None
94 }
95}
96
97impl From<io::Error> for EthStreamError {
98 fn from(err: io::Error) -> Self {
99 P2PStreamError::from(err).into()
100 }
101}
102
103#[derive(thiserror::Error, Debug)]
105pub enum EthHandshakeError {
106 #[error("status message can only be recv/sent in handshake")]
108 StatusNotInHandshake,
109 #[error("received non-status message when trying to handshake")]
111 NonStatusMessageInHandshake,
112 #[error("no response received when sending out handshake")]
113 NoResponse,
115 #[error(transparent)]
116 InvalidFork(#[from] ValidationError),
118 #[error("mismatched genesis in status message: {0}")]
119 MismatchedGenesis(GotExpectedBoxed<B256>),
121 #[error("mismatched protocol version in status message: {0}")]
122 MismatchedProtocolVersion(GotExpected<EthVersion>),
124 #[error("mismatched chain in status message: {0}")]
125 MismatchedChain(GotExpected<Chain>),
127 #[error("total difficulty bitlen is too large: got {got}, maximum {maximum}")]
128 TotalDifficultyBitLenTooLarge {
130 got: usize,
132 maximum: usize,
134 },
135 #[error("earliest block > latest block: got {got}, latest {latest}")]
136 EarliestBlockGreaterThanLatestBlock {
138 got: u64,
140 latest: u64,
142 },
143 #[error("blockhash is zero")]
144 BlockhashZero,
146}