hotshot_types/new_protocol/
proposal.rs1use serde::{Deserialize, Serialize};
2
3use crate::{
4 data::{
5 EpochNumber, Leaf2, QuorumProposal2, QuorumProposalWrapper, ViewChangeEvidence2, ViewNumber,
6 },
7 drb::DrbResult,
8 simple_certificate::{
9 LightClientStateUpdateCertificateV2, QuorumCertificate2, SimpleCertificate,
10 SuccessThreshold, TimeoutEvidence, UpgradeCertificate2, optional_timeout_evidence,
11 },
12 simple_vote::{HasEpoch, Vote2Data},
13 traits::node_implementation::NodeType,
14 vote::HasViewNumber,
15};
16
17#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq, Hash)]
19#[serde(bound(deserialize = ""))]
20pub struct Proposal<T: NodeType> {
21 pub block_header: T::BlockHeader,
23
24 pub view_number: ViewNumber,
26
27 pub epoch: EpochNumber,
29
30 pub justify_qc: QuorumCertificate2<T>,
32
33 pub next_epoch_justify_qc: Option<SimpleCertificate<T, Vote2Data<T>, SuccessThreshold>>,
35
36 pub upgrade_certificate: Option<UpgradeCertificate2<T>>,
39
40 #[serde(with = "optional_timeout_evidence")]
45 pub view_change_evidence: Option<TimeoutEvidence<T>>,
46
47 #[serde(with = "serde_bytes")]
52 pub next_drb_result: Option<DrbResult>,
53
54 pub state_cert: Option<LightClientStateUpdateCertificateV2<T>>,
57}
58
59impl<T: NodeType> HasViewNumber for Proposal<T> {
60 fn view_number(&self) -> ViewNumber {
61 self.view_number
62 }
63}
64
65impl<T: NodeType> HasEpoch for Proposal<T> {
66 fn epoch(&self) -> Option<EpochNumber> {
67 Some(self.epoch)
68 }
69}
70
71impl<T: NodeType> From<QuorumProposalWrapper<T>> for Proposal<T> {
72 fn from(wrapper: QuorumProposalWrapper<T>) -> Self {
73 let qp = wrapper.proposal;
74 let epoch = qp.epoch.unwrap_or(EpochNumber::new(0));
75 Self {
76 block_header: qp.block_header,
77 view_number: qp.view_number,
78 epoch,
79 justify_qc: qp.justify_qc,
80 next_epoch_justify_qc: None,
81 upgrade_certificate: qp
82 .upgrade_certificate
83 .map(|cert| UpgradeCertificate2::restore_epoch(cert, epoch)),
84 view_change_evidence: qp
85 .view_change_evidence
86 .and_then(ViewChangeEvidence2::timeout_evidence),
87 next_drb_result: qp.next_drb_result,
88 state_cert: qp.state_cert,
89 }
90 }
91}
92
93impl<T: NodeType> From<Proposal<T>> for QuorumProposalWrapper<T> {
94 fn from(p: Proposal<T>) -> Self {
95 QuorumProposalWrapper::from(QuorumProposal2 {
96 block_header: p.block_header,
97 view_number: p.view_number,
98 epoch: Some(p.epoch),
99 justify_qc: p.justify_qc,
100 next_epoch_justify_qc: None,
101 upgrade_certificate: p.upgrade_certificate.map(UpgradeCertificate2::strip_epoch),
102 view_change_evidence: p.view_change_evidence.map(ViewChangeEvidence2::from),
103 next_drb_result: p.next_drb_result,
104 state_cert: p.state_cert,
105 })
106 }
107}
108
109impl<T: NodeType> From<Proposal<T>> for Leaf2<T> {
110 fn from(p: Proposal<T>) -> Self {
111 QuorumProposalWrapper::from(p).into()
112 }
113}