reth_network_p2p/bodies/
client.rs

1use std::{
2    pin::Pin,
3    task::{ready, Context, Poll},
4};
5
6use crate::{download::DownloadClient, error::PeerRequestResult, priority::Priority};
7use alloy_primitives::B256;
8use futures::{Future, FutureExt};
9use reth_primitives_traits::BlockBody;
10
11/// The bodies future type
12pub type BodiesFut<B = reth_ethereum_primitives::BlockBody> =
13    Pin<Box<dyn Future<Output = PeerRequestResult<Vec<B>>> + Send + Sync>>;
14
15/// A client capable of downloading block bodies.
16#[auto_impl::auto_impl(&, Arc, Box)]
17pub trait BodiesClient: DownloadClient {
18    /// The body type this client fetches.
19    type Body: BlockBody;
20    /// The output of the request future for querying block bodies.
21    type Output: Future<Output = PeerRequestResult<Vec<Self::Body>>> + Sync + Send + Unpin;
22
23    /// Fetches the block body for the requested block.
24    fn get_block_bodies(&self, hashes: Vec<B256>) -> Self::Output {
25        self.get_block_bodies_with_priority(hashes, Priority::Normal)
26    }
27
28    /// Fetches the block body for the requested block with priority
29    fn get_block_bodies_with_priority(&self, hashes: Vec<B256>, priority: Priority)
30        -> Self::Output;
31
32    /// Fetches a single block body for the requested hash.
33    fn get_block_body(&self, hash: B256) -> SingleBodyRequest<Self::Output> {
34        self.get_block_body_with_priority(hash, Priority::Normal)
35    }
36
37    /// Fetches a single block body for the requested hash with priority
38    fn get_block_body_with_priority(
39        &self,
40        hash: B256,
41        priority: Priority,
42    ) -> SingleBodyRequest<Self::Output> {
43        let fut = self.get_block_bodies_with_priority(vec![hash], priority);
44        SingleBodyRequest { fut }
45    }
46}
47
48/// A Future that resolves to a single block body.
49#[derive(Debug)]
50#[must_use = "futures do nothing unless polled"]
51pub struct SingleBodyRequest<Fut> {
52    fut: Fut,
53}
54
55impl<Fut, B> Future for SingleBodyRequest<Fut>
56where
57    Fut: Future<Output = PeerRequestResult<Vec<B>>> + Sync + Send + Unpin,
58{
59    type Output = PeerRequestResult<Option<B>>;
60
61    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
62        let resp = ready!(self.get_mut().fut.poll_unpin(cx));
63        let resp = resp.map(|res| res.map(|bodies| bodies.into_iter().next()));
64        Poll::Ready(resp)
65    }
66}