use tendermint::block::CommitSig;
use crate::{
errors::VerificationError,
types::{SignedHeader, ValidatorSet},
};
pub trait CommitValidator: Send + Sync {
fn validate(
&self,
signed_header: &SignedHeader,
validator_set: &ValidatorSet,
) -> Result<(), VerificationError> {
let signatures = &signed_header.commit.signatures;
let has_present_signatures = signatures.iter().any(|cs| !cs.is_absent());
if !has_present_signatures {
return Err(VerificationError::no_signature_for_commit());
}
if signatures.len() != validator_set.validators().len() {
return Err(VerificationError::mismatch_pre_commit_length(
signatures.len(),
validator_set.validators().len(),
));
}
Ok(())
}
fn validate_full(
&self,
signed_header: &SignedHeader,
validator_set: &ValidatorSet,
) -> Result<(), VerificationError> {
for commit_sig in signed_header.commit.signatures.iter() {
let validator_address = match commit_sig {
CommitSig::BlockIdFlagAbsent => continue,
CommitSig::BlockIdFlagCommit {
validator_address, ..
} => validator_address,
CommitSig::BlockIdFlagNil {
validator_address, ..
} => validator_address,
};
if validator_set.validator(*validator_address).is_none() {
return Err(VerificationError::faulty_signer(
*validator_address,
validator_set.clone(),
));
}
}
Ok(())
}
}
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq)]
pub struct ProdCommitValidator;
impl CommitValidator for ProdCommitValidator {}