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