1#![doc(
10 html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png",
11 html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256",
12 issue_tracker_base_url = "https://github.com/SeismicSystems/seismic-reth/issues/"
13)]
14#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
15
16pub mod downloaders;
17pub mod error;
19pub mod events;
20pub mod noop;
22
23pub mod test_utils;
24use test_utils::PeersHandleProvider;
25
26pub use alloy_rpc_types_admin::EthProtocolInfo;
27pub use reth_network_p2p::{BlockClient, HeadersClient};
28pub use reth_network_types::{PeerKind, Reputation, ReputationChangeKind};
29
30pub use downloaders::BlockDownloaderProvider;
31pub use error::NetworkError;
32pub use events::{
33 DiscoveredEvent, DiscoveryEvent, NetworkEvent, NetworkEventListenerProvider, PeerRequest,
34 PeerRequestSender,
35};
36
37use reth_eth_wire_types::{
38 capability::Capabilities, DisconnectReason, EthVersion, NetworkPrimitives, UnifiedStatus,
39};
40use reth_network_p2p::sync::NetworkSyncUpdater;
41use reth_network_peers::NodeRecord;
42use std::{future::Future, net::SocketAddr, sync::Arc, time::Instant};
43
44pub type PeerId = alloy_primitives::B512;
46
47pub trait FullNetwork:
49 BlockDownloaderProvider<
50 Client: BlockClient<Block = <Self::Primitives as NetworkPrimitives>::Block>,
51 > + NetworkSyncUpdater
52 + NetworkInfo
53 + NetworkEventListenerProvider
54 + Peers
55 + PeersHandleProvider
56 + Clone
57 + Unpin
58 + 'static
59{
60}
61
62impl<T> FullNetwork for T where
63 T: BlockDownloaderProvider<
64 Client: BlockClient<Block = <Self::Primitives as NetworkPrimitives>::Block>,
65 > + NetworkSyncUpdater
66 + NetworkInfo
67 + NetworkEventListenerProvider
68 + Peers
69 + PeersHandleProvider
70 + Clone
71 + Unpin
72 + 'static
73{
74}
75
76#[auto_impl::auto_impl(&, Arc)]
78pub trait NetworkInfo: Send + Sync {
79 fn local_addr(&self) -> SocketAddr;
81
82 fn network_status(&self) -> impl Future<Output = Result<NetworkStatus, NetworkError>> + Send;
84
85 fn chain_id(&self) -> u64;
87
88 fn is_syncing(&self) -> bool;
90
91 fn is_initially_syncing(&self) -> bool;
93}
94
95#[auto_impl::auto_impl(&, Arc)]
97pub trait PeersInfo: Send + Sync {
98 fn num_connected_peers(&self) -> usize;
102
103 fn local_node_record(&self) -> NodeRecord;
105
106 fn local_enr(&self) -> enr::Enr<enr::secp256k1::SecretKey>;
108}
109
110#[auto_impl::auto_impl(&, Arc)]
112pub trait Peers: PeersInfo {
113 fn add_peer(&self, peer: PeerId, tcp_addr: SocketAddr) {
115 self.add_peer_kind(peer, PeerKind::Static, tcp_addr, None);
116 }
117
118 fn add_peer_with_udp(&self, peer: PeerId, tcp_addr: SocketAddr, udp_addr: SocketAddr) {
120 self.add_peer_kind(peer, PeerKind::Static, tcp_addr, Some(udp_addr));
121 }
122
123 fn add_trusted_peer_id(&self, peer: PeerId);
127
128 fn add_trusted_peer(&self, peer: PeerId, tcp_addr: SocketAddr) {
130 self.add_peer_kind(peer, PeerKind::Trusted, tcp_addr, None);
131 }
132
133 fn add_trusted_peer_with_udp(&self, peer: PeerId, tcp_addr: SocketAddr, udp_addr: SocketAddr) {
135 self.add_peer_kind(peer, PeerKind::Trusted, tcp_addr, Some(udp_addr));
136 }
137
138 fn add_peer_kind(
140 &self,
141 peer: PeerId,
142 kind: PeerKind,
143 tcp_addr: SocketAddr,
144 udp_addr: Option<SocketAddr>,
145 );
146
147 fn get_trusted_peers(
149 &self,
150 ) -> impl Future<Output = Result<Vec<PeerInfo>, NetworkError>> + Send {
151 self.get_peers_by_kind(PeerKind::Trusted)
152 }
153
154 fn get_basic_peers(&self) -> impl Future<Output = Result<Vec<PeerInfo>, NetworkError>> + Send {
156 self.get_peers_by_kind(PeerKind::Basic)
157 }
158
159 fn get_peers_by_kind(
161 &self,
162 kind: PeerKind,
163 ) -> impl Future<Output = Result<Vec<PeerInfo>, NetworkError>> + Send;
164
165 fn get_all_peers(&self) -> impl Future<Output = Result<Vec<PeerInfo>, NetworkError>> + Send;
167
168 fn get_peer_by_id(
172 &self,
173 peer_id: PeerId,
174 ) -> impl Future<Output = Result<Option<PeerInfo>, NetworkError>> + Send;
175
176 fn get_peers_by_id(
181 &self,
182 peer_ids: Vec<PeerId>,
183 ) -> impl Future<Output = Result<Vec<PeerInfo>, NetworkError>> + Send;
184
185 fn remove_peer(&self, peer: PeerId, kind: PeerKind);
187
188 fn disconnect_peer(&self, peer: PeerId);
190
191 fn disconnect_peer_with_reason(&self, peer: PeerId, reason: DisconnectReason);
193
194 fn connect_peer(&self, peer: PeerId, tcp_addr: SocketAddr) {
197 self.connect_peer_kind(peer, PeerKind::Static, tcp_addr, None)
198 }
199
200 fn connect_peer_kind(
202 &self,
203 peer: PeerId,
204 kind: PeerKind,
205 tcp_addr: SocketAddr,
206 udp_addr: Option<SocketAddr>,
207 );
208
209 fn reputation_change(&self, peer_id: PeerId, kind: ReputationChangeKind);
211
212 fn reputation_by_id(
214 &self,
215 peer_id: PeerId,
216 ) -> impl Future<Output = Result<Option<Reputation>, NetworkError>> + Send;
217}
218
219#[derive(Debug, Clone)]
221pub struct PeerInfo {
222 pub capabilities: Arc<Capabilities>,
224 pub remote_id: PeerId,
226 pub client_version: Arc<str>,
228 pub enode: String,
230 pub enr: Option<String>,
232 pub remote_addr: SocketAddr,
234 pub local_addr: Option<SocketAddr>,
236 pub direction: Direction,
238 pub eth_version: EthVersion,
240 pub status: Arc<UnifiedStatus>,
242 pub session_established: Instant,
244 pub kind: PeerKind,
246}
247
248#[derive(Debug, Copy, Clone, PartialEq, Eq)]
250pub enum Direction {
251 Incoming,
253 Outgoing(PeerId),
255}
256
257impl Direction {
258 pub const fn is_incoming(&self) -> bool {
260 matches!(self, Self::Incoming)
261 }
262
263 pub const fn is_outgoing(&self) -> bool {
265 matches!(self, Self::Outgoing(_))
266 }
267}
268
269impl std::fmt::Display for Direction {
270 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
271 match self {
272 Self::Incoming => write!(f, "incoming"),
273 Self::Outgoing(_) => write!(f, "outgoing"),
274 }
275 }
276}
277
278#[derive(Clone, Debug)]
280#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
281pub struct NetworkStatus {
282 pub client_version: String,
284 pub protocol_version: u64,
286 pub eth_protocol_info: EthProtocolInfo,
288}