1use linera_base::{
6 crypto::CryptoHash,
7 data_types::{BlobContent, BlockHeight, NetworkDescription},
8 identifiers::{BlobId, ChainId, EventId},
9};
10use linera_chain::{
11 data_types::{BlockProposal, LiteVote},
12 types::{ConfirmedBlock, ConfirmedBlockCertificate},
13};
14use linera_core::{
15 data_types::{ChainInfoQuery, ChainInfoResponse, CrossChainRequest},
16 node::NodeError,
17 worker::Notification,
18};
19use linera_version::VersionInfo;
20use serde::{Deserialize, Serialize};
21
22use crate::{
23 config::ShardId, HandleConfirmedCertificateRequest, HandleLiteCertRequest,
24 HandleTimeoutCertificateRequest, HandleValidatedCertificateRequest,
25};
26
27#[derive(Clone, Serialize, Deserialize, Debug)]
29#[cfg_attr(with_testing, derive(Eq, PartialEq))]
30pub struct ShardInfo {
31 pub shard_id: ShardId,
33 pub total_shards: usize,
35}
36
37#[derive(Clone, Serialize, Deserialize, Debug)]
38#[cfg_attr(with_testing, derive(Eq, PartialEq))]
39pub enum RpcMessage {
40 BlockProposal(Box<BlockProposal>),
42 TimeoutCertificate(Box<HandleTimeoutCertificateRequest>),
43 ValidatedCertificate(Box<HandleValidatedCertificateRequest>),
44 ConfirmedCertificate(Box<HandleConfirmedCertificateRequest>),
45 LiteCertificate(Box<HandleLiteCertRequest<'static>>),
46 ChainInfoQuery(Box<ChainInfoQuery>),
47 UploadBlob(Box<BlobContent>),
48 DownloadBlob(Box<BlobId>),
49 DownloadBlobs(Vec<BlobId>),
50 DownloadPendingBlob(Box<(ChainId, BlobId)>),
51 HandlePendingBlob(Box<(ChainId, BlobContent)>),
52 DownloadConfirmedBlock(Box<CryptoHash>),
53 DownloadCertificates(Vec<CryptoHash>),
54 DownloadCertificatesByHeights(ChainId, Vec<BlockHeight>),
55 BlobLastUsedBy(Box<BlobId>),
56 MissingBlobIds(Vec<BlobId>),
57 EventBlockHeights(Vec<EventId>),
58 VersionInfoQuery,
59 NetworkDescriptionQuery,
60
61 Vote(Box<LiteVote>),
63 ChainInfoResponse(Box<ChainInfoResponse>),
64 Error(Box<NodeError>),
65 VersionInfoResponse(Box<VersionInfo>),
66 NetworkDescriptionResponse(Box<NetworkDescription>),
67 UploadBlobResponse(Box<BlobId>),
68 DownloadBlobResponse(Box<BlobContent>),
69 DownloadPendingBlobResponse(Box<BlobContent>),
70 DownloadConfirmedBlockResponse(Box<ConfirmedBlock>),
71 DownloadCertificatesResponse(Vec<ConfirmedBlockCertificate>),
72 DownloadCertificatesByHeightsResponse(Vec<ConfirmedBlockCertificate>),
73 BlobLastUsedByResponse(Box<CryptoHash>),
74 MissingBlobIdsResponse(Vec<BlobId>),
75 EventBlockHeightsResponse(Vec<Option<BlockHeight>>),
76
77 CrossChainRequest(Box<CrossChainRequest>),
79
80 BlobLastUsedByCertificate(Box<BlobId>),
81 BlobLastUsedByCertificateResponse(Box<ConfirmedBlockCertificate>),
82 ShardInfoQuery(ChainId),
83 ShardInfoResponse(ShardInfo),
84
85 SubscribeNotifications(Vec<ChainId>),
87 Notification(Box<Notification>),
88}
89
90impl RpcMessage {
91 pub fn target_chain_id(&self) -> Option<ChainId> {
95 use RpcMessage::*;
96
97 let chain_id = match self {
98 BlockProposal(proposal) => proposal.content.block.chain_id,
99 LiteCertificate(request) => request.certificate.value.chain_id,
100 TimeoutCertificate(request) => request.certificate.inner().chain_id(),
101 ValidatedCertificate(request) => request.certificate.inner().chain_id(),
102 ConfirmedCertificate(request) => request.certificate.inner().chain_id(),
103 ChainInfoQuery(query) => query.chain_id,
104 CrossChainRequest(request) => request.target_chain_id(),
105 DownloadPendingBlob(request) => request.0,
106 DownloadCertificatesByHeights(chain_id, _) => *chain_id,
107 HandlePendingBlob(request) => request.0,
108 ShardInfoQuery(chain_id) => *chain_id,
109 Vote(_)
110 | Error(_)
111 | ChainInfoResponse(_)
112 | VersionInfoQuery
113 | VersionInfoResponse(_)
114 | NetworkDescriptionQuery
115 | NetworkDescriptionResponse(_)
116 | UploadBlob(_)
117 | UploadBlobResponse(_)
118 | DownloadBlob(_)
119 | DownloadBlobs(_)
120 | DownloadBlobResponse(_)
121 | DownloadPendingBlobResponse(_)
122 | DownloadConfirmedBlock(_)
123 | DownloadConfirmedBlockResponse(_)
124 | DownloadCertificatesByHeightsResponse(_)
125 | DownloadCertificates(_)
126 | BlobLastUsedBy(_)
127 | BlobLastUsedByResponse(_)
128 | BlobLastUsedByCertificate(_)
129 | BlobLastUsedByCertificateResponse(_)
130 | MissingBlobIds(_)
131 | MissingBlobIdsResponse(_)
132 | EventBlockHeights(_)
133 | EventBlockHeightsResponse(_)
134 | ShardInfoResponse(_)
135 | DownloadCertificatesResponse(_)
136 | SubscribeNotifications(_)
137 | Notification(_) => {
138 return None;
139 }
140 };
141
142 Some(chain_id)
143 }
144
145 pub fn is_local_message(&self) -> bool {
148 use RpcMessage::*;
149
150 match self {
151 VersionInfoQuery
152 | NetworkDescriptionQuery
153 | ShardInfoQuery(_)
154 | UploadBlob(_)
155 | DownloadBlob(_)
156 | DownloadBlobs(_)
157 | DownloadConfirmedBlock(_)
158 | BlobLastUsedBy(_)
159 | BlobLastUsedByCertificate(_)
160 | MissingBlobIds(_)
161 | EventBlockHeights(_)
162 | DownloadCertificates(_)
163 | DownloadCertificatesByHeights(_, _) => true,
164 BlockProposal(_)
165 | LiteCertificate(_)
166 | TimeoutCertificate(_)
167 | ValidatedCertificate(_)
168 | ConfirmedCertificate(_)
169 | ChainInfoQuery(_)
170 | CrossChainRequest(_)
171 | Vote(_)
172 | Error(_)
173 | ChainInfoResponse(_)
174 | VersionInfoResponse(_)
175 | NetworkDescriptionResponse(_)
176 | ShardInfoResponse(_)
177 | UploadBlobResponse(_)
178 | DownloadPendingBlob(_)
179 | DownloadPendingBlobResponse(_)
180 | HandlePendingBlob(_)
181 | DownloadBlobResponse(_)
182 | DownloadConfirmedBlockResponse(_)
183 | BlobLastUsedByResponse(_)
184 | BlobLastUsedByCertificateResponse(_)
185 | MissingBlobIdsResponse(_)
186 | EventBlockHeightsResponse(_)
187 | DownloadCertificatesResponse(_)
188 | DownloadCertificatesByHeightsResponse(_)
189 | SubscribeNotifications(_)
190 | Notification(_) => false,
191 }
192 }
193}
194
195impl TryFrom<RpcMessage> for ChainInfoResponse {
196 type Error = NodeError;
197 fn try_from(message: RpcMessage) -> Result<Self, Self::Error> {
198 match message {
199 RpcMessage::ChainInfoResponse(response) => Ok(*response),
200 RpcMessage::Error(error) => Err(*error),
201 _ => Err(NodeError::UnexpectedMessage),
202 }
203 }
204}
205
206impl TryFrom<RpcMessage> for VersionInfo {
207 type Error = NodeError;
208 fn try_from(message: RpcMessage) -> Result<Self, Self::Error> {
209 match message {
210 RpcMessage::VersionInfoResponse(version_info) => Ok(*version_info),
211 RpcMessage::Error(error) => Err(*error),
212 _ => Err(NodeError::UnexpectedMessage),
213 }
214 }
215}
216
217impl TryFrom<RpcMessage> for BlobContent {
218 type Error = NodeError;
219 fn try_from(message: RpcMessage) -> Result<Self, Self::Error> {
220 match message {
221 RpcMessage::DownloadBlobResponse(blob)
222 | RpcMessage::DownloadPendingBlobResponse(blob) => Ok(*blob),
223 RpcMessage::Error(error) => Err(*error),
224 _ => Err(NodeError::UnexpectedMessage),
225 }
226 }
227}
228
229impl TryFrom<RpcMessage> for ConfirmedBlock {
230 type Error = NodeError;
231 fn try_from(message: RpcMessage) -> Result<Self, Self::Error> {
232 match message {
233 RpcMessage::DownloadConfirmedBlockResponse(certificate) => Ok(*certificate),
234 RpcMessage::Error(error) => Err(*error),
235 _ => Err(NodeError::UnexpectedMessage),
236 }
237 }
238}
239
240impl TryFrom<RpcMessage> for ConfirmedBlockCertificate {
241 type Error = NodeError;
242 fn try_from(message: RpcMessage) -> Result<Self, Self::Error> {
243 match message {
244 RpcMessage::BlobLastUsedByCertificateResponse(certificate) => Ok(*certificate),
245 RpcMessage::Error(error) => Err(*error),
246 _ => Err(NodeError::UnexpectedMessage),
247 }
248 }
249}
250
251impl TryFrom<RpcMessage> for Vec<ConfirmedBlockCertificate> {
252 type Error = NodeError;
253 fn try_from(message: RpcMessage) -> Result<Self, Self::Error> {
254 match message {
255 RpcMessage::DownloadCertificatesResponse(certificates) => Ok(certificates),
256 RpcMessage::DownloadCertificatesByHeightsResponse(certificates) => Ok(certificates),
257 RpcMessage::Error(error) => Err(*error),
258 _ => Err(NodeError::UnexpectedMessage),
259 }
260 }
261}
262
263impl TryFrom<RpcMessage> for CryptoHash {
264 type Error = NodeError;
265 fn try_from(message: RpcMessage) -> Result<Self, Self::Error> {
266 match message {
267 RpcMessage::BlobLastUsedByResponse(hash) => Ok(*hash),
268 RpcMessage::Error(error) => Err(*error),
269 _ => Err(NodeError::UnexpectedMessage),
270 }
271 }
272}
273
274impl TryFrom<RpcMessage> for NetworkDescription {
275 type Error = NodeError;
276 fn try_from(message: RpcMessage) -> Result<Self, Self::Error> {
277 match message {
278 RpcMessage::NetworkDescriptionResponse(description) => Ok(*description),
279 _ => Err(NodeError::UnexpectedMessage),
280 }
281 }
282}
283
284impl TryFrom<RpcMessage> for Vec<Option<BlockHeight>> {
285 type Error = NodeError;
286 fn try_from(message: RpcMessage) -> Result<Self, Self::Error> {
287 match message {
288 RpcMessage::EventBlockHeightsResponse(heights) => Ok(heights),
289 RpcMessage::Error(error) => Err(*error),
290 _ => Err(NodeError::UnexpectedMessage),
291 }
292 }
293}
294
295impl TryFrom<RpcMessage> for Vec<BlobId> {
296 type Error = NodeError;
297 fn try_from(message: RpcMessage) -> Result<Self, Self::Error> {
298 match message {
299 RpcMessage::MissingBlobIdsResponse(blob_ids) => Ok(blob_ids),
300 RpcMessage::Error(error) => Err(*error),
301 _ => Err(NodeError::UnexpectedMessage),
302 }
303 }
304}
305
306impl TryFrom<RpcMessage> for BlobId {
307 type Error = NodeError;
308 fn try_from(message: RpcMessage) -> Result<Self, Self::Error> {
309 match message {
310 RpcMessage::UploadBlobResponse(blob_id) => Ok(*blob_id),
311 RpcMessage::Error(error) => Err(*error),
312 _ => Err(NodeError::UnexpectedMessage),
313 }
314 }
315}
316
317impl TryFrom<RpcMessage> for ShardInfo {
318 type Error = NodeError;
319 fn try_from(message: RpcMessage) -> Result<Self, Self::Error> {
320 match message {
321 RpcMessage::ShardInfoResponse(shard_info) => Ok(shard_info),
322 RpcMessage::Error(error) => Err(*error),
323 _ => Err(NodeError::UnexpectedMessage),
324 }
325 }
326}
327
328impl From<NodeError> for RpcMessage {
329 fn from(error: NodeError) -> Self {
330 RpcMessage::Error(Box::new(error))
331 }
332}