1use reth_eth_wire_types::{
4 message::RequestPair, snap::SnapProtocolMessage, BlockAccessLists, BlockBodies, BlockHeaders,
5 Capabilities, Cells, DisconnectReason, EthMessage, EthNetworkPrimitives, EthVersion,
6 GetBlockAccessLists, GetBlockBodies, GetBlockHeaders, GetCells, GetNodeData,
7 GetPooledTransactions, GetReceipts, GetReceipts70, NetworkPrimitives, NodeData,
8 PooledTransactions, Receipts, Receipts69, Receipts70, UnifiedStatus,
9};
10use reth_ethereum_forks::ForkId;
11use reth_network_p2p::{
12 error::{RequestError, RequestResult},
13 snap::client::SnapResponse,
14};
15use reth_network_peers::{NodeRecord, PeerId};
16use reth_network_types::{PeerAddr, PeerKind};
17use reth_tokio_util::EventStream;
18use std::{
19 fmt,
20 net::SocketAddr,
21 pin::Pin,
22 sync::Arc,
23 task::{Context, Poll},
24};
25use tokio::sync::{mpsc, oneshot};
26use tokio_stream::{wrappers::UnboundedReceiverStream, Stream, StreamExt};
27
28pub struct PeerEventStream(Pin<Box<dyn Stream<Item = PeerEvent> + Send + Sync>>);
30
31impl fmt::Debug for PeerEventStream {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 f.debug_struct("PeerEventStream").finish_non_exhaustive()
34 }
35}
36
37impl PeerEventStream {
38 pub fn new<S, T>(stream: S) -> Self
41 where
42 S: Stream<Item = T> + Send + Sync + 'static,
43 T: Into<PeerEvent> + 'static,
44 {
45 let mapped_stream = stream.map(Into::into);
46 Self(Box::pin(mapped_stream))
47 }
48}
49
50impl Stream for PeerEventStream {
51 type Item = PeerEvent;
52
53 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
54 self.0.as_mut().poll_next(cx)
55 }
56}
57
58#[derive(Debug, Clone)]
60pub struct SessionInfo {
61 pub peer_id: PeerId,
63 pub remote_addr: SocketAddr,
65 pub client_version: Arc<str>,
67 pub capabilities: Arc<Capabilities>,
69 pub status: Arc<UnifiedStatus>,
71 pub version: EthVersion,
73 pub peer_kind: PeerKind,
75}
76
77#[derive(Debug, Clone)]
83pub enum PeerEvent {
84 SessionClosed {
86 peer_id: PeerId,
88 reason: Option<DisconnectReason>,
90 },
91 SessionEstablished(SessionInfo),
93 PeerAdded(PeerId),
95 PeerRemoved(PeerId),
97}
98
99#[derive(Debug)]
101pub enum NetworkEvent<R = PeerRequest> {
102 Peer(PeerEvent),
104 ActivePeerSession {
106 info: SessionInfo,
108 messages: PeerRequestSender<R>,
110 },
111}
112
113impl<R> Clone for NetworkEvent<R> {
114 fn clone(&self) -> Self {
115 match self {
116 Self::Peer(event) => Self::Peer(event.clone()),
117 Self::ActivePeerSession { info, messages } => {
118 Self::ActivePeerSession { info: info.clone(), messages: messages.clone() }
119 }
120 }
121 }
122}
123
124impl<R> From<NetworkEvent<R>> for PeerEvent {
125 fn from(event: NetworkEvent<R>) -> Self {
126 match event {
127 NetworkEvent::Peer(peer_event) => peer_event,
128 NetworkEvent::ActivePeerSession { info, .. } => Self::SessionEstablished(info),
129 }
130 }
131}
132
133#[auto_impl::auto_impl(&, Arc)]
135pub trait NetworkPeersEvents: Send + Sync {
136 fn peer_events(&self) -> PeerEventStream;
138}
139
140#[auto_impl::auto_impl(&, Arc)]
142pub trait NetworkEventListenerProvider: NetworkPeersEvents {
143 type Primitives: NetworkPrimitives;
145
146 fn event_listener(&self) -> EventStream<NetworkEvent<PeerRequest<Self::Primitives>>>;
148 fn discovery_listener(&self) -> UnboundedReceiverStream<DiscoveryEvent>;
152}
153
154#[derive(Debug, Clone, PartialEq, Eq)]
156pub enum DiscoveryEvent {
157 NewNode(DiscoveredEvent),
159 EnrForkId(NodeRecord, ForkId),
166}
167
168#[derive(Debug, Clone, PartialEq, Eq)]
170pub enum DiscoveredEvent {
171 EventQueued {
183 peer_id: PeerId,
185 addr: PeerAddr,
187 fork_id: Option<ForkId>,
190 },
191}
192
193#[derive(Debug)]
195pub enum PeerRequest<N: NetworkPrimitives = EthNetworkPrimitives> {
196 GetBlockHeaders {
200 request: GetBlockHeaders,
202 response: oneshot::Sender<RequestResult<BlockHeaders<N::BlockHeader>>>,
204 },
205 GetBlockBodies {
209 request: GetBlockBodies,
211 response: oneshot::Sender<RequestResult<BlockBodies<N::BlockBody>>>,
213 },
214 GetPooledTransactions {
218 request: GetPooledTransactions,
220 response: oneshot::Sender<RequestResult<PooledTransactions<N::PooledTransaction>>>,
222 },
223 GetNodeData {
227 request: GetNodeData,
229 response: oneshot::Sender<RequestResult<NodeData>>,
231 },
232 GetReceipts {
236 request: GetReceipts,
238 response: oneshot::Sender<RequestResult<Receipts<N::Receipt>>>,
240 },
241 GetReceipts69 {
245 request: GetReceipts,
247 response: oneshot::Sender<RequestResult<Receipts69<N::Receipt>>>,
249 },
250 GetReceipts70 {
254 request: GetReceipts70,
256 response: oneshot::Sender<RequestResult<Receipts70<N::Receipt>>>,
258 },
259 GetBlockAccessLists {
263 request: GetBlockAccessLists,
265 response: oneshot::Sender<RequestResult<BlockAccessLists>>,
267 },
268 GetCells {
272 request: GetCells,
274 response: oneshot::Sender<RequestResult<Cells>>,
276 },
277 GetSnap {
281 request: SnapProtocolMessage,
283 response: oneshot::Sender<RequestResult<SnapResponse>>,
285 },
286}
287
288#[derive(Debug)]
291pub enum RequestMessage<N: NetworkPrimitives = EthNetworkPrimitives> {
292 Eth(EthMessage<N>),
294 Snap(SnapProtocolMessage),
296}
297
298impl<N: NetworkPrimitives> PeerRequest<N> {
301 pub fn send_bad_response(self) {
303 self.send_err_response(RequestError::BadResponse)
304 }
305
306 pub fn send_err_response(self, err: RequestError) {
308 let _ = match self {
309 Self::GetBlockHeaders { response, .. } => response.send(Err(err)).ok(),
310 Self::GetBlockBodies { response, .. } => response.send(Err(err)).ok(),
311 Self::GetPooledTransactions { response, .. } => response.send(Err(err)).ok(),
312 Self::GetNodeData { response, .. } => response.send(Err(err)).ok(),
313 Self::GetReceipts { response, .. } => response.send(Err(err)).ok(),
314 Self::GetReceipts69 { response, .. } => response.send(Err(err)).ok(),
315 Self::GetReceipts70 { response, .. } => response.send(Err(err)).ok(),
316 Self::GetBlockAccessLists { response, .. } => response.send(Err(err)).ok(),
317 Self::GetCells { response, .. } => response.send(Err(err)).ok(),
318 Self::GetSnap { response, .. } => response.send(Err(err)).ok(),
319 };
320 }
321
322 #[inline]
324 pub fn is_supported_by_eth_version(&self, version: EthVersion) -> bool {
325 match self {
326 Self::GetBlockAccessLists { .. } => version >= EthVersion::Eth71,
327 Self::GetCells { .. } => version >= EthVersion::Eth72,
328 _ => true,
329 }
330 }
331
332 pub fn create_request_message(&self, request_id: u64) -> RequestMessage<N> {
334 match self {
335 Self::GetBlockHeaders { request, .. } => {
336 RequestMessage::Eth(EthMessage::GetBlockHeaders(RequestPair {
337 request_id,
338 message: *request,
339 }))
340 }
341 Self::GetBlockBodies { request, .. } => {
342 RequestMessage::Eth(EthMessage::GetBlockBodies(RequestPair {
343 request_id,
344 message: request.clone(),
345 }))
346 }
347 Self::GetPooledTransactions { request, .. } => {
348 RequestMessage::Eth(EthMessage::GetPooledTransactions(RequestPair {
349 request_id,
350 message: request.clone(),
351 }))
352 }
353 Self::GetNodeData { request, .. } => {
354 RequestMessage::Eth(EthMessage::GetNodeData(RequestPair {
355 request_id,
356 message: request.clone(),
357 }))
358 }
359 Self::GetReceipts { request, .. } | Self::GetReceipts69 { request, .. } => {
360 RequestMessage::Eth(EthMessage::GetReceipts(RequestPair {
361 request_id,
362 message: request.clone(),
363 }))
364 }
365 Self::GetReceipts70 { request, .. } => {
366 RequestMessage::Eth(EthMessage::GetReceipts70(RequestPair {
367 request_id,
368 message: request.clone(),
369 }))
370 }
371 Self::GetBlockAccessLists { request, .. } => {
372 RequestMessage::Eth(EthMessage::GetBlockAccessLists(RequestPair {
373 request_id,
374 message: request.clone(),
375 }))
376 }
377 Self::GetCells { request, .. } => {
378 RequestMessage::Eth(EthMessage::GetCells(RequestPair {
379 request_id,
380 message: request.clone(),
381 }))
382 }
383 Self::GetSnap { request, .. } => {
384 let mut message = request.clone();
385 message.set_request_id(request_id);
386 RequestMessage::Snap(message)
387 }
388 }
389 }
390
391 pub fn into_get_pooled_transactions(self) -> Option<GetPooledTransactions> {
393 match self {
394 Self::GetPooledTransactions { request, .. } => Some(request),
395 _ => None,
396 }
397 }
398}
399
400pub struct PeerRequestSender<R = PeerRequest> {
402 pub peer_id: PeerId,
404 pub to_session_tx: mpsc::Sender<R>,
406}
407
408impl<R> Clone for PeerRequestSender<R> {
409 fn clone(&self) -> Self {
410 Self { peer_id: self.peer_id, to_session_tx: self.to_session_tx.clone() }
411 }
412}
413
414impl<R> PeerRequestSender<R> {
417 pub const fn new(peer_id: PeerId, to_session_tx: mpsc::Sender<R>) -> Self {
419 Self { peer_id, to_session_tx }
420 }
421
422 pub fn try_send(&self, req: R) -> Result<(), mpsc::error::TrySendError<R>> {
424 self.to_session_tx.try_send(req)
425 }
426
427 pub const fn peer_id(&self) -> &PeerId {
429 &self.peer_id
430 }
431}
432
433impl<R> fmt::Debug for PeerRequestSender<R> {
434 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
435 f.debug_struct("PeerRequestSender").field("peer_id", &self.peer_id).finish_non_exhaustive()
436 }
437}
438
439#[cfg(test)]
440mod tests {
441 use super::*;
442
443 #[test]
444 fn test_get_block_access_lists_version_support() {
445 let (tx, _rx) = oneshot::channel();
446 let req: PeerRequest<EthNetworkPrimitives> =
447 PeerRequest::GetBlockAccessLists { request: GetBlockAccessLists(vec![]), response: tx };
448
449 assert!(!req.is_supported_by_eth_version(EthVersion::Eth70));
450 assert!(req.is_supported_by_eth_version(EthVersion::Eth71));
451 }
452
453 #[test]
454 fn test_get_cells_version_support() {
455 let (tx, _rx) = oneshot::channel();
456 let req: PeerRequest<EthNetworkPrimitives> =
457 PeerRequest::GetCells { request: GetCells::default(), response: tx };
458
459 assert!(!req.is_supported_by_eth_version(EthVersion::Eth71));
460 assert!(req.is_supported_by_eth_version(EthVersion::Eth72));
461 }
462}