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(SnapProtocolMessage),
144}
145
146#[derive(Debug)]
148pub enum PeerResponse<N: NetworkPrimitives = EthNetworkPrimitives> {
149 BlockHeaders {
151 response: oneshot::Receiver<RequestResult<BlockHeaders<N::BlockHeader>>>,
153 },
154 BlockBodies {
156 response: oneshot::Receiver<RequestResult<BlockBodies<N::BlockBody>>>,
158 },
159 PooledTransactions {
161 response: oneshot::Receiver<RequestResult<PooledTransactions<N::PooledTransaction>>>,
163 },
164 NodeData {
166 response: oneshot::Receiver<RequestResult<NodeData>>,
168 },
169 Receipts {
171 response: oneshot::Receiver<RequestResult<Receipts<N::Receipt>>>,
173 },
174 Receipts69 {
180 response: oneshot::Receiver<RequestResult<Receipts69<N::Receipt>>>,
182 },
183 Receipts70 {
185 response: oneshot::Receiver<RequestResult<Receipts70<N::Receipt>>>,
187 },
188 BlockAccessLists {
190 response: oneshot::Receiver<RequestResult<BlockAccessLists>>,
192 },
193 Cells {
196 response: oneshot::Receiver<RequestResult<Cells>>,
198 },
199 Snap {
201 response: oneshot::Receiver<RequestResult<SnapResponse>>,
203 },
204}
205
206impl<N: NetworkPrimitives> PeerResponse<N> {
209 pub(crate) fn poll(&mut self, cx: &mut Context<'_>) -> Poll<PeerResponseResult<N>> {
211 macro_rules! poll_request {
212 ($response:ident, $item:ident, $cx:ident) => {
213 match ready!($response.poll_unpin($cx)) {
214 Ok(res) => PeerResponseResult::$item(res.map(|item| item.0)),
215 Err(err) => PeerResponseResult::$item(Err(err.into())),
216 }
217 };
218 }
219
220 let res = match self {
221 Self::BlockHeaders { response } => {
222 poll_request!(response, BlockHeaders, cx)
223 }
224 Self::BlockBodies { response } => {
225 poll_request!(response, BlockBodies, cx)
226 }
227 Self::PooledTransactions { response } => {
228 poll_request!(response, PooledTransactions, cx)
229 }
230 Self::NodeData { response } => {
231 poll_request!(response, NodeData, cx)
232 }
233 Self::Receipts { response } => {
234 poll_request!(response, Receipts, cx)
235 }
236 Self::Receipts69 { response } => {
237 poll_request!(response, Receipts69, cx)
238 }
239 Self::Receipts70 { response } => match ready!(response.poll_unpin(cx)) {
240 Ok(res) => PeerResponseResult::Receipts70(res),
241 Err(err) => PeerResponseResult::Receipts70(Err(err.into())),
242 },
243 Self::BlockAccessLists { response } => match ready!(response.poll_unpin(cx)) {
244 Ok(res) => PeerResponseResult::BlockAccessLists(res),
245 Err(err) => PeerResponseResult::BlockAccessLists(Err(err.into())),
246 },
247 Self::Cells { response } => match ready!(response.poll_unpin(cx)) {
248 Ok(res) => PeerResponseResult::Cells(res),
249 Err(err) => PeerResponseResult::Cells(Err(err.into())),
250 },
251 Self::Snap { response } => match ready!(response.poll_unpin(cx)) {
252 Ok(res) => PeerResponseResult::Snap(res),
253 Err(err) => PeerResponseResult::Snap(Err(err.into())),
254 },
255 };
256 Poll::Ready(res)
257 }
258}
259
260#[derive(Debug)]
262pub enum PeerResponseResult<N: NetworkPrimitives = EthNetworkPrimitives> {
263 BlockHeaders(RequestResult<Vec<N::BlockHeader>>),
265 BlockBodies(RequestResult<Vec<N::BlockBody>>),
267 PooledTransactions(RequestResult<Vec<N::PooledTransaction>>),
269 NodeData(RequestResult<Vec<Bytes>>),
271 Receipts(RequestResult<Vec<Vec<ReceiptWithBloom<N::Receipt>>>>),
273 Receipts69(RequestResult<Vec<Vec<N::Receipt>>>),
275 Receipts70(RequestResult<Receipts70<N::Receipt>>),
277 BlockAccessLists(RequestResult<BlockAccessLists>),
279 Cells(RequestResult<Cells>),
281 Snap(RequestResult<SnapResponse>),
283}
284
285impl<N: NetworkPrimitives> PeerResponseResult<N> {
288 pub fn try_into_message(self, id: u64) -> RequestResult<RequestMessage<N>> {
292 macro_rules! to_message {
293 ($response:ident, $item:ident, $request_id:ident) => {
294 match $response {
295 Ok(res) => {
296 let request = RequestPair { request_id: $request_id, message: $item(res) };
297 Ok(RequestMessage::Eth(EthMessage::$item(request)))
298 }
299 Err(err) => Err(err),
300 }
301 };
302 }
303 match self {
304 Self::BlockHeaders(resp) => {
305 to_message!(resp, BlockHeaders, id)
306 }
307 Self::BlockBodies(resp) => {
308 to_message!(resp, BlockBodies, id)
309 }
310 Self::PooledTransactions(resp) => {
311 to_message!(resp, PooledTransactions, id)
312 }
313 Self::NodeData(resp) => {
314 to_message!(resp, NodeData, id)
315 }
316 Self::Receipts(resp) => {
317 to_message!(resp, Receipts, id)
318 }
319 Self::Receipts69(resp) => {
320 to_message!(resp, Receipts69, id)
321 }
322 Self::Receipts70(resp) => match resp {
323 Ok(res) => {
324 let request = RequestPair { request_id: id, message: res };
325 Ok(RequestMessage::Eth(EthMessage::Receipts70(request)))
326 }
327 Err(err) => Err(err),
328 },
329 Self::BlockAccessLists(resp) => match resp {
330 Ok(res) => {
331 let request = RequestPair { request_id: id, message: res };
332 Ok(RequestMessage::Eth(EthMessage::BlockAccessLists(request)))
333 }
334 Err(err) => Err(err),
335 },
336 Self::Cells(resp) => match resp {
337 Ok(res) => {
338 let request = RequestPair { request_id: id, message: res };
339 Ok(RequestMessage::Eth(EthMessage::Cells(request)))
340 }
341 Err(err) => Err(err),
342 },
343 Self::Snap(resp) => match resp {
344 Ok(res) => {
345 let mut message: SnapProtocolMessage = res.into();
346 message.set_request_id(id);
347 Ok(RequestMessage::Snap(message))
348 }
349 Err(err) => Err(err),
350 },
351 }
352 }
353
354 pub fn err(&self) -> Option<&RequestError> {
356 match self {
357 Self::BlockHeaders(res) => res.as_ref().err(),
358 Self::BlockBodies(res) => res.as_ref().err(),
359 Self::PooledTransactions(res) => res.as_ref().err(),
360 Self::NodeData(res) => res.as_ref().err(),
361 Self::Receipts(res) => res.as_ref().err(),
362 Self::Receipts69(res) => res.as_ref().err(),
363 Self::Receipts70(res) => res.as_ref().err(),
364 Self::BlockAccessLists(res) => res.as_ref().err(),
365 Self::Cells(res) => res.as_ref().err(),
366 Self::Snap(res) => res.as_ref().err(),
367 }
368 }
369
370 pub fn is_err(&self) -> bool {
372 self.err().is_some()
373 }
374}