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::trace;
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 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(&mut self, reputation: i32) -> ReputationChangeOutcome {
87        let previous = self.reputation;
88        // we add reputation since negative reputation change decrease total reputation
89        self.reputation = previous.saturating_add(reputation);
90
91        trace!(target: "net::peers", reputation=%self.reputation, banned=%self.is_banned(), "applied reputation change");
92
93        if self.state.is_connected() && self.is_banned() {
94            self.state.disconnect();
95            return ReputationChangeOutcome::DisconnectAndBan
96        }
97
98        if self.is_banned() && !is_banned_reputation(previous) {
99            return ReputationChangeOutcome::Ban
100        }
101
102        if !self.is_banned() && is_banned_reputation(previous) {
103            return ReputationChangeOutcome::Unban
104        }
105
106        ReputationChangeOutcome::None
107    }
108
109    /// Returns true if the peer's reputation is below the banned threshold.
110    #[inline]
111    pub const fn is_banned(&self) -> bool {
112        is_banned_reputation(self.reputation)
113    }
114
115    /// Returns `true` if peer is banned.
116    #[inline]
117    pub const fn is_backed_off(&self) -> bool {
118        self.backed_off
119    }
120
121    /// Unbans the peer by resetting its reputation
122    #[inline]
123    pub fn unban(&mut self) {
124        self.reputation = DEFAULT_REPUTATION
125    }
126
127    /// Returns whether this peer is trusted
128    #[inline]
129    pub const fn is_trusted(&self) -> bool {
130        matches!(self.kind, PeerKind::Trusted)
131    }
132
133    /// Returns whether this peer is static
134    #[inline]
135    pub const fn is_static(&self) -> bool {
136        matches!(self.kind, PeerKind::Static)
137    }
138}