Skip to main content

linera_rpc/
client.rs

1// Copyright (c) Zefchain Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use linera_base::{
5    crypto::CryptoHash,
6    data_types::{BlobContent, BlockHeight, NetworkDescription},
7    identifiers::{BlobId, ChainId, EventId},
8};
9use linera_chain::{
10    data_types::BlockProposal,
11    types::{
12        ConfirmedBlockCertificate, LiteCertificate, TimeoutCertificate, ValidatedBlockCertificate,
13    },
14};
15use linera_core::{
16    data_types::{ChainInfoQuery, ChainInfoResponse},
17    node::{BlobStream, CrossChainMessageDelivery, NodeError, NotificationStream, ValidatorNode},
18};
19use linera_storage::Arc as CacheArc;
20
21use crate::grpc::GrpcClient;
22#[cfg(with_simple_network)]
23use crate::simple::SimpleClient;
24
25/// A client for communicating with a validator over one of the supported networks.
26#[derive(Clone)]
27pub enum Client {
28    /// A client using the gRPC network.
29    Grpc(Box<GrpcClient>),
30    /// A client using the simple (UDP or TCP) network.
31    #[cfg(with_simple_network)]
32    Simple(SimpleClient),
33}
34
35impl From<GrpcClient> for Client {
36    fn from(client: GrpcClient) -> Self {
37        Self::Grpc(Box::new(client))
38    }
39}
40
41#[cfg(with_simple_network)]
42impl From<SimpleClient> for Client {
43    fn from(client: SimpleClient) -> Self {
44        Self::Simple(client)
45    }
46}
47
48impl ValidatorNode for Client {
49    type NotificationStream = NotificationStream;
50
51    fn address(&self) -> String {
52        match self {
53            Client::Grpc(grpc_client) => grpc_client.address().to_string(),
54            #[cfg(with_simple_network)]
55            Client::Simple(simple_client) => simple_client.address(),
56        }
57    }
58
59    async fn handle_block_proposal(
60        &self,
61        proposal: BlockProposal,
62    ) -> Result<ChainInfoResponse, NodeError> {
63        match self {
64            Client::Grpc(grpc_client) => grpc_client.handle_block_proposal(proposal).await,
65
66            #[cfg(with_simple_network)]
67            Client::Simple(simple_client) => simple_client.handle_block_proposal(proposal).await,
68        }
69    }
70
71    async fn handle_lite_certificate(
72        &self,
73        certificate: LiteCertificate<'_>,
74        delivery: CrossChainMessageDelivery,
75    ) -> Result<ChainInfoResponse, NodeError> {
76        match self {
77            Client::Grpc(grpc_client) => {
78                grpc_client
79                    .handle_lite_certificate(certificate, delivery)
80                    .await
81            }
82
83            #[cfg(with_simple_network)]
84            Client::Simple(simple_client) => {
85                simple_client
86                    .handle_lite_certificate(certificate, delivery)
87                    .await
88            }
89        }
90    }
91
92    async fn handle_timeout_certificate(
93        &self,
94        certificate: TimeoutCertificate,
95    ) -> Result<ChainInfoResponse, NodeError> {
96        match self {
97            Client::Grpc(grpc_client) => grpc_client.handle_timeout_certificate(certificate).await,
98
99            #[cfg(with_simple_network)]
100            Client::Simple(simple_client) => {
101                simple_client.handle_timeout_certificate(certificate).await
102            }
103        }
104    }
105
106    async fn handle_confirmed_certificate(
107        &self,
108        certificate: CacheArc<ConfirmedBlockCertificate>,
109        delivery: CrossChainMessageDelivery,
110    ) -> Result<ChainInfoResponse, NodeError> {
111        match self {
112            Client::Grpc(grpc_client) => {
113                grpc_client
114                    .handle_confirmed_certificate(certificate, delivery)
115                    .await
116            }
117
118            #[cfg(with_simple_network)]
119            Client::Simple(simple_client) => {
120                simple_client
121                    .handle_confirmed_certificate(certificate, delivery)
122                    .await
123            }
124        }
125    }
126
127    async fn handle_validated_certificate(
128        &self,
129        certificate: ValidatedBlockCertificate,
130    ) -> Result<ChainInfoResponse, NodeError> {
131        match self {
132            Client::Grpc(grpc_client) => {
133                grpc_client.handle_validated_certificate(certificate).await
134            }
135
136            #[cfg(with_simple_network)]
137            Client::Simple(simple_client) => {
138                simple_client
139                    .handle_validated_certificate(certificate)
140                    .await
141            }
142        }
143    }
144
145    async fn handle_chain_info_query(
146        &self,
147        query: ChainInfoQuery,
148    ) -> Result<ChainInfoResponse, NodeError> {
149        match self {
150            Client::Grpc(grpc_client) => grpc_client.handle_chain_info_query(query).await,
151
152            #[cfg(with_simple_network)]
153            Client::Simple(simple_client) => simple_client.handle_chain_info_query(query).await,
154        }
155    }
156
157    async fn subscribe(&self, chains: Vec<ChainId>) -> Result<Self::NotificationStream, NodeError> {
158        Ok(match self {
159            Client::Grpc(grpc_client) => Box::pin(grpc_client.subscribe(chains).await?),
160
161            #[cfg(with_simple_network)]
162            Client::Simple(simple_client) => Box::pin(simple_client.subscribe(chains).await?),
163        })
164    }
165
166    async fn get_version_info(&self) -> Result<linera_version::VersionInfo, NodeError> {
167        Ok(match self {
168            Client::Grpc(grpc_client) => grpc_client.get_version_info().await?,
169
170            #[cfg(with_simple_network)]
171            Client::Simple(simple_client) => simple_client.get_version_info().await?,
172        })
173    }
174
175    async fn get_network_description(&self) -> Result<NetworkDescription, NodeError> {
176        Ok(match self {
177            Client::Grpc(grpc_client) => grpc_client.get_network_description().await?,
178
179            #[cfg(with_simple_network)]
180            Client::Simple(simple_client) => simple_client.get_network_description().await?,
181        })
182    }
183
184    async fn upload_blob(&self, content: BlobContent) -> Result<BlobId, NodeError> {
185        Ok(match self {
186            Client::Grpc(grpc_client) => grpc_client.upload_blob(content).await?,
187
188            #[cfg(with_simple_network)]
189            Client::Simple(simple_client) => simple_client.upload_blob(content).await?,
190        })
191    }
192
193    async fn download_blob(&self, blob_id: BlobId) -> Result<BlobContent, NodeError> {
194        Ok(match self {
195            Client::Grpc(grpc_client) => grpc_client.download_blob(blob_id).await?,
196
197            #[cfg(with_simple_network)]
198            Client::Simple(simple_client) => simple_client.download_blob(blob_id).await?,
199        })
200    }
201
202    async fn download_blobs(&self, blob_ids: Vec<BlobId>) -> Result<BlobStream, NodeError> {
203        Ok(match self {
204            Client::Grpc(grpc_client) => grpc_client.download_blobs(blob_ids).await?,
205
206            #[cfg(with_simple_network)]
207            Client::Simple(simple_client) => simple_client.download_blobs(blob_ids).await?,
208        })
209    }
210
211    async fn download_pending_blob(
212        &self,
213        chain_id: ChainId,
214        blob_id: BlobId,
215    ) -> Result<BlobContent, NodeError> {
216        Ok(match self {
217            Client::Grpc(grpc_client) => {
218                grpc_client.download_pending_blob(chain_id, blob_id).await?
219            }
220
221            #[cfg(with_simple_network)]
222            Client::Simple(simple_client) => {
223                simple_client
224                    .download_pending_blob(chain_id, blob_id)
225                    .await?
226            }
227        })
228    }
229
230    async fn handle_pending_blob(
231        &self,
232        chain_id: ChainId,
233        blob: BlobContent,
234    ) -> Result<ChainInfoResponse, NodeError> {
235        Ok(match self {
236            Client::Grpc(grpc_client) => grpc_client.handle_pending_blob(chain_id, blob).await?,
237
238            #[cfg(with_simple_network)]
239            Client::Simple(simple_client) => {
240                simple_client.handle_pending_blob(chain_id, blob).await?
241            }
242        })
243    }
244
245    async fn download_certificate(
246        &self,
247        hash: CryptoHash,
248    ) -> Result<ConfirmedBlockCertificate, NodeError> {
249        Ok(match self {
250            Client::Grpc(grpc_client) => grpc_client.download_certificate(hash).await?,
251
252            #[cfg(with_simple_network)]
253            Client::Simple(simple_client) => simple_client.download_certificate(hash).await?,
254        })
255    }
256
257    async fn download_certificates(
258        &self,
259        hashes: Vec<CryptoHash>,
260    ) -> Result<Vec<ConfirmedBlockCertificate>, NodeError> {
261        Ok(match self {
262            Client::Grpc(grpc_client) => grpc_client.download_certificates(hashes).await?,
263
264            #[cfg(with_simple_network)]
265            Client::Simple(simple_client) => simple_client.download_certificates(hashes).await?,
266        })
267    }
268
269    async fn download_certificates_by_heights(
270        &self,
271        chain_id: ChainId,
272        mut heights: Vec<BlockHeight>,
273    ) -> Result<Vec<ConfirmedBlockCertificate>, NodeError> {
274        heights.sort();
275        Ok(match self {
276            Client::Grpc(grpc_client) => {
277                grpc_client
278                    .download_certificates_by_heights(chain_id, heights)
279                    .await?
280            }
281
282            #[cfg(with_simple_network)]
283            Client::Simple(simple_client) => {
284                simple_client
285                    .download_certificates_by_heights(chain_id, heights)
286                    .await?
287            }
288        })
289    }
290
291    async fn event_block_heights(
292        &self,
293        event_ids: Vec<EventId>,
294    ) -> Result<Vec<Option<BlockHeight>>, NodeError> {
295        Ok(match self {
296            Client::Grpc(grpc_client) => grpc_client.event_block_heights(event_ids).await?,
297
298            #[cfg(with_simple_network)]
299            Client::Simple(simple_client) => simple_client.event_block_heights(event_ids).await?,
300        })
301    }
302
303    async fn blob_last_used_by(&self, blob_id: BlobId) -> Result<CryptoHash, NodeError> {
304        Ok(match self {
305            Client::Grpc(grpc_client) => grpc_client.blob_last_used_by(blob_id).await?,
306
307            #[cfg(with_simple_network)]
308            Client::Simple(simple_client) => simple_client.blob_last_used_by(blob_id).await?,
309        })
310    }
311
312    async fn blob_last_used_by_certificate(
313        &self,
314        blob_id: BlobId,
315    ) -> Result<ConfirmedBlockCertificate, NodeError> {
316        Ok(match self {
317            Client::Grpc(grpc_client) => grpc_client.blob_last_used_by_certificate(blob_id).await?,
318
319            #[cfg(with_simple_network)]
320            Client::Simple(simple_client) => {
321                simple_client.blob_last_used_by_certificate(blob_id).await?
322            }
323        })
324    }
325
326    async fn missing_blob_ids(&self, blob_ids: Vec<BlobId>) -> Result<Vec<BlobId>, NodeError> {
327        Ok(match self {
328            Client::Grpc(grpc_client) => grpc_client.missing_blob_ids(blob_ids).await?,
329
330            #[cfg(with_simple_network)]
331            Client::Simple(simple_client) => simple_client.missing_blob_ids(blob_ids).await?,
332        })
333    }
334
335    async fn get_shard_info(
336        &self,
337        chain_id: ChainId,
338    ) -> Result<linera_core::data_types::ShardInfo, NodeError> {
339        Ok(match self {
340            Client::Grpc(grpc_client) => grpc_client.get_shard_info(chain_id).await?,
341
342            #[cfg(with_simple_network)]
343            Client::Simple(simple_client) => simple_client.get_shard_info(chain_id).await?,
344        })
345    }
346}