hotmint_types/
certificate.rs1use serde::{Deserialize, Serialize};
2
3use crate::block::BlockHash;
4use crate::crypto::AggregateSignature;
5use crate::epoch::EpochNumber;
6use crate::view::ViewNumber;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct QuorumCertificate {
11 pub block_hash: BlockHash,
12 pub view: ViewNumber,
13 pub aggregate_signature: AggregateSignature,
14 #[serde(default)]
17 pub epoch: EpochNumber,
18}
19
20impl QuorumCertificate {
21 pub fn rank(&self) -> ViewNumber {
23 self.view
24 }
25}
26
27#[derive(Debug, Clone, Serialize, Deserialize)]
29pub struct DoubleCertificate {
30 pub inner_qc: QuorumCertificate,
31 pub outer_qc: QuorumCertificate,
32}
33
34#[derive(Debug, Clone, Serialize, Deserialize)]
36pub struct TimeoutCertificate {
37 pub view: ViewNumber,
38 pub aggregate_signature: AggregateSignature,
39 pub highest_qcs: Vec<Option<QuorumCertificate>>,
41}
42
43impl TimeoutCertificate {
44 pub fn highest_qc(&self) -> Option<&QuorumCertificate> {
46 self.highest_qcs
47 .iter()
48 .filter_map(|qc| qc.as_ref())
49 .max_by_key(|qc| qc.view)
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 fn make_qc(view: u64, hash: [u8; 32]) -> QuorumCertificate {
58 QuorumCertificate {
59 block_hash: BlockHash(hash),
60 view: ViewNumber(view),
61 aggregate_signature: AggregateSignature::new(4),
62 epoch: EpochNumber(0),
63 }
64 }
65
66 #[test]
67 fn test_qc_rank() {
68 let qc = make_qc(5, [1u8; 32]);
69 assert_eq!(qc.rank(), ViewNumber(5));
70 }
71
72 #[test]
73 fn test_tc_highest_qc_some() {
74 let qc1 = make_qc(3, [1u8; 32]);
75 let qc2 = make_qc(7, [2u8; 32]);
76 let tc = TimeoutCertificate {
77 view: ViewNumber(8),
78 aggregate_signature: AggregateSignature::new(4),
79 highest_qcs: vec![Some(qc1), None, Some(qc2), None],
80 };
81 let highest = tc.highest_qc().unwrap();
82 assert_eq!(highest.view, ViewNumber(7));
83 }
84
85 #[test]
86 fn test_tc_highest_qc_all_none() {
87 let tc = TimeoutCertificate {
88 view: ViewNumber(5),
89 aggregate_signature: AggregateSignature::new(4),
90 highest_qcs: vec![None, None, None, None],
91 };
92 assert!(tc.highest_qc().is_none());
93 }
94
95 #[test]
96 fn test_tc_highest_qc_empty() {
97 let tc = TimeoutCertificate {
98 view: ViewNumber(5),
99 aggregate_signature: AggregateSignature::new(4),
100 highest_qcs: vec![],
101 };
102 assert!(tc.highest_qc().is_none());
103 }
104}