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