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 destructure(self) -> (T, Round, Vec<(ValidatorPublicKey, ValidatorSignature)>) {
76        (self.value, self.round, self.signatures)
77    }
78
79    pub fn signatures(&self) -> &Vec<(ValidatorPublicKey, ValidatorSignature)> {
80        &self.signatures
81    }
82
83    #[cfg(with_testing)]
84    pub fn signatures_mut(&mut self) -> &mut Vec<(ValidatorPublicKey, ValidatorSignature)> {
85        &mut self.signatures
86    }
87
88    /// Adds a signature to the certificate's list of signatures
89    /// It's the responsibility of the caller to not insert duplicates
90    pub fn add_signature(
91        &mut self,
92        signature: (ValidatorPublicKey, ValidatorSignature),
93    ) -> &Vec<(ValidatorPublicKey, ValidatorSignature)> {
94        let index = self
95            .signatures
96            .binary_search_by(|(name, _)| name.cmp(&signature.0))
97            .unwrap_or_else(std::convert::identity);
98        self.signatures.insert(index, signature);
99        &self.signatures
100    }
101
102    /// Returns whether the validator is among the signatories of this certificate.
103    pub fn is_signed_by(&self, validator_name: &ValidatorPublicKey) -> bool {
104        self.signatures
105            .binary_search_by(|(name, _)| name.cmp(validator_name))
106            .is_ok()
107    }
108
109    /// Verifies the certificate.
110    pub fn check(&self, committee: &Committee) -> Result<(), ChainError>
111    where
112        T: CertificateValue,
113    {
114        crate::data_types::check_signatures(
115            self.hash(),
116            T::KIND,
117            self.round,
118            &self.signatures,
119            committee,
120        )?;
121        Ok(())
122    }
123
124    pub fn lite_certificate(&self) -> crate::certificate::LiteCertificate<'_>
125    where
126        T: CertificateValue,
127    {
128        crate::certificate::LiteCertificate {
129            value: LiteValue::new(&self.value),
130            round: self.round,
131            signatures: std::borrow::Cow::Borrowed(&self.signatures),
132        }
133    }
134}
135
136impl<T: CertificateValue> Clone for GenericCertificate<T> {
137    fn clone(&self) -> Self {
138        Self {
139            value: self.value.clone(),
140            round: self.round,
141            signatures: self.signatures.clone(),
142        }
143    }
144}
145
146#[cfg(with_testing)]
147impl<T: CertificateValue + Eq + PartialEq> Eq for GenericCertificate<T> {}
148#[cfg(with_testing)]
149impl<T: CertificateValue + Eq + PartialEq> PartialEq for GenericCertificate<T> {
150    fn eq(&self, other: &Self) -> bool {
151        self.hash() == other.hash()
152            && self.round == other.round
153            && self.signatures == other.signatures
154    }
155}