linera_chain/certificate/
generic.rs

1// Copyright (c) Facebook, Inc. and its affiliates.
2// Copyright (c) Zefchain Labs, Inc.
3// SPDX-License-Identifier: Apache-2.0
4
5use custom_debug_derive::Debug;
6use linera_base::{
7    crypto::{CryptoHash, ValidatorPublicKey, ValidatorSignature},
8    data_types::Round,
9};
10use linera_execution::committee::Committee;
11
12use super::CertificateValue;
13use crate::{data_types::LiteValue, ChainError};
14
15/// Generic type representing a certificate for `value` of type `T`.
16#[derive(Debug)]
17pub struct GenericCertificate<T: CertificateValue> {
18    value: T,
19    pub round: Round,
20    signatures: Vec<(ValidatorPublicKey, ValidatorSignature)>,
21}
22
23impl<T: CertificateValue> GenericCertificate<T> {
24    pub fn new(
25        value: T,
26        round: Round,
27        mut signatures: Vec<(ValidatorPublicKey, ValidatorSignature)>,
28    ) -> Self {
29        signatures.sort_by_key(|&(validator_name, _)| validator_name);
30
31        Self {
32            value,
33            round,
34            signatures,
35        }
36    }
37
38    /// Returns a reference to the `Hashed` value contained in this certificate.
39    pub fn value(&self) -> &T {
40        &self.value
41    }
42
43    /// Consumes this certificate, returning the value it contains.
44    pub fn into_value(self) -> T {
45        self.value
46    }
47
48    /// Returns reference to the value contained in this certificate.
49    pub fn inner(&self) -> &T {
50        &self.value
51    }
52
53    /// Consumes this certificate, returning the value it contains.
54    pub fn into_inner(self) -> T {
55        self.value
56    }
57
58    /// Returns the certified value's hash.
59    pub fn hash(&self) -> CryptoHash {
60        self.value.hash()
61    }
62
63    pub fn destructure(self) -> (T, Round, Vec<(ValidatorPublicKey, ValidatorSignature)>) {
64        (self.value, self.round, self.signatures)
65    }
66
67    pub fn signatures(&self) -> &Vec<(ValidatorPublicKey, ValidatorSignature)> {
68        &self.signatures
69    }
70
71    #[cfg(with_testing)]
72    pub fn signatures_mut(&mut self) -> &mut Vec<(ValidatorPublicKey, ValidatorSignature)> {
73        &mut self.signatures
74    }
75
76    /// Adds a signature to the certificate's list of signatures
77    /// It's the responsibility of the caller to not insert duplicates
78    pub fn add_signature(
79        &mut self,
80        signature: (ValidatorPublicKey, ValidatorSignature),
81    ) -> &Vec<(ValidatorPublicKey, ValidatorSignature)> {
82        let index = self
83            .signatures
84            .binary_search_by(|(name, _)| name.cmp(&signature.0))
85            .unwrap_or_else(std::convert::identity);
86        self.signatures.insert(index, signature);
87        &self.signatures
88    }
89
90    /// Returns whether the validator is among the signatories of this certificate.
91    pub fn is_signed_by(&self, validator_name: &ValidatorPublicKey) -> bool {
92        self.signatures
93            .binary_search_by(|(name, _)| name.cmp(validator_name))
94            .is_ok()
95    }
96
97    /// Verifies the certificate.
98    pub fn check(&self, committee: &Committee) -> Result<(), ChainError>
99    where
100        T: CertificateValue,
101    {
102        crate::data_types::check_signatures(
103            self.hash(),
104            T::KIND,
105            self.round,
106            &self.signatures,
107            committee,
108        )?;
109        Ok(())
110    }
111
112    pub fn lite_certificate(&self) -> crate::certificate::LiteCertificate<'_>
113    where
114        T: CertificateValue,
115    {
116        crate::certificate::LiteCertificate {
117            value: LiteValue::new(&self.value),
118            round: self.round,
119            signatures: std::borrow::Cow::Borrowed(&self.signatures),
120        }
121    }
122}
123
124impl<T: CertificateValue> Clone for GenericCertificate<T> {
125    fn clone(&self) -> Self {
126        Self {
127            value: self.value.clone(),
128            round: self.round,
129            signatures: self.signatures.clone(),
130        }
131    }
132}
133
134#[cfg(with_testing)]
135impl<T: CertificateValue + Eq + PartialEq> Eq for GenericCertificate<T> {}
136#[cfg(with_testing)]
137impl<T: CertificateValue + Eq + PartialEq> PartialEq for GenericCertificate<T> {
138    fn eq(&self, other: &Self) -> bool {
139        self.hash() == other.hash()
140            && self.round == other.round
141            && self.signatures == other.signatures
142    }
143}