cometbft_p2p/
error.rs

1//! Error types
2
3use crate::PeerId;
4use std::fmt::{self, Display};
5
6/// Result type for the `cometbft-p2p` crate.
7pub type Result<T> = std::result::Result<T, Error>;
8
9/// Error type
10#[derive(Debug)]
11#[non_exhaustive]
12pub enum Error {
13    /// Cryptographic errors
14    Crypto(CryptoError),
15
16    /// Protobuf decode message
17    Decode(prost::DecodeError),
18
19    /// I/O error
20    Io(std::io::Error),
21
22    /// Message exceeds the maximum allowed size.
23    MessageSize {
24        /// Size of the message.
25        size: usize,
26    },
27
28    /// Failure to verify the remote peer ID.
29    VerifyPeer(VerifyPeerError),
30}
31
32impl Display for Error {
33    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34        match self {
35            Self::Crypto(_) => f.write_str("cryptographic error"),
36            Self::Decode(_) => f.write_str("malformed protocol message (version mismatch?)"),
37            Self::Io(_) => f.write_str("I/O error"),
38            Self::MessageSize { size } => write!(f, "unexpected message size ({size} bytes)"),
39            Self::VerifyPeer(_) => f.write_str("peer verification failed"),
40        }
41    }
42}
43
44impl std::error::Error for Error {
45    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
46        match self {
47            Self::Crypto(e) => Some(e),
48            Self::Decode(e) => Some(e),
49            Self::Io(e) => Some(e),
50            Self::VerifyPeer(e) => Some(e),
51            _ => None,
52        }
53    }
54}
55
56impl From<CryptoError> for Error {
57    fn from(err: CryptoError) -> Self {
58        Error::Crypto(err)
59    }
60}
61
62impl From<VerifyPeerError> for Error {
63    fn from(err: VerifyPeerError) -> Self {
64        Error::VerifyPeer(err)
65    }
66}
67
68impl From<ed25519_dalek::ed25519::Error> for Error {
69    fn from(err: ed25519_dalek::ed25519::Error) -> Self {
70        CryptoError::from(err).into()
71    }
72}
73
74impl From<prost::DecodeError> for Error {
75    fn from(e: prost::DecodeError) -> Self {
76        Self::Decode(e)
77    }
78}
79
80impl From<std::io::Error> for Error {
81    fn from(e: std::io::Error) -> Self {
82        Self::Io(e)
83    }
84}
85
86/// Opaque type for cryptographic errors which still internally tracks what went wrong for debugging
87/// purposes.
88///
89/// Intentionally kept opaque to reduce potential for sidechannels.
90#[derive(Debug)]
91pub struct CryptoError(pub(crate) InternalCryptoError);
92
93impl CryptoError {
94    pub(crate) const INSECURE_KEY: Self = Self(InternalCryptoError::InsecureKey);
95    pub(crate) const ENCRYPTION: Self = Self(InternalCryptoError::PacketEncryption);
96    pub(crate) const SIGNATURE: Self = Self(InternalCryptoError::SignatureInvalid);
97}
98
99impl Display for CryptoError {
100    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101        match self.0 {
102            InternalCryptoError::InsecureKey => {
103                f.write_str("insecure public key (potential MitM attack!)")
104            }
105            InternalCryptoError::PacketEncryption => {
106                f.write_str("packet encryption error (forget packet?)")
107            }
108            InternalCryptoError::SignatureInvalid => f.write_str("signature error"),
109        }
110    }
111}
112
113impl std::error::Error for CryptoError {}
114
115impl From<aead::Error> for CryptoError {
116    fn from(_: aead::Error) -> Self {
117        CryptoError::ENCRYPTION
118    }
119}
120
121impl From<ed25519_dalek::ed25519::Error> for CryptoError {
122    fn from(_: ed25519_dalek::ed25519::Error) -> Self {
123        CryptoError::SIGNATURE
124    }
125}
126
127/// Hidden inner type for tracking what type of cryptographic error occurred.
128#[derive(Debug)]
129pub(crate) enum InternalCryptoError {
130    /// Public key is a low-order-point. Possible man-in-the-middle attack!
131    InsecureKey,
132
133    /// Packet encryption error. Possible forgery.
134    PacketEncryption,
135
136    /// Signature error
137    SignatureInvalid,
138}
139
140/// Peer verification error.
141#[derive(Clone, Debug, Eq, PartialEq)]
142pub struct VerifyPeerError {
143    /// Expected peer ID.
144    pub expected_peer_id: PeerId,
145
146    /// Actual peer ID.
147    pub actual_peer_id: PeerId,
148}
149
150impl Display for VerifyPeerError {
151    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152        write!(
153            f,
154            "peer verification error: expected {}, got {}",
155            self.expected_peer_id, self.actual_peer_id
156        )
157    }
158}
159
160impl std::error::Error for VerifyPeerError {}