1use 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#[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 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 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}