Skip to main content

celestia_rpc/
fraud.rs

1//! celestia-node rpc types and methods related to fraud proofs
2
3use std::future::Future;
4use std::marker::{Send, Sync};
5use std::pin::Pin;
6
7use async_stream::try_stream;
8use futures_util::{Stream, StreamExt};
9use jsonrpsee::core::client::{ClientT, Error, SubscriptionClientT};
10use jsonrpsee::proc_macros::rpc;
11
12use crate::{HeaderClient, custom_client_error};
13
14pub use celestia_types::fraud_proof::{Proof, ProofType};
15
16mod rpc {
17    use jsonrpsee::core::{RpcResult, SubscriptionResult};
18
19    use super::*;
20
21    /// Fraud proof RPC methods.
22    #[rpc(client, server, namespace = "fraud", namespace_separator = ".")]
23    pub trait Fraud {
24        /// See [`crate::FraudClient::fraud_get`].
25        #[method(name = "Get")]
26        async fn fraud_get(&self, proof_type: ProofType) -> RpcResult<Vec<Proof>>;
27    }
28
29    /// Fraud proof subscription RPC methods.
30    #[rpc(client, server, namespace = "fraud", namespace_separator = ".")]
31    pub trait FraudSubscription {
32        /// See [`crate::FraudClient::fraud_subscribe`].
33        #[subscription(name = "Subscribe", unsubscribe = "Unsubscribe", item = Proof)]
34        async fn fraud_subscribe(&self, proof_type: ProofType) -> SubscriptionResult;
35    }
36}
37
38/// Client implementation for the `Fraud` RPC API.
39pub trait FraudClient: ClientT {
40    /// Fetches fraud proofs by their type.
41    fn fraud_get<'a, 'fut>(
42        &'a self,
43        proof_type: ProofType,
44    ) -> impl Future<Output = Result<Vec<Proof>, Error>> + Send + 'fut
45    where
46        'a: 'fut,
47        Self: Sized + Sync + 'fut,
48    {
49        rpc::FraudClient::fraud_get(self, proof_type)
50    }
51
52    /// Subscribe to fraud proof by its type.
53    ///
54    /// # Notes
55    ///
56    /// If client returns [`Error::HttpNotImplemented`], the subscription will fallback to
57    /// using combination of [`HeaderClient::header_wait_for_height`] and
58    /// [`FraudClient::fraud_get`] for streaming the proofs. The fallback stream will end
59    /// after the first batch of proofs is returned.
60    ///
61    /// Unsubscribe is not implemented by Celestia nodes.
62    fn fraud_subscribe<'a>(
63        &'a self,
64        proof_type: ProofType,
65    ) -> Pin<Box<dyn Stream<Item = Result<Proof, Error>> + Send + 'a>>
66    where
67        Self: SubscriptionClientT + Sized + Sync,
68    {
69        try_stream! {
70            match rpc::FraudSubscriptionClient::fraud_subscribe(self, proof_type).await {
71                Ok(mut fraud_sub) => loop {
72                    yield fraud_sub
73                        .next()
74                        .await
75                        .ok_or_else(|| custom_client_error("unexpected end of stream"))??;
76                },
77                Err(Error::HttpNotImplemented) => {
78                    let mut header_sub = HeaderClient::header_subscribe(self);
79                    loop {
80                        // tick; we don't care about the header
81                        header_sub
82                            .next()
83                            .await
84                            .ok_or_else(|| custom_client_error("unexpected end of stream"))??;
85
86                        let proofs = rpc::FraudClient::fraud_get(self, proof_type).await?;
87                        if !proofs.is_empty() {
88                            for proof in proofs {
89                                yield proof;
90                            }
91
92                            // after we get any proofs from the node, it will
93                            // keep giving us the same proofs on each request,
94                            // so we just end the stream here
95                            break;
96                        }
97                    }
98                }
99                err => {
100                    err?;
101                }
102            };
103        }
104        .boxed()
105    }
106}
107
108impl<T> FraudClient for T where T: ClientT {}
109
110/// Server trait for Fraud RPC endpoints.
111pub trait FraudServer: rpc::FraudServer + rpc::FraudSubscriptionServer {}
112
113impl<T> FraudServer for T where T: rpc::FraudServer + rpc::FraudSubscriptionServer {}
114
115pub use rpc::FraudServer as FraudRpcServer;
116pub use rpc::FraudSubscriptionServer as FraudSubscriptionRpcServer;