linera_chain/certificate/
mod.rs1mod confirmed;
6mod generic;
7mod lite;
8mod timeout;
9mod validated;
10
11use std::collections::BTreeSet;
12
13use allocative::Allocative;
14pub use confirmed::ConfirmedBlockCertificate;
15pub use generic::GenericCertificate;
16use linera_base::{
17 crypto::{CryptoHash, ValidatorPublicKey, ValidatorSignature},
18 data_types::{BlockHeight, Epoch, Round},
19 identifiers::{BlobId, ChainId},
20};
21use linera_execution::committee::Committee;
22pub use lite::LiteCertificate;
23use serde::{Deserialize, Serialize};
24pub use validated::ValidatedBlockCertificate;
25
26use crate::{
27 types::{ConfirmedBlock, Timeout, ValidatedBlock},
28 ChainError,
29};
30
31pub type TimeoutCertificate = GenericCertificate<Timeout>;
34
35pub trait Certified {
38 type Value: CertificateValue;
40
41 fn value(&self) -> &Self::Value;
43
44 fn round(&self) -> Round;
46
47 fn unlocking_round(&self) -> Option<Round>;
49
50 fn signatures(&self) -> &Vec<(ValidatorPublicKey, ValidatorSignature)>;
52
53 fn hash(&self) -> CryptoHash {
55 self.value().hash()
56 }
57
58 fn lite_certificate(&self) -> LiteCertificate<'_>;
61
62 fn check(&self, committee: &Committee) -> Result<(), ChainError>;
64
65 fn is_signed_by(&self, validator_name: &ValidatorPublicKey) -> bool {
67 self.signatures()
68 .binary_search_by(|(name, _)| name.cmp(validator_name))
69 .is_ok()
70 }
71}
72
73impl<T: CertificateValue> Certified for GenericCertificate<T> {
74 type Value = T;
75
76 fn value(&self) -> &T {
77 GenericCertificate::value(self)
78 }
79
80 fn round(&self) -> Round {
81 GenericCertificate::round(self)
82 }
83
84 fn unlocking_round(&self) -> Option<Round> {
85 GenericCertificate::unlocking_round(self)
86 }
87
88 fn signatures(&self) -> &Vec<(ValidatorPublicKey, ValidatorSignature)> {
89 GenericCertificate::signatures(self)
90 }
91
92 fn lite_certificate(&self) -> LiteCertificate<'_> {
93 GenericCertificate::lite_certificate_without_justification(self)
94 }
95
96 fn check(&self, committee: &Committee) -> Result<(), ChainError> {
97 GenericCertificate::check(self, committee)
98 }
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
105#[cfg_attr(with_testing, derive(Eq, PartialEq))]
106pub enum Certificate {
107 Validated(ValidatedBlockCertificate),
109 Confirmed(ConfirmedBlockCertificate),
111 Timeout(TimeoutCertificate),
113}
114
115impl Certificate {
116 pub fn round(&self) -> Round {
118 match self {
119 Certificate::Validated(cert) => cert.round(),
120 Certificate::Confirmed(cert) => cert.round(),
121 Certificate::Timeout(cert) => cert.round(),
122 }
123 }
124
125 pub fn height(&self) -> BlockHeight {
127 match self {
128 Certificate::Validated(cert) => cert.value().block().header.height,
129 Certificate::Confirmed(cert) => cert.value().block().header.height,
130 Certificate::Timeout(cert) => cert.value().height(),
131 }
132 }
133
134 pub fn chain_id(&self) -> ChainId {
136 match self {
137 Certificate::Validated(cert) => cert.value().block().header.chain_id,
138 Certificate::Confirmed(cert) => cert.value().block().header.chain_id,
139 Certificate::Timeout(cert) => cert.value().chain_id(),
140 }
141 }
142
143 pub fn signatures(&self) -> &Vec<(ValidatorPublicKey, ValidatorSignature)> {
145 match self {
146 Certificate::Validated(cert) => cert.signatures(),
147 Certificate::Confirmed(cert) => cert.signatures(),
148 Certificate::Timeout(cert) => cert.signatures(),
149 }
150 }
151}
152
153#[derive(Clone, Copy, Debug, Serialize, Deserialize, Hash, Eq, PartialEq, Allocative)]
155#[repr(u8)]
156#[allow(missing_docs)]
157pub enum CertificateKind {
158 Timeout = 0,
159 Validated = 1,
160 Confirmed = 2,
161}
162
163pub trait CertificateValue: Clone {
165 const KIND: CertificateKind;
167
168 fn chain_id(&self) -> ChainId;
170
171 fn epoch(&self) -> Epoch;
173
174 fn height(&self) -> BlockHeight;
176
177 fn required_blob_ids(&self) -> BTreeSet<BlobId>;
179
180 fn hash(&self) -> CryptoHash;
182}
183
184impl CertificateValue for Timeout {
185 const KIND: CertificateKind = CertificateKind::Timeout;
186
187 fn chain_id(&self) -> ChainId {
188 self.chain_id()
189 }
190
191 fn epoch(&self) -> Epoch {
192 self.epoch()
193 }
194
195 fn height(&self) -> BlockHeight {
196 self.height()
197 }
198
199 fn required_blob_ids(&self) -> BTreeSet<BlobId> {
200 BTreeSet::new()
201 }
202
203 fn hash(&self) -> CryptoHash {
204 self.inner().hash()
205 }
206}
207
208impl CertificateValue for ValidatedBlock {
209 const KIND: CertificateKind = CertificateKind::Validated;
210
211 fn chain_id(&self) -> ChainId {
212 self.block().header.chain_id
213 }
214
215 fn epoch(&self) -> Epoch {
216 self.block().header.epoch
217 }
218
219 fn height(&self) -> BlockHeight {
220 self.block().header.height
221 }
222
223 fn required_blob_ids(&self) -> BTreeSet<BlobId> {
224 self.block().required_blob_ids()
225 }
226
227 fn hash(&self) -> CryptoHash {
228 self.inner().hash()
229 }
230}
231
232impl CertificateValue for ConfirmedBlock {
233 const KIND: CertificateKind = CertificateKind::Confirmed;
234
235 fn chain_id(&self) -> ChainId {
236 self.block().header.chain_id
237 }
238
239 fn epoch(&self) -> Epoch {
240 self.block().header.epoch
241 }
242
243 fn height(&self) -> BlockHeight {
244 self.block().header.height
245 }
246
247 fn required_blob_ids(&self) -> BTreeSet<BlobId> {
248 self.block().required_blob_ids()
249 }
250
251 fn hash(&self) -> CryptoHash {
252 self.inner().hash()
253 }
254}