1use crate::types::{BlockAccessLists, Receipts69, Receipts70};
7use alloy_consensus::{BlockHeader, ReceiptWithBloom};
8use alloy_primitives::{Bytes, B256};
9use futures::FutureExt;
10use reth_eth_wire::{
11 message::RequestPair, BlockBodies, BlockHeaders, BlockRangeUpdate, BroadcastPoolTransactions,
12 Cells, EthMessage, EthNetworkPrimitives, GetBlockAccessLists, GetBlockBodies, GetBlockHeaders,
13 GetReceipts, NetworkPrimitives, NewBlock, NewBlockHashes, NewBlockPayload,
14 NewPooledTransactionHashes, NodeData, PooledTransactions, Receipts, SharedTransactions,
15 Transactions,
16};
17use reth_eth_wire_types::{snap::SnapProtocolMessage, RawCapabilityMessage};
18use reth_network_api::{PeerRequest, RequestMessage};
19use reth_network_p2p::{
20 error::{RequestError, RequestResult},
21 snap::client::SnapResponse,
22};
23use reth_primitives_traits::Block;
24use std::{
25 sync::Arc,
26 task::{ready, Context, Poll},
27};
28use tokio::sync::oneshot;
29
30#[derive(Debug, Clone)]
32pub struct NewBlockMessage<P = NewBlock<reth_ethereum_primitives::Block>> {
33 pub hash: B256,
35 pub block: Arc<P>,
37}
38
39impl<P: NewBlockPayload> NewBlockMessage<P> {
42 pub fn number(&self) -> u64 {
44 self.block.block().header().number()
45 }
46}
47
48#[derive(Debug)]
51pub enum PeerMessage<N: NetworkPrimitives = EthNetworkPrimitives> {
52 NewBlockHashes(NewBlockHashes),
54 NewBlock(NewBlockMessage<N::NewBlockPayload>),
56 ReceivedTransaction(Transactions<N::BroadcastedTransaction>),
58 SendTransactions(SharedTransactions<N::BroadcastedTransaction>),
60 SendBroadcastPoolTransactions(BroadcastPoolTransactions),
62 PooledTransactions(NewPooledTransactionHashes),
64 EthRequest(PeerRequest<N>),
66 BlockRangeUpdated(BlockRangeUpdate),
68 Other(RawCapabilityMessage),
72}
73
74impl<N: NetworkPrimitives> PeerMessage<N> {
75 pub const fn message_kind(&self) -> &'static str {
77 match self {
78 Self::NewBlockHashes(_) => "NewBlockHashes",
79 Self::NewBlock(_) => "NewBlock",
80 Self::ReceivedTransaction(_) => "ReceivedTransaction",
81 Self::SendTransactions(_) => "SendTransactions",
82 Self::SendBroadcastPoolTransactions(_) => "SendBroadcastPoolTransactions",
83 Self::PooledTransactions(_) => "PooledTransactions",
84 Self::EthRequest(_) => "EthRequest",
85 Self::BlockRangeUpdated(_) => "BlockRangeUpdated",
86 Self::Other(_) => "Other",
87 }
88 }
89
90 pub const fn is_broadcast(&self) -> bool {
93 matches!(
94 self,
95 Self::NewBlockHashes(_) |
96 Self::NewBlock(_) |
97 Self::SendTransactions(_) |
98 Self::SendBroadcastPoolTransactions(_) |
99 Self::PooledTransactions(_)
100 )
101 }
102
103 pub fn message_item_count(&self) -> usize {
105 match self {
106 Self::NewBlockHashes(msg) => msg.len(),
107 Self::ReceivedTransaction(msg) => msg.len(),
108 Self::SendTransactions(msg) => msg.len(),
109 Self::SendBroadcastPoolTransactions(msg) => msg.len(),
110 Self::PooledTransactions(msg) => msg.len(),
111 Self::NewBlock(_) |
112 Self::EthRequest(_) |
113 Self::BlockRangeUpdated(_) |
114 Self::Other(_) => 1,
115 }
116 }
117}
118
119#[derive(Debug, Clone, PartialEq, Eq)]
121pub enum BlockRequest {
122 GetBlockHeaders(GetBlockHeaders),
126
127 GetBlockBodies(GetBlockBodies),
131 GetBlockAccessLists(GetBlockAccessLists),
135
136 GetReceipts(GetReceipts),
140 GetSnap(Box<SnapProtocolMessage>),
145}
146
147#[derive(Debug)]
149pub enum PeerResponse<N: NetworkPrimitives = EthNetworkPrimitives> {
150 BlockHeaders {
152 response: oneshot::Receiver<RequestResult<BlockHeaders<N::BlockHeader>>>,
154 },
155 BlockBodies {
157 response: oneshot::Receiver<RequestResult<BlockBodies<N::BlockBody>>>,
159 },
160 PooledTransactions {
162 response: oneshot::Receiver<RequestResult<PooledTransactions<N::PooledTransaction>>>,
164 },
165 NodeData {
167 response: oneshot::Receiver<RequestResult<NodeData>>,
169 },
170 Receipts {
172 response: oneshot::Receiver<RequestResult<Receipts<N::Receipt>>>,
174 },
175 Receipts69 {
181 response: oneshot::Receiver<RequestResult<Receipts69<N::Receipt>>>,
183 },
184 Receipts70 {
186 response: oneshot::Receiver<RequestResult<Receipts70<N::Receipt>>>,
188 },
189 BlockAccessLists {
191 response: oneshot::Receiver<RequestResult<BlockAccessLists>>,
193 },
194 Cells {
197 response: oneshot::Receiver<RequestResult<Cells>>,
199 },
200 Snap {
202 response: oneshot::Receiver<RequestResult<SnapResponse>>,
204 },
205}
206
207impl<N: NetworkPrimitives> PeerResponse<N> {
210 pub(crate) fn poll(&mut self, cx: &mut Context<'_>) -> Poll<PeerResponseResult<N>> {
212 macro_rules! poll_request {
213 ($response:ident, $item:ident, $cx:ident) => {
214 match ready!($response.poll_unpin($cx)) {
215 Ok(res) => PeerResponseResult::$item(res.map(|item| item.0)),
216 Err(err) => PeerResponseResult::$item(Err(err.into())),
217 }
218 };
219 }
220
221 let res = match self {
222 Self::BlockHeaders { response } => {
223 poll_request!(response, BlockHeaders, cx)
224 }
225 Self::BlockBodies { response } => {
226 poll_request!(response, BlockBodies, cx)
227 }
228 Self::PooledTransactions { response } => {
229 poll_request!(response, PooledTransactions, cx)
230 }
231 Self::NodeData { response } => {
232 poll_request!(response, NodeData, cx)
233 }
234 Self::Receipts { response } => {
235 poll_request!(response, Receipts, cx)
236 }
237 Self::Receipts69 { response } => {
238 poll_request!(response, Receipts69, cx)
239 }
240 Self::Receipts70 { response } => match ready!(response.poll_unpin(cx)) {
241 Ok(res) => PeerResponseResult::Receipts70(res),
242 Err(err) => PeerResponseResult::Receipts70(Err(err.into())),
243 },
244 Self::BlockAccessLists { response } => match ready!(response.poll_unpin(cx)) {
245 Ok(res) => PeerResponseResult::BlockAccessLists(res),
246 Err(err) => PeerResponseResult::BlockAccessLists(Err(err.into())),
247 },
248 Self::Cells { response } => match ready!(response.poll_unpin(cx)) {
249 Ok(res) => PeerResponseResult::Cells(res),
250 Err(err) => PeerResponseResult::Cells(Err(err.into())),
251 },
252 Self::Snap { response } => match ready!(response.poll_unpin(cx)) {
253 Ok(res) => PeerResponseResult::Snap(res),
254 Err(err) => PeerResponseResult::Snap(Err(err.into())),
255 },
256 };
257 Poll::Ready(res)
258 }
259}
260
261#[derive(Debug)]
263pub enum PeerResponseResult<N: NetworkPrimitives = EthNetworkPrimitives> {
264 BlockHeaders(RequestResult<Vec<N::BlockHeader>>),
266 BlockBodies(RequestResult<Vec<N::BlockBody>>),
268 PooledTransactions(RequestResult<Vec<N::PooledTransaction>>),
270 NodeData(RequestResult<Vec<Bytes>>),
272 Receipts(RequestResult<Vec<Vec<ReceiptWithBloom<N::Receipt>>>>),
274 Receipts69(RequestResult<Vec<Vec<N::Receipt>>>),
276 Receipts70(RequestResult<Receipts70<N::Receipt>>),
278 BlockAccessLists(RequestResult<BlockAccessLists>),
280 Cells(RequestResult<Cells>),
282 Snap(RequestResult<SnapResponse>),
284}
285
286impl<N: NetworkPrimitives> PeerResponseResult<N> {
289 pub fn try_into_message(self, id: u64) -> RequestResult<RequestMessage<N>> {
293 macro_rules! to_message {
294 ($response:ident, $item:ident, $request_id:ident) => {
295 match $response {
296 Ok(res) => {
297 let request = RequestPair { request_id: $request_id, message: $item(res) };
298 Ok(RequestMessage::Eth(EthMessage::$item(request)))
299 }
300 Err(err) => Err(err),
301 }
302 };
303 }
304 match self {
305 Self::BlockHeaders(resp) => {
306 to_message!(resp, BlockHeaders, id)
307 }
308 Self::BlockBodies(resp) => {
309 to_message!(resp, BlockBodies, id)
310 }
311 Self::PooledTransactions(resp) => {
312 to_message!(resp, PooledTransactions, id)
313 }
314 Self::NodeData(resp) => {
315 to_message!(resp, NodeData, id)
316 }
317 Self::Receipts(resp) => {
318 to_message!(resp, Receipts, id)
319 }
320 Self::Receipts69(resp) => {
321 to_message!(resp, Receipts69, id)
322 }
323 Self::Receipts70(resp) => match resp {
324 Ok(res) => {
325 let request = RequestPair { request_id: id, message: res };
326 Ok(RequestMessage::Eth(EthMessage::Receipts70(request)))
327 }
328 Err(err) => Err(err),
329 },
330 Self::BlockAccessLists(resp) => match resp {
331 Ok(res) => {
332 let request = RequestPair { request_id: id, message: res };
333 Ok(RequestMessage::Eth(EthMessage::BlockAccessLists(request)))
334 }
335 Err(err) => Err(err),
336 },
337 Self::Cells(resp) => match resp {
338 Ok(res) => {
339 let request = RequestPair { request_id: id, message: res };
340 Ok(RequestMessage::Eth(EthMessage::Cells(request)))
341 }
342 Err(err) => Err(err),
343 },
344 Self::Snap(resp) => match resp {
345 Ok(res) => {
346 let mut message: SnapProtocolMessage = res.into();
347 message.set_request_id(id);
348 Ok(RequestMessage::Snap(message))
349 }
350 Err(err) => Err(err),
351 },
352 }
353 }
354
355 pub fn err(&self) -> Option<&RequestError> {
357 match self {
358 Self::BlockHeaders(res) => res.as_ref().err(),
359 Self::BlockBodies(res) => res.as_ref().err(),
360 Self::PooledTransactions(res) => res.as_ref().err(),
361 Self::NodeData(res) => res.as_ref().err(),
362 Self::Receipts(res) => res.as_ref().err(),
363 Self::Receipts69(res) => res.as_ref().err(),
364 Self::Receipts70(res) => res.as_ref().err(),
365 Self::BlockAccessLists(res) => res.as_ref().err(),
366 Self::Cells(res) => res.as_ref().err(),
367 Self::Snap(res) => res.as_ref().err(),
368 }
369 }
370
371 pub fn is_err(&self) -> bool {
373 self.err().is_some()
374 }
375}