use custom_debug_derive::Debug;
use linera_base::{
crypto::{CryptoHash, ValidatorPublicKey, ValidatorSignature},
data_types::Round,
hashed::Hashed,
};
use linera_execution::committee::Committee;
use super::CertificateValue;
use crate::{data_types::LiteValue, ChainError};
#[derive(Debug)]
pub struct GenericCertificate<T> {
value: Hashed<T>,
pub round: Round,
signatures: Vec<(ValidatorPublicKey, ValidatorSignature)>,
}
impl<T> GenericCertificate<T> {
pub fn new(
value: Hashed<T>,
round: Round,
mut signatures: Vec<(ValidatorPublicKey, ValidatorSignature)>,
) -> Self {
signatures.sort_by_key(|&(validator_name, _)| validator_name);
Self {
value,
round,
signatures,
}
}
pub fn value(&self) -> &Hashed<T> {
&self.value
}
pub fn into_value(self) -> Hashed<T> {
self.value
}
pub fn inner(&self) -> &T {
self.value.inner()
}
pub fn into_inner(self) -> T {
self.value.into_inner()
}
pub fn hash(&self) -> CryptoHash {
self.value.hash()
}
pub fn destructure(
self,
) -> (
Hashed<T>,
Round,
Vec<(ValidatorPublicKey, ValidatorSignature)>,
) {
(self.value, self.round, self.signatures)
}
pub fn signatures(&self) -> &Vec<(ValidatorPublicKey, ValidatorSignature)> {
&self.signatures
}
#[cfg(with_testing)]
pub fn signatures_mut(&mut self) -> &mut Vec<(ValidatorPublicKey, ValidatorSignature)> {
&mut self.signatures
}
pub fn add_signature(
&mut self,
signature: (ValidatorPublicKey, ValidatorSignature),
) -> &Vec<(ValidatorPublicKey, ValidatorSignature)> {
let index = self
.signatures
.binary_search_by(|(name, _)| name.cmp(&signature.0))
.unwrap_or_else(std::convert::identity);
self.signatures.insert(index, signature);
&self.signatures
}
pub fn is_signed_by(&self, validator_name: &ValidatorPublicKey) -> bool {
self.signatures
.binary_search_by(|(name, _)| name.cmp(validator_name))
.is_ok()
}
pub fn check(&self, committee: &Committee) -> Result<(), ChainError>
where
T: CertificateValue,
{
crate::data_types::check_signatures(
self.hash(),
T::KIND,
self.round,
&self.signatures,
committee,
)?;
Ok(())
}
pub fn lite_certificate(&self) -> crate::certificate::LiteCertificate<'_>
where
T: CertificateValue,
{
crate::certificate::LiteCertificate {
value: LiteValue::new(&self.value),
round: self.round,
signatures: std::borrow::Cow::Borrowed(&self.signatures),
}
}
}
impl<T: Clone> Clone for GenericCertificate<T> {
fn clone(&self) -> Self {
Self {
value: self.value.clone(),
round: self.round,
signatures: self.signatures.clone(),
}
}
}
#[cfg(with_testing)]
impl<T: Eq + PartialEq> Eq for GenericCertificate<T> {}
#[cfg(with_testing)]
impl<T: Eq + PartialEq> PartialEq for GenericCertificate<T> {
fn eq(&self, other: &Self) -> bool {
self.hash() == other.hash()
&& self.round == other.round
&& self.signatures == other.signatures
}
}