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::Round,
8    identifiers::{BlobId, ChainId, MessageId},
9};
10use linera_execution::committee::Epoch;
11use serde::{ser::SerializeStruct, Deserialize, Deserializer, Serialize};
12
13use super::{generic::GenericCertificate, Certificate};
14use crate::{
15    block::{Block, ConfirmedBlock, ConversionError},
16    data_types::{Medium, MessageBundle},
17};
18
19impl GenericCertificate<ConfirmedBlock> {
20    /// Returns reference to the `Block` contained in this certificate.
21    pub fn block(&self) -> &Block {
22        self.inner().block()
23    }
24
25    /// Returns whether this value contains the message with the specified ID.
26    pub fn has_message(&self, message_id: &MessageId) -> bool {
27        self.block().message_by_id(message_id).is_some()
28    }
29
30    /// Returns the bundles of messages sent via the given medium to the specified
31    /// recipient. Messages originating from different transactions of the original block
32    /// are kept in separate bundles. If the medium is a channel, does not verify that the
33    /// recipient is actually subscribed to that channel.
34    pub fn message_bundles_for<'a>(
35        &'a self,
36        medium: &'a Medium,
37        recipient: ChainId,
38    ) -> impl Iterator<Item = (Epoch, MessageBundle)> + 'a {
39        let certificate_hash = self.hash();
40        self.block()
41            .message_bundles_for(medium, recipient, certificate_hash)
42    }
43
44    pub fn requires_blob(&self, blob_id: &BlobId) -> bool {
45        self.block().requires_blob(blob_id)
46    }
47
48    #[cfg(with_testing)]
49    pub fn outgoing_message_count(&self) -> usize {
50        self.block().messages().iter().map(Vec::len).sum()
51    }
52}
53
54impl TryFrom<Certificate> for GenericCertificate<ConfirmedBlock> {
55    type Error = ConversionError;
56
57    fn try_from(cert: Certificate) -> Result<Self, Self::Error> {
58        match cert {
59            Certificate::Confirmed(confirmed) => Ok(confirmed),
60            _ => Err(ConversionError::ConfirmedBlock),
61        }
62    }
63}
64
65impl From<GenericCertificate<ConfirmedBlock>> for Certificate {
66    fn from(cert: GenericCertificate<ConfirmedBlock>) -> Certificate {
67        Certificate::Confirmed(cert)
68    }
69}
70
71impl Serialize for GenericCertificate<ConfirmedBlock> {
72    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
73    where
74        S: serde::Serializer,
75    {
76        let mut state = serializer.serialize_struct("ConfirmedBlockCertificate", 3)?;
77        state.serialize_field("value", self.inner())?;
78        state.serialize_field("round", &self.round)?;
79        state.serialize_field("signatures", self.signatures())?;
80        state.end()
81    }
82}
83
84impl<'de> Deserialize<'de> for GenericCertificate<ConfirmedBlock> {
85    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
86    where
87        D: Deserializer<'de>,
88    {
89        #[derive(Debug, Deserialize)]
90        #[serde(rename = "ConfirmedBlockCertificate")]
91        struct Helper {
92            value: ConfirmedBlock,
93            round: Round,
94            signatures: Vec<(ValidatorPublicKey, ValidatorSignature)>,
95        }
96
97        let helper = Helper::deserialize(deserializer)?;
98        if !crate::data_types::is_strictly_ordered(&helper.signatures) {
99            Err(serde::de::Error::custom("Vector is not strictly sorted"))
100        } else {
101            Ok(Self::new(helper.value, helper.round, helper.signatures))
102        }
103    }
104}