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: Debug + HasViewNumber<TYPES> + for<'a> Deserialize<'a>>(
759        &self,
760        message: &[u8],
761    ) -> Result<(M, Version)> {
762        let (actual_version, rest) = Version::deserialize(message)
764            .wrap()
765            .context(info!("Failed to read message version!"))?;
766
767        let deserialized_message: M = match actual_version {
769            v if v == EXTERNAL_MESSAGE_VERSION => {
771                Serializer::<StaticVersion<0, 0>>::deserialize(message)
772            },
773            v if v == V::Base::VERSION => Serializer::<V::Base>::deserialize(message),
774            v if v == V::Upgrade::VERSION => Serializer::<V::Upgrade>::deserialize(message),
775            v => {
776                let attempted_deserialization: M = match bincode::deserialize(rest) {
777                    Ok(m) => m,
778                    Err(e) => {
779                        bail!("Cannot deserialize message with state version: {v}. Error: {e}");
780                    },
781                };
782
783                bail!(warn!(
784                    "Received a message with state version {v} which is invalid for its view: {:?}",
785                    attempted_deserialization
786                ));
787            },
788        }
789        .wrap()
790        .context(info!("Failed to deserialize message!"))?;
791
792        if actual_version == EXTERNAL_MESSAGE_VERSION {
795            return Ok((deserialized_message, actual_version));
796        }
797
798        let view = deserialized_message.view_number();
800
801        let expected_version = self.version(view).await?;
803
804        if actual_version != expected_version {
806            return Err(error!(format!(
807                "Message has invalid version number for its view. Expected: {expected_version}, \
808                 Actual: {actual_version}, View: {view:?}"
809            )));
810        };
811
812        Ok((deserialized_message, actual_version))
813    }
814}