use std::time::Duration;
use crate::{bans::BAN_DURATION_LONG, peer_manager::NodeId};
#[derive(Debug, Clone, thiserror::Error)]
pub enum PeerValidatorError {
#[error("Peer signature was invalid for peer '{peer}'")]
InvalidPeerSignature { peer: NodeId },
#[error("One or more peer addresses were invalid for '{peer}'")]
InvalidPeerAddresses { peer: NodeId },
#[error("Peer '{peer}' has no address claims")]
PeerHasNoAddresses { peer: NodeId },
#[error("Peer '{peer}' has address claims, but none are usable")]
PeerHasNoUsableAddresses { peer: NodeId },
#[error("Invalid multiaddr: {0}")]
InvalidMultiaddr(String),
#[error("Onion v2 is deprecated and not supported")]
OnionV2NotSupported,
#[error("Peer provided too many supported protocols: expected max {max} but got {length}")]
PeerIdentityTooManyProtocols { length: usize, max: usize },
#[error("Peer provided too many addresses: expected max {max} but got {length}")]
PeerIdentityTooManyAddresses { length: usize, max: usize },
#[error("Peer provided a protocol id that exceeds the maximum length: expected max {max} but got {length}")]
PeerIdentityProtocolIdTooLong { length: usize, max: usize },
#[error("Peer provided a user agent that exceeds the maximum length: expected max {max} but got {length}")]
PeerIdentityUserAgentTooLong { length: usize, max: usize },
}
impl PeerValidatorError {
pub fn is_ban_offence(&self) -> bool {
match self {
Self::PeerHasNoAddresses { .. } | Self::PeerHasNoUsableAddresses { .. } => false,
Self::InvalidPeerSignature { .. } |
Self::InvalidPeerAddresses { .. } |
Self::InvalidMultiaddr(_) |
Self::OnionV2NotSupported |
Self::PeerIdentityTooManyProtocols { .. } |
Self::PeerIdentityTooManyAddresses { .. } |
Self::PeerIdentityProtocolIdTooLong { .. } |
Self::PeerIdentityUserAgentTooLong { .. } => true,
}
}
pub fn as_ban_duration(&self) -> Option<Duration> {
self.is_ban_offence().then_some(BAN_DURATION_LONG)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn only_non_hostile_address_absence_errors_avoid_a_ban() {
let peer = NodeId::default();
assert!(
PeerValidatorError::PeerHasNoAddresses { peer: peer.clone() }
.as_ban_duration()
.is_none()
);
assert!(
PeerValidatorError::PeerHasNoUsableAddresses { peer }
.as_ban_duration()
.is_none()
);
assert!(
PeerValidatorError::InvalidMultiaddr("bad address".to_string())
.as_ban_duration()
.is_some()
);
}
}