Skip to main content

espresso_node/request_response/
mod.rs

1use std::future::Future;
2
3use data_source::DataSource;
4use derive_more::derive::Deref;
5use espresso_types::{PubKey, traits::SequencerPersistence};
6use hotshot_types::signature_key::BLSPrivKey;
7use network::Sender;
8use recipient_source::RecipientSource;
9use request::{Request, Response};
10use request_response::{RequestError, RequestResponse, RequestResponseConfig, network::Bytes};
11use tokio::sync::mpsc::Receiver;
12
13pub mod catchup;
14pub mod data_source;
15pub mod network;
16pub mod recipient_source;
17pub mod request;
18
19/// A concrete type wrapper around `RequestResponse`. We need this so that we can implement
20/// local traits like `StateCatchup`. It also helps with readability.
21#[derive(Clone, Deref)]
22pub struct RequestResponseProtocol<P: SequencerPersistence> {
23    #[deref]
24    #[allow(clippy::type_complexity)]
25    /// The actual inner request response protocol
26    inner: RequestResponse<
27        Sender,
28        Receiver<Bytes>,
29        Request,
30        RecipientSource<P>,
31        DataSource<P>,
32        PubKey,
33    >,
34
35    /// The configuration we used for the above inner protocol. This is nice to have for
36    /// estimating when we should make another request
37    config: RequestResponseConfig,
38
39    /// The public key of this node
40    public_key: PubKey,
41    /// The private key of this node
42    private_key: BLSPrivKey,
43}
44
45impl<P: SequencerPersistence> RequestResponseProtocol<P> {
46    /// Create a new RequestResponseProtocol from the inner
47    pub fn new(
48        // The configuration for the protocol
49        config: RequestResponseConfig,
50        // The network sender that [`RequestResponseProtocol`] will use to send messages
51        sender: Sender,
52        // The network receiver that [`RequestResponseProtocol`] will use to receive messages
53        receiver: Receiver<Bytes>,
54        // The recipient source that [`RequestResponseProtocol`] will use to get the recipients
55        // that a specific message should expect responses from
56        recipient_source: RecipientSource<P>,
57        // The [response] data source that [`RequestResponseProtocol`] will use to derive the
58        // response data for a specific request
59        data_source: DataSource<P>,
60        // The public key of this node
61        public_key: PubKey,
62        // The private key of this node
63        private_key: BLSPrivKey,
64    ) -> Self {
65        Self {
66            inner: RequestResponse::new(
67                config.clone(),
68                sender,
69                receiver,
70                recipient_source,
71                data_source,
72            ),
73            config,
74            public_key,
75            private_key,
76        }
77    }
78}
79
80impl<P: SequencerPersistence> RequestResponseProtocol<P> {
81    pub async fn request_indefinitely<F, Fut, O>(
82        &self,
83        // The request to make
84        request: Request,
85        // The response validation function
86        response_validation_fn: F,
87    ) -> std::result::Result<O, RequestError>
88    where
89        F: Fn(&Request, Response) -> Fut + Send + Sync + 'static + Clone,
90        Fut: Future<Output = anyhow::Result<O>> + Send + Sync + 'static,
91        O: Send + Sync + 'static + Clone,
92    {
93        // Request from the inner protocol
94        self.inner
95            .request_indefinitely(
96                &self.public_key,
97                &self.private_key,
98                self.config.incoming_request_ttl,
99                request,
100                response_validation_fn,
101            )
102            .await
103    }
104}