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/SeismicSystems/seismic-reth/issues/"
13)]
14#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_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, 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
44/// The `PeerId` type.
45pub type PeerId = alloy_primitives::B512;
46
47/// Helper trait that unifies network API needed to launch node.
48pub 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/// Provides general purpose information about the network.
77#[auto_impl::auto_impl(&, Arc)]
78pub trait NetworkInfo: Send + Sync {
79    /// Returns the [`SocketAddr`] that listens for incoming connections.
80    fn local_addr(&self) -> SocketAddr;
81
82    /// Returns the current status of the network being ran by the local node.
83    fn network_status(&self) -> impl Future<Output = Result<NetworkStatus, NetworkError>> + Send;
84
85    /// Returns the chain id
86    fn chain_id(&self) -> u64;
87
88    /// Returns `true` if the network is undergoing sync.
89    fn is_syncing(&self) -> bool;
90
91    /// Returns `true` when the node is undergoing the very first Pipeline sync.
92    fn is_initially_syncing(&self) -> bool;
93}
94
95/// Provides general purpose information about Peers in the network.
96#[auto_impl::auto_impl(&, Arc)]
97pub trait PeersInfo: Send + Sync {
98    /// Returns how many peers the network is currently connected to.
99    ///
100    /// Note: this should only include established connections and _not_ ongoing attempts.
101    fn num_connected_peers(&self) -> usize;
102
103    /// Returns the Ethereum Node Record of the node.
104    fn local_node_record(&self) -> NodeRecord;
105
106    /// Returns the local ENR of the node.
107    fn local_enr(&self) -> enr::Enr<enr::secp256k1::SecretKey>;
108}
109
110/// Provides an API for managing the peers of the network.
111#[auto_impl::auto_impl(&, Arc)]
112pub trait Peers: PeersInfo {
113    /// Adds a peer to the peer set with TCP `SocketAddr`.
114    fn add_peer(&self, peer: PeerId, tcp_addr: SocketAddr) {
115        self.add_peer_kind(peer, PeerKind::Static, tcp_addr, None);
116    }
117
118    /// Adds a peer to the peer set with TCP and UDP `SocketAddr`.
119    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    /// Adds a trusted [`PeerId`] to the peer set.
124    ///
125    /// This allows marking a peer as trusted without having to know the peer's address.
126    fn add_trusted_peer_id(&self, peer: PeerId);
127
128    /// Adds a trusted peer to the peer set with TCP `SocketAddr`.
129    fn add_trusted_peer(&self, peer: PeerId, tcp_addr: SocketAddr) {
130        self.add_peer_kind(peer, PeerKind::Trusted, tcp_addr, None);
131    }
132
133    /// Adds a trusted peer with TCP and UDP `SocketAddr` to the peer set.
134    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    /// Adds a peer to the known peer set, with the given kind.
139    fn add_peer_kind(
140        &self,
141        peer: PeerId,
142        kind: PeerKind,
143        tcp_addr: SocketAddr,
144        udp_addr: Option<SocketAddr>,
145    );
146
147    /// Returns the rpc [`PeerInfo`] for all connected [`PeerKind::Trusted`] peers.
148    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    /// Returns the rpc [`PeerInfo`] for all connected [`PeerKind::Basic`] peers.
155    fn get_basic_peers(&self) -> impl Future<Output = Result<Vec<PeerInfo>, NetworkError>> + Send {
156        self.get_peers_by_kind(PeerKind::Basic)
157    }
158
159    /// Returns the rpc [`PeerInfo`] for all connected peers with the given kind.
160    fn get_peers_by_kind(
161        &self,
162        kind: PeerKind,
163    ) -> impl Future<Output = Result<Vec<PeerInfo>, NetworkError>> + Send;
164
165    /// Returns the rpc [`PeerInfo`] for all connected peers.
166    fn get_all_peers(&self) -> impl Future<Output = Result<Vec<PeerInfo>, NetworkError>> + Send;
167
168    /// Returns the rpc [`PeerInfo`] for the given peer id.
169    ///
170    /// Returns `None` if the peer is not connected.
171    fn get_peer_by_id(
172        &self,
173        peer_id: PeerId,
174    ) -> impl Future<Output = Result<Option<PeerInfo>, NetworkError>> + Send;
175
176    /// Returns the rpc [`PeerInfo`] for the given peers if they are connected.
177    ///
178    /// Note: This only returns peers that are connected, unconnected peers are ignored but keeping
179    /// the order in which they were requested.
180    fn get_peers_by_id(
181        &self,
182        peer_ids: Vec<PeerId>,
183    ) -> impl Future<Output = Result<Vec<PeerInfo>, NetworkError>> + Send;
184
185    /// Removes a peer from the peer set that corresponds to given kind.
186    fn remove_peer(&self, peer: PeerId, kind: PeerKind);
187
188    /// Disconnect an existing connection to the given peer.
189    fn disconnect_peer(&self, peer: PeerId);
190
191    /// Disconnect an existing connection to the given peer using the provided reason
192    fn disconnect_peer_with_reason(&self, peer: PeerId, reason: DisconnectReason);
193
194    /// Connect to the given peer. NOTE: if the maximum number out outbound sessions is reached,
195    /// this won't do anything. See `reth_network::SessionManager::dial_outbound`.
196    fn connect_peer(&self, peer: PeerId, tcp_addr: SocketAddr) {
197        self.connect_peer_kind(peer, PeerKind::Static, tcp_addr, None)
198    }
199
200    /// Connects a peer to the known peer set, with the given kind.
201    fn connect_peer_kind(
202        &self,
203        peer: PeerId,
204        kind: PeerKind,
205        tcp_addr: SocketAddr,
206        udp_addr: Option<SocketAddr>,
207    );
208
209    /// Send a reputation change for the given peer.
210    fn reputation_change(&self, peer_id: PeerId, kind: ReputationChangeKind);
211
212    /// Get the reputation of a peer.
213    fn reputation_by_id(
214        &self,
215        peer_id: PeerId,
216    ) -> impl Future<Output = Result<Option<Reputation>, NetworkError>> + Send;
217}
218
219/// Info about an active peer session.
220#[derive(Debug, Clone)]
221pub struct PeerInfo {
222    /// Announced capabilities of the peer
223    pub capabilities: Arc<Capabilities>,
224    /// The identifier of the remote peer
225    pub remote_id: PeerId,
226    /// The client's name and version
227    pub client_version: Arc<str>,
228    /// The peer's enode
229    pub enode: String,
230    /// The peer's enr
231    pub enr: Option<String>,
232    /// The peer's address we're connected to
233    pub remote_addr: SocketAddr,
234    /// The local address of the connection
235    pub local_addr: Option<SocketAddr>,
236    /// The direction of the session
237    pub direction: Direction,
238    /// The negotiated eth version.
239    pub eth_version: EthVersion,
240    /// The Status message the peer sent for the `eth` handshake
241    pub status: Arc<UnifiedStatus>,
242    /// The timestamp when the session to that peer has been established.
243    pub session_established: Instant,
244    /// The peer's connection kind
245    pub kind: PeerKind,
246}
247
248/// The direction of the connection.
249#[derive(Debug, Copy, Clone, PartialEq, Eq)]
250pub enum Direction {
251    /// Incoming connection.
252    Incoming,
253    /// Outgoing connection to a specific node.
254    Outgoing(PeerId),
255}
256
257impl Direction {
258    /// Returns `true` if this an incoming connection.
259    pub const fn is_incoming(&self) -> bool {
260        matches!(self, Self::Incoming)
261    }
262
263    /// Returns `true` if this an outgoing connection.
264    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/// The status of the network being ran by the local node.
279#[derive(Clone, Debug)]
280#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
281pub struct NetworkStatus {
282    /// The local node client version.
283    pub client_version: String,
284    /// The current ethereum protocol version
285    pub protocol_version: u64,
286    /// Information about the Ethereum Wire Protocol.
287    pub eth_protocol_info: EthProtocolInfo,
288}