mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 23:21:02 +00:00
Refactor finality relay helpers (#1220)
* refactor finality relay helper definitions * add missing doc * removed commented code * fmt * disable rustfmt for macro * move best_finalized method const to relay chain def
This commit is contained in:
committed by
Bastian Köcher
parent
f84590817b
commit
e675b13042
@@ -14,18 +14,20 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Substrate-to-Substrate headers sync entrypoint.
|
||||
//! Types and functions intended to ease adding of new Substrate -> Substrate
|
||||
//! finality proofs synchronization pipelines.
|
||||
|
||||
use crate::{finality_target::SubstrateFinalityTarget, STALL_TIMEOUT};
|
||||
use crate::{finality_source::SubstrateFinalitySource, finality_target::SubstrateFinalityTarget};
|
||||
|
||||
use bp_header_chain::justification::GrandpaJustification;
|
||||
use bp_runtime::AccountIdOf;
|
||||
use finality_relay::{FinalitySyncParams, FinalitySyncPipeline};
|
||||
use finality_relay::FinalitySyncPipeline;
|
||||
use pallet_bridge_grandpa::{Call as BridgeGrandpaCall, Config as BridgeGrandpaConfig};
|
||||
use relay_substrate_client::{
|
||||
finality_source::FinalitySource, BlockNumberOf, Chain, Client, HashOf, SyncHeader,
|
||||
transaction_stall_timeout, AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, Client,
|
||||
HashOf, HeaderOf, SyncHeader, TransactionSignScheme,
|
||||
};
|
||||
use relay_utils::{metrics::MetricsParams, BlockNumberBase};
|
||||
use sp_core::Bytes;
|
||||
use relay_utils::metrics::MetricsParams;
|
||||
use sp_core::Pair;
|
||||
use std::{fmt::Debug, marker::PhantomData};
|
||||
|
||||
/// Default limit of recent finality proofs.
|
||||
@@ -34,130 +36,152 @@ use std::{fmt::Debug, marker::PhantomData};
|
||||
/// Substrate+GRANDPA based chains (good to know).
|
||||
pub(crate) const RECENT_FINALITY_PROOFS_LIMIT: usize = 4096;
|
||||
|
||||
/// Headers sync pipeline for Substrate <-> Substrate relays.
|
||||
/// Submit-finality-proofs transaction creation parameters.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct TransactionParams<TS> {
|
||||
/// Transactions author.
|
||||
pub transactions_signer: TS,
|
||||
/// Transactions mortality.
|
||||
pub transactions_mortality: Option<u32>,
|
||||
}
|
||||
|
||||
/// Substrate -> Substrate finality proofs synchronization pipeline.
|
||||
pub trait SubstrateFinalitySyncPipeline: 'static + Clone + Debug + Send + Sync {
|
||||
/// Pipeline for syncing finalized Source chain headers to Target chain.
|
||||
type FinalitySyncPipeline: FinalitySyncPipeline;
|
||||
|
||||
/// Name of the runtime method that returns id of best finalized source header at target chain.
|
||||
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str;
|
||||
|
||||
/// Chain with GRANDPA bridge pallet.
|
||||
/// Headers of this chain are submitted to the `TargetChain`.
|
||||
type SourceChain: Chain;
|
||||
/// Headers of the `SourceChain` are submitted to this chain.
|
||||
type TargetChain: Chain;
|
||||
|
||||
/// Customize metrics exposed by headers sync loop.
|
||||
fn customize_metrics(params: MetricsParams) -> anyhow::Result<MetricsParams> {
|
||||
Ok(params)
|
||||
}
|
||||
/// How submit finality proof call is built?
|
||||
type SubmitFinalityProofCallBuilder: SubmitFinalityProofCallBuilder<Self>;
|
||||
/// Scheme used to sign target chain transactions.
|
||||
type TransactionSignScheme: TransactionSignScheme;
|
||||
|
||||
/// Start finality relay guards.
|
||||
///
|
||||
/// Different finality bridges may have different set of guards - e.g. on ephemeral chains we
|
||||
/// don't need a version guards, on test chains we don't care that much about relayer account
|
||||
/// balance, ... So the implementation is left to the specific bridges.
|
||||
fn start_relay_guards(&self) {}
|
||||
|
||||
/// Returns id of account that we're using to sign transactions at target chain.
|
||||
fn transactions_author(&self) -> AccountIdOf<Self::TargetChain>;
|
||||
|
||||
/// Make submit header transaction.
|
||||
fn make_submit_finality_proof_transaction(
|
||||
&self,
|
||||
era: bp_runtime::TransactionEraOf<Self::TargetChain>,
|
||||
transaction_nonce: bp_runtime::IndexOf<Self::TargetChain>,
|
||||
header: <Self::FinalitySyncPipeline as FinalitySyncPipeline>::Header,
|
||||
proof: <Self::FinalitySyncPipeline as FinalitySyncPipeline>::FinalityProof,
|
||||
) -> Bytes;
|
||||
}
|
||||
|
||||
/// Substrate-to-Substrate finality proof pipeline.
|
||||
#[derive(Clone)]
|
||||
pub struct SubstrateFinalityToSubstrate<SourceChain, TargetChain: Chain, TargetSign> {
|
||||
/// Client for the target chain.
|
||||
pub target_client: Client<TargetChain>,
|
||||
/// Data required to sign target chain transactions.
|
||||
pub target_sign: TargetSign,
|
||||
/// Unused generic arguments dump.
|
||||
_marker: PhantomData<SourceChain>,
|
||||
}
|
||||
|
||||
impl<SourceChain, TargetChain: Chain, TargetSign> Debug
|
||||
for SubstrateFinalityToSubstrate<SourceChain, TargetChain, TargetSign>
|
||||
{
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
f.debug_struct("SubstrateFinalityToSubstrate")
|
||||
.field("target_client", &self.target_client)
|
||||
.finish()
|
||||
/// Add relay guards if required.
|
||||
fn start_relay_guards(
|
||||
_target_client: &Client<Self::TargetChain>,
|
||||
_transaction_params: &TransactionParams<AccountKeyPairOf<Self::TransactionSignScheme>>,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
impl<SourceChain, TargetChain: Chain, TargetSign>
|
||||
SubstrateFinalityToSubstrate<SourceChain, TargetChain, TargetSign>
|
||||
{
|
||||
/// Create new Substrate-to-Substrate headers pipeline.
|
||||
pub fn new(target_client: Client<TargetChain>, target_sign: TargetSign) -> Self {
|
||||
SubstrateFinalityToSubstrate { target_client, target_sign, _marker: Default::default() }
|
||||
}
|
||||
/// Adapter that allows all `SubstrateFinalitySyncPipeline` to act as `FinalitySyncPipeline`.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct FinalitySyncPipelineAdapter<P: SubstrateFinalitySyncPipeline> {
|
||||
_phantom: PhantomData<P>,
|
||||
}
|
||||
|
||||
impl<SourceChain, TargetChain, TargetSign> FinalitySyncPipeline
|
||||
for SubstrateFinalityToSubstrate<SourceChain, TargetChain, TargetSign>
|
||||
impl<P: SubstrateFinalitySyncPipeline> FinalitySyncPipeline for FinalitySyncPipelineAdapter<P> {
|
||||
const SOURCE_NAME: &'static str = P::SourceChain::NAME;
|
||||
const TARGET_NAME: &'static str = P::TargetChain::NAME;
|
||||
|
||||
type Hash = HashOf<P::SourceChain>;
|
||||
type Number = BlockNumberOf<P::SourceChain>;
|
||||
type Header = relay_substrate_client::SyncHeader<HeaderOf<P::SourceChain>>;
|
||||
type FinalityProof = GrandpaJustification<HeaderOf<P::SourceChain>>;
|
||||
}
|
||||
|
||||
/// Different ways of building `submit_finality_proof` calls.
|
||||
pub trait SubmitFinalityProofCallBuilder<P: SubstrateFinalitySyncPipeline> {
|
||||
/// Given source chain header and its finality proofs, build call of `submit_finality_proof`
|
||||
/// function of bridge GRANDPA module at the target chain.
|
||||
fn build_submit_finality_proof_call(
|
||||
header: SyncHeader<HeaderOf<P::SourceChain>>,
|
||||
proof: GrandpaJustification<HeaderOf<P::SourceChain>>,
|
||||
) -> CallOf<P::TargetChain>;
|
||||
}
|
||||
|
||||
/// Building `submit_finality_proof` call when you have direct access to the target
|
||||
/// chain runtime.
|
||||
pub struct DirectSubmitFinalityProofCallBuilder<P, R, I> {
|
||||
_phantom: PhantomData<(P, R, I)>,
|
||||
}
|
||||
|
||||
impl<P, R, I> SubmitFinalityProofCallBuilder<P> for DirectSubmitFinalityProofCallBuilder<P, R, I>
|
||||
where
|
||||
SourceChain: Clone + Chain + Debug,
|
||||
BlockNumberOf<SourceChain>: BlockNumberBase,
|
||||
TargetChain: Clone + Chain + Debug,
|
||||
TargetSign: 'static + Clone + Send + Sync,
|
||||
P: SubstrateFinalitySyncPipeline,
|
||||
R: BridgeGrandpaConfig<I>,
|
||||
I: 'static,
|
||||
R::BridgedChain: bp_runtime::Chain<Header = HeaderOf<P::SourceChain>>,
|
||||
CallOf<P::TargetChain>: From<BridgeGrandpaCall<R, I>>,
|
||||
{
|
||||
const SOURCE_NAME: &'static str = SourceChain::NAME;
|
||||
const TARGET_NAME: &'static str = TargetChain::NAME;
|
||||
|
||||
type Hash = HashOf<SourceChain>;
|
||||
type Number = BlockNumberOf<SourceChain>;
|
||||
type Header = SyncHeader<SourceChain::Header>;
|
||||
type FinalityProof = GrandpaJustification<SourceChain::Header>;
|
||||
fn build_submit_finality_proof_call(
|
||||
header: SyncHeader<HeaderOf<P::SourceChain>>,
|
||||
proof: GrandpaJustification<HeaderOf<P::SourceChain>>,
|
||||
) -> CallOf<P::TargetChain> {
|
||||
BridgeGrandpaCall::<R, I>::submit_finality_proof {
|
||||
finality_target: Box::new(header.into_inner()),
|
||||
justification: proof,
|
||||
}
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
/// Run Substrate-to-Substrate finality sync.
|
||||
pub async fn run<SourceChain, TargetChain, P>(
|
||||
pipeline: P,
|
||||
source_client: Client<SourceChain>,
|
||||
target_client: Client<TargetChain>,
|
||||
/// Macro that generates `SubmitFinalityProofCallBuilder` implementation for the case when
|
||||
/// you only have an access to the mocked version of target chain runtime. In this case you
|
||||
/// should provide "name" of the call variant for the bridge GRANDPA calls and the "name" of
|
||||
/// the variant for the `submit_finality_proof` call within that first option.
|
||||
#[rustfmt::skip]
|
||||
#[macro_export]
|
||||
macro_rules! generate_mocked_submit_finality_proof_call_builder {
|
||||
($pipeline:ident, $mocked_builder:ident, $bridge_grandpa:path, $submit_finality_proof:path) => {
|
||||
pub struct $mocked_builder;
|
||||
|
||||
impl $crate::finality_pipeline::SubmitFinalityProofCallBuilder<$pipeline>
|
||||
for $mocked_builder
|
||||
{
|
||||
fn build_submit_finality_proof_call(
|
||||
header: relay_substrate_client::SyncHeader<
|
||||
relay_substrate_client::HeaderOf<
|
||||
<$pipeline as $crate::finality_pipeline::SubstrateFinalitySyncPipeline>::SourceChain
|
||||
>
|
||||
>,
|
||||
proof: bp_header_chain::justification::GrandpaJustification<
|
||||
relay_substrate_client::HeaderOf<
|
||||
<$pipeline as $crate::finality_pipeline::SubstrateFinalitySyncPipeline>::SourceChain
|
||||
>
|
||||
>,
|
||||
) -> relay_substrate_client::CallOf<
|
||||
<$pipeline as $crate::finality_pipeline::SubstrateFinalitySyncPipeline>::TargetChain
|
||||
> {
|
||||
$bridge_grandpa($submit_finality_proof(Box::new(header.into_inner()), proof))
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Run Substrate-to-Substrate finality sync loop.
|
||||
pub async fn run<P: SubstrateFinalitySyncPipeline>(
|
||||
source_client: Client<P::SourceChain>,
|
||||
target_client: Client<P::TargetChain>,
|
||||
only_mandatory_headers: bool,
|
||||
transactions_mortality: Option<u32>,
|
||||
transaction_params: TransactionParams<AccountKeyPairOf<P::TransactionSignScheme>>,
|
||||
metrics_params: MetricsParams,
|
||||
) -> anyhow::Result<()>
|
||||
where
|
||||
P: SubstrateFinalitySyncPipeline<TargetChain = TargetChain>,
|
||||
P::FinalitySyncPipeline: FinalitySyncPipeline<
|
||||
Hash = HashOf<SourceChain>,
|
||||
Number = BlockNumberOf<SourceChain>,
|
||||
Header = SyncHeader<SourceChain::Header>,
|
||||
FinalityProof = GrandpaJustification<SourceChain::Header>,
|
||||
>,
|
||||
SourceChain: Clone + Chain,
|
||||
BlockNumberOf<SourceChain>: BlockNumberBase,
|
||||
TargetChain: Clone + Chain,
|
||||
AccountIdOf<P::TargetChain>: From<<AccountKeyPairOf<P::TransactionSignScheme> as Pair>::Public>,
|
||||
P::TransactionSignScheme: TransactionSignScheme<Chain = P::TargetChain>,
|
||||
{
|
||||
log::info!(
|
||||
target: "bridge",
|
||||
"Starting {} -> {} finality proof relay",
|
||||
SourceChain::NAME,
|
||||
TargetChain::NAME,
|
||||
P::SourceChain::NAME,
|
||||
P::TargetChain::NAME,
|
||||
);
|
||||
|
||||
finality_relay::run(
|
||||
FinalitySource::new(source_client, None),
|
||||
SubstrateFinalityTarget::new(target_client, pipeline, transactions_mortality),
|
||||
FinalitySyncParams {
|
||||
SubstrateFinalitySource::<P>::new(source_client, None),
|
||||
SubstrateFinalityTarget::<P>::new(target_client, transaction_params.clone()),
|
||||
finality_relay::FinalitySyncParams {
|
||||
tick: std::cmp::max(
|
||||
SourceChain::AVERAGE_BLOCK_INTERVAL,
|
||||
TargetChain::AVERAGE_BLOCK_INTERVAL,
|
||||
P::SourceChain::AVERAGE_BLOCK_INTERVAL,
|
||||
P::TargetChain::AVERAGE_BLOCK_INTERVAL,
|
||||
),
|
||||
recent_finality_proofs_limit: RECENT_FINALITY_PROOFS_LIMIT,
|
||||
stall_timeout: relay_substrate_client::transaction_stall_timeout(
|
||||
transactions_mortality,
|
||||
TargetChain::AVERAGE_BLOCK_INTERVAL,
|
||||
STALL_TIMEOUT,
|
||||
stall_timeout: transaction_stall_timeout(
|
||||
transaction_params.transactions_mortality,
|
||||
P::TargetChain::AVERAGE_BLOCK_INTERVAL,
|
||||
crate::STALL_TIMEOUT,
|
||||
),
|
||||
only_mandatory_headers,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user