Skip to main content

linera_chain/certificate/
confirmed.rs

1// Copyright (c) Facebook, Inc. and its affiliates.
2// Copyright (c) Zefchain Labs, Inc.
3// SPDX-License-Identifier: Apache-2.0
4
5use linera_base::{
6    crypto::{ValidatorPublicKey, ValidatorSignature},
7    data_types::{Epoch, Round},
8    identifiers::ChainId,
9};
10use serde::{ser::SerializeStruct, Deserialize, Deserializer, Serialize};
11
12use super::{generic::GenericCertificate, Certificate};
13use crate::{
14    block::{Block, ConfirmedBlock, ConversionError},
15    data_types::MessageBundle,
16};
17
18impl GenericCertificate<ConfirmedBlock> {
19    /// Returns reference to the `Block` contained in this certificate.
20    pub fn block(&self) -> &Block {
21        self.inner().block()
22    }
23
24    /// Returns the bundles of messages sent to the specified recipient.
25    /// Messages originating from different transactions of the original block
26    /// are kept in separate bundles.
27    pub fn message_bundles_for(
28        &self,
29        recipient: ChainId,
30    ) -> impl Iterator<Item = (Epoch, MessageBundle)> + '_ {
31        let certificate_hash = self.hash();
32        self.block()
33            .message_bundles_for(recipient, certificate_hash)
34    }
35
36    #[cfg(with_testing)]
37    pub fn outgoing_message_count(&self) -> usize {
38        self.block().messages().iter().map(Vec::len).sum()
39    }
40}
41
42impl TryFrom<Certificate> for GenericCertificate<ConfirmedBlock> {
43    type Error = ConversionError;
44
45    fn try_from(cert: Certificate) -> Result<Self, Self::Error> {
46        match cert {
47            Certificate::Confirmed(confirmed) => Ok(confirmed),
48            _ => Err(ConversionError::ConfirmedBlock),
49        }
50    }
51}
52
53impl From<GenericCertificate<ConfirmedBlock>> for Certificate {
54    fn from(cert: GenericCertificate<ConfirmedBlock>) -> Certificate {
55        Certificate::Confirmed(cert)
56    }
57}
58
59impl From<&GenericCertificate<ConfirmedBlock>> for Certificate {
60    fn from(cert: &GenericCertificate<ConfirmedBlock>) -> Certificate {
61        Certificate::Confirmed(cert.clone())
62    }
63}
64
65impl Serialize for GenericCertificate<ConfirmedBlock> {
66    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
67    where
68        S: serde::Serializer,
69    {
70        let mut state = serializer.serialize_struct("ConfirmedBlockCertificate", 3)?;
71        state.serialize_field("value", self.inner())?;
72        state.serialize_field("round", &self.round)?;
73        state.serialize_field("signatures", self.signatures())?;
74        state.end()
75    }
76}
77
78impl<'de> Deserialize<'de> for GenericCertificate<ConfirmedBlock> {
79    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
80    where
81        D: Deserializer<'de>,
82    {
83        #[derive(Debug, Deserialize)]
84        #[serde(rename = "ConfirmedBlockCertificate")]
85        struct Helper {
86            value: ConfirmedBlock,
87            round: Round,
88            signatures: Vec<(ValidatorPublicKey, ValidatorSignature)>,
89        }
90
91        let helper = Helper::deserialize(deserializer)?;
92        if !crate::data_types::is_strictly_ordered(&helper.signatures) {
93            Err(serde::de::Error::custom("Vector is not strictly sorted"))
94        } else {
95            Ok(Self::new(helper.value, helper.round, helper.signatures))
96        }
97    }
98}