1use 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#[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 pub fn new() -> Self {
43 let (tx, _) = mpsc::unbounded_channel();
44
45 Self {
46 chain_id: 1, peers_handle: PeersHandle::new(tx),
48 cell_custody: CellCustody::default(),
49 _marker: PhantomData,
50 }
51 }
52
53 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 connect_peer_kind(
163 &self,
164 _peer: PeerId,
165 _kind: PeerKind,
166 _tcp_addr: SocketAddr,
167 _udp_addr: Option<SocketAddr>,
168 ) {
169 }
170
171 fn reputation_change(&self, _peer_id: PeerId, _kind: ReputationChangeKind) {}
172
173 async fn reputation_by_id(&self, _peer_id: PeerId) -> Result<Option<Reputation>, NetworkError> {
174 Ok(None)
175 }
176}
177
178impl<Net> BlockDownloaderProvider for NoopNetwork<Net>
179where
180 Net: NetworkPrimitives,
181{
182 type Client = NoopFullBlockClient<Net>;
183
184 async fn fetch_client(&self) -> Result<Self::Client, oneshot::error::RecvError> {
185 Ok(NoopFullBlockClient::<Net>::default())
186 }
187}
188
189impl<Net> NetworkSyncUpdater for NoopNetwork<Net>
190where
191 Net: fmt::Debug + Send + Sync + 'static,
192{
193 fn update_status(&self, _head: reth_ethereum_forks::Head) {}
194
195 fn update_sync_state(&self, _state: reth_network_p2p::sync::SyncState) {}
196
197 fn update_block_range(&self, _: reth_eth_wire_types::BlockRangeUpdate) {}
198}
199
200impl<Net> NetworkEventListenerProvider for NoopNetwork<Net>
201where
202 Net: NetworkPrimitives,
203{
204 type Primitives = Net;
205
206 fn event_listener(&self) -> EventStream<NetworkEvent<PeerRequest<Self::Primitives>>> {
207 let event_sender: EventSender<NetworkEvent<PeerRequest<Net>>> = Default::default();
208 event_sender.new_listener()
209 }
210
211 fn discovery_listener(&self) -> UnboundedReceiverStream<DiscoveryEvent> {
212 let (_, rx) = mpsc::unbounded_channel();
213 UnboundedReceiverStream::new(rx)
214 }
215}
216
217impl<Net> NetworkPeersEvents for NoopNetwork<Net>
218where
219 Net: NetworkPrimitives,
220{
221 fn peer_events(&self) -> PeerEventStream {
222 let event_sender: EventSender<NetworkEvent<PeerRequest<Net>>> = Default::default();
223 PeerEventStream::new(event_sender.new_listener())
224 }
225}
226
227impl<Net> PeersHandleProvider for NoopNetwork<Net>
228where
229 Net: NetworkPrimitives,
230{
231 fn peers_handle(&self) -> &PeersHandle {
232 &self.peers_handle
233 }
234}