linera_chain/certificate/
lite.rs1use std::borrow::Cow;
6
7use linera_base::{
8 crypto::{ValidatorPublicKey, ValidatorSignature},
9 data_types::Round,
10};
11use linera_execution::committee::Committee;
12use serde::{Deserialize, Serialize};
13
14use super::{CertificateValue, GenericCertificate};
15use crate::{
16 data_types::{check_signatures, LiteValue, LiteVote},
17 ChainError,
18};
19
20#[derive(Clone, Debug, Serialize, Deserialize)]
22#[cfg_attr(with_testing, derive(Eq, PartialEq))]
23pub struct LiteCertificate<'a> {
24 pub value: LiteValue,
26 pub round: Round,
28 pub signatures: Cow<'a, [(ValidatorPublicKey, ValidatorSignature)]>,
30}
31
32impl LiteCertificate<'_> {
33 pub fn new(
34 value: LiteValue,
35 round: Round,
36 mut signatures: Vec<(ValidatorPublicKey, ValidatorSignature)>,
37 ) -> Self {
38 signatures.sort_by_key(|&(validator_name, _)| validator_name);
39
40 let signatures = Cow::Owned(signatures);
41 Self {
42 value,
43 round,
44 signatures,
45 }
46 }
47
48 pub fn try_from_votes(votes: impl IntoIterator<Item = LiteVote>) -> Option<Self> {
51 let mut votes = votes.into_iter();
52 let LiteVote {
53 value,
54 round,
55 public_key,
56 signature,
57 } = votes.next()?;
58 let mut signatures = vec![(public_key, signature)];
59 for vote in votes {
60 if vote.value.value_hash != value.value_hash || vote.round != round {
61 return None;
62 }
63 signatures.push((vote.public_key, vote.signature));
64 }
65 Some(LiteCertificate::new(value, round, signatures))
66 }
67
68 pub fn check(&self, committee: &Committee) -> Result<&LiteValue, ChainError> {
70 check_signatures(
71 self.value.value_hash,
72 self.value.kind,
73 self.round,
74 &self.signatures,
75 committee,
76 )?;
77 Ok(&self.value)
78 }
79
80 pub fn check_value<T: CertificateValue>(&self, value: &T) -> bool {
82 self.value.chain_id == value.chain_id()
83 && T::KIND == self.value.kind
84 && self.value.value_hash == value.hash()
85 }
86
87 pub fn with_value<T: CertificateValue>(self, value: T) -> Option<GenericCertificate<T>> {
89 if self.value.chain_id != value.chain_id()
90 || T::KIND != self.value.kind
91 || self.value.value_hash != value.hash()
92 {
93 return None;
94 }
95 Some(GenericCertificate::new(
96 value,
97 self.round,
98 self.signatures.into_owned(),
99 ))
100 }
101
102 pub fn cloned(&self) -> LiteCertificate<'static> {
104 LiteCertificate {
105 value: self.value.clone(),
106 round: self.round,
107 signatures: Cow::Owned(self.signatures.clone().into_owned()),
108 }
109 }
110}