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 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 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 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 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}