1use std::{
13 fmt::{self, Debug},
14 marker::PhantomData,
15 sync::Arc,
16};
17
18use committable::Committable;
19use hotshot_utils::anytrace::*;
20use parking_lot::RwLock;
21use serde::{Deserialize, Serialize, de::DeserializeOwned};
22use vbs::version::Version;
23use versions::{
24 DRB_AND_HEADER_UPGRADE_VERSION, EPOCH_VERSION, NEW_PROTOCOL_VERSION, TIMEOUT_EPOCH_VERSION,
25 Upgrade,
26};
27
28pub const EXTERNAL_MESSAGE_VERSION: Version = Version { major: 0, minor: 0 };
30
31use crate::{
32 data::{
33 DaProposal, DaProposal2, EpochNumber, Leaf2, QuorumProposal, QuorumProposal2,
34 QuorumProposal2Legacy, QuorumProposalWrapper, UpgradeProposal, VidDisperseShare0,
35 VidDisperseShare1, VidDisperseShare2, ViewNumber,
36 },
37 epoch_membership::{EpochMembership, EpochMembershipCoordinator},
38 request_response::ProposalRequestPayload,
39 simple_certificate::{
40 DaCertificate, DaCertificate2, EpochRootQuorumCertificateV1, EpochRootQuorumCertificateV2,
41 NextEpochQuorumCertificate2, QuorumCertificate2, UpgradeCertificate,
42 ViewSyncCommitCertificate, ViewSyncCommitCertificate2, ViewSyncFinalizeCertificate,
43 ViewSyncFinalizeCertificate2, ViewSyncPreCommitCertificate, ViewSyncPreCommitCertificate2,
44 },
45 simple_vote::{
46 DaVote, DaVote2, EpochRootQuorumVote, EpochRootQuorumVote2, HasEpoch, QuorumVote,
47 QuorumVote2, TimeoutVote, TimeoutVote2, UpgradeVote, ViewSyncCommitVote,
48 ViewSyncCommitVote2, ViewSyncFinalizeVote, ViewSyncFinalizeVote2, ViewSyncPreCommitVote,
49 ViewSyncPreCommitVote2,
50 },
51 traits::{
52 network::{DataRequest, ResponseMessage, ViewMessage},
53 node_implementation::NodeType,
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 for Message<TYPES> {
81 fn view_number(&self) -> ViewNumber {
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(#[serde(with = "serde_bytes")] 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) -> ViewNumber {
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 => ViewNumber::new(1),
170 },
171 MessageKind::External(_) => ViewNumber::new(1),
172 }
173 }
174}
175
176impl<TYPES: NodeType> HasEpoch for MessageKind<TYPES> {
177 fn epoch(&self) -> Option<EpochNumber> {
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>),
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, VidDisperseShare0<TYPES>>),
314
315 DaProposal2(Proposal<TYPES, DaProposal2<TYPES>>),
317
318 DaVote2(DaVote2<TYPES>),
320
321 DaCertificate2(DaCertificate2<TYPES>),
323
324 VidDisperseMsg1(Proposal<TYPES, VidDisperseShare1<TYPES>>),
326
327 VidDisperseMsg2(Proposal<TYPES, VidDisperseShare2<TYPES>>),
329}
330
331#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, Hash)]
333#[serde(bound(deserialize = "", serialize = ""))]
334#[allow(clippy::large_enum_variant)]
335pub enum SequencingMessage<TYPES: NodeType> {
336 General(GeneralConsensusMessage<TYPES>),
338
339 Da(DaConsensusMessage<TYPES>),
341}
342
343impl<TYPES: NodeType> SequencingMessage<TYPES> {
344 fn view_number(&self) -> ViewNumber {
346 match &self {
347 SequencingMessage::General(general_message) => {
348 match general_message {
349 GeneralConsensusMessage::Proposal(p) => {
350 p.data.view_number()
353 },
354 GeneralConsensusMessage::Proposal2Legacy(p) => {
355 p.data.view_number()
358 },
359 GeneralConsensusMessage::Proposal2(p) => {
360 p.data.view_number()
363 },
364 GeneralConsensusMessage::ProposalRequested(req, _) => req.view_number,
365 GeneralConsensusMessage::ProposalResponse(proposal) => {
366 proposal.data.view_number()
367 },
368 GeneralConsensusMessage::ProposalResponse2Legacy(proposal) => {
369 proposal.data.view_number()
370 },
371 GeneralConsensusMessage::ProposalResponse2(proposal) => {
372 proposal.data.view_number()
373 },
374 GeneralConsensusMessage::Vote(vote_message) => vote_message.view_number(),
375 GeneralConsensusMessage::Vote2(vote_message) => vote_message.view_number(),
376 GeneralConsensusMessage::TimeoutVote(message) => message.view_number(),
377 GeneralConsensusMessage::ViewSyncPreCommitVote(message) => {
378 message.view_number()
379 },
380 GeneralConsensusMessage::ViewSyncCommitVote(message) => message.view_number(),
381 GeneralConsensusMessage::ViewSyncFinalizeVote(message) => message.view_number(),
382 GeneralConsensusMessage::ViewSyncPreCommitCertificate(message) => {
383 message.view_number()
384 },
385 GeneralConsensusMessage::ViewSyncCommitCertificate(message) => {
386 message.view_number()
387 },
388 GeneralConsensusMessage::ViewSyncFinalizeCertificate(message) => {
389 message.view_number()
390 },
391 GeneralConsensusMessage::TimeoutVote2(message) => message.view_number(),
392 GeneralConsensusMessage::ViewSyncPreCommitVote2(message) => {
393 message.view_number()
394 },
395 GeneralConsensusMessage::ViewSyncCommitVote2(message) => message.view_number(),
396 GeneralConsensusMessage::ViewSyncFinalizeVote2(message) => {
397 message.view_number()
398 },
399 GeneralConsensusMessage::ViewSyncPreCommitCertificate2(message) => {
400 message.view_number()
401 },
402 GeneralConsensusMessage::ViewSyncCommitCertificate2(message) => {
403 message.view_number()
404 },
405 GeneralConsensusMessage::ViewSyncFinalizeCertificate2(message) => {
406 message.view_number()
407 },
408 GeneralConsensusMessage::UpgradeProposal(message) => message.data.view_number(),
409 GeneralConsensusMessage::UpgradeVote(message) => message.view_number(),
410 GeneralConsensusMessage::HighQc(qc, _)
411 | GeneralConsensusMessage::ExtendedQc(qc, _) => qc.view_number(),
412 GeneralConsensusMessage::EpochRootQuorumVote(vote) => vote.view_number(),
413 GeneralConsensusMessage::EpochRootQuorumVote2(vote) => vote.view_number(),
414 GeneralConsensusMessage::EpochRootQc(root_qc) => root_qc.view_number(),
415 GeneralConsensusMessage::EpochRootQcV1(root_qc) => root_qc.view_number(),
416 }
417 },
418 SequencingMessage::Da(da_message) => {
419 match da_message {
420 DaConsensusMessage::DaProposal(p) => {
421 p.data.view_number()
424 },
425 DaConsensusMessage::DaVote(vote_message) => vote_message.view_number(),
426 DaConsensusMessage::DaCertificate(cert) => cert.view_number,
427 DaConsensusMessage::VidDisperseMsg(disperse) => disperse.data.view_number(),
428 DaConsensusMessage::DaProposal2(p) => {
429 p.data.view_number()
432 },
433 DaConsensusMessage::DaVote2(vote_message) => vote_message.view_number(),
434 DaConsensusMessage::DaCertificate2(cert) => cert.view_number,
435 DaConsensusMessage::VidDisperseMsg1(disperse) => disperse.data.view_number(),
436 DaConsensusMessage::VidDisperseMsg2(disperse) => disperse.data.view_number(),
437 }
438 },
439 }
440 }
441
442 fn epoch_number(&self) -> Option<EpochNumber> {
444 match &self {
445 SequencingMessage::General(general_message) => {
446 match general_message {
447 GeneralConsensusMessage::Proposal(p) => {
448 p.data.epoch()
451 },
452 GeneralConsensusMessage::Proposal2Legacy(p) => {
453 p.data.epoch()
456 },
457 GeneralConsensusMessage::Proposal2(p) => {
458 p.data.epoch()
461 },
462 GeneralConsensusMessage::ProposalRequested(..) => None,
463 GeneralConsensusMessage::ProposalResponse(proposal) => proposal.data.epoch(),
464 GeneralConsensusMessage::ProposalResponse2Legacy(proposal) => {
465 proposal.data.epoch()
466 },
467 GeneralConsensusMessage::ProposalResponse2(proposal) => proposal.data.epoch(),
468 GeneralConsensusMessage::Vote(vote_message) => vote_message.epoch(),
469 GeneralConsensusMessage::Vote2(vote_message) => vote_message.epoch(),
470 GeneralConsensusMessage::TimeoutVote(message) => message.epoch(),
471 GeneralConsensusMessage::ViewSyncPreCommitVote(message) => message.epoch(),
472 GeneralConsensusMessage::ViewSyncCommitVote(message) => message.epoch(),
473 GeneralConsensusMessage::ViewSyncFinalizeVote(message) => message.epoch(),
474 GeneralConsensusMessage::ViewSyncPreCommitCertificate(message) => {
475 message.epoch()
476 },
477 GeneralConsensusMessage::ViewSyncCommitCertificate(message) => message.epoch(),
478 GeneralConsensusMessage::ViewSyncFinalizeCertificate(message) => {
479 message.epoch()
480 },
481 GeneralConsensusMessage::TimeoutVote2(message) => message.epoch(),
482 GeneralConsensusMessage::ViewSyncPreCommitVote2(message) => message.epoch(),
483 GeneralConsensusMessage::ViewSyncCommitVote2(message) => message.epoch(),
484 GeneralConsensusMessage::ViewSyncFinalizeVote2(message) => message.epoch(),
485 GeneralConsensusMessage::ViewSyncPreCommitCertificate2(message) => {
486 message.epoch()
487 },
488 GeneralConsensusMessage::ViewSyncCommitCertificate2(message) => message.epoch(),
489 GeneralConsensusMessage::ViewSyncFinalizeCertificate2(message) => {
490 message.epoch()
491 },
492 GeneralConsensusMessage::UpgradeProposal(message) => message.data.epoch(),
493 GeneralConsensusMessage::UpgradeVote(message) => message.epoch(),
494 GeneralConsensusMessage::HighQc(qc, _)
495 | GeneralConsensusMessage::ExtendedQc(qc, _) => qc.epoch(),
496 GeneralConsensusMessage::EpochRootQuorumVote(vote) => vote.epoch(),
497 GeneralConsensusMessage::EpochRootQuorumVote2(vote) => vote.epoch(),
498 GeneralConsensusMessage::EpochRootQc(root_qc) => root_qc.epoch(),
499 GeneralConsensusMessage::EpochRootQcV1(root_qc) => root_qc.epoch(),
500 }
501 },
502 SequencingMessage::Da(da_message) => {
503 match da_message {
504 DaConsensusMessage::DaProposal(p) => {
505 p.data.epoch()
508 },
509 DaConsensusMessage::DaVote(vote_message) => vote_message.epoch(),
510 DaConsensusMessage::DaCertificate(cert) => cert.epoch(),
511 DaConsensusMessage::VidDisperseMsg(disperse) => disperse.data.epoch(),
512 DaConsensusMessage::VidDisperseMsg1(disperse) => disperse.data.epoch(),
513 DaConsensusMessage::VidDisperseMsg2(disperse) => disperse.data.epoch(),
514 DaConsensusMessage::DaProposal2(p) => {
515 p.data.epoch()
518 },
519 DaConsensusMessage::DaVote2(vote_message) => vote_message.epoch(),
520 DaConsensusMessage::DaCertificate2(cert) => cert.epoch(),
521 }
522 },
523 }
524 }
525}
526
527#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)]
528#[serde(bound(deserialize = ""))]
529#[allow(clippy::large_enum_variant)]
530pub enum DataMessage<TYPES: NodeType> {
533 SubmitTransaction(TYPES::Transaction, ViewNumber),
537 RequestData(DataRequest<TYPES>),
539 DataResponse(ResponseMessage<TYPES>),
541}
542
543#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)]
544#[serde(bound(deserialize = ""))]
545pub struct Proposal<TYPES: NodeType, PROPOSAL: HasViewNumber + HasEpoch + DeserializeOwned> {
547 pub data: PROPOSAL,
551 pub signature: <TYPES::SignatureKey as SignatureKey>::PureAssembledSignatureType,
553 pub _pd: PhantomData<TYPES>,
555}
556
557impl<TYPES: NodeType, PROPOSAL: HasViewNumber + HasEpoch + DeserializeOwned>
558 Proposal<TYPES, PROPOSAL>
559{
560 pub fn new(
561 data: PROPOSAL,
562 signature: <TYPES::SignatureKey as SignatureKey>::PureAssembledSignatureType,
563 ) -> Self {
564 Self {
565 data,
566 signature,
567 _pd: PhantomData,
568 }
569 }
570}
571
572pub fn convert_proposal<TYPES, PROPOSAL, PROPOSAL2>(
574 proposal: Proposal<TYPES, PROPOSAL>,
575) -> Proposal<TYPES, PROPOSAL2>
576where
577 TYPES: NodeType,
578 PROPOSAL: HasViewNumber + HasEpoch + DeserializeOwned,
579 PROPOSAL2: HasViewNumber + HasEpoch + DeserializeOwned + From<PROPOSAL>,
580{
581 Proposal {
582 data: proposal.data.into(),
583 signature: proposal.signature,
584 _pd: proposal._pd,
585 }
586}
587
588impl<TYPES> Proposal<TYPES, QuorumProposalWrapper<TYPES>>
589where
590 TYPES: NodeType,
591{
592 pub fn validate_signature(&self, membership: &EpochMembership<TYPES>) -> Result<()> {
596 let view_number = self.data.proposal.view_number();
597 let view_leader_key = membership.leader(view_number)?;
598 let proposed_leaf = Leaf2::from_quorum_proposal(&self.data);
599
600 ensure!(
601 view_leader_key.validate(&self.signature, proposed_leaf.commit().as_ref()),
602 "Proposal signature is invalid."
603 );
604
605 Ok(())
606 }
607}
608
609impl<TYPES> Proposal<TYPES, QuorumProposal2<TYPES>>
610where
611 TYPES: NodeType,
612{
613 pub fn validate_signature(
614 &self,
615 membership_coordinator: &EpochMembershipCoordinator<TYPES>,
616 ) -> Result<()> {
617 let view_number = self.data.view_number();
618 let epoch = self.data.epoch().ok_or(error!("Epoch is not set"))?;
619 let membership = membership_coordinator.membership_for_epoch(Some(epoch))?;
620 let view_leader_key = membership.leader(view_number)?;
621 let proposed_leaf =
622 Leaf2::from_quorum_proposal(&QuorumProposalWrapper::from(self.data.clone()));
623
624 ensure!(
625 view_leader_key.validate(&self.signature, proposed_leaf.commit().as_ref()),
626 "Proposal signature is invalid."
627 );
628
629 Ok(())
630 }
631}
632
633#[derive(Clone, Debug)]
635pub struct UpgradeLock<TYPES: NodeType> {
636 decided_upgrade_certificate: Arc<RwLock<Option<UpgradeCertificate<TYPES>>>>,
637 upgrade: Upgrade,
638}
639
640impl<TYPES: NodeType> UpgradeLock<TYPES> {
641 pub fn new(upgrade: Upgrade) -> Self {
643 Self {
644 decided_upgrade_certificate: Arc::new(RwLock::new(None)),
645 upgrade,
646 }
647 }
648
649 pub fn from_certificate(
651 upgrade: Upgrade,
652 certificate: &Option<UpgradeCertificate<TYPES>>,
653 ) -> Self {
654 Self {
655 decided_upgrade_certificate: Arc::new(RwLock::new(certificate.clone())),
656 upgrade,
657 }
658 }
659
660 pub fn upgrade(&self) -> Upgrade {
661 self.upgrade
662 }
663
664 pub fn upgrade_view(&self) -> Option<ViewNumber> {
665 self.decided_upgrade_certificate
666 .read()
667 .as_ref()
668 .map(|cert| cert.data.new_version_first_view)
669 }
670
671 pub fn decided_upgrade_cert(&self) -> Option<UpgradeCertificate<TYPES>> {
672 self.decided_upgrade_certificate.read().clone()
673 }
674
675 pub fn set_decided_upgrade_cert<C>(&self, cert: C)
676 where
677 C: Into<Option<UpgradeCertificate<TYPES>>>,
678 {
679 *self.decided_upgrade_certificate.write() = cert.into()
680 }
681
682 pub fn apply<F>(&self, f: F)
684 where
685 F: FnOnce(&mut Option<UpgradeCertificate<TYPES>>),
686 {
687 let mut guard = self.decided_upgrade_certificate.write();
688 f(&mut *guard)
689 }
690
691 pub fn version(&self, view: ViewNumber) -> Result<Version> {
696 if let Some(cert) = &*self.decided_upgrade_certificate.read() {
697 if view >= cert.data.new_version_first_view {
698 if cert.data.new_version == self.upgrade.target {
699 Ok(self.upgrade.target)
700 } else {
701 bail!("The network has upgraded to a new version that we do not support!");
702 }
703 } else {
704 Ok(self.upgrade.base)
705 }
706 } else {
707 Ok(self.upgrade.base)
708 }
709 }
710
711 pub fn version_infallible(&self, view: ViewNumber) -> Version {
715 if let Some(cert) = &*self.decided_upgrade_certificate.read() {
716 if view >= cert.data.new_version_first_view {
717 cert.data.new_version
718 } else {
719 cert.data.old_version
720 }
721 } else {
722 self.upgrade.base
723 }
724 }
725
726 pub fn epochs_enabled(&self, view: ViewNumber) -> bool {
728 self.version_infallible(view) >= EPOCH_VERSION
729 }
730
731 pub fn proposal2_legacy_version(&self, view: ViewNumber) -> bool {
733 let version = self.version_infallible(view);
734 version >= EPOCH_VERSION && version < DRB_AND_HEADER_UPGRADE_VERSION
735 }
736
737 pub fn proposal2_version(&self, view: ViewNumber) -> bool {
739 let version = self.version_infallible(view);
740 version >= EPOCH_VERSION && version >= DRB_AND_HEADER_UPGRADE_VERSION
741 }
742
743 pub fn upgraded_drb_and_header(&self, view: ViewNumber) -> bool {
745 self.version_infallible(view) >= DRB_AND_HEADER_UPGRADE_VERSION
746 }
747
748 pub fn upgraded_vid2(&self, view: ViewNumber) -> bool {
749 self.version_infallible(view) >= NEW_PROTOCOL_VERSION
750 }
751
752 pub fn timeout_epoch_bound(&self, timed_out_view: ViewNumber) -> bool {
754 let v = ViewNumber::new(timed_out_view.u64().saturating_add(1));
755 self.version_infallible(v) >= TIMEOUT_EPOCH_VERSION
756 }
757
758 pub fn certificate_rule(&self, view: ViewNumber) -> bool {
767 self.version_infallible(view) >= TIMEOUT_EPOCH_VERSION
768 }
769
770 pub fn serialize<M: HasViewNumber + Serialize>(&self, message: &M) -> Result<Vec<u8>> {
778 let view = message.view_number();
779
780 let version = self.version(view)?;
781
782 let serialized_message = if version == self.upgrade.base || version == self.upgrade.target {
783 versions::encode(version, message)
784 } else {
785 bail!(
786 "Attempted to serialize with version {version}, which is incompatible. This \
787 should be impossible."
788 );
789 };
790
791 serialized_message
792 .wrap()
793 .context(info!("Failed to serialize message!"))
794 }
795
796 pub fn deserialize<M: Debug + HasViewNumber + DeserializeOwned>(
806 &self,
807 message: &[u8],
808 ) -> Result<(M, Version)> {
809 let (version, deserialized_message) = versions::decode::<M>(message)
810 .wrap()
811 .context(info!("Failed to read version and message!"))?;
812
813 if EXTERNAL_MESSAGE_VERSION != version
814 && self.upgrade.base != version
815 && self.upgrade.target != version
816 {
817 bail!(warn!(
818 "Received a message with state version {version} which is invalid for its view: \
819 {:?}",
820 deserialized_message
821 ));
822 }
823
824 if version == EXTERNAL_MESSAGE_VERSION {
827 return Ok((deserialized_message, version));
828 }
829
830 let view = deserialized_message.view_number();
832
833 let expected_version = self.version(view)?;
835
836 if version != expected_version {
838 return Err(error!(format!(
839 "Message has invalid version number for its view. Expected: {expected_version}, \
840 Actual: {version}, View: {view:?}\n\n{deserialized_message:?}"
841 )));
842 };
843
844 Ok((deserialized_message, version))
845 }
846}