reth_network_api/
lib.rs

1//! Reth interface definitions and commonly used types for the reth-network crate.
2//!
3//! Provides abstractions for the reth-network crate.
4//!
5//! ## Feature Flags
6//!
7//! - `serde` (default): Enable serde support
8
9#![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/paradigmxyz/reth/issues/"
13)]
14#![cfg_attr(docsrs, feature(doc_cfg))]
15
16pub mod downloaders;
17/// Network Error
18pub mod error;
19pub mod events;
20/// Implementation of network traits for that does nothing.
21pub 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, Capability, DisconnectReason, EthVersion, NetworkPrimitives,
39    UnifiedStatus,
40};
41use reth_network_p2p::sync::NetworkSyncUpdater;
42use reth_network_peers::NodeRecord;
43use std::{future::Future, net::SocketAddr, sync::Arc, time::Instant};
44
45/// The `PeerId` type.
46pub type PeerId = alloy_primitives::B512;
47
48/// Helper trait that unifies network API needed to launch node.
49pub trait FullNetwork:
50    BlockDownloaderProvider<
51        Client: BlockClient<Block = <Self::Primitives as NetworkPrimitives>::Block>,
52    > + NetworkSyncUpdater
53    + NetworkInfo
54    + NetworkEventListenerProvider
55    + Peers
56    + PeersHandleProvider
57    + Clone
58    + Unpin
59    + 'static
60{
61}
62
63impl<T> FullNetwork for T where
64    T: BlockDownloaderProvider<
65            Client: BlockClient<Block = <Self::Primitives as NetworkPrimitives>::Block>,
66        > + NetworkSyncUpdater
67        + NetworkInfo
68        + NetworkEventListenerProvider
69        + Peers
70        + PeersHandleProvider
71        + Clone
72        + Unpin
73        + 'static
74{
75}
76
77/// Provides general purpose information about the network.
78#[auto_impl::auto_impl(&, Arc)]
79pub trait NetworkInfo: Send + Sync {
80    /// Returns the [`SocketAddr`] that listens for incoming connections.
81    fn local_addr(&self) -> SocketAddr;
82
83    /// Returns the current status of the network being ran by the local node.
84    fn network_status(&self) -> impl Future<Output = Result<NetworkStatus, NetworkError>> + Send;
85
86    /// Returns the chain id
87    fn chain_id(&self) -> u64;
88
89    /// Returns `true` if the network is undergoing sync.
90    fn is_syncing(&self) -> bool;
91
92    /// Returns `true` when the node is undergoing the very first Pipeline sync.
93    fn is_initially_syncing(&self) -> bool;
94}
95
96/// Provides general purpose information about Peers in the network.
97#[auto_impl::auto_impl(&, Arc)]
98pub trait PeersInfo: Send + Sync {
99    /// Returns how many peers the network is currently connected to.
100    ///
101    /// Note: this should only include established connections and _not_ ongoing attempts.
102    fn num_connected_peers(&self) -> usize;
103
104    /// Returns the Ethereum Node Record of the node.
105    fn local_node_record(&self) -> NodeRecord;
106
107    /// Returns the local ENR of the node.
108    fn local_enr(&self) -> enr::Enr<enr::secp256k1::SecretKey>;
109}
110
111/// Provides an API for managing the peers of the network.
112#[auto_impl::auto_impl(&, Arc)]
113pub trait Peers: PeersInfo {
114    /// Adds a peer to the peer set with TCP `SocketAddr`.
115    ///
116    /// If the peer already exists, then this will update its tracked info.
117    fn add_peer(&self, peer: PeerId, tcp_addr: SocketAddr) {
118        self.add_peer_kind(peer, PeerKind::Static, tcp_addr, None);
119    }
120
121    /// Adds a peer to the peer set with TCP and UDP `SocketAddr`.
122    ///
123    /// If the peer already exists, then this will update its tracked info.
124    fn add_peer_with_udp(&self, peer: PeerId, tcp_addr: SocketAddr, udp_addr: SocketAddr) {
125        self.add_peer_kind(peer, PeerKind::Static, tcp_addr, Some(udp_addr));
126    }
127
128    /// Adds a trusted [`PeerId`] to the peer set.
129    ///
130    /// This allows marking a peer as trusted without having to know the peer's address.
131    fn add_trusted_peer_id(&self, peer: PeerId);
132
133    /// Adds a trusted peer to the peer set with TCP `SocketAddr`.
134    fn add_trusted_peer(&self, peer: PeerId, tcp_addr: SocketAddr) {
135        self.add_peer_kind(peer, PeerKind::Trusted, tcp_addr, None);
136    }
137
138    /// Adds a trusted peer with TCP and UDP `SocketAddr` to the peer set.
139    fn add_trusted_peer_with_udp(&self, peer: PeerId, tcp_addr: SocketAddr, udp_addr: SocketAddr) {
140        self.add_peer_kind(peer, PeerKind::Trusted, tcp_addr, Some(udp_addr));
141    }
142
143    /// Adds a peer to the known peer set, with the given kind.
144    ///
145    /// If the peer already exists, then this will update its tracked info.
146    fn add_peer_kind(
147        &self,
148        peer: PeerId,
149        kind: PeerKind,
150        tcp_addr: SocketAddr,
151        udp_addr: Option<SocketAddr>,
152    );
153
154    /// Returns the rpc [`PeerInfo`] for all connected [`PeerKind::Trusted`] peers.
155    fn get_trusted_peers(
156        &self,
157    ) -> impl Future<Output = Result<Vec<PeerInfo>, NetworkError>> + Send {
158        self.get_peers_by_kind(PeerKind::Trusted)
159    }
160
161    /// Returns the rpc [`PeerInfo`] for all connected [`PeerKind::Basic`] peers.
162    fn get_basic_peers(&self) -> impl Future<Output = Result<Vec<PeerInfo>, NetworkError>> + Send {
163        self.get_peers_by_kind(PeerKind::Basic)
164    }
165
166    /// Returns the rpc [`PeerInfo`] for all connected peers with the given kind.
167    fn get_peers_by_kind(
168        &self,
169        kind: PeerKind,
170    ) -> impl Future<Output = Result<Vec<PeerInfo>, NetworkError>> + Send;
171
172    /// Returns the rpc [`PeerInfo`] for all connected peers.
173    fn get_all_peers(&self) -> impl Future<Output = Result<Vec<PeerInfo>, NetworkError>> + Send;
174
175    /// Returns the rpc [`PeerInfo`] for the given peer id.
176    ///
177    /// Returns `None` if the peer is not connected.
178    fn get_peer_by_id(
179        &self,
180        peer_id: PeerId,
181    ) -> impl Future<Output = Result<Option<PeerInfo>, NetworkError>> + Send;
182
183    /// Returns the rpc [`PeerInfo`] for the given peers if they are connected.
184    ///
185    /// Note: This only returns peers that are connected, unconnected peers are ignored but keeping
186    /// the order in which they were requested.
187    fn get_peers_by_id(
188        &self,
189        peer_ids: Vec<PeerId>,
190    ) -> impl Future<Output = Result<Vec<PeerInfo>, NetworkError>> + Send;
191
192    /// Removes a peer from the peer set that corresponds to given kind.
193    fn remove_peer(&self, peer: PeerId, kind: PeerKind);
194
195    /// Disconnect an existing connection to the given peer.
196    fn disconnect_peer(&self, peer: PeerId);
197
198    /// Disconnect an existing connection to the given peer using the provided reason
199    fn disconnect_peer_with_reason(&self, peer: PeerId, reason: DisconnectReason);
200
201    /// Connect to the given peer. NOTE: if the maximum number of outbound sessions is reached,
202    /// this won't do anything. See `reth_network::SessionManager::dial_outbound`.
203    fn connect_peer(&self, peer: PeerId, tcp_addr: SocketAddr) {
204        self.connect_peer_kind(peer, PeerKind::Static, tcp_addr, None)
205    }
206
207    /// Connects a peer to the known peer set, with the given kind.
208    fn connect_peer_kind(
209        &self,
210        peer: PeerId,
211        kind: PeerKind,
212        tcp_addr: SocketAddr,
213        udp_addr: Option<SocketAddr>,
214    );
215
216    /// Send a reputation change for the given peer.
217    fn reputation_change(&self, peer_id: PeerId, kind: ReputationChangeKind);
218
219    /// Get the reputation of a peer.
220    fn reputation_by_id(
221        &self,
222        peer_id: PeerId,
223    ) -> impl Future<Output = Result<Option<Reputation>, NetworkError>> + Send;
224}
225
226/// Info about an active peer session.
227#[derive(Debug, Clone)]
228pub struct PeerInfo {
229    /// Announced capabilities of the peer
230    pub capabilities: Arc<Capabilities>,
231    /// The identifier of the remote peer
232    pub remote_id: PeerId,
233    /// The client's name and version
234    pub client_version: Arc<str>,
235    /// The peer's enode
236    pub enode: String,
237    /// The peer's enr
238    pub enr: Option<String>,
239    /// The peer's address we're connected to
240    pub remote_addr: SocketAddr,
241    /// The local address of the connection
242    pub local_addr: Option<SocketAddr>,
243    /// The direction of the session
244    pub direction: Direction,
245    /// The negotiated eth version.
246    pub eth_version: EthVersion,
247    /// The Status message the peer sent for the `eth` handshake
248    pub status: Arc<UnifiedStatus>,
249    /// The timestamp when the session to that peer has been established.
250    pub session_established: Instant,
251    /// The peer's connection kind
252    pub kind: PeerKind,
253}
254
255/// The direction of the connection.
256#[derive(Debug, Copy, Clone, PartialEq, Eq)]
257pub enum Direction {
258    /// Incoming connection.
259    Incoming,
260    /// Outgoing connection to a specific node.
261    Outgoing(PeerId),
262}
263
264impl Direction {
265    /// Returns `true` if this an incoming connection.
266    pub const fn is_incoming(&self) -> bool {
267        matches!(self, Self::Incoming)
268    }
269
270    /// Returns `true` if this an outgoing connection.
271    pub const fn is_outgoing(&self) -> bool {
272        matches!(self, Self::Outgoing(_))
273    }
274}
275
276impl std::fmt::Display for Direction {
277    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
278        match self {
279            Self::Incoming => write!(f, "incoming"),
280            Self::Outgoing(_) => write!(f, "outgoing"),
281        }
282    }
283}
284
285/// The status of the network being ran by the local node.
286#[derive(Clone, Debug)]
287#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
288pub struct NetworkStatus {
289    /// The local node client version.
290    pub client_version: String,
291    /// The current ethereum protocol version
292    pub protocol_version: u64,
293    /// Information about the Ethereum Wire Protocol.
294    pub eth_protocol_info: EthProtocolInfo,
295    /// The list of supported capabilities and their versions.
296    pub capabilities: Vec<Capability>,
297}