reth_network_api/
noop.rs

1//! A network implementation that does nothing.
2//!
3//! This is useful for wiring components together that don't require network but still need to be
4//! generic over it.
5
6use core::{fmt, marker::PhantomData};
7use std::net::{IpAddr, SocketAddr};
8
9use alloy_rpc_types_admin::EthProtocolInfo;
10use enr::{secp256k1::SecretKey, Enr};
11use reth_eth_wire_types::{
12    DisconnectReason, EthNetworkPrimitives, NetworkPrimitives, ProtocolVersion,
13};
14use reth_network_p2p::{sync::NetworkSyncUpdater, NoopFullBlockClient};
15use reth_network_peers::NodeRecord;
16use reth_network_types::{PeerKind, Reputation, ReputationChangeKind};
17use reth_tokio_util::{EventSender, EventStream};
18use tokio::sync::{mpsc, oneshot};
19use tokio_stream::wrappers::UnboundedReceiverStream;
20
21use crate::{
22    events::{NetworkPeersEvents, PeerEventStream},
23    test_utils::{PeersHandle, PeersHandleProvider},
24    BlockDownloaderProvider, DiscoveryEvent, NetworkError, NetworkEvent,
25    NetworkEventListenerProvider, NetworkInfo, NetworkStatus, PeerId, PeerInfo, PeerRequest, Peers,
26    PeersInfo,
27};
28
29/// A type that implements all network trait that does nothing.
30///
31/// Intended for testing purposes where network is not used.
32#[derive(Debug, Clone)]
33#[non_exhaustive]
34pub struct NoopNetwork<Net = EthNetworkPrimitives> {
35    peers_handle: PeersHandle,
36    _marker: PhantomData<Net>,
37}
38
39impl<Net> NoopNetwork<Net> {
40    /// Creates a new [`NoopNetwork`].
41    pub fn new() -> Self {
42        let (tx, _) = mpsc::unbounded_channel();
43
44        Self { peers_handle: PeersHandle::new(tx), _marker: PhantomData }
45    }
46}
47
48impl Default for NoopNetwork<EthNetworkPrimitives> {
49    fn default() -> Self {
50        let (tx, _) = mpsc::unbounded_channel();
51
52        Self { peers_handle: PeersHandle::new(tx), _marker: PhantomData }
53    }
54}
55
56impl<Net> NetworkInfo for NoopNetwork<Net>
57where
58    Net: Send + Sync,
59{
60    fn local_addr(&self) -> SocketAddr {
61        (IpAddr::from(std::net::Ipv4Addr::UNSPECIFIED), 30303).into()
62    }
63
64    async fn network_status(&self) -> Result<NetworkStatus, NetworkError> {
65        #[expect(deprecated)]
66        Ok(NetworkStatus {
67            client_version: "reth-test".to_string(),
68            protocol_version: ProtocolVersion::V5 as u64,
69            eth_protocol_info: EthProtocolInfo {
70                network: 1,
71                difficulty: None,
72                genesis: Default::default(),
73                config: Default::default(),
74                head: Default::default(),
75            },
76        })
77    }
78
79    fn chain_id(&self) -> u64 {
80        // mainnet
81        1
82    }
83
84    fn is_syncing(&self) -> bool {
85        false
86    }
87
88    fn is_initially_syncing(&self) -> bool {
89        false
90    }
91}
92
93impl<Net> PeersInfo for NoopNetwork<Net>
94where
95    Net: Send + Sync,
96{
97    fn num_connected_peers(&self) -> usize {
98        0
99    }
100
101    fn local_node_record(&self) -> NodeRecord {
102        NodeRecord::new(self.local_addr(), PeerId::random())
103    }
104
105    fn local_enr(&self) -> Enr<SecretKey> {
106        let sk = SecretKey::from_slice(&[0xcd; 32]).unwrap();
107        Enr::builder().build(&sk).unwrap()
108    }
109}
110
111impl<Net> Peers for NoopNetwork<Net>
112where
113    Net: Send + Sync,
114{
115    fn add_trusted_peer_id(&self, _peer: PeerId) {}
116
117    fn add_peer_kind(
118        &self,
119        _peer: PeerId,
120        _kind: PeerKind,
121        _tcp_addr: SocketAddr,
122        _udp_addr: Option<SocketAddr>,
123    ) {
124    }
125
126    async fn get_peers_by_kind(&self, _kind: PeerKind) -> Result<Vec<PeerInfo>, NetworkError> {
127        Ok(vec![])
128    }
129
130    async fn get_all_peers(&self) -> Result<Vec<PeerInfo>, NetworkError> {
131        Ok(vec![])
132    }
133
134    async fn get_peer_by_id(&self, _peer_id: PeerId) -> Result<Option<PeerInfo>, NetworkError> {
135        Ok(None)
136    }
137
138    async fn get_peers_by_id(&self, _peer_id: Vec<PeerId>) -> Result<Vec<PeerInfo>, NetworkError> {
139        Ok(vec![])
140    }
141
142    fn remove_peer(&self, _peer: PeerId, _kind: PeerKind) {}
143
144    fn disconnect_peer(&self, _peer: PeerId) {}
145
146    fn disconnect_peer_with_reason(&self, _peer: PeerId, _reason: DisconnectReason) {}
147
148    fn connect_peer_kind(
149        &self,
150        _peer: PeerId,
151        _kind: PeerKind,
152        _tcp_addr: SocketAddr,
153        _udp_addr: Option<SocketAddr>,
154    ) {
155    }
156
157    fn reputation_change(&self, _peer_id: PeerId, _kind: ReputationChangeKind) {}
158
159    async fn reputation_by_id(&self, _peer_id: PeerId) -> Result<Option<Reputation>, NetworkError> {
160        Ok(None)
161    }
162}
163
164impl<Net> BlockDownloaderProvider for NoopNetwork<Net>
165where
166    Net: NetworkPrimitives + Default,
167{
168    type Client = NoopFullBlockClient<Net>;
169
170    async fn fetch_client(&self) -> Result<Self::Client, oneshot::error::RecvError> {
171        Ok(NoopFullBlockClient::<Net>::default())
172    }
173}
174
175impl<Net> NetworkSyncUpdater for NoopNetwork<Net>
176where
177    Net: fmt::Debug + Send + Sync + 'static,
178{
179    fn update_status(&self, _head: reth_ethereum_forks::Head) {}
180
181    fn update_sync_state(&self, _state: reth_network_p2p::sync::SyncState) {}
182
183    fn update_block_range(&self, _: reth_eth_wire_types::BlockRangeUpdate) {}
184}
185
186impl<Net> NetworkEventListenerProvider for NoopNetwork<Net>
187where
188    Net: NetworkPrimitives,
189{
190    type Primitives = Net;
191
192    fn event_listener(&self) -> EventStream<NetworkEvent<PeerRequest<Self::Primitives>>> {
193        let event_sender: EventSender<NetworkEvent<PeerRequest<Net>>> = Default::default();
194        event_sender.new_listener()
195    }
196
197    fn discovery_listener(&self) -> UnboundedReceiverStream<DiscoveryEvent> {
198        let (_, rx) = mpsc::unbounded_channel();
199        UnboundedReceiverStream::new(rx)
200    }
201}
202
203impl<Net> NetworkPeersEvents for NoopNetwork<Net>
204where
205    Net: NetworkPrimitives,
206{
207    fn peer_events(&self) -> PeerEventStream {
208        let event_sender: EventSender<NetworkEvent<PeerRequest<Net>>> = Default::default();
209        PeerEventStream::new(event_sender.new_listener())
210    }
211}
212
213impl<Net> PeersHandleProvider for NoopNetwork<Net>
214where
215    Net: NetworkPrimitives,
216{
217    fn peers_handle(&self) -> &PeersHandle {
218        &self.peers_handle
219    }
220}