linera_chain/certificate/
generic.rs1use allocative::{Allocative, Key, Visitor};
6use custom_debug_derive::Debug;
7use linera_base::{
8 crypto::{CryptoHash, ValidatorPublicKey, ValidatorSignature},
9 data_types::Round,
10};
11use linera_execution::committee::Committee;
12
13use super::CertificateValue;
14use crate::{data_types::LiteValue, ChainError};
15
16#[derive(Debug)]
18pub struct GenericCertificate<T: CertificateValue> {
19 value: T,
20 pub round: Round,
22 unlocking_round: Option<Round>,
27 first_round: bool,
33 justification_commitment: Option<CryptoHash>,
39 signatures: Vec<(ValidatorPublicKey, ValidatorSignature)>,
40}
41
42impl<T: Allocative + CertificateValue> Allocative for GenericCertificate<T> {
43 fn visit<'a, 'b: 'a>(&self, visitor: &'a mut Visitor<'b>) {
44 visitor.visit_field(Key::new("GenericCertificate_value"), &self.value);
45 visitor.visit_field(Key::new("GenericCertificate_round"), &self.round);
46 for (public_key, signature) in &self.signatures {
47 visitor.visit_field(Key::new("ValidatorPublicKey"), public_key);
48 visitor.visit_field(Key::new("ValidatorSignature"), signature);
49 }
50 }
51}
52
53impl<T: CertificateValue> GenericCertificate<T> {
54 pub fn new(
56 value: T,
57 round: Round,
58 signatures: Vec<(ValidatorPublicKey, ValidatorSignature)>,
59 ) -> Self {
60 Self::new_with_payload(value, round, None, false, None, signatures)
61 }
62
63 pub fn new_with_payload(
70 value: T,
71 round: Round,
72 unlocking_round: Option<Round>,
73 first_round: bool,
74 justification_commitment: Option<CryptoHash>,
75 mut signatures: Vec<(ValidatorPublicKey, ValidatorSignature)>,
76 ) -> Self {
77 signatures.sort_by_key(|&(validator_name, _)| validator_name);
78
79 Self {
80 value,
81 round,
82 unlocking_round,
83 first_round,
84 justification_commitment,
85 signatures,
86 }
87 }
88
89 pub fn round(&self) -> Round {
91 self.round
92 }
93
94 pub fn unlocking_round(&self) -> Option<Round> {
96 self.unlocking_round
97 }
98
99 pub fn first_round(&self) -> bool {
101 self.first_round
102 }
103
104 pub fn justification_commitment(&self) -> Option<CryptoHash> {
106 self.justification_commitment
107 }
108
109 pub fn value(&self) -> &T {
111 &self.value
112 }
113
114 pub fn into_value(self) -> T {
116 self.value
117 }
118
119 pub fn inner(&self) -> &T {
121 &self.value
122 }
123
124 pub fn into_inner(self) -> T {
126 self.value
127 }
128
129 pub fn hash(&self) -> CryptoHash {
131 self.value.hash()
132 }
133
134 pub fn signatures(&self) -> &Vec<(ValidatorPublicKey, ValidatorSignature)> {
136 &self.signatures
137 }
138
139 #[cfg(with_testing)]
141 pub fn signatures_mut(&mut self) -> &mut Vec<(ValidatorPublicKey, ValidatorSignature)> {
142 &mut self.signatures
143 }
144
145 pub fn add_signature(
148 &mut self,
149 signature: (ValidatorPublicKey, ValidatorSignature),
150 ) -> &Vec<(ValidatorPublicKey, ValidatorSignature)> {
151 let index = self
152 .signatures
153 .binary_search_by(|(name, _)| name.cmp(&signature.0))
154 .unwrap_or_else(std::convert::identity);
155 self.signatures.insert(index, signature);
156 &self.signatures
157 }
158
159 pub fn is_signed_by(&self, validator_name: &ValidatorPublicKey) -> bool {
161 self.signatures
162 .binary_search_by(|(name, _)| name.cmp(validator_name))
163 .is_ok()
164 }
165
166 pub fn check(&self, committee: &Committee) -> Result<(), ChainError>
168 where
169 T: CertificateValue,
170 {
171 let value = crate::data_types::VoteValue(
172 self.hash(),
173 self.round,
174 T::KIND,
175 self.unlocking_round,
176 self.first_round,
177 self.justification_commitment,
178 );
179 crate::data_types::check_signatures(&value, &self.signatures, committee)?;
180 Ok(())
181 }
182
183 pub fn lite_certificate_without_justification(&self) -> crate::certificate::LiteCertificate<'_>
195 where
196 T: CertificateValue,
197 {
198 crate::certificate::LiteCertificate {
199 value: LiteValue::new(&self.value),
200 round: self.round,
201 unlocking_round: self.unlocking_round,
202 first_round: self.first_round,
203 justification_commitment: self.justification_commitment,
204 justification: std::borrow::Cow::Owned(
205 crate::justification::JustificationChain::default(),
206 ),
207 signatures: std::borrow::Cow::Borrowed(&self.signatures),
208 }
209 }
210}
211
212impl<T: CertificateValue> Clone for GenericCertificate<T> {
213 fn clone(&self) -> Self {
214 Self {
215 value: self.value.clone(),
216 round: self.round,
217 unlocking_round: self.unlocking_round,
218 first_round: self.first_round,
219 justification_commitment: self.justification_commitment,
220 signatures: self.signatures.clone(),
221 }
222 }
223}
224
225#[cfg(with_testing)]
226impl<T: CertificateValue + Eq + PartialEq> Eq for GenericCertificate<T> {}
227#[cfg(with_testing)]
228impl<T: CertificateValue + Eq + PartialEq> PartialEq for GenericCertificate<T> {
229 fn eq(&self, other: &Self) -> bool {
230 self.hash() == other.hash()
231 && self.round == other.round
232 && self.unlocking_round == other.unlocking_round
233 && self.first_round == other.first_round
234 && self.justification_commitment == other.justification_commitment
235 && self.signatures == other.signatures
236 }
237}