linera_chain/certificate/
mod.rs

1// Copyright (c) Facebook, Inc. and its affiliates.
2// Copyright (c) Zefchain Labs, Inc.
3// SPDX-License-Identifier: Apache-2.0
4
5mod confirmed;
6mod generic;
7mod lite;
8mod timeout;
9mod validated;
10
11use std::collections::BTreeSet;
12
13pub use generic::GenericCertificate;
14use linera_base::{
15    crypto::{CryptoHash, ValidatorPublicKey, ValidatorSignature},
16    data_types::{BlockHeight, Epoch, Round},
17    identifiers::{BlobId, ChainId},
18};
19pub use lite::LiteCertificate;
20use serde::{Deserialize, Serialize};
21
22use crate::types::{ConfirmedBlock, Timeout, ValidatedBlock};
23
24/// Certificate for a [`ValidatedBlock`] instance.
25/// A validated block certificate means the block is valid (but not necessarily finalized yet).
26/// Since only one block per round is validated,
27/// there can be at most one such certificate in every round.
28pub type ValidatedBlockCertificate = GenericCertificate<ValidatedBlock>;
29
30/// Certificate for a [`ConfirmedBlock`] instance.
31/// A confirmed block certificate means that the block is finalized:
32/// It is the agreed block at that height on that chain.
33pub type ConfirmedBlockCertificate = GenericCertificate<ConfirmedBlock>;
34
35/// Certificate for a [`Timeout`] instance.
36/// A timeout certificate means that the next consensus round has begun.
37pub type TimeoutCertificate = GenericCertificate<Timeout>;
38
39/// Enum wrapping all types of certificates that can be created.
40/// A certified statement from the committee.
41/// Every certificate is a statement signed by the quorum of the committee.
42#[derive(Debug, Clone, Serialize, Deserialize)]
43#[cfg_attr(with_testing, derive(Eq, PartialEq))]
44pub enum Certificate {
45    /// Certificate for [`ValidatedBlock`].
46    Validated(ValidatedBlockCertificate),
47    /// Certificate for [`ConfirmedBlock`].
48    Confirmed(ConfirmedBlockCertificate),
49    /// Certificate for [`Timeout`].
50    Timeout(TimeoutCertificate),
51}
52
53impl Certificate {
54    pub fn round(&self) -> Round {
55        match self {
56            Certificate::Validated(cert) => cert.round,
57            Certificate::Confirmed(cert) => cert.round,
58            Certificate::Timeout(cert) => cert.round,
59        }
60    }
61
62    pub fn height(&self) -> BlockHeight {
63        match self {
64            Certificate::Validated(cert) => cert.value().block().header.height,
65            Certificate::Confirmed(cert) => cert.value().block().header.height,
66            Certificate::Timeout(cert) => cert.value().height(),
67        }
68    }
69
70    pub fn chain_id(&self) -> ChainId {
71        match self {
72            Certificate::Validated(cert) => cert.value().block().header.chain_id,
73            Certificate::Confirmed(cert) => cert.value().block().header.chain_id,
74            Certificate::Timeout(cert) => cert.value().chain_id(),
75        }
76    }
77
78    pub fn signatures(&self) -> &Vec<(ValidatorPublicKey, ValidatorSignature)> {
79        match self {
80            Certificate::Validated(cert) => cert.signatures(),
81            Certificate::Confirmed(cert) => cert.signatures(),
82            Certificate::Timeout(cert) => cert.signatures(),
83        }
84    }
85}
86
87#[derive(Clone, Copy, Debug, Serialize, Deserialize, Hash, Eq, PartialEq)]
88#[repr(u8)]
89pub enum CertificateKind {
90    Timeout = 0,
91    Validated = 1,
92    Confirmed = 2,
93}
94
95pub trait CertificateValue: Clone {
96    const KIND: CertificateKind;
97
98    fn chain_id(&self) -> ChainId;
99
100    fn epoch(&self) -> Epoch;
101
102    fn height(&self) -> BlockHeight;
103
104    fn required_blob_ids(&self) -> BTreeSet<BlobId>;
105
106    fn hash(&self) -> CryptoHash;
107}
108
109impl CertificateValue for Timeout {
110    const KIND: CertificateKind = CertificateKind::Timeout;
111
112    fn chain_id(&self) -> ChainId {
113        self.chain_id()
114    }
115
116    fn epoch(&self) -> Epoch {
117        self.epoch()
118    }
119
120    fn height(&self) -> BlockHeight {
121        self.height()
122    }
123
124    fn required_blob_ids(&self) -> BTreeSet<BlobId> {
125        BTreeSet::new()
126    }
127
128    fn hash(&self) -> CryptoHash {
129        self.inner().hash()
130    }
131}
132
133impl CertificateValue for ValidatedBlock {
134    const KIND: CertificateKind = CertificateKind::Validated;
135
136    fn chain_id(&self) -> ChainId {
137        self.block().header.chain_id
138    }
139
140    fn epoch(&self) -> Epoch {
141        self.block().header.epoch
142    }
143
144    fn height(&self) -> BlockHeight {
145        self.block().header.height
146    }
147
148    fn required_blob_ids(&self) -> BTreeSet<BlobId> {
149        self.block().required_blob_ids()
150    }
151
152    fn hash(&self) -> CryptoHash {
153        self.inner().hash()
154    }
155}
156
157impl CertificateValue for ConfirmedBlock {
158    const KIND: CertificateKind = CertificateKind::Confirmed;
159
160    fn chain_id(&self) -> ChainId {
161        self.block().header.chain_id
162    }
163
164    fn epoch(&self) -> Epoch {
165        self.block().header.epoch
166    }
167
168    fn height(&self) -> BlockHeight {
169        self.block().header.height
170    }
171
172    fn required_blob_ids(&self) -> BTreeSet<BlobId> {
173        self.block().required_blob_ids()
174    }
175
176    fn hash(&self) -> CryptoHash {
177        self.inner().hash()
178    }
179}