1use std::{
13 fmt::{self, Debug},
14 marker::PhantomData,
15 sync::Arc,
16};
17
18use async_lock::RwLock;
19use committable::Committable;
20use hotshot_utils::anytrace::*;
21use serde::{de::DeserializeOwned, Deserialize, Serialize};
22use vbs::{
23 version::{StaticVersion, StaticVersionType, Version},
24 BinarySerializer, Serializer,
25};
26
27pub const EXTERNAL_MESSAGE_VERSION: Version = Version { major: 0, minor: 0 };
29
30use crate::{
31 data::{
32 vid_disperse::{ADVZDisperseShare, VidDisperseShare2},
33 DaProposal, DaProposal2, Leaf, Leaf2, QuorumProposal, QuorumProposal2,
34 QuorumProposal2Legacy, QuorumProposalWrapper, UpgradeProposal,
35 },
36 epoch_membership::EpochMembership,
37 request_response::ProposalRequestPayload,
38 simple_certificate::{
39 DaCertificate, DaCertificate2, EpochRootQuorumCertificateV1, EpochRootQuorumCertificateV2,
40 NextEpochQuorumCertificate2, QuorumCertificate2, UpgradeCertificate,
41 ViewSyncCommitCertificate, ViewSyncCommitCertificate2, ViewSyncFinalizeCertificate,
42 ViewSyncFinalizeCertificate2, ViewSyncPreCommitCertificate, ViewSyncPreCommitCertificate2,
43 },
44 simple_vote::{
45 DaVote, DaVote2, EpochRootQuorumVote, EpochRootQuorumVote2, HasEpoch, QuorumVote,
46 QuorumVote2, TimeoutVote, TimeoutVote2, UpgradeVote, ViewSyncCommitVote,
47 ViewSyncCommitVote2, ViewSyncFinalizeVote, ViewSyncFinalizeVote2, ViewSyncPreCommitVote,
48 ViewSyncPreCommitVote2,
49 },
50 traits::{
51 election::Membership,
52 network::{DataRequest, ResponseMessage, ViewMessage},
53 node_implementation::{ConsensusTime, NodeType, Versions},
54 signature_key::SignatureKey,
55 },
56 utils::mnemonic,
57 vote::HasViewNumber,
58};
59
60#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
62#[serde(bound(deserialize = "", serialize = ""))]
63pub struct Message<TYPES: NodeType> {
64 pub sender: TYPES::SignatureKey,
66
67 pub kind: MessageKind<TYPES>,
69}
70
71impl<TYPES: NodeType> fmt::Debug for Message<TYPES> {
72 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
73 fmt.debug_struct("Message")
74 .field("sender", &mnemonic(&self.sender))
75 .field("kind", &self.kind)
76 .finish()
77 }
78}
79
80impl<TYPES: NodeType> HasViewNumber<TYPES> for Message<TYPES> {
81 fn view_number(&self) -> TYPES::View {
83 self.kind.view_number()
84 }
85}
86
87#[derive(Clone, Debug)]
89pub struct Messages<TYPES: NodeType>(pub Vec<Message<TYPES>>);
90
91#[derive(PartialEq, Copy, Clone)]
93pub enum MessagePurpose {
94 Proposal,
96 LatestProposal,
98 LatestViewSyncCertificate,
100 Vote,
102 ViewSyncVote,
104 ViewSyncCertificate,
106 DaCertificate,
108 Internal,
110 Data,
112 VidDisperse,
114 UpgradeProposal,
116 UpgradeVote,
118 External,
120}
121
122#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)]
126#[serde(bound(deserialize = "", serialize = ""))]
127pub enum MessageKind<TYPES: NodeType> {
128 Consensus(SequencingMessage<TYPES>),
130 Data(DataMessage<TYPES>),
132 External(Vec<u8>),
134}
135
136pub enum RecipientList<K: SignatureKey> {
138 Broadcast,
140 Direct(K),
142 Many(Vec<K>),
144}
145
146impl<TYPES: NodeType> MessageKind<TYPES> {
147 pub fn from_consensus_message(m: SequencingMessage<TYPES>) -> Self {
151 Self::Consensus(m)
152 }
153}
154
155impl<TYPES: NodeType> From<DataMessage<TYPES>> for MessageKind<TYPES> {
156 fn from(m: DataMessage<TYPES>) -> Self {
157 Self::Data(m)
158 }
159}
160
161impl<TYPES: NodeType> ViewMessage<TYPES> for MessageKind<TYPES> {
162 fn view_number(&self) -> TYPES::View {
163 match &self {
164 MessageKind::Consensus(message) => message.view_number(),
165 MessageKind::Data(DataMessage::SubmitTransaction(_, v)) => *v,
166 MessageKind::Data(DataMessage::RequestData(msg)) => msg.view,
167 MessageKind::Data(DataMessage::DataResponse(msg)) => match msg {
168 ResponseMessage::Found(m) => m.view_number(),
169 ResponseMessage::NotFound | ResponseMessage::Denied => TYPES::View::new(1),
170 },
171 MessageKind::External(_) => TYPES::View::new(1),
172 }
173 }
174}
175
176impl<TYPES: NodeType> HasEpoch<TYPES> for MessageKind<TYPES> {
177 fn epoch(&self) -> Option<TYPES::Epoch> {
178 match &self {
179 MessageKind::Consensus(message) => message.epoch_number(),
180 MessageKind::Data(DataMessage::SubmitTransaction(..) | DataMessage::RequestData(_))
181 | MessageKind::External(_) => None,
182 MessageKind::Data(DataMessage::DataResponse(msg)) => match msg {
183 ResponseMessage::Found(m) => m.epoch_number(),
184 ResponseMessage::NotFound | ResponseMessage::Denied => None,
185 },
186 }
187 }
188}
189
190#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)]
191#[serde(bound(deserialize = "", serialize = ""))]
192pub enum GeneralConsensusMessage<TYPES: NodeType> {
194 Proposal(Proposal<TYPES, QuorumProposal<TYPES>>),
196
197 Vote(QuorumVote<TYPES>),
199
200 ViewSyncPreCommitVote(ViewSyncPreCommitVote<TYPES>),
202
203 ViewSyncCommitVote(ViewSyncCommitVote<TYPES>),
205
206 ViewSyncFinalizeVote(ViewSyncFinalizeVote<TYPES>),
208
209 ViewSyncPreCommitCertificate(ViewSyncPreCommitCertificate<TYPES>),
211
212 ViewSyncCommitCertificate(ViewSyncCommitCertificate<TYPES>),
214
215 ViewSyncFinalizeCertificate(ViewSyncFinalizeCertificate<TYPES>),
217
218 TimeoutVote(TimeoutVote<TYPES>),
220
221 UpgradeProposal(Proposal<TYPES, UpgradeProposal<TYPES>>),
223
224 UpgradeVote(UpgradeVote<TYPES>),
226
227 ProposalRequested(
229 ProposalRequestPayload<TYPES>,
230 <TYPES::SignatureKey as SignatureKey>::PureAssembledSignatureType,
231 ),
232
233 ProposalResponse(Proposal<TYPES, QuorumProposal<TYPES>>),
235
236 Proposal2Legacy(Proposal<TYPES, QuorumProposal2Legacy<TYPES>>),
238
239 Vote2(QuorumVote2<TYPES>),
241
242 EpochRootQuorumVote(EpochRootQuorumVote<TYPES>),
244
245 ProposalResponse2Legacy(Proposal<TYPES, QuorumProposal2Legacy<TYPES>>),
247
248 HighQc(
250 QuorumCertificate2<TYPES>,
251 Option<NextEpochQuorumCertificate2<TYPES>>,
252 ),
253
254 ExtendedQc(
256 QuorumCertificate2<TYPES>,
257 NextEpochQuorumCertificate2<TYPES>,
258 ),
259
260 EpochRootQcV1(EpochRootQuorumCertificateV1<TYPES>),
262
263 ViewSyncPreCommitVote2(ViewSyncPreCommitVote2<TYPES>),
265
266 ViewSyncCommitVote2(ViewSyncCommitVote2<TYPES>),
268
269 ViewSyncFinalizeVote2(ViewSyncFinalizeVote2<TYPES>),
271
272 ViewSyncPreCommitCertificate2(ViewSyncPreCommitCertificate2<TYPES>),
274
275 ViewSyncCommitCertificate2(ViewSyncCommitCertificate2<TYPES>),
277
278 ViewSyncFinalizeCertificate2(ViewSyncFinalizeCertificate2<TYPES>),
280
281 TimeoutVote2(TimeoutVote2<TYPES>),
283
284 EpochRootQc(EpochRootQuorumCertificateV2<TYPES>),
286
287 Proposal2(Proposal<TYPES, QuorumProposal2<TYPES>>),
289
290 ProposalResponse2(Proposal<TYPES, QuorumProposal2<TYPES>>),
292
293 EpochRootQuorumVote2(EpochRootQuorumVote2<TYPES>),
295}
296
297#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Hash, Eq)]
298#[serde(bound(deserialize = "", serialize = ""))]
299pub enum DaConsensusMessage<TYPES: NodeType> {
301 DaProposal(Proposal<TYPES, DaProposal<TYPES>>),
303
304 DaVote(DaVote<TYPES>),
306
307 DaCertificate(DaCertificate<TYPES>),
309
310 VidDisperseMsg(Proposal<TYPES, ADVZDisperseShare<TYPES>>),
314
315 DaProposal2(Proposal<TYPES, DaProposal2<TYPES>>),
317
318 DaVote2(DaVote2<TYPES>),
320
321 DaCertificate2(DaCertificate2<TYPES>),
323
324 VidDisperseMsg2(Proposal<TYPES, VidDisperseShare2<TYPES>>),
328}
329
330#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, Hash)]
332#[serde(bound(deserialize = "", serialize = ""))]
333#[allow(clippy::large_enum_variant)]
334pub enum SequencingMessage<TYPES: NodeType> {
335 General(GeneralConsensusMessage<TYPES>),
337
338 Da(DaConsensusMessage<TYPES>),
340}
341
342impl<TYPES: NodeType> SequencingMessage<TYPES> {
343 fn view_number(&self) -> TYPES::View {
345 match &self {
346 SequencingMessage::General(general_message) => {
347 match general_message {
348 GeneralConsensusMessage::Proposal(p) => {
349 p.data.view_number()
352 },
353 GeneralConsensusMessage::Proposal2Legacy(p) => {
354 p.data.view_number()
357 },
358 GeneralConsensusMessage::Proposal2(p) => {
359 p.data.view_number()
362 },
363 GeneralConsensusMessage::ProposalRequested(req, _) => req.view_number,
364 GeneralConsensusMessage::ProposalResponse(proposal) => {
365 proposal.data.view_number()
366 },
367 GeneralConsensusMessage::ProposalResponse2Legacy(proposal) => {
368 proposal.data.view_number()
369 },
370 GeneralConsensusMessage::ProposalResponse2(proposal) => {
371 proposal.data.view_number()
372 },
373 GeneralConsensusMessage::Vote(vote_message) => vote_message.view_number(),
374 GeneralConsensusMessage::Vote2(vote_message) => vote_message.view_number(),
375 GeneralConsensusMessage::TimeoutVote(message) => message.view_number(),
376 GeneralConsensusMessage::ViewSyncPreCommitVote(message) => {
377 message.view_number()
378 },
379 GeneralConsensusMessage::ViewSyncCommitVote(message) => message.view_number(),
380 GeneralConsensusMessage::ViewSyncFinalizeVote(message) => message.view_number(),
381 GeneralConsensusMessage::ViewSyncPreCommitCertificate(message) => {
382 message.view_number()
383 },
384 GeneralConsensusMessage::ViewSyncCommitCertificate(message) => {
385 message.view_number()
386 },
387 GeneralConsensusMessage::ViewSyncFinalizeCertificate(message) => {
388 message.view_number()
389 },
390 GeneralConsensusMessage::TimeoutVote2(message) => message.view_number(),
391 GeneralConsensusMessage::ViewSyncPreCommitVote2(message) => {
392 message.view_number()
393 },
394 GeneralConsensusMessage::ViewSyncCommitVote2(message) => message.view_number(),
395 GeneralConsensusMessage::ViewSyncFinalizeVote2(message) => {
396 message.view_number()
397 },
398 GeneralConsensusMessage::ViewSyncPreCommitCertificate2(message) => {
399 message.view_number()
400 },
401 GeneralConsensusMessage::ViewSyncCommitCertificate2(message) => {
402 message.view_number()
403 },
404 GeneralConsensusMessage::ViewSyncFinalizeCertificate2(message) => {
405 message.view_number()
406 },
407 GeneralConsensusMessage::UpgradeProposal(message) => message.data.view_number(),
408 GeneralConsensusMessage::UpgradeVote(message) => message.view_number(),
409 GeneralConsensusMessage::HighQc(qc, _)
410 | GeneralConsensusMessage::ExtendedQc(qc, _) => qc.view_number(),
411 GeneralConsensusMessage::EpochRootQuorumVote(vote) => vote.view_number(),
412 GeneralConsensusMessage::EpochRootQuorumVote2(vote) => vote.view_number(),
413 GeneralConsensusMessage::EpochRootQc(root_qc) => root_qc.view_number(),
414 GeneralConsensusMessage::EpochRootQcV1(root_qc) => root_qc.view_number(),
415 }
416 },
417 SequencingMessage::Da(da_message) => {
418 match da_message {
419 DaConsensusMessage::DaProposal(p) => {
420 p.data.view_number()
423 },
424 DaConsensusMessage::DaVote(vote_message) => vote_message.view_number(),
425 DaConsensusMessage::DaCertificate(cert) => cert.view_number,
426 DaConsensusMessage::VidDisperseMsg(disperse) => disperse.data.view_number(),
427 DaConsensusMessage::DaProposal2(p) => {
428 p.data.view_number()
431 },
432 DaConsensusMessage::DaVote2(vote_message) => vote_message.view_number(),
433 DaConsensusMessage::DaCertificate2(cert) => cert.view_number,
434 DaConsensusMessage::VidDisperseMsg2(disperse) => disperse.data.view_number(),
435 }
436 },
437 }
438 }
439
440 fn epoch_number(&self) -> Option<TYPES::Epoch> {
442 match &self {
443 SequencingMessage::General(general_message) => {
444 match general_message {
445 GeneralConsensusMessage::Proposal(p) => {
446 p.data.epoch()
449 },
450 GeneralConsensusMessage::Proposal2Legacy(p) => {
451 p.data.epoch()
454 },
455 GeneralConsensusMessage::Proposal2(p) => {
456 p.data.epoch()
459 },
460 GeneralConsensusMessage::ProposalRequested(..) => None,
461 GeneralConsensusMessage::ProposalResponse(proposal) => proposal.data.epoch(),
462 GeneralConsensusMessage::ProposalResponse2Legacy(proposal) => {
463 proposal.data.epoch()
464 },
465 GeneralConsensusMessage::ProposalResponse2(proposal) => proposal.data.epoch(),
466 GeneralConsensusMessage::Vote(vote_message) => vote_message.epoch(),
467 GeneralConsensusMessage::Vote2(vote_message) => vote_message.epoch(),
468 GeneralConsensusMessage::TimeoutVote(message) => message.epoch(),
469 GeneralConsensusMessage::ViewSyncPreCommitVote(message) => message.epoch(),
470 GeneralConsensusMessage::ViewSyncCommitVote(message) => message.epoch(),
471 GeneralConsensusMessage::ViewSyncFinalizeVote(message) => message.epoch(),
472 GeneralConsensusMessage::ViewSyncPreCommitCertificate(message) => {
473 message.epoch()
474 },
475 GeneralConsensusMessage::ViewSyncCommitCertificate(message) => message.epoch(),
476 GeneralConsensusMessage::ViewSyncFinalizeCertificate(message) => {
477 message.epoch()
478 },
479 GeneralConsensusMessage::TimeoutVote2(message) => message.epoch(),
480 GeneralConsensusMessage::ViewSyncPreCommitVote2(message) => message.epoch(),
481 GeneralConsensusMessage::ViewSyncCommitVote2(message) => message.epoch(),
482 GeneralConsensusMessage::ViewSyncFinalizeVote2(message) => message.epoch(),
483 GeneralConsensusMessage::ViewSyncPreCommitCertificate2(message) => {
484 message.epoch()
485 },
486 GeneralConsensusMessage::ViewSyncCommitCertificate2(message) => message.epoch(),
487 GeneralConsensusMessage::ViewSyncFinalizeCertificate2(message) => {
488 message.epoch()
489 },
490 GeneralConsensusMessage::UpgradeProposal(message) => message.data.epoch(),
491 GeneralConsensusMessage::UpgradeVote(message) => message.epoch(),
492 GeneralConsensusMessage::HighQc(qc, _)
493 | GeneralConsensusMessage::ExtendedQc(qc, _) => qc.epoch(),
494 GeneralConsensusMessage::EpochRootQuorumVote(vote) => vote.epoch(),
495 GeneralConsensusMessage::EpochRootQuorumVote2(vote) => vote.epoch(),
496 GeneralConsensusMessage::EpochRootQc(root_qc) => root_qc.epoch(),
497 GeneralConsensusMessage::EpochRootQcV1(root_qc) => root_qc.epoch(),
498 }
499 },
500 SequencingMessage::Da(da_message) => {
501 match da_message {
502 DaConsensusMessage::DaProposal(p) => {
503 p.data.epoch()
506 },
507 DaConsensusMessage::DaVote(vote_message) => vote_message.epoch(),
508 DaConsensusMessage::DaCertificate(cert) => cert.epoch(),
509 DaConsensusMessage::VidDisperseMsg(disperse) => disperse.data.epoch(),
510 DaConsensusMessage::VidDisperseMsg2(disperse) => disperse.data.epoch(),
511 DaConsensusMessage::DaProposal2(p) => {
512 p.data.epoch()
515 },
516 DaConsensusMessage::DaVote2(vote_message) => vote_message.epoch(),
517 DaConsensusMessage::DaCertificate2(cert) => cert.epoch(),
518 }
519 },
520 }
521 }
522}
523
524#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)]
525#[serde(bound(deserialize = ""))]
526#[allow(clippy::large_enum_variant)]
527pub enum DataMessage<TYPES: NodeType> {
530 SubmitTransaction(TYPES::Transaction, TYPES::View),
534 RequestData(DataRequest<TYPES>),
536 DataResponse(ResponseMessage<TYPES>),
538}
539
540#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)]
541#[serde(bound(deserialize = ""))]
542pub struct Proposal<
544 TYPES: NodeType,
545 PROPOSAL: HasViewNumber<TYPES> + HasEpoch<TYPES> + DeserializeOwned,
546> {
547 pub data: PROPOSAL,
551 pub signature: <TYPES::SignatureKey as SignatureKey>::PureAssembledSignatureType,
553 pub _pd: PhantomData<TYPES>,
555}
556
557pub fn convert_proposal<TYPES, PROPOSAL, PROPOSAL2>(
559 proposal: Proposal<TYPES, PROPOSAL>,
560) -> Proposal<TYPES, PROPOSAL2>
561where
562 TYPES: NodeType,
563 PROPOSAL: HasViewNumber<TYPES> + HasEpoch<TYPES> + DeserializeOwned,
564 PROPOSAL2: HasViewNumber<TYPES> + HasEpoch<TYPES> + DeserializeOwned + From<PROPOSAL>,
565{
566 Proposal {
567 data: proposal.data.into(),
568 signature: proposal.signature,
569 _pd: proposal._pd,
570 }
571}
572
573impl<TYPES> Proposal<TYPES, QuorumProposal<TYPES>>
574where
575 TYPES: NodeType,
576{
577 pub async fn validate_signature<V: Versions>(
581 &self,
582 membership: &TYPES::Membership,
583 _epoch_height: u64,
584 upgrade_lock: &UpgradeLock<TYPES, V>,
585 ) -> Result<()> {
586 let view_number = self.data.view_number();
587 let view_leader_key = membership.leader(view_number, None)?;
588 let proposed_leaf = Leaf::from_quorum_proposal(&self.data);
589
590 ensure!(
591 view_leader_key.validate(
592 &self.signature,
593 proposed_leaf.commit(upgrade_lock).await.as_ref()
594 ),
595 "Proposal signature is invalid."
596 );
597
598 Ok(())
599 }
600}
601
602impl<TYPES> Proposal<TYPES, QuorumProposalWrapper<TYPES>>
603where
604 TYPES: NodeType,
605{
606 pub async fn validate_signature(&self, membership: &EpochMembership<TYPES>) -> Result<()> {
610 let view_number = self.data.proposal.view_number();
611 let view_leader_key = membership.leader(view_number).await?;
612 let proposed_leaf = Leaf2::from_quorum_proposal(&self.data);
613
614 ensure!(
615 view_leader_key.validate(&self.signature, proposed_leaf.commit().as_ref()),
616 "Proposal signature is invalid."
617 );
618
619 Ok(())
620 }
621}
622
623#[derive(Clone, Debug)]
624pub struct UpgradeLock<TYPES: NodeType, V: Versions> {
626 pub decided_upgrade_certificate: Arc<RwLock<Option<UpgradeCertificate<TYPES>>>>,
628
629 pub _pd: PhantomData<V>,
631}
632
633impl<TYPES: NodeType, V: Versions> UpgradeLock<TYPES, V> {
634 #[allow(clippy::new_without_default)]
635 pub fn new() -> Self {
637 Self {
638 decided_upgrade_certificate: Arc::new(RwLock::new(None)),
639 _pd: PhantomData::<V>,
640 }
641 }
642
643 #[allow(clippy::new_without_default)]
644 pub fn from_certificate(certificate: &Option<UpgradeCertificate<TYPES>>) -> Self {
646 Self {
647 decided_upgrade_certificate: Arc::new(RwLock::new(certificate.clone())),
648 _pd: PhantomData::<V>,
649 }
650 }
651
652 pub async fn upgrade_view(&self) -> Option<TYPES::View> {
653 let upgrade_certificate = self.decided_upgrade_certificate.read().await;
654 upgrade_certificate
655 .as_ref()
656 .map(|cert| cert.data.new_version_first_view)
657 }
658
659 pub async fn version(&self, view: TYPES::View) -> Result<Version> {
664 let upgrade_certificate = self.decided_upgrade_certificate.read().await;
665
666 let version = match *upgrade_certificate {
667 Some(ref cert) => {
668 if view >= cert.data.new_version_first_view {
669 if cert.data.new_version == V::Upgrade::VERSION {
670 V::Upgrade::VERSION
671 } else {
672 bail!("The network has upgraded to a new version that we do not support!");
673 }
674 } else {
675 V::Base::VERSION
676 }
677 },
678 None => V::Base::VERSION,
679 };
680
681 Ok(version)
682 }
683
684 pub async fn version_infallible(&self, view: TYPES::View) -> Version {
688 let upgrade_certificate = self.decided_upgrade_certificate.read().await;
689
690 match *upgrade_certificate {
691 Some(ref cert) => {
692 if view >= cert.data.new_version_first_view {
693 cert.data.new_version
694 } else {
695 cert.data.old_version
696 }
697 },
698 None => V::Base::VERSION,
699 }
700 }
701
702 pub async fn epochs_enabled(&self, view: TYPES::View) -> bool {
704 self.version_infallible(view).await >= V::Epochs::VERSION
705 }
706
707 pub async fn proposal2_legacy_version(&self, view: TYPES::View) -> bool {
709 self.epochs_enabled(view).await && !self.upgraded_drb_and_header(view).await
710 }
711
712 pub async fn proposal2_version(&self, view: TYPES::View) -> bool {
714 self.epochs_enabled(view).await && self.upgraded_drb_and_header(view).await
715 }
716
717 pub async fn upgraded_drb_and_header(&self, view: TYPES::View) -> bool {
719 self.version_infallible(view).await >= V::DrbAndHeaderUpgrade::VERSION
720 }
721
722 pub async fn serialize<M: HasViewNumber<TYPES> + Serialize>(
728 &self,
729 message: &M,
730 ) -> Result<Vec<u8>> {
731 let view = message.view_number();
732
733 let version = self.version(view).await?;
734
735 let serialized_message = match version {
736 v if v == V::Base::VERSION => Serializer::<V::Base>::serialize(&message),
738 v if v == V::Upgrade::VERSION => Serializer::<V::Upgrade>::serialize(&message),
739 v => {
740 bail!(
741 "Attempted to serialize with version {v}, which is incompatible. This should \
742 be impossible."
743 );
744 },
745 };
746
747 serialized_message
748 .wrap()
749 .context(info!("Failed to serialize message!"))
750 }
751
752 pub async fn deserialize<M: HasViewNumber<TYPES> + for<'a> Deserialize<'a>>(
759 &self,
760 message: &[u8],
761 ) -> Result<(M, Version)> {
762 let actual_version = Version::deserialize(message)
764 .wrap()
765 .context(info!("Failed to read message version!"))?
766 .0;
767
768 let deserialized_message: M = match actual_version {
770 v if v == EXTERNAL_MESSAGE_VERSION => {
772 Serializer::<StaticVersion<0, 0>>::deserialize(message)
773 },
774 v if v == V::Base::VERSION => Serializer::<V::Base>::deserialize(message),
775 v if v == V::Upgrade::VERSION => Serializer::<V::Upgrade>::deserialize(message),
776 v => {
777 bail!("Cannot deserialize message with stated version {v}");
778 },
779 }
780 .wrap()
781 .context(info!("Failed to deserialize message!"))?;
782
783 if actual_version == EXTERNAL_MESSAGE_VERSION {
786 return Ok((deserialized_message, actual_version));
787 }
788
789 let view = deserialized_message.view_number();
791
792 let expected_version = self.version(view).await?;
794
795 if actual_version != expected_version {
797 return Err(error!(format!(
798 "Message has invalid version number for its view. Expected: {expected_version}, \
799 Actual: {actual_version}, View: {view:?}"
800 )));
801 };
802
803 Ok((deserialized_message, actual_version))
804 }
805}