reth_network_types/peers/
mod.rs1pub 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 reth_network_peers::{NodeRecord, PeerId};
12use tracing::trace;
13
14use crate::{
15 is_banned_reputation, PeerAddr, PeerConnectionState, PeerKind, ReputationChangeOutcome,
16 DEFAULT_REPUTATION,
17};
18
19#[derive(Debug, Clone)]
21pub struct Peer {
22 pub addr: PeerAddr,
24 pub reputation: i32,
26 pub state: PeerConnectionState,
28 pub fork_id: Option<Box<ForkId>>,
30 pub remove_after_disconnect: bool,
32 pub kind: PeerKind,
34 pub backed_off: bool,
36 pub severe_backoff_counter: u8,
39}
40
41impl Peer {
44 pub fn new(addr: PeerAddr) -> Self {
46 Self::with_state(addr, Default::default())
47 }
48
49 pub fn trusted(addr: PeerAddr) -> Self {
51 Self { kind: PeerKind::Trusted, ..Self::new(addr) }
52 }
53
54 pub const fn reputation(&self) -> i32 {
56 self.reputation
57 }
58
59 pub fn with_state(addr: PeerAddr, state: PeerConnectionState) -> Self {
61 Self {
62 addr,
63 state,
64 reputation: DEFAULT_REPUTATION,
65 fork_id: None,
66 remove_after_disconnect: false,
67 kind: Default::default(),
68 backed_off: false,
69 severe_backoff_counter: 0,
70 }
71 }
72
73 pub fn with_kind(addr: PeerAddr, kind: PeerKind) -> Self {
75 Self { kind, ..Self::new(addr) }
76 }
77
78 pub const fn reset_reputation(&mut self) -> ReputationChangeOutcome {
81 self.reputation = DEFAULT_REPUTATION;
82
83 ReputationChangeOutcome::None
84 }
85
86 pub fn apply_reputation(
88 &mut self,
89 reputation: i32,
90 kind: ReputationChangeKind,
91 ) -> ReputationChangeOutcome {
92 let previous = self.reputation;
93 self.reputation = previous.saturating_add(reputation);
95
96 trace!(target: "net::peers", reputation=%self.reputation, banned=%self.is_banned(), ?kind, "applied reputation change");
97
98 if self.state.is_connected() && self.is_banned() {
99 self.state.disconnect();
100 return ReputationChangeOutcome::DisconnectAndBan
101 }
102
103 if self.is_banned() && !is_banned_reputation(previous) {
104 return ReputationChangeOutcome::Ban
105 }
106
107 if !self.is_banned() && is_banned_reputation(previous) {
108 return ReputationChangeOutcome::Unban
109 }
110
111 ReputationChangeOutcome::None
112 }
113
114 #[inline]
116 pub const fn is_banned(&self) -> bool {
117 is_banned_reputation(self.reputation)
118 }
119
120 #[inline]
122 pub const fn is_backed_off(&self) -> bool {
123 self.backed_off
124 }
125
126 #[inline]
128 pub const fn unban(&mut self) {
129 self.reputation = DEFAULT_REPUTATION
130 }
131
132 #[inline]
134 pub const fn is_trusted(&self) -> bool {
135 matches!(self.kind, PeerKind::Trusted)
136 }
137
138 #[inline]
140 pub const fn is_static(&self) -> bool {
141 matches!(self.kind, PeerKind::Static)
142 }
143}
144
145#[derive(Debug, Clone, PartialEq, Eq)]
150#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
151pub struct PersistedPeerInfo {
152 pub record: NodeRecord,
154 pub kind: PeerKind,
156 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "Option::is_none"))]
158 pub fork_id: Option<ForkId>,
159 pub reputation: i32,
161}
162
163impl PersistedPeerInfo {
164 pub const fn peer_id(&self) -> PeerId {
166 self.record.id
167 }
168
169 pub const fn from_node_record(record: NodeRecord) -> Self {
171 Self { record, kind: PeerKind::Basic, fork_id: None, reputation: DEFAULT_REPUTATION }
172 }
173}