mod verification;
use crate::ChainWithGrandpa;
pub use verification::{
equivocation::{EquivocationsCollector, GrandpaEquivocationsFinder},
optimizer::verify_and_optimize_justification,
strict::verify_justification,
AncestryChain, Error as JustificationVerificationError, JustificationVerificationContext,
PrecommitError,
};
use bp_runtime::{BlockNumberOf, Chain, HashOf, HeaderId};
use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
use sp_consensus_grandpa::{AuthorityId, AuthoritySignature};
use sp_runtime::{traits::Header as HeaderT, SaturatedConversion};
use sp_std::prelude::*;
#[derive(Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, TypeInfo)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct GrandpaJustification<Header: HeaderT> {
pub round: u64,
pub commit:
finality_grandpa::Commit<Header::Hash, Header::Number, AuthoritySignature, AuthorityId>,
pub votes_ancestries: Vec<Header>,
}
#[cfg(not(feature = "std"))]
impl<H: HeaderT> core::fmt::Debug for GrandpaJustification<H> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "GrandpaJustification {{ round: {:?}, commit: <wasm:stripped>, votes_ancestries: {:?} }}", self.round, self.votes_ancestries)
}
}
impl<H: HeaderT> GrandpaJustification<H> {
pub fn max_reasonable_size<C>(required_precommits: u32) -> u32
where
C: Chain + ChainWithGrandpa,
{
let signed_precommit_size: u32 = BlockNumberOf::<C>::max_encoded_len()
.saturating_add(HashOf::<C>::max_encoded_len().saturated_into())
.saturating_add(64)
.saturating_add(AuthorityId::max_encoded_len().saturated_into())
.saturated_into();
let max_expected_signed_commit_size = signed_precommit_size
.saturating_mul(required_precommits)
.saturating_add(BlockNumberOf::<C>::max_encoded_len().saturated_into())
.saturating_add(HashOf::<C>::max_encoded_len().saturated_into());
let max_expected_votes_ancestries_size =
C::REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY.saturating_mul(C::AVERAGE_HEADER_SIZE);
8u32.saturating_add(max_expected_signed_commit_size)
.saturating_add(max_expected_votes_ancestries_size)
}
pub fn commit_target_id(&self) -> HeaderId<H::Hash, H::Number> {
HeaderId(self.commit.target_number, self.commit.target_hash)
}
}
impl<H: HeaderT> crate::FinalityProof<H::Hash, H::Number> for GrandpaJustification<H> {
fn target_header_hash(&self) -> H::Hash {
self.commit.target_hash
}
fn target_header_number(&self) -> H::Number {
self.commit.target_number
}
}
#[derive(Eq, Debug, PartialEq)]
pub enum Error {
JustificationDecode,
}
pub fn required_justification_precommits(authorities_set_length: u32) -> u32 {
authorities_set_length - authorities_set_length.saturating_sub(1) / 3
}
pub fn decode_justification_target<Header: HeaderT>(
raw_justification: &[u8],
) -> Result<(Header::Hash, Header::Number), Error> {
GrandpaJustification::<Header>::decode(&mut &*raw_justification)
.map(|justification| (justification.commit.target_hash, justification.commit.target_number))
.map_err(|_| Error::JustificationDecode)
}