mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 09:51:02 +00:00
Finality loop: get block justification and authorities change by consensus engine ID (#1619)
* SignedBlock: get justification by consensus engine id * Define ConsensusLogReader Making the check for authority changes more generic * cod review changes
This commit is contained in:
committed by
Bastian Köcher
parent
f58e076ca2
commit
01538bc5fa
@@ -19,9 +19,8 @@
|
||||
use crate::error::Error;
|
||||
use async_trait::async_trait;
|
||||
use bp_header_chain::{
|
||||
find_grandpa_authorities_scheduled_change,
|
||||
justification::{verify_justification, GrandpaJustification},
|
||||
FinalityProof,
|
||||
ConsensusLogReader, FinalityProof, GrandpaConsensusLogReader,
|
||||
};
|
||||
use bp_runtime::{BasicOperatingMode, OperatingMode};
|
||||
use codec::{Decode, Encode};
|
||||
@@ -32,7 +31,7 @@ use relay_substrate_client::{
|
||||
Subscription, SubstrateFinalityClient, SubstrateGrandpaFinalityClient,
|
||||
};
|
||||
use sp_core::{storage::StorageKey, Bytes};
|
||||
use sp_finality_grandpa::AuthorityList as GrandpaAuthoritiesSet;
|
||||
use sp_finality_grandpa::{AuthorityList as GrandpaAuthoritiesSet, GRANDPA_ENGINE_ID};
|
||||
use sp_runtime::{traits::Header, ConsensusEngineId};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
@@ -41,6 +40,8 @@ use std::marker::PhantomData;
|
||||
pub trait Engine<C: Chain>: Send {
|
||||
/// Unique consensus engine identifier.
|
||||
const ID: ConsensusEngineId;
|
||||
/// A reader that can extract the consensus log from the header digest and interpret it.
|
||||
type ConsensusLogReader: ConsensusLogReader;
|
||||
/// Type of Finality RPC client used by this engine.
|
||||
type FinalityClient: SubstrateFinalityClient<C>;
|
||||
/// Type of finality proofs, used by consensus engine.
|
||||
@@ -50,22 +51,11 @@ pub trait Engine<C: Chain>: Send {
|
||||
/// Type of bridge pallet operating mode.
|
||||
type OperatingMode: OperatingMode + 'static;
|
||||
|
||||
/// Returns storage key at the bridged (target) chain that corresponds to the variable
|
||||
/// that holds the operating mode of the pallet.
|
||||
fn pallet_operating_mode_key() -> StorageKey;
|
||||
/// Returns storage at the bridged (target) chain that corresponds to some value that is
|
||||
/// missing from the storage until bridge pallet is initialized.
|
||||
///
|
||||
/// Note that we don't care about type of the value - just if it present or not.
|
||||
fn is_initialized_key() -> StorageKey;
|
||||
/// A method to subscribe to encoded finality proofs, given source client.
|
||||
async fn finality_proofs(client: &Client<C>) -> Result<Subscription<Bytes>, SubstrateError> {
|
||||
client.subscribe_finality_justifications::<Self::FinalityClient>().await
|
||||
}
|
||||
/// Prepare initialization data for the finality bridge pallet.
|
||||
async fn prepare_initialization_data(
|
||||
client: Client<C>,
|
||||
) -> Result<Self::InitializationData, Error<HashOf<C>, BlockNumberOf<C>>>;
|
||||
|
||||
/// Returns `Ok(true)` if finality pallet at the bridged chain has already been initialized.
|
||||
async fn is_initialized<TargetChain: Chain>(
|
||||
@@ -77,6 +67,10 @@ pub trait Engine<C: Chain>: Send {
|
||||
.is_some())
|
||||
}
|
||||
|
||||
/// Returns storage key at the bridged (target) chain that corresponds to the variable
|
||||
/// that holds the operating mode of the pallet.
|
||||
fn pallet_operating_mode_key() -> StorageKey;
|
||||
|
||||
/// Returns `Ok(true)` if finality pallet at the bridged chain is halted.
|
||||
async fn is_halted<TargetChain: Chain>(
|
||||
target_client: &Client<TargetChain>,
|
||||
@@ -87,6 +81,16 @@ pub trait Engine<C: Chain>: Send {
|
||||
.map(|operating_mode| operating_mode.is_halted())
|
||||
.unwrap_or(false))
|
||||
}
|
||||
|
||||
/// A method to subscribe to encoded finality proofs, given source client.
|
||||
async fn finality_proofs(client: &Client<C>) -> Result<Subscription<Bytes>, SubstrateError> {
|
||||
client.subscribe_finality_justifications::<Self::FinalityClient>().await
|
||||
}
|
||||
|
||||
/// Prepare initialization data for the finality bridge pallet.
|
||||
async fn prepare_initialization_data(
|
||||
client: Client<C>,
|
||||
) -> Result<Self::InitializationData, Error<HashOf<C>, BlockNumberOf<C>>>;
|
||||
}
|
||||
|
||||
/// GRANDPA finality engine.
|
||||
@@ -120,20 +124,21 @@ impl<C: ChainWithGrandpa> Grandpa<C> {
|
||||
|
||||
#[async_trait]
|
||||
impl<C: ChainWithGrandpa> Engine<C> for Grandpa<C> {
|
||||
const ID: ConsensusEngineId = sp_finality_grandpa::GRANDPA_ENGINE_ID;
|
||||
const ID: ConsensusEngineId = GRANDPA_ENGINE_ID;
|
||||
type ConsensusLogReader = GrandpaConsensusLogReader<<C::Header as Header>::Number>;
|
||||
type FinalityClient = SubstrateGrandpaFinalityClient;
|
||||
type FinalityProof = GrandpaJustification<HeaderOf<C>>;
|
||||
type InitializationData = bp_header_chain::InitializationData<C::Header>;
|
||||
type OperatingMode = BasicOperatingMode;
|
||||
|
||||
fn pallet_operating_mode_key() -> StorageKey {
|
||||
bp_header_chain::storage_keys::pallet_operating_mode_key(C::WITH_CHAIN_GRANDPA_PALLET_NAME)
|
||||
}
|
||||
|
||||
fn is_initialized_key() -> StorageKey {
|
||||
bp_header_chain::storage_keys::best_finalized_key(C::WITH_CHAIN_GRANDPA_PALLET_NAME)
|
||||
}
|
||||
|
||||
fn pallet_operating_mode_key() -> StorageKey {
|
||||
bp_header_chain::storage_keys::pallet_operating_mode_key(C::WITH_CHAIN_GRANDPA_PALLET_NAME)
|
||||
}
|
||||
|
||||
/// Prepare initialization data for the GRANDPA verifier pallet.
|
||||
async fn prepare_initialization_data(
|
||||
source_client: Client<C>,
|
||||
@@ -183,11 +188,14 @@ impl<C: ChainWithGrandpa> Engine<C> for Grandpa<C> {
|
||||
// If initial header changes the GRANDPA authorities set, then we need previous authorities
|
||||
// to verify justification.
|
||||
let mut authorities_for_verification = initial_authorities_set.clone();
|
||||
let scheduled_change = find_grandpa_authorities_scheduled_change(&initial_header);
|
||||
let scheduled_change =
|
||||
GrandpaConsensusLogReader::<BlockNumberOf<C>>::find_authorities_change(
|
||||
initial_header.digest(),
|
||||
);
|
||||
assert!(
|
||||
scheduled_change.as_ref().map(|c| c.delay.is_zero()).unwrap_or(true),
|
||||
"GRANDPA authorities change at {} scheduled to happen in {:?} blocks. We expect\
|
||||
regular hange to have zero delay",
|
||||
regular change to have zero delay",
|
||||
initial_header_hash,
|
||||
scheduled_change.as_ref().map(|c| c.delay),
|
||||
);
|
||||
|
||||
@@ -87,7 +87,8 @@ impl<P: SubstrateFinalitySyncPipeline> FinalitySyncPipeline for FinalitySyncPipe
|
||||
|
||||
type Hash = HashOf<P::SourceChain>;
|
||||
type Number = BlockNumberOf<P::SourceChain>;
|
||||
type Header = relay_substrate_client::SyncHeader<HeaderOf<P::SourceChain>>;
|
||||
type ConsensusLogReader = <P::FinalityEngine as Engine<P::SourceChain>>::ConsensusLogReader;
|
||||
type Header = SyncHeader<HeaderOf<P::SourceChain>>;
|
||||
type FinalityProof = SubstrateFinalityProof<P>;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,15 +33,8 @@ use std::pin::Pin;
|
||||
pub type RequiredHeaderNumberRef<C> = Arc<Mutex<<C as bp_runtime::Chain>::BlockNumber>>;
|
||||
|
||||
/// Substrate finality proofs stream.
|
||||
pub type SubstrateFinalityProofsStream<P> = Pin<
|
||||
Box<
|
||||
dyn Stream<
|
||||
Item = <<P as SubstrateFinalitySyncPipeline>::FinalityEngine as Engine<
|
||||
<P as SubstrateFinalitySyncPipeline>::SourceChain,
|
||||
>>::FinalityProof,
|
||||
> + Send,
|
||||
>,
|
||||
>;
|
||||
pub type SubstrateFinalityProofsStream<P> =
|
||||
Pin<Box<dyn Stream<Item = SubstrateFinalityProof<P>> + Send>>;
|
||||
|
||||
/// Substrate finality proof. Specific to the used `FinalityEngine`.
|
||||
pub type SubstrateFinalityProof<P> =
|
||||
@@ -130,7 +123,7 @@ impl<P: SubstrateFinalitySyncPipeline> SourceClient<FinalitySyncPipelineAdapter<
|
||||
let signed_block = self.client.get_block(Some(header_hash)).await?;
|
||||
|
||||
let justification = signed_block
|
||||
.justification()
|
||||
.justification(P::FinalityEngine::ID)
|
||||
.map(|raw_justification| {
|
||||
SubstrateFinalityProof::<P>::decode(&mut raw_justification.as_slice())
|
||||
})
|
||||
|
||||
@@ -18,13 +18,14 @@
|
||||
|
||||
use async_std::sync::{Arc, Mutex};
|
||||
use async_trait::async_trait;
|
||||
use bp_header_chain::ConsensusLogReader;
|
||||
use futures::{select, FutureExt};
|
||||
use num_traits::{One, Zero};
|
||||
use sp_runtime::traits::Header;
|
||||
|
||||
use finality_relay::{FinalitySyncParams, SourceHeader, TargetClient as FinalityTargetClient};
|
||||
use finality_relay::{FinalitySyncParams, TargetClient as FinalityTargetClient};
|
||||
use relay_substrate_client::{
|
||||
AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, HeaderOf, SyncHeader,
|
||||
TransactionSignScheme,
|
||||
AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, TransactionSignScheme,
|
||||
};
|
||||
use relay_utils::{
|
||||
metrics::MetricsParams, relay_loop::Client as RelayClient, FailedClient, MaybeConnectionError,
|
||||
@@ -33,6 +34,7 @@ use relay_utils::{
|
||||
|
||||
use crate::{
|
||||
finality::{
|
||||
engine::Engine,
|
||||
source::{RequiredHeaderNumberRef, SubstrateFinalitySource},
|
||||
target::SubstrateFinalityTarget,
|
||||
SubstrateFinalitySyncPipeline, RECENT_FINALITY_PROOFS_LIMIT,
|
||||
@@ -416,9 +418,10 @@ async fn find_mandatory_header_in_range<P: SubstrateFinalitySyncPipeline>(
|
||||
) -> Result<Option<BlockNumberOf<P::SourceChain>>, relay_substrate_client::Error> {
|
||||
let mut current = range.0;
|
||||
while current <= range.1 {
|
||||
let header: SyncHeader<HeaderOf<P::SourceChain>> =
|
||||
finality_source.client().header_by_number(current).await?.into();
|
||||
if header.is_mandatory() {
|
||||
let header = finality_source.client().header_by_number(current).await?;
|
||||
if <P::FinalityEngine as Engine<P::SourceChain>>::ConsensusLogReader::schedules_authorities_change(
|
||||
header.digest(),
|
||||
) {
|
||||
return Ok(Some(current))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user