Skip to main content

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