reth_network_types/peers/
mod.rs

1pub mod addr;
2pub mod config;
3pub mod kind;
4pub mod reputation;
5pub mod state;
6
7pub use config::{ConnectionsConfig, PeersConfig};
8pub use reputation::{Reputation, ReputationChange, ReputationChangeKind, ReputationChangeWeights};
9
10use alloy_eip2124::ForkId;
11use tracing::debug;
12
13use crate::{
14    is_banned_reputation, PeerAddr, PeerConnectionState, PeerKind, ReputationChangeOutcome,
15    DEFAULT_REPUTATION,
16};
17
18/// Tracks info about a single peer.
19#[derive(Debug, Clone)]
20pub struct Peer {
21    /// Where to reach the peer.
22    pub addr: PeerAddr,
23    /// Reputation of the peer.
24    pub reputation: i32,
25    /// The state of the connection, if any.
26    pub state: PeerConnectionState,
27    /// The [`ForkId`] that the peer announced via discovery.
28    pub fork_id: Option<ForkId>,
29    /// Whether the entry should be removed after an existing session was terminated.
30    pub remove_after_disconnect: bool,
31    /// The kind of peer
32    pub kind: PeerKind,
33    /// Whether the peer is currently backed off.
34    pub backed_off: bool,
35    /// Counts number of times the peer was backed off due to a severe
36    /// [`BackoffKind`](crate::BackoffKind).
37    pub severe_backoff_counter: u8,
38}
39
40// === impl Peer ===
41
42impl Peer {
43    /// Returns a new peer for given [`PeerAddr`].
44    pub fn new(addr: PeerAddr) -> Self {
45        Self::with_state(addr, Default::default())
46    }
47
48    /// Returns a new trusted peer for given [`PeerAddr`].
49    pub fn trusted(addr: PeerAddr) -> Self {
50        Self { kind: PeerKind::Trusted, ..Self::new(addr) }
51    }
52
53    /// Returns the reputation of the peer
54    pub const fn reputation(&self) -> i32 {
55        self.reputation
56    }
57
58    /// Returns a new peer for given [`PeerAddr`] and [`PeerConnectionState`].
59    pub fn with_state(addr: PeerAddr, state: PeerConnectionState) -> Self {
60        Self {
61            addr,
62            state,
63            reputation: DEFAULT_REPUTATION,
64            fork_id: None,
65            remove_after_disconnect: false,
66            kind: Default::default(),
67            backed_off: false,
68            severe_backoff_counter: 0,
69        }
70    }
71
72    /// Returns a new peer for given [`PeerAddr`] and [`PeerKind`].
73    pub fn with_kind(addr: PeerAddr, kind: PeerKind) -> Self {
74        Self { kind, ..Self::new(addr) }
75    }
76
77    /// Resets the reputation of the peer to the default value. This always returns
78    /// [`ReputationChangeOutcome::None`].
79    pub const fn reset_reputation(&mut self) -> ReputationChangeOutcome {
80        self.reputation = DEFAULT_REPUTATION;
81
82        ReputationChangeOutcome::None
83    }
84
85    /// Applies a reputation change to the peer and returns what action should be taken.
86    pub fn apply_reputation(
87        &mut self,
88        reputation: i32,
89        kind: ReputationChangeKind,
90    ) -> ReputationChangeOutcome {
91        let previous = self.reputation;
92        // we add reputation since negative reputation change decrease total reputation
93        self.reputation = previous.saturating_add(reputation);
94
95        debug!(target: "net::peers", reputation=%self.reputation, banned=%self.is_banned(), ?kind, "applied reputation change");
96
97        if self.state.is_connected() && self.is_banned() {
98            self.state.disconnect();
99            return ReputationChangeOutcome::DisconnectAndBan
100        }
101
102        if self.is_banned() && !is_banned_reputation(previous) {
103            return ReputationChangeOutcome::Ban
104        }
105
106        if !self.is_banned() && is_banned_reputation(previous) {
107            return ReputationChangeOutcome::Unban
108        }
109
110        ReputationChangeOutcome::None
111    }
112
113    /// Returns true if the peer's reputation is below the banned threshold.
114    #[inline]
115    pub const fn is_banned(&self) -> bool {
116        is_banned_reputation(self.reputation)
117    }
118
119    /// Returns `true` if peer is banned.
120    #[inline]
121    pub const fn is_backed_off(&self) -> bool {
122        self.backed_off
123    }
124
125    /// Unbans the peer by resetting its reputation
126    #[inline]
127    pub const fn unban(&mut self) {
128        self.reputation = DEFAULT_REPUTATION
129    }
130
131    /// Returns whether this peer is trusted
132    #[inline]
133    pub const fn is_trusted(&self) -> bool {
134        matches!(self.kind, PeerKind::Trusted)
135    }
136
137    /// Returns whether this peer is static
138    #[inline]
139    pub const fn is_static(&self) -> bool {
140        matches!(self.kind, PeerKind::Static)
141    }
142}