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