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(
51 votes: impl IntoIterator<Item = (ValidatorPublicKey, LiteVote)>,
52 ) -> Option<Self> {
53 let mut votes = votes.into_iter();
54 let (
55 public_key,
56 LiteVote {
57 value,
58 round,
59 signature,
60 },
61 ) = votes.next()?;
62 let mut signatures = vec![(public_key, signature)];
63 for (validator_key, vote) in votes {
64 if vote.value.value_hash != value.value_hash || vote.round != round {
65 return None;
66 }
67 signatures.push((validator_key, vote.signature));
68 }
69 Some(LiteCertificate::new(value, round, signatures))
70 }
71
72 pub fn check(&self, committee: &Committee) -> Result<&LiteValue, ChainError> {
74 check_signatures(
75 self.value.value_hash,
76 self.value.kind,
77 self.round,
78 &self.signatures,
79 committee,
80 )?;
81 Ok(&self.value)
82 }
83
84 pub fn check_value<T: CertificateValue>(&self, value: &T) -> bool {
86 self.value.chain_id == value.chain_id()
87 && T::KIND == self.value.kind
88 && self.value.value_hash == value.hash()
89 }
90
91 pub fn with_value<T: CertificateValue>(self, value: T) -> Option<GenericCertificate<T>> {
93 if self.value.chain_id != value.chain_id()
94 || T::KIND != self.value.kind
95 || self.value.value_hash != value.hash()
96 {
97 return None;
98 }
99 Some(GenericCertificate::new(
100 value,
101 self.round,
102 self.signatures.into_owned(),
103 ))
104 }
105
106 pub fn cloned(&self) -> LiteCertificate<'static> {
108 LiteCertificate {
109 value: self.value.clone(),
110 round: self.round,
111 signatures: Cow::Owned(self.signatures.clone().into_owned()),
112 }
113 }
114}