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