linera_chain/certificate/
generic.rs1use 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#[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 pub fn value(&self) -> &T {
52 &self.value
53 }
54
55 pub fn into_value(self) -> T {
57 self.value
58 }
59
60 pub fn inner(&self) -> &T {
62 &self.value
63 }
64
65 pub fn into_inner(self) -> T {
67 self.value
68 }
69
70 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 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 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 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}