1use std::{
10 fmt::{self, Debug, Display, Formatter},
11 future::Future,
12 hash::Hash,
13 marker::PhantomData,
14};
15
16use alloy::primitives::U256;
17use committable::{Commitment, Committable};
18use hotshot_utils::anytrace::*;
19use serde::{Deserialize, Serialize};
20
21use crate::{
22 data::serialize_signature2,
23 epoch_membership::EpochMembership,
24 light_client::{LightClientState, StakeTableState},
25 message::UpgradeLock,
26 simple_vote::{
27 DaData, DaData2, HasEpoch, NextEpochQuorumData2, QuorumData, QuorumData2, QuorumMarker,
28 TimeoutData, TimeoutData2, UpgradeProposalData, VersionedVoteData, ViewSyncCommitData,
29 ViewSyncCommitData2, ViewSyncFinalizeData, ViewSyncFinalizeData2, ViewSyncPreCommitData,
30 ViewSyncPreCommitData2, Voteable,
31 },
32 stake_table::{HSStakeTable, StakeTableEntries},
33 traits::{
34 node_implementation::{ConsensusTime, NodeType, Versions},
35 signature_key::{SignatureKey, StateSignatureKey},
36 },
37 vote::{Certificate, HasViewNumber},
38 PeerConfig,
39};
40
41pub trait Threshold<TYPES: NodeType> {
43 fn threshold(membership: &EpochMembership<TYPES>) -> impl Future<Output = U256> + Send;
45}
46
47#[derive(Serialize, Deserialize, Eq, Hash, PartialEq, Debug, Clone)]
49pub struct SuccessThreshold {}
50
51impl<TYPES: NodeType> Threshold<TYPES> for SuccessThreshold {
52 async fn threshold(membership: &EpochMembership<TYPES>) -> U256 {
53 membership.success_threshold().await
54 }
55}
56
57#[derive(Serialize, Deserialize, Eq, Hash, PartialEq, Debug, Clone)]
59pub struct OneHonestThreshold {}
60
61impl<TYPES: NodeType> Threshold<TYPES> for OneHonestThreshold {
62 async fn threshold(membership: &EpochMembership<TYPES>) -> U256 {
63 membership.failure_threshold().await
64 }
65}
66
67#[derive(Serialize, Deserialize, Eq, Hash, PartialEq, Debug, Clone)]
69pub struct UpgradeThreshold {}
70
71impl<TYPES: NodeType> Threshold<TYPES> for UpgradeThreshold {
72 async fn threshold(membership: &EpochMembership<TYPES>) -> U256 {
73 membership.upgrade_threshold().await
74 }
75}
76
77#[derive(Serialize, Deserialize, Eq, Hash, PartialEq, Debug, Clone)]
79pub struct SimpleCertificate<
80 TYPES: NodeType,
81 VOTEABLE: Voteable<TYPES>,
82 THRESHOLD: Threshold<TYPES>,
83> {
84 pub data: VOTEABLE,
86 vote_commitment: Commitment<VOTEABLE>,
88 pub view_number: TYPES::View,
90 pub signatures: Option<<TYPES::SignatureKey as SignatureKey>::QcType>,
92 pub _pd: PhantomData<(TYPES, THRESHOLD)>,
94}
95
96impl<TYPES: NodeType, VOTEABLE: Voteable<TYPES>, THRESHOLD: Threshold<TYPES>>
97 SimpleCertificate<TYPES, VOTEABLE, THRESHOLD>
98{
99 pub fn new(
101 data: VOTEABLE,
102 vote_commitment: Commitment<VOTEABLE>,
103 view_number: TYPES::View,
104 signatures: Option<<TYPES::SignatureKey as SignatureKey>::QcType>,
105 pd: PhantomData<(TYPES, THRESHOLD)>,
106 ) -> Self {
107 Self {
108 data,
109 vote_commitment,
110 view_number,
111 signatures,
112 _pd: pd,
113 }
114 }
115}
116
117impl<TYPES: NodeType, VOTEABLE: Voteable<TYPES> + Committable, THRESHOLD: Threshold<TYPES>>
118 Committable for SimpleCertificate<TYPES, VOTEABLE, THRESHOLD>
119{
120 fn commit(&self) -> Commitment<Self> {
121 let signature_bytes = match self.signatures.as_ref() {
122 Some(sigs) => serialize_signature2::<TYPES>(sigs),
123 None => vec![],
124 };
125 committable::RawCommitmentBuilder::new("Certificate")
126 .field("data", self.data.commit())
127 .field("vote_commitment", self.vote_commitment)
128 .field("view number", self.view_number.commit())
129 .var_size_field("signatures", &signature_bytes)
130 .finalize()
131 }
132}
133
134impl<TYPES: NodeType, THRESHOLD: Threshold<TYPES>> Certificate<TYPES, DaData>
135 for SimpleCertificate<TYPES, DaData, THRESHOLD>
136{
137 type Voteable = DaData;
138 type Threshold = THRESHOLD;
139
140 fn create_signed_certificate<V: Versions>(
141 vote_commitment: Commitment<VersionedVoteData<TYPES, DaData, V>>,
142 data: Self::Voteable,
143 sig: <TYPES::SignatureKey as SignatureKey>::QcType,
144 view: TYPES::View,
145 ) -> Self {
146 let vote_commitment_bytes: [u8; 32] = vote_commitment.into();
147
148 SimpleCertificate {
149 data,
150 vote_commitment: Commitment::from_raw(vote_commitment_bytes),
151 view_number: view,
152 signatures: Some(sig),
153 _pd: PhantomData,
154 }
155 }
156 async fn is_valid_cert<V: Versions>(
157 &self,
158 stake_table: &[<TYPES::SignatureKey as SignatureKey>::StakeTableEntry],
159 threshold: U256,
160 upgrade_lock: &UpgradeLock<TYPES, V>,
161 ) -> Result<()> {
162 if self.view_number == TYPES::View::genesis() {
163 return Ok(());
164 }
165 let real_qc_pp =
166 <TYPES::SignatureKey as SignatureKey>::public_parameter(stake_table, threshold);
167 let commit = self.data_commitment(upgrade_lock).await?;
168
169 <TYPES::SignatureKey as SignatureKey>::check(
170 &real_qc_pp,
171 commit.as_ref(),
172 self.signatures.as_ref().unwrap(),
173 )
174 .wrap()
175 .context(|e| warn!("Signature check failed: {}", e))
176 }
177 async fn stake_table_entry(
179 membership: &EpochMembership<TYPES>,
180 pub_key: &TYPES::SignatureKey,
181 ) -> Option<PeerConfig<TYPES>> {
182 membership.da_stake(pub_key).await
183 }
184
185 async fn stake_table(membership: &EpochMembership<TYPES>) -> HSStakeTable<TYPES> {
187 membership.da_stake_table().await
188 }
189 async fn total_nodes(membership: &EpochMembership<TYPES>) -> usize {
191 membership.da_total_nodes().await
192 }
193 async fn threshold(membership: &EpochMembership<TYPES>) -> U256 {
194 membership.da_success_threshold().await
195 }
196 fn data(&self) -> &Self::Voteable {
197 &self.data
198 }
199 async fn data_commitment<V: Versions>(
200 &self,
201 upgrade_lock: &UpgradeLock<TYPES, V>,
202 ) -> Result<Commitment<VersionedVoteData<TYPES, DaData, V>>> {
203 Ok(
204 VersionedVoteData::new(self.data.clone(), self.view_number, upgrade_lock)
205 .await?
206 .commit(),
207 )
208 }
209}
210
211impl<TYPES: NodeType, THRESHOLD: Threshold<TYPES>> Certificate<TYPES, DaData2<TYPES>>
212 for SimpleCertificate<TYPES, DaData2<TYPES>, THRESHOLD>
213{
214 type Voteable = DaData2<TYPES>;
215 type Threshold = THRESHOLD;
216
217 fn create_signed_certificate<V: Versions>(
218 vote_commitment: Commitment<VersionedVoteData<TYPES, DaData2<TYPES>, V>>,
219 data: Self::Voteable,
220 sig: <TYPES::SignatureKey as SignatureKey>::QcType,
221 view: TYPES::View,
222 ) -> Self {
223 let vote_commitment_bytes: [u8; 32] = vote_commitment.into();
224
225 SimpleCertificate {
226 data,
227 vote_commitment: Commitment::from_raw(vote_commitment_bytes),
228 view_number: view,
229 signatures: Some(sig),
230 _pd: PhantomData,
231 }
232 }
233 async fn is_valid_cert<V: Versions>(
234 &self,
235 stake_table: &[<TYPES::SignatureKey as SignatureKey>::StakeTableEntry],
236 threshold: U256,
237 upgrade_lock: &UpgradeLock<TYPES, V>,
238 ) -> Result<()> {
239 if self.view_number == TYPES::View::genesis() {
240 return Ok(());
241 }
242 let real_qc_pp =
243 <TYPES::SignatureKey as SignatureKey>::public_parameter(stake_table, threshold);
244 let commit = self.data_commitment(upgrade_lock).await?;
245
246 <TYPES::SignatureKey as SignatureKey>::check(
247 &real_qc_pp,
248 commit.as_ref(),
249 self.signatures.as_ref().unwrap(),
250 )
251 .wrap()
252 .context(|e| warn!("Signature check failed: {}", e))
253 }
254 async fn stake_table_entry(
256 membership: &EpochMembership<TYPES>,
257 pub_key: &TYPES::SignatureKey,
258 ) -> Option<PeerConfig<TYPES>> {
259 membership.da_stake(pub_key).await
260 }
261
262 async fn stake_table(membership: &EpochMembership<TYPES>) -> HSStakeTable<TYPES> {
264 membership.da_stake_table().await
265 }
266 async fn total_nodes(membership: &EpochMembership<TYPES>) -> usize {
268 membership.da_total_nodes().await
269 }
270 async fn threshold(membership: &EpochMembership<TYPES>) -> U256 {
271 membership.da_success_threshold().await
272 }
273 fn data(&self) -> &Self::Voteable {
274 &self.data
275 }
276 async fn data_commitment<V: Versions>(
277 &self,
278 upgrade_lock: &UpgradeLock<TYPES, V>,
279 ) -> Result<Commitment<VersionedVoteData<TYPES, DaData2<TYPES>, V>>> {
280 Ok(
281 VersionedVoteData::new(self.data.clone(), self.view_number, upgrade_lock)
282 .await?
283 .commit(),
284 )
285 }
286}
287
288impl<
289 TYPES: NodeType,
290 VOTEABLE: Voteable<TYPES> + 'static + QuorumMarker,
291 THRESHOLD: Threshold<TYPES>,
292 > Certificate<TYPES, VOTEABLE> for SimpleCertificate<TYPES, VOTEABLE, THRESHOLD>
293{
294 type Voteable = VOTEABLE;
295 type Threshold = THRESHOLD;
296
297 fn create_signed_certificate<V: Versions>(
298 vote_commitment: Commitment<VersionedVoteData<TYPES, VOTEABLE, V>>,
299 data: Self::Voteable,
300 sig: <TYPES::SignatureKey as SignatureKey>::QcType,
301 view: TYPES::View,
302 ) -> Self {
303 let vote_commitment_bytes: [u8; 32] = vote_commitment.into();
304
305 SimpleCertificate {
306 data,
307 vote_commitment: Commitment::from_raw(vote_commitment_bytes),
308 view_number: view,
309 signatures: Some(sig),
310 _pd: PhantomData,
311 }
312 }
313 async fn is_valid_cert<V: Versions>(
314 &self,
315 stake_table: &[<TYPES::SignatureKey as SignatureKey>::StakeTableEntry],
316 threshold: U256,
317 upgrade_lock: &UpgradeLock<TYPES, V>,
318 ) -> Result<()> {
319 if self.view_number == TYPES::View::genesis() {
320 return Ok(());
321 }
322 let real_qc_pp =
323 <TYPES::SignatureKey as SignatureKey>::public_parameter(stake_table, threshold);
324 let commit = self.data_commitment(upgrade_lock).await?;
325
326 <TYPES::SignatureKey as SignatureKey>::check(
327 &real_qc_pp,
328 commit.as_ref(),
329 self.signatures.as_ref().unwrap(),
330 )
331 .wrap()
332 .context(|e| warn!("Signature check failed: {}", e))
333 }
334 async fn threshold(membership: &EpochMembership<TYPES>) -> U256 {
335 THRESHOLD::threshold(membership).await
336 }
337
338 async fn stake_table_entry(
339 membership: &EpochMembership<TYPES>,
340 pub_key: &TYPES::SignatureKey,
341 ) -> Option<PeerConfig<TYPES>> {
342 membership.stake(pub_key).await
343 }
344
345 async fn stake_table(membership: &EpochMembership<TYPES>) -> HSStakeTable<TYPES> {
346 membership.stake_table().await
347 }
348
349 async fn total_nodes(membership: &EpochMembership<TYPES>) -> usize {
351 membership.total_nodes().await
352 }
353
354 fn data(&self) -> &Self::Voteable {
355 &self.data
356 }
357 async fn data_commitment<V: Versions>(
358 &self,
359 upgrade_lock: &UpgradeLock<TYPES, V>,
360 ) -> Result<Commitment<VersionedVoteData<TYPES, VOTEABLE, V>>> {
361 Ok(
362 VersionedVoteData::new(self.data.clone(), self.view_number, upgrade_lock)
363 .await?
364 .commit(),
365 )
366 }
367}
368
369impl<TYPES: NodeType, VOTEABLE: Voteable<TYPES> + 'static, THRESHOLD: Threshold<TYPES>>
370 HasViewNumber<TYPES> for SimpleCertificate<TYPES, VOTEABLE, THRESHOLD>
371{
372 fn view_number(&self) -> TYPES::View {
373 self.view_number
374 }
375}
376
377impl<
378 TYPES: NodeType,
379 VOTEABLE: Voteable<TYPES> + HasEpoch<TYPES> + 'static,
380 THRESHOLD: Threshold<TYPES>,
381 > HasEpoch<TYPES> for SimpleCertificate<TYPES, VOTEABLE, THRESHOLD>
382{
383 fn epoch(&self) -> Option<TYPES::Epoch> {
384 self.data.epoch()
385 }
386}
387
388impl<TYPES: NodeType> Display for QuorumCertificate<TYPES> {
389 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
390 write!(f, "view: {:?}", self.view_number)
391 }
392}
393
394impl<TYPES: NodeType> UpgradeCertificate<TYPES> {
395 pub async fn is_relevant(&self, view_number: TYPES::View) -> Result<()> {
401 ensure!(
402 self.data.new_version_first_view >= view_number,
403 "Upgrade certificate is no longer relevant."
404 );
405
406 Ok(())
407 }
408
409 pub async fn validate<V: Versions>(
413 upgrade_certificate: &Option<Self>,
414 membership: &EpochMembership<TYPES>,
415 epoch: Option<TYPES::Epoch>,
416 upgrade_lock: &UpgradeLock<TYPES, V>,
417 ) -> Result<()> {
418 ensure!(epoch == membership.epoch(), "Epochs don't match!");
419 if let Some(ref cert) = upgrade_certificate {
420 let membership_stake_table = membership.stake_table().await;
421 let membership_upgrade_threshold = membership.upgrade_threshold().await;
422
423 cert.is_valid_cert(
424 &StakeTableEntries::<TYPES>::from(membership_stake_table).0,
425 membership_upgrade_threshold,
426 upgrade_lock,
427 )
428 .await
429 .context(|e| warn!("Invalid upgrade certificate: {}", e))?;
430 }
431
432 Ok(())
433 }
434
435 pub fn upgrading_in(&self, view: TYPES::View) -> bool {
438 view > self.data.old_version_last_view && view < self.data.new_version_first_view
439 }
440}
441
442impl<TYPES: NodeType> QuorumCertificate<TYPES> {
443 pub fn to_qc2(self) -> QuorumCertificate2<TYPES> {
445 let bytes: [u8; 32] = self.data.leaf_commit.into();
446 let data = QuorumData2 {
447 leaf_commit: Commitment::from_raw(bytes),
448 epoch: None,
449 block_number: None,
450 };
451
452 let bytes: [u8; 32] = self.vote_commitment.into();
453 let vote_commitment = Commitment::from_raw(bytes);
454
455 SimpleCertificate {
456 data,
457 vote_commitment,
458 view_number: self.view_number,
459 signatures: self.signatures.clone(),
460 _pd: PhantomData,
461 }
462 }
463}
464
465impl<TYPES: NodeType> QuorumCertificate2<TYPES> {
466 pub fn to_qc(self) -> QuorumCertificate<TYPES> {
468 let bytes: [u8; 32] = self.data.leaf_commit.into();
469 let data = QuorumData {
470 leaf_commit: Commitment::from_raw(bytes),
471 };
472
473 let bytes: [u8; 32] = self.vote_commitment.into();
474 let vote_commitment = Commitment::from_raw(bytes);
475
476 SimpleCertificate {
477 data,
478 vote_commitment,
479 view_number: self.view_number,
480 signatures: self.signatures.clone(),
481 _pd: PhantomData,
482 }
483 }
484}
485
486impl<TYPES: NodeType> DaCertificate<TYPES> {
487 pub fn to_dac2(self) -> DaCertificate2<TYPES> {
489 let data = DaData2 {
490 payload_commit: self.data.payload_commit,
491 next_epoch_payload_commit: None,
492 epoch: None,
493 };
494
495 let bytes: [u8; 32] = self.vote_commitment.into();
496 let vote_commitment = Commitment::from_raw(bytes);
497
498 SimpleCertificate {
499 data,
500 vote_commitment,
501 view_number: self.view_number,
502 signatures: self.signatures.clone(),
503 _pd: PhantomData,
504 }
505 }
506}
507
508impl<TYPES: NodeType> DaCertificate2<TYPES> {
509 pub fn to_dac(self) -> DaCertificate<TYPES> {
511 let data = DaData {
512 payload_commit: self.data.payload_commit,
513 };
514
515 let bytes: [u8; 32] = self.vote_commitment.into();
516 let vote_commitment = Commitment::from_raw(bytes);
517
518 SimpleCertificate {
519 data,
520 vote_commitment,
521 view_number: self.view_number,
522 signatures: self.signatures.clone(),
523 _pd: PhantomData,
524 }
525 }
526}
527
528impl<TYPES: NodeType> ViewSyncPreCommitCertificate<TYPES> {
529 pub fn to_vsc2(self) -> ViewSyncPreCommitCertificate2<TYPES> {
531 let data = ViewSyncPreCommitData2 {
532 relay: self.data.relay,
533 round: self.data.round,
534 epoch: None,
535 };
536
537 let bytes: [u8; 32] = self.vote_commitment.into();
538 let vote_commitment = Commitment::from_raw(bytes);
539
540 SimpleCertificate {
541 data,
542 vote_commitment,
543 view_number: self.view_number,
544 signatures: self.signatures.clone(),
545 _pd: PhantomData,
546 }
547 }
548}
549
550impl<TYPES: NodeType> ViewSyncPreCommitCertificate2<TYPES> {
551 pub fn to_vsc(self) -> ViewSyncPreCommitCertificate<TYPES> {
553 let data = ViewSyncPreCommitData {
554 relay: self.data.relay,
555 round: self.data.round,
556 };
557
558 let bytes: [u8; 32] = self.vote_commitment.into();
559 let vote_commitment = Commitment::from_raw(bytes);
560
561 SimpleCertificate {
562 data,
563 vote_commitment,
564 view_number: self.view_number,
565 signatures: self.signatures.clone(),
566 _pd: PhantomData,
567 }
568 }
569}
570
571impl<TYPES: NodeType> ViewSyncCommitCertificate<TYPES> {
572 pub fn to_vsc2(self) -> ViewSyncCommitCertificate2<TYPES> {
574 let data = ViewSyncCommitData2 {
575 relay: self.data.relay,
576 round: self.data.round,
577 epoch: None,
578 };
579
580 let bytes: [u8; 32] = self.vote_commitment.into();
581 let vote_commitment = Commitment::from_raw(bytes);
582
583 SimpleCertificate {
584 data,
585 vote_commitment,
586 view_number: self.view_number,
587 signatures: self.signatures.clone(),
588 _pd: PhantomData,
589 }
590 }
591}
592
593impl<TYPES: NodeType> ViewSyncCommitCertificate2<TYPES> {
594 pub fn to_vsc(self) -> ViewSyncCommitCertificate<TYPES> {
596 let data = ViewSyncCommitData {
597 relay: self.data.relay,
598 round: self.data.round,
599 };
600
601 let bytes: [u8; 32] = self.vote_commitment.into();
602 let vote_commitment = Commitment::from_raw(bytes);
603
604 SimpleCertificate {
605 data,
606 vote_commitment,
607 view_number: self.view_number,
608 signatures: self.signatures.clone(),
609 _pd: PhantomData,
610 }
611 }
612}
613
614impl<TYPES: NodeType> ViewSyncFinalizeCertificate<TYPES> {
615 pub fn to_vsc2(self) -> ViewSyncFinalizeCertificate2<TYPES> {
617 let data = ViewSyncFinalizeData2 {
618 relay: self.data.relay,
619 round: self.data.round,
620 epoch: None,
621 };
622
623 let bytes: [u8; 32] = self.vote_commitment.into();
624 let vote_commitment = Commitment::from_raw(bytes);
625
626 SimpleCertificate {
627 data,
628 vote_commitment,
629 view_number: self.view_number,
630 signatures: self.signatures.clone(),
631 _pd: PhantomData,
632 }
633 }
634}
635
636impl<TYPES: NodeType> ViewSyncFinalizeCertificate2<TYPES> {
637 pub fn to_vsc(self) -> ViewSyncFinalizeCertificate<TYPES> {
639 let data = ViewSyncFinalizeData {
640 relay: self.data.relay,
641 round: self.data.round,
642 };
643
644 let bytes: [u8; 32] = self.vote_commitment.into();
645 let vote_commitment = Commitment::from_raw(bytes);
646
647 SimpleCertificate {
648 data,
649 vote_commitment,
650 view_number: self.view_number,
651 signatures: self.signatures.clone(),
652 _pd: PhantomData,
653 }
654 }
655}
656
657impl<TYPES: NodeType> TimeoutCertificate<TYPES> {
658 pub fn to_tc2(self) -> TimeoutCertificate2<TYPES> {
660 let data = TimeoutData2 {
661 view: self.data.view,
662 epoch: None,
663 };
664
665 let bytes: [u8; 32] = self.vote_commitment.into();
666 let vote_commitment = Commitment::from_raw(bytes);
667
668 SimpleCertificate {
669 data,
670 vote_commitment,
671 view_number: self.view_number,
672 signatures: self.signatures.clone(),
673 _pd: PhantomData,
674 }
675 }
676}
677
678impl<TYPES: NodeType> TimeoutCertificate2<TYPES> {
679 pub fn to_tc(self) -> TimeoutCertificate<TYPES> {
681 let data = TimeoutData {
682 view: self.data.view,
683 };
684
685 let bytes: [u8; 32] = self.vote_commitment.into();
686 let vote_commitment = Commitment::from_raw(bytes);
687
688 SimpleCertificate {
689 data,
690 vote_commitment,
691 view_number: self.view_number,
692 signatures: self.signatures.clone(),
693 _pd: PhantomData,
694 }
695 }
696}
697
698pub type QuorumCertificate<TYPES> = SimpleCertificate<TYPES, QuorumData<TYPES>, SuccessThreshold>;
700pub type QuorumCertificate2<TYPES> = SimpleCertificate<TYPES, QuorumData2<TYPES>, SuccessThreshold>;
702pub type NextEpochQuorumCertificate2<TYPES> =
704 SimpleCertificate<TYPES, NextEpochQuorumData2<TYPES>, SuccessThreshold>;
705pub type DaCertificate<TYPES> = SimpleCertificate<TYPES, DaData, SuccessThreshold>;
707pub type DaCertificate2<TYPES> = SimpleCertificate<TYPES, DaData2<TYPES>, SuccessThreshold>;
709pub type TimeoutCertificate<TYPES> = SimpleCertificate<TYPES, TimeoutData<TYPES>, SuccessThreshold>;
711pub type TimeoutCertificate2<TYPES> =
713 SimpleCertificate<TYPES, TimeoutData2<TYPES>, SuccessThreshold>;
714pub type ViewSyncPreCommitCertificate<TYPES> =
716 SimpleCertificate<TYPES, ViewSyncPreCommitData<TYPES>, OneHonestThreshold>;
717pub type ViewSyncPreCommitCertificate2<TYPES> =
719 SimpleCertificate<TYPES, ViewSyncPreCommitData2<TYPES>, OneHonestThreshold>;
720pub type ViewSyncCommitCertificate<TYPES> =
722 SimpleCertificate<TYPES, ViewSyncCommitData<TYPES>, SuccessThreshold>;
723pub type ViewSyncCommitCertificate2<TYPES> =
725 SimpleCertificate<TYPES, ViewSyncCommitData2<TYPES>, SuccessThreshold>;
726pub type ViewSyncFinalizeCertificate<TYPES> =
728 SimpleCertificate<TYPES, ViewSyncFinalizeData<TYPES>, SuccessThreshold>;
729pub type ViewSyncFinalizeCertificate2<TYPES> =
731 SimpleCertificate<TYPES, ViewSyncFinalizeData2<TYPES>, SuccessThreshold>;
732pub type UpgradeCertificate<TYPES> =
734 SimpleCertificate<TYPES, UpgradeProposalData<TYPES>, UpgradeThreshold>;
735
736#[derive(Serialize, Deserialize, Eq, Hash, PartialEq, Debug, Clone)]
738pub struct LightClientStateUpdateCertificate<TYPES: NodeType> {
739 pub epoch: TYPES::Epoch,
741 pub light_client_state: LightClientState,
743 pub next_stake_table_state: StakeTableState,
745 pub signatures: Vec<(
747 TYPES::StateSignatureKey,
748 <TYPES::StateSignatureKey as StateSignatureKey>::StateSignature,
749 )>,
750}
751
752impl<TYPES: NodeType> HasViewNumber<TYPES> for LightClientStateUpdateCertificate<TYPES> {
753 fn view_number(&self) -> TYPES::View {
754 TYPES::View::new(self.light_client_state.view_number)
755 }
756}
757
758impl<TYPES: NodeType> HasEpoch<TYPES> for LightClientStateUpdateCertificate<TYPES> {
759 fn epoch(&self) -> Option<TYPES::Epoch> {
760 Some(self.epoch)
761 }
762}
763
764impl<TYPES: NodeType> LightClientStateUpdateCertificate<TYPES> {
765 pub fn genesis() -> Self {
766 Self {
767 epoch: TYPES::Epoch::genesis(),
768 light_client_state: Default::default(),
769 next_stake_table_state: Default::default(),
770 signatures: vec![],
771 }
772 }
773}
774
775#[derive(Serialize, Deserialize, Eq, Hash, PartialEq, Debug, Clone)]
776#[serde(bound(deserialize = "QuorumCertificate2<TYPES>:for<'a> Deserialize<'a>"))]
777pub struct EpochRootQuorumCertificate<TYPES: NodeType> {
778 pub qc: QuorumCertificate2<TYPES>,
779 pub state_cert: LightClientStateUpdateCertificate<TYPES>,
780}
781
782impl<TYPES: NodeType> HasViewNumber<TYPES> for EpochRootQuorumCertificate<TYPES> {
783 fn view_number(&self) -> TYPES::View {
784 self.qc.view_number()
785 }
786}
787
788impl<TYPES: NodeType> HasEpoch<TYPES> for EpochRootQuorumCertificate<TYPES> {
789 fn epoch(&self) -> Option<TYPES::Epoch> {
790 self.qc.epoch()
791 }
792}