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