mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 18:41:03 +00:00
Bridges subtree sync (#3022)
* Squashed 'bridges/' changes from edf33a2c85..277f0d5496 277f0d5496 Dynamic fees for bridges-v1 (#2294) b1c51f7dd2 Finality loop refactoring (#2357) 620db2b10f Add equivocation detector crate and implement clients (#2348) (#2353) 3fe4b13eb4 Add basic equivocation detection pipeline schema (#2338) (#2341) git-subtree-dir: bridges git-subtree-split: 277f0d54961c800b231d8123c6445f378b1deb89 * [dynfees] Rococo/Wococo does not need congestion and dynamic fees (for now) * Fix * ".git/.scripts/commands/fmt/fmt.sh" * Forgotten bridges/Cargo.lock --------- Co-authored-by: command-bot <>
This commit is contained in:
@@ -23,10 +23,11 @@ mod verification;
|
||||
|
||||
use crate::ChainWithGrandpa;
|
||||
pub use verification::{
|
||||
equivocation::{EquivocationsCollector, Error as EquivocationsCollectorError},
|
||||
equivocation::{EquivocationsCollector, GrandpaEquivocationsFinder},
|
||||
optimizer::verify_and_optimize_justification,
|
||||
strict::verify_justification,
|
||||
AncestryChain, Error as JustificationVerificationError, PrecommitError,
|
||||
AncestryChain, Error as JustificationVerificationError, JustificationVerificationContext,
|
||||
PrecommitError,
|
||||
};
|
||||
|
||||
use bp_runtime::{BlockNumberOf, Chain, HashOf, HeaderId};
|
||||
|
||||
+61
-47
@@ -16,33 +16,26 @@
|
||||
|
||||
//! Logic for extracting equivocations from multiple GRANDPA Finality Proofs.
|
||||
|
||||
use crate::justification::{
|
||||
verification::{
|
||||
Error as JustificationVerificationError, JustificationVerifier, PrecommitError,
|
||||
SignedPrecommit,
|
||||
use crate::{
|
||||
justification::{
|
||||
verification::{
|
||||
Error as JustificationVerificationError, IterationFlow,
|
||||
JustificationVerificationContext, JustificationVerifier, PrecommitError,
|
||||
SignedPrecommit,
|
||||
},
|
||||
GrandpaJustification,
|
||||
},
|
||||
GrandpaJustification,
|
||||
ChainWithGrandpa, FindEquivocations,
|
||||
};
|
||||
|
||||
use crate::justification::verification::IterationFlow;
|
||||
use finality_grandpa::voter_set::VoterSet;
|
||||
use frame_support::RuntimeDebug;
|
||||
use sp_consensus_grandpa::{AuthorityId, AuthoritySignature, EquivocationProof, Precommit, SetId};
|
||||
use bp_runtime::{BlockNumberOf, HashOf, HeaderOf};
|
||||
use sp_consensus_grandpa::{AuthorityId, AuthoritySignature, EquivocationProof, Precommit};
|
||||
use sp_runtime::traits::Header as HeaderT;
|
||||
use sp_std::{
|
||||
collections::{btree_map::BTreeMap, btree_set::BTreeSet},
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
/// Justification verification error.
|
||||
#[derive(Eq, RuntimeDebug, PartialEq)]
|
||||
pub enum Error {
|
||||
/// Justification is targeting unexpected round.
|
||||
InvalidRound,
|
||||
/// Justification verification error.
|
||||
JustificationVerification(JustificationVerificationError),
|
||||
}
|
||||
|
||||
enum AuthorityVotes<Header: HeaderT> {
|
||||
SingleVote(SignedPrecommit<Header>),
|
||||
Equivocation(
|
||||
@@ -53,8 +46,7 @@ enum AuthorityVotes<Header: HeaderT> {
|
||||
/// Structure that can extract equivocations from multiple GRANDPA justifications.
|
||||
pub struct EquivocationsCollector<'a, Header: HeaderT> {
|
||||
round: u64,
|
||||
authorities_set_id: SetId,
|
||||
authorities_set: &'a VoterSet<AuthorityId>,
|
||||
context: &'a JustificationVerificationContext,
|
||||
|
||||
votes: BTreeMap<AuthorityId, AuthorityVotes<Header>>,
|
||||
}
|
||||
@@ -62,38 +54,34 @@ pub struct EquivocationsCollector<'a, Header: HeaderT> {
|
||||
impl<'a, Header: HeaderT> EquivocationsCollector<'a, Header> {
|
||||
/// Create a new instance of `EquivocationsCollector`.
|
||||
pub fn new(
|
||||
authorities_set_id: SetId,
|
||||
authorities_set: &'a VoterSet<AuthorityId>,
|
||||
context: &'a JustificationVerificationContext,
|
||||
base_justification: &GrandpaJustification<Header>,
|
||||
) -> Result<Self, Error> {
|
||||
let mut checker = Self {
|
||||
round: base_justification.round,
|
||||
authorities_set_id,
|
||||
authorities_set,
|
||||
votes: BTreeMap::new(),
|
||||
};
|
||||
) -> Result<Self, JustificationVerificationError> {
|
||||
let mut checker = Self { round: base_justification.round, context, votes: BTreeMap::new() };
|
||||
|
||||
checker.verify_justification(
|
||||
(base_justification.commit.target_hash, base_justification.commit.target_number),
|
||||
checker.context,
|
||||
base_justification,
|
||||
)?;
|
||||
|
||||
checker.parse_justification(base_justification)?;
|
||||
Ok(checker)
|
||||
}
|
||||
|
||||
/// Parse an additional justification for equivocations.
|
||||
pub fn parse_justification(
|
||||
&mut self,
|
||||
justification: &GrandpaJustification<Header>,
|
||||
) -> Result<(), Error> {
|
||||
// The justification should target the same round as the base justification.
|
||||
if self.round != justification.round {
|
||||
return Err(Error::InvalidRound)
|
||||
/// Parse additional justifications for equivocations.
|
||||
pub fn parse_justifications(&mut self, justifications: &[GrandpaJustification<Header>]) {
|
||||
let round = self.round;
|
||||
for justification in
|
||||
justifications.iter().filter(|justification| round == justification.round)
|
||||
{
|
||||
// We ignore the Errors received here since we don't care if the proofs are valid.
|
||||
// We only care about collecting equivocations.
|
||||
let _ = self.verify_justification(
|
||||
(justification.commit.target_hash, justification.commit.target_number),
|
||||
self.context,
|
||||
justification,
|
||||
);
|
||||
}
|
||||
|
||||
self.verify_justification(
|
||||
(justification.commit.target_hash, justification.commit.target_number),
|
||||
self.authorities_set_id,
|
||||
self.authorities_set,
|
||||
justification,
|
||||
)
|
||||
.map_err(Error::JustificationVerification)
|
||||
}
|
||||
|
||||
/// Extract the equivocation proofs that have been collected.
|
||||
@@ -102,7 +90,7 @@ impl<'a, Header: HeaderT> EquivocationsCollector<'a, Header> {
|
||||
for (_authority, vote) in self.votes {
|
||||
if let AuthorityVotes::Equivocation(equivocation) = vote {
|
||||
equivocations.push(EquivocationProof::new(
|
||||
self.authorities_set_id,
|
||||
self.context.authority_set_id,
|
||||
sp_consensus_grandpa::Equivocation::Precommit(equivocation),
|
||||
));
|
||||
}
|
||||
@@ -177,3 +165,29 @@ impl<'a, Header: HeaderT> JustificationVerifier<Header> for EquivocationsCollect
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper struct for finding equivocations in GRANDPA proofs.
|
||||
pub struct GrandpaEquivocationsFinder<C>(sp_std::marker::PhantomData<C>);
|
||||
|
||||
impl<C: ChainWithGrandpa>
|
||||
FindEquivocations<
|
||||
GrandpaJustification<HeaderOf<C>>,
|
||||
JustificationVerificationContext,
|
||||
EquivocationProof<HashOf<C>, BlockNumberOf<C>>,
|
||||
> for GrandpaEquivocationsFinder<C>
|
||||
{
|
||||
type Error = JustificationVerificationError;
|
||||
|
||||
fn find_equivocations(
|
||||
verification_context: &JustificationVerificationContext,
|
||||
synced_proof: &GrandpaJustification<HeaderOf<C>>,
|
||||
source_proofs: &[GrandpaJustification<HeaderOf<C>>],
|
||||
) -> Result<Vec<EquivocationProof<HashOf<C>, BlockNumberOf<C>>>, Self::Error> {
|
||||
let mut equivocations_collector =
|
||||
EquivocationsCollector::new(verification_context, synced_proof)?;
|
||||
|
||||
equivocations_collector.parse_justifications(source_proofs);
|
||||
|
||||
Ok(equivocations_collector.into_equivocation_proofs())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ pub mod equivocation;
|
||||
pub mod optimizer;
|
||||
pub mod strict;
|
||||
|
||||
use crate::justification::GrandpaJustification;
|
||||
use crate::{justification::GrandpaJustification, AuthoritySet};
|
||||
|
||||
use bp_runtime::HeaderId;
|
||||
use finality_grandpa::voter_set::VoterSet;
|
||||
@@ -114,6 +114,8 @@ impl<Header: HeaderT> AncestryChain<Header> {
|
||||
/// Justification verification error.
|
||||
#[derive(Eq, RuntimeDebug, PartialEq)]
|
||||
pub enum Error {
|
||||
/// Could not convert `AuthorityList` to `VoterSet`.
|
||||
InvalidAuthorityList,
|
||||
/// Justification is finalizing unexpected header.
|
||||
InvalidJustificationTarget,
|
||||
/// Error validating a precommit
|
||||
@@ -141,6 +143,24 @@ pub enum PrecommitError {
|
||||
UnrelatedAncestryVote,
|
||||
}
|
||||
|
||||
/// The context needed for validating GRANDPA finality proofs.
|
||||
pub struct JustificationVerificationContext {
|
||||
/// The authority set used to verify the justification.
|
||||
pub voter_set: VoterSet<AuthorityId>,
|
||||
/// The ID of the authority set used to verify the justification.
|
||||
pub authority_set_id: SetId,
|
||||
}
|
||||
|
||||
impl TryFrom<AuthoritySet> for JustificationVerificationContext {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(authority_set: AuthoritySet) -> Result<Self, Self::Error> {
|
||||
let voter_set =
|
||||
VoterSet::new(authority_set.authorities).ok_or(Error::InvalidAuthorityList)?;
|
||||
Ok(JustificationVerificationContext { voter_set, authority_set_id: authority_set.set_id })
|
||||
}
|
||||
}
|
||||
|
||||
enum IterationFlow {
|
||||
Run,
|
||||
Skip,
|
||||
@@ -185,8 +205,7 @@ trait JustificationVerifier<Header: HeaderT> {
|
||||
fn verify_justification(
|
||||
&mut self,
|
||||
finalized_target: (Header::Hash, Header::Number),
|
||||
authorities_set_id: SetId,
|
||||
authorities_set: &VoterSet<AuthorityId>,
|
||||
context: &JustificationVerificationContext,
|
||||
justification: &GrandpaJustification<Header>,
|
||||
) -> Result<(), Error> {
|
||||
// ensure that it is justification for the expected header
|
||||
@@ -196,7 +215,7 @@ trait JustificationVerifier<Header: HeaderT> {
|
||||
return Err(Error::InvalidJustificationTarget)
|
||||
}
|
||||
|
||||
let threshold = authorities_set.threshold().get();
|
||||
let threshold = context.voter_set.threshold().get();
|
||||
let mut chain = AncestryChain::new(justification);
|
||||
let mut signature_buffer = Vec::new();
|
||||
let mut cumulative_weight = 0u64;
|
||||
@@ -211,7 +230,7 @@ trait JustificationVerifier<Header: HeaderT> {
|
||||
}
|
||||
|
||||
// authority must be in the set
|
||||
let authority_info = match authorities_set.get(&signed.id) {
|
||||
let authority_info = match context.voter_set.get(&signed.id) {
|
||||
Some(authority_info) => {
|
||||
// The implementer may want to do extra checks here.
|
||||
// For example to see if the authority has already voted in the same round.
|
||||
@@ -248,7 +267,7 @@ trait JustificationVerifier<Header: HeaderT> {
|
||||
&signed.id,
|
||||
&signed.signature,
|
||||
justification.round,
|
||||
authorities_set_id,
|
||||
context.authority_set_id,
|
||||
&mut signature_buffer,
|
||||
) {
|
||||
self.process_invalid_signature_vote(precommit_idx).map_err(Error::Precommit)?;
|
||||
|
||||
+6
-11
@@ -21,9 +21,10 @@ use crate::justification::{
|
||||
GrandpaJustification,
|
||||
};
|
||||
|
||||
use crate::justification::verification::{IterationFlow, SignedPrecommit};
|
||||
use finality_grandpa::voter_set::VoterSet;
|
||||
use sp_consensus_grandpa::{AuthorityId, SetId};
|
||||
use crate::justification::verification::{
|
||||
IterationFlow, JustificationVerificationContext, SignedPrecommit,
|
||||
};
|
||||
use sp_consensus_grandpa::AuthorityId;
|
||||
use sp_runtime::traits::Header as HeaderT;
|
||||
use sp_std::{collections::btree_set::BTreeSet, prelude::*};
|
||||
|
||||
@@ -111,8 +112,7 @@ impl<Header: HeaderT> JustificationVerifier<Header> for JustificationOptimizer<H
|
||||
/// Verify and optimize given justification by removing unknown and duplicate votes.
|
||||
pub fn verify_and_optimize_justification<Header: HeaderT>(
|
||||
finalized_target: (Header::Hash, Header::Number),
|
||||
authorities_set_id: SetId,
|
||||
authorities_set: &VoterSet<AuthorityId>,
|
||||
context: &JustificationVerificationContext,
|
||||
justification: &mut GrandpaJustification<Header>,
|
||||
) -> Result<(), Error> {
|
||||
let mut optimizer = JustificationOptimizer {
|
||||
@@ -120,12 +120,7 @@ pub fn verify_and_optimize_justification<Header: HeaderT>(
|
||||
extra_precommits: vec![],
|
||||
redundant_votes_ancestries: Default::default(),
|
||||
};
|
||||
optimizer.verify_justification(
|
||||
finalized_target,
|
||||
authorities_set_id,
|
||||
authorities_set,
|
||||
justification,
|
||||
)?;
|
||||
optimizer.verify_justification(finalized_target, context, justification)?;
|
||||
optimizer.optimize(justification);
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -21,9 +21,10 @@ use crate::justification::{
|
||||
GrandpaJustification,
|
||||
};
|
||||
|
||||
use crate::justification::verification::{IterationFlow, SignedPrecommit};
|
||||
use finality_grandpa::voter_set::VoterSet;
|
||||
use sp_consensus_grandpa::{AuthorityId, SetId};
|
||||
use crate::justification::verification::{
|
||||
IterationFlow, JustificationVerificationContext, SignedPrecommit,
|
||||
};
|
||||
use sp_consensus_grandpa::AuthorityId;
|
||||
use sp_runtime::traits::Header as HeaderT;
|
||||
use sp_std::collections::btree_set::BTreeSet;
|
||||
|
||||
@@ -92,15 +93,9 @@ impl<Header: HeaderT> JustificationVerifier<Header> for StrictJustificationVerif
|
||||
/// Verify that justification, that is generated by given authority set, finalizes given header.
|
||||
pub fn verify_justification<Header: HeaderT>(
|
||||
finalized_target: (Header::Hash, Header::Number),
|
||||
authorities_set_id: SetId,
|
||||
authorities_set: &VoterSet<AuthorityId>,
|
||||
context: &JustificationVerificationContext,
|
||||
justification: &GrandpaJustification<Header>,
|
||||
) -> Result<(), Error> {
|
||||
let mut verifier = StrictJustificationVerifier { votes: BTreeSet::new() };
|
||||
verifier.verify_justification(
|
||||
finalized_target,
|
||||
authorities_set_id,
|
||||
authorities_set,
|
||||
justification,
|
||||
)
|
||||
verifier.verify_justification(finalized_target, context, justification)
|
||||
}
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use crate::justification::{
|
||||
GrandpaJustification, JustificationVerificationContext, JustificationVerificationError,
|
||||
};
|
||||
use bp_runtime::{
|
||||
BasicOperatingMode, Chain, HashOf, HasherOf, HeaderOf, RawStorageProof, StorageProofChecker,
|
||||
StorageProofError, UnderlyingChainProvider,
|
||||
@@ -30,7 +33,7 @@ use scale_info::TypeInfo;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sp_consensus_grandpa::{AuthorityList, ConsensusLog, SetId, GRANDPA_ENGINE_ID};
|
||||
use sp_runtime::{traits::Header as HeaderT, Digest, RuntimeDebug};
|
||||
use sp_std::boxed::Box;
|
||||
use sp_std::{boxed::Box, vec::Vec};
|
||||
|
||||
pub mod justification;
|
||||
pub mod storage_keys;
|
||||
@@ -172,13 +175,48 @@ impl<Number: Codec> ConsensusLogReader for GrandpaConsensusLogReader<Number> {
|
||||
}
|
||||
}
|
||||
|
||||
/// The Grandpa-related info associated to a header.
|
||||
/// The finality-related info associated to a header.
|
||||
#[derive(Encode, Decode, Debug, PartialEq, Clone, TypeInfo)]
|
||||
pub struct HeaderGrandpaInfo<Header: HeaderT> {
|
||||
/// The header justification
|
||||
pub justification: justification::GrandpaJustification<Header>,
|
||||
/// The authority set introduced by the header.
|
||||
pub authority_set: Option<AuthoritySet>,
|
||||
pub struct HeaderFinalityInfo<FinalityProof, FinalityVerificationContext> {
|
||||
/// The header finality proof.
|
||||
pub finality_proof: FinalityProof,
|
||||
/// The new verification context introduced by the header.
|
||||
pub new_verification_context: Option<FinalityVerificationContext>,
|
||||
}
|
||||
|
||||
/// Grandpa-related info associated to a header. This info can be saved to events.
|
||||
pub type StoredHeaderGrandpaInfo<Header> =
|
||||
HeaderFinalityInfo<GrandpaJustification<Header>, AuthoritySet>;
|
||||
|
||||
/// Processed Grandpa-related info associated to a header.
|
||||
pub type HeaderGrandpaInfo<Header> =
|
||||
HeaderFinalityInfo<GrandpaJustification<Header>, JustificationVerificationContext>;
|
||||
|
||||
impl<Header: HeaderT> TryFrom<StoredHeaderGrandpaInfo<Header>> for HeaderGrandpaInfo<Header> {
|
||||
type Error = JustificationVerificationError;
|
||||
|
||||
fn try_from(grandpa_info: StoredHeaderGrandpaInfo<Header>) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
finality_proof: grandpa_info.finality_proof,
|
||||
new_verification_context: match grandpa_info.new_verification_context {
|
||||
Some(authority_set) => Some(authority_set.try_into()?),
|
||||
None => None,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper trait for finding equivocations in finality proofs.
|
||||
pub trait FindEquivocations<FinalityProof, FinalityVerificationContext, EquivocationProof> {
|
||||
/// The type returned when encountering an error while looking for equivocations.
|
||||
type Error;
|
||||
|
||||
/// Find equivocations.
|
||||
fn find_equivocations(
|
||||
verification_context: &FinalityVerificationContext,
|
||||
synced_proof: &FinalityProof,
|
||||
source_proofs: &[FinalityProof],
|
||||
) -> Result<Vec<EquivocationProof>, Self::Error>;
|
||||
}
|
||||
|
||||
/// A minimized version of `pallet-bridge-grandpa::Call` that can be used without a runtime.
|
||||
@@ -244,16 +282,17 @@ pub trait ChainWithGrandpa: Chain {
|
||||
const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32;
|
||||
}
|
||||
|
||||
/// A trait that provides the type of the underlying `ChainWithGrandpa`.
|
||||
pub trait UnderlyingChainWithGrandpaProvider: UnderlyingChainProvider {
|
||||
/// Underlying `ChainWithGrandpa` type.
|
||||
type ChainWithGrandpa: ChainWithGrandpa;
|
||||
}
|
||||
|
||||
impl<T> UnderlyingChainWithGrandpaProvider for T
|
||||
impl<T> ChainWithGrandpa for T
|
||||
where
|
||||
T: UnderlyingChainProvider,
|
||||
T: Chain + UnderlyingChainProvider,
|
||||
T::Chain: ChainWithGrandpa,
|
||||
{
|
||||
type ChainWithGrandpa = T::Chain;
|
||||
const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str =
|
||||
<T::Chain as ChainWithGrandpa>::WITH_CHAIN_GRANDPA_PALLET_NAME;
|
||||
const MAX_AUTHORITIES_COUNT: u32 = <T::Chain as ChainWithGrandpa>::MAX_AUTHORITIES_COUNT;
|
||||
const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 =
|
||||
<T::Chain as ChainWithGrandpa>::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY;
|
||||
const MAX_HEADER_SIZE: u32 = <T::Chain as ChainWithGrandpa>::MAX_HEADER_SIZE;
|
||||
const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 =
|
||||
<T::Chain as ChainWithGrandpa>::AVERAGE_HEADER_SIZE_IN_JUSTIFICATION;
|
||||
}
|
||||
|
||||
@@ -22,14 +22,15 @@
|
||||
//! but their purpose is different.
|
||||
|
||||
use bp_header_chain::justification::{
|
||||
verify_justification, GrandpaJustification, JustificationVerificationError, PrecommitError,
|
||||
verify_justification, GrandpaJustification, JustificationVerificationContext,
|
||||
JustificationVerificationError, PrecommitError,
|
||||
};
|
||||
use bp_test_utils::{
|
||||
header_id, make_justification_for_header, signed_precommit, test_header, Account,
|
||||
JustificationGeneratorParams, ALICE, BOB, CHARLIE, DAVE, EVE, FERDIE, TEST_GRANDPA_SET_ID,
|
||||
};
|
||||
use finality_grandpa::voter_set::VoterSet;
|
||||
use sp_consensus_grandpa::{AuthorityId, AuthorityWeight};
|
||||
use sp_consensus_grandpa::{AuthorityId, AuthorityWeight, SetId};
|
||||
use sp_runtime::traits::Header as HeaderT;
|
||||
|
||||
type TestHeader = sp_runtime::testing::Header;
|
||||
@@ -81,6 +82,11 @@ fn full_voter_set() -> VoterSet<AuthorityId> {
|
||||
VoterSet::new(full_accounts_set().iter().map(|(id, w)| (AuthorityId::from(*id), *w))).unwrap()
|
||||
}
|
||||
|
||||
pub fn full_verification_context(set_id: SetId) -> JustificationVerificationContext {
|
||||
let voter_set = full_voter_set();
|
||||
JustificationVerificationContext { voter_set, authority_set_id: set_id }
|
||||
}
|
||||
|
||||
/// Get a minimal set of accounts.
|
||||
fn minimal_accounts_set() -> Vec<(Account, AuthorityWeight)> {
|
||||
// there are 5 accounts in the full set => we need 2/3 + 1 accounts, which results in 4 accounts
|
||||
@@ -115,8 +121,7 @@ fn same_result_when_precommit_target_has_lower_number_than_commit_target() {
|
||||
assert_eq!(
|
||||
verify_justification::<TestHeader>(
|
||||
header_id::<TestHeader>(1),
|
||||
TEST_GRANDPA_SET_ID,
|
||||
&full_voter_set(),
|
||||
&full_verification_context(TEST_GRANDPA_SET_ID),
|
||||
&justification,
|
||||
),
|
||||
Err(JustificationVerificationError::Precommit(PrecommitError::UnrelatedAncestryVote)),
|
||||
@@ -148,8 +153,7 @@ fn same_result_when_precommit_target_is_not_descendant_of_commit_target() {
|
||||
assert_eq!(
|
||||
verify_justification::<TestHeader>(
|
||||
header_id::<TestHeader>(1),
|
||||
TEST_GRANDPA_SET_ID,
|
||||
&full_voter_set(),
|
||||
&full_verification_context(TEST_GRANDPA_SET_ID),
|
||||
&justification,
|
||||
),
|
||||
Err(JustificationVerificationError::Precommit(PrecommitError::UnrelatedAncestryVote)),
|
||||
@@ -182,8 +186,7 @@ fn same_result_when_there_are_not_enough_cumulative_weight_to_finalize_commit_ta
|
||||
assert_eq!(
|
||||
verify_justification::<TestHeader>(
|
||||
header_id::<TestHeader>(1),
|
||||
TEST_GRANDPA_SET_ID,
|
||||
&full_voter_set(),
|
||||
&full_verification_context(TEST_GRANDPA_SET_ID),
|
||||
&justification,
|
||||
),
|
||||
Err(JustificationVerificationError::TooLowCumulativeWeight),
|
||||
@@ -220,8 +223,7 @@ fn different_result_when_justification_contains_duplicate_vote() {
|
||||
assert_eq!(
|
||||
verify_justification::<TestHeader>(
|
||||
header_id::<TestHeader>(1),
|
||||
TEST_GRANDPA_SET_ID,
|
||||
&full_voter_set(),
|
||||
&full_verification_context(TEST_GRANDPA_SET_ID),
|
||||
&justification,
|
||||
),
|
||||
Err(JustificationVerificationError::Precommit(PrecommitError::DuplicateAuthorityVote)),
|
||||
@@ -261,8 +263,7 @@ fn different_results_when_authority_equivocates_once_in_a_round() {
|
||||
assert_eq!(
|
||||
verify_justification::<TestHeader>(
|
||||
header_id::<TestHeader>(1),
|
||||
TEST_GRANDPA_SET_ID,
|
||||
&full_voter_set(),
|
||||
&full_verification_context(TEST_GRANDPA_SET_ID),
|
||||
&justification,
|
||||
),
|
||||
Err(JustificationVerificationError::Precommit(PrecommitError::DuplicateAuthorityVote)),
|
||||
@@ -314,8 +315,7 @@ fn different_results_when_authority_equivocates_twice_in_a_round() {
|
||||
assert_eq!(
|
||||
verify_justification::<TestHeader>(
|
||||
header_id::<TestHeader>(1),
|
||||
TEST_GRANDPA_SET_ID,
|
||||
&full_voter_set(),
|
||||
&full_verification_context(TEST_GRANDPA_SET_ID),
|
||||
&justification,
|
||||
),
|
||||
Err(JustificationVerificationError::Precommit(PrecommitError::DuplicateAuthorityVote)),
|
||||
@@ -353,8 +353,7 @@ fn different_results_when_there_are_more_than_enough_votes() {
|
||||
assert_eq!(
|
||||
verify_justification::<TestHeader>(
|
||||
header_id::<TestHeader>(1),
|
||||
TEST_GRANDPA_SET_ID,
|
||||
&full_voter_set(),
|
||||
&full_verification_context(TEST_GRANDPA_SET_ID),
|
||||
&justification,
|
||||
),
|
||||
Err(JustificationVerificationError::Precommit(PrecommitError::RedundantAuthorityVote)),
|
||||
@@ -394,8 +393,7 @@ fn different_results_when_there_is_a_vote_of_unknown_authority() {
|
||||
assert_eq!(
|
||||
verify_justification::<TestHeader>(
|
||||
header_id::<TestHeader>(1),
|
||||
TEST_GRANDPA_SET_ID,
|
||||
&full_voter_set(),
|
||||
&full_verification_context(TEST_GRANDPA_SET_ID),
|
||||
&justification,
|
||||
),
|
||||
Err(JustificationVerificationError::Precommit(PrecommitError::UnknownAuthorityVote)),
|
||||
|
||||
@@ -25,19 +25,18 @@ type TestHeader = sp_runtime::testing::Header;
|
||||
|
||||
#[test]
|
||||
fn duplicate_votes_are_not_considered_equivocations() {
|
||||
let voter_set = voter_set();
|
||||
let verification_context = verification_context(TEST_GRANDPA_SET_ID);
|
||||
let base_justification = make_default_justification::<TestHeader>(&test_header(1));
|
||||
|
||||
let mut collector =
|
||||
EquivocationsCollector::new(TEST_GRANDPA_SET_ID, &voter_set, &base_justification).unwrap();
|
||||
collector.parse_justification(&base_justification.clone()).unwrap();
|
||||
EquivocationsCollector::new(&verification_context, &base_justification).unwrap();
|
||||
collector.parse_justifications(&[base_justification.clone()]);
|
||||
|
||||
assert_eq!(collector.into_equivocation_proofs().len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn equivocations_are_detected_in_base_justification_redundant_votes() {
|
||||
let voter_set = voter_set();
|
||||
let mut base_justification = make_default_justification::<TestHeader>(&test_header(1));
|
||||
|
||||
let first_vote = base_justification.commit.precommits[0].clone();
|
||||
@@ -49,8 +48,9 @@ fn equivocations_are_detected_in_base_justification_redundant_votes() {
|
||||
);
|
||||
base_justification.commit.precommits.push(equivocation.clone());
|
||||
|
||||
let verification_context = verification_context(TEST_GRANDPA_SET_ID);
|
||||
let collector =
|
||||
EquivocationsCollector::new(TEST_GRANDPA_SET_ID, &voter_set, &base_justification).unwrap();
|
||||
EquivocationsCollector::new(&verification_context, &base_justification).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
collector.into_equivocation_proofs(),
|
||||
@@ -80,7 +80,6 @@ fn equivocations_are_detected_in_base_justification_redundant_votes() {
|
||||
|
||||
#[test]
|
||||
fn equivocations_are_detected_in_extra_justification_redundant_votes() {
|
||||
let voter_set = voter_set();
|
||||
let base_justification = make_default_justification::<TestHeader>(&test_header(1));
|
||||
let first_vote = base_justification.commit.precommits[0].clone();
|
||||
|
||||
@@ -93,9 +92,10 @@ fn equivocations_are_detected_in_extra_justification_redundant_votes() {
|
||||
);
|
||||
extra_justification.commit.precommits.push(equivocation.clone());
|
||||
|
||||
let verification_context = verification_context(TEST_GRANDPA_SET_ID);
|
||||
let mut collector =
|
||||
EquivocationsCollector::new(TEST_GRANDPA_SET_ID, &voter_set, &base_justification).unwrap();
|
||||
collector.parse_justification(&extra_justification).unwrap();
|
||||
EquivocationsCollector::new(&verification_context, &base_justification).unwrap();
|
||||
collector.parse_justifications(&[extra_justification]);
|
||||
|
||||
assert_eq!(
|
||||
collector.into_equivocation_proofs(),
|
||||
|
||||
@@ -30,8 +30,7 @@ fn optimizer_does_noting_with_minimal_justification() {
|
||||
let num_precommits_before = justification.commit.precommits.len();
|
||||
verify_and_optimize_justification::<TestHeader>(
|
||||
header_id::<TestHeader>(1),
|
||||
TEST_GRANDPA_SET_ID,
|
||||
&voter_set(),
|
||||
&verification_context(TEST_GRANDPA_SET_ID),
|
||||
&mut justification,
|
||||
)
|
||||
.unwrap();
|
||||
@@ -53,8 +52,7 @@ fn unknown_authority_votes_are_removed_by_optimizer() {
|
||||
let num_precommits_before = justification.commit.precommits.len();
|
||||
verify_and_optimize_justification::<TestHeader>(
|
||||
header_id::<TestHeader>(1),
|
||||
TEST_GRANDPA_SET_ID,
|
||||
&voter_set(),
|
||||
&verification_context(TEST_GRANDPA_SET_ID),
|
||||
&mut justification,
|
||||
)
|
||||
.unwrap();
|
||||
@@ -74,8 +72,7 @@ fn duplicate_authority_votes_are_removed_by_optimizer() {
|
||||
let num_precommits_before = justification.commit.precommits.len();
|
||||
verify_and_optimize_justification::<TestHeader>(
|
||||
header_id::<TestHeader>(1),
|
||||
TEST_GRANDPA_SET_ID,
|
||||
&voter_set(),
|
||||
&verification_context(TEST_GRANDPA_SET_ID),
|
||||
&mut justification,
|
||||
)
|
||||
.unwrap();
|
||||
@@ -105,8 +102,7 @@ fn invalid_authority_signatures_are_removed_by_optimizer() {
|
||||
let num_precommits_before = justification.commit.precommits.len();
|
||||
verify_and_optimize_justification::<TestHeader>(
|
||||
header_id::<TestHeader>(1),
|
||||
TEST_GRANDPA_SET_ID,
|
||||
&voter_set(),
|
||||
&verification_context(TEST_GRANDPA_SET_ID),
|
||||
&mut justification,
|
||||
)
|
||||
.unwrap();
|
||||
@@ -128,8 +124,7 @@ fn redundant_authority_votes_are_removed_by_optimizer() {
|
||||
let num_precommits_before = justification.commit.precommits.len();
|
||||
verify_and_optimize_justification::<TestHeader>(
|
||||
header_id::<TestHeader>(1),
|
||||
TEST_GRANDPA_SET_ID,
|
||||
&voter_set(),
|
||||
&verification_context(TEST_GRANDPA_SET_ID),
|
||||
&mut justification,
|
||||
)
|
||||
.unwrap();
|
||||
@@ -154,8 +149,7 @@ fn unrelated_ancestry_votes_are_removed_by_optimizer() {
|
||||
let num_precommits_before = justification.commit.precommits.len();
|
||||
verify_and_optimize_justification::<TestHeader>(
|
||||
header_id::<TestHeader>(2),
|
||||
TEST_GRANDPA_SET_ID,
|
||||
&voter_set(),
|
||||
&verification_context(TEST_GRANDPA_SET_ID),
|
||||
&mut justification,
|
||||
)
|
||||
.unwrap();
|
||||
@@ -172,8 +166,7 @@ fn redundant_votes_ancestries_are_removed_by_optimizer() {
|
||||
let num_votes_ancestries_before = justification.votes_ancestries.len();
|
||||
verify_and_optimize_justification::<TestHeader>(
|
||||
header_id::<TestHeader>(1),
|
||||
TEST_GRANDPA_SET_ID,
|
||||
&voter_set(),
|
||||
&verification_context(TEST_GRANDPA_SET_ID),
|
||||
&mut justification,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
//! Tests for Grandpa strict justification verifier code.
|
||||
|
||||
use bp_header_chain::justification::{
|
||||
required_justification_precommits, verify_justification, JustificationVerificationError,
|
||||
PrecommitError,
|
||||
required_justification_precommits, verify_justification, JustificationVerificationContext,
|
||||
JustificationVerificationError, PrecommitError,
|
||||
};
|
||||
use bp_test_utils::*;
|
||||
|
||||
@@ -40,8 +40,7 @@ fn valid_justification_accepted() {
|
||||
assert_eq!(
|
||||
verify_justification::<TestHeader>(
|
||||
header_id::<TestHeader>(1),
|
||||
TEST_GRANDPA_SET_ID,
|
||||
&voter_set(),
|
||||
&verification_context(TEST_GRANDPA_SET_ID),
|
||||
&justification,
|
||||
),
|
||||
Ok(()),
|
||||
@@ -65,8 +64,7 @@ fn valid_justification_accepted_with_single_fork() {
|
||||
assert_eq!(
|
||||
verify_justification::<TestHeader>(
|
||||
header_id::<TestHeader>(1),
|
||||
TEST_GRANDPA_SET_ID,
|
||||
&voter_set(),
|
||||
&verification_context(TEST_GRANDPA_SET_ID),
|
||||
&make_justification_for_header::<TestHeader>(params)
|
||||
),
|
||||
Ok(()),
|
||||
@@ -100,8 +98,7 @@ fn valid_justification_accepted_with_arbitrary_number_of_authorities() {
|
||||
assert_eq!(
|
||||
verify_justification::<TestHeader>(
|
||||
header_id::<TestHeader>(1),
|
||||
TEST_GRANDPA_SET_ID,
|
||||
&voter_set,
|
||||
&JustificationVerificationContext { voter_set, authority_set_id: TEST_GRANDPA_SET_ID },
|
||||
&make_justification_for_header::<TestHeader>(params)
|
||||
),
|
||||
Ok(()),
|
||||
@@ -113,8 +110,7 @@ fn justification_with_invalid_target_rejected() {
|
||||
assert_eq!(
|
||||
verify_justification::<TestHeader>(
|
||||
header_id::<TestHeader>(2),
|
||||
TEST_GRANDPA_SET_ID,
|
||||
&voter_set(),
|
||||
&verification_context(TEST_GRANDPA_SET_ID),
|
||||
&make_default_justification::<TestHeader>(&test_header(1)),
|
||||
),
|
||||
Err(JustificationVerificationError::InvalidJustificationTarget),
|
||||
@@ -129,8 +125,7 @@ fn justification_with_invalid_commit_rejected() {
|
||||
assert_eq!(
|
||||
verify_justification::<TestHeader>(
|
||||
header_id::<TestHeader>(1),
|
||||
TEST_GRANDPA_SET_ID,
|
||||
&voter_set(),
|
||||
&verification_context(TEST_GRANDPA_SET_ID),
|
||||
&justification,
|
||||
),
|
||||
Err(JustificationVerificationError::TooLowCumulativeWeight),
|
||||
@@ -146,8 +141,7 @@ fn justification_with_invalid_authority_signature_rejected() {
|
||||
assert_eq!(
|
||||
verify_justification::<TestHeader>(
|
||||
header_id::<TestHeader>(1),
|
||||
TEST_GRANDPA_SET_ID,
|
||||
&voter_set(),
|
||||
&verification_context(TEST_GRANDPA_SET_ID),
|
||||
&justification,
|
||||
),
|
||||
Err(JustificationVerificationError::Precommit(PrecommitError::InvalidAuthoritySignature)),
|
||||
@@ -162,8 +156,7 @@ fn justification_with_invalid_precommit_ancestry() {
|
||||
assert_eq!(
|
||||
verify_justification::<TestHeader>(
|
||||
header_id::<TestHeader>(1),
|
||||
TEST_GRANDPA_SET_ID,
|
||||
&voter_set(),
|
||||
&verification_context(TEST_GRANDPA_SET_ID),
|
||||
&justification,
|
||||
),
|
||||
Err(JustificationVerificationError::RedundantVotesAncestries),
|
||||
@@ -187,8 +180,7 @@ fn justification_is_invalid_if_we_dont_meet_threshold() {
|
||||
assert_eq!(
|
||||
verify_justification::<TestHeader>(
|
||||
header_id::<TestHeader>(1),
|
||||
TEST_GRANDPA_SET_ID,
|
||||
&voter_set(),
|
||||
&verification_context(TEST_GRANDPA_SET_ID),
|
||||
&make_justification_for_header::<TestHeader>(params)
|
||||
),
|
||||
Err(JustificationVerificationError::TooLowCumulativeWeight),
|
||||
|
||||
Reference in New Issue
Block a user