1use 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#[derive(Debug, Clone)]
32#[non_exhaustive]
33pub struct NoopNetwork<Net = EthNetworkPrimitives> {
34 peers_handle: PeersHandle,
35 _marker: PhantomData<Net>,
36}
37
38impl<Net> NoopNetwork<Net> {
39 pub fn new() -> Self {
41 let (tx, _) = mpsc::unbounded_channel();
42
43 Self { peers_handle: PeersHandle::new(tx), _marker: PhantomData }
44 }
45}
46
47impl Default for NoopNetwork<EthNetworkPrimitives> {
48 fn default() -> Self {
49 let (tx, _) = mpsc::unbounded_channel();
50
51 Self { peers_handle: PeersHandle::new(tx), _marker: PhantomData }
52 }
53}
54
55impl<Net> NetworkInfo for NoopNetwork<Net>
56where
57 Net: Send + Sync,
58{
59 fn local_addr(&self) -> SocketAddr {
60 (IpAddr::from(std::net::Ipv4Addr::UNSPECIFIED), 30303).into()
61 }
62
63 async fn network_status(&self) -> Result<NetworkStatus, NetworkError> {
64 #[expect(deprecated)]
65 Ok(NetworkStatus {
66 client_version: "reth-test".to_string(),
67 protocol_version: ProtocolVersion::V5 as u64,
68 eth_protocol_info: EthProtocolInfo {
69 network: 1,
70 difficulty: None,
71 genesis: Default::default(),
72 config: Default::default(),
73 head: Default::default(),
74 },
75 capabilities: vec![],
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,
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}