Skip to main content

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