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