Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bridges: added helper function to relay single GRANDPA proof + header #4307

Merged
merged 3 commits into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 38 additions & 1 deletion bridges/relays/lib-substrate-relay/src/cli/relay_headers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@
use async_trait::async_trait;
use structopt::StructOpt;

use relay_utils::metrics::{GlobalMetrics, StandaloneMetric};
use relay_utils::{
metrics::{GlobalMetrics, StandaloneMetric},
UniqueSaturatedInto,
};

use crate::{
cli::{bridge::*, chain_schema::*, PrometheusParams},
Expand Down Expand Up @@ -48,6 +51,21 @@ pub struct RelayHeadersParams {
prometheus_params: PrometheusParams,
}

/// Single header relaying params.
#[derive(StructOpt)]
pub struct RelayHeaderParams {
#[structopt(flatten)]
source: SourceConnectionParams,
#[structopt(flatten)]
target: TargetConnectionParams,
#[structopt(flatten)]
target_sign: TargetSigningParams,
/// Number of the source chain header that we want to relay. It must have a persistent
/// storage proof at the [`Self::source`] node, otherwise the command will fail.
#[structopt(long)]
number: u128,
}

impl RelayHeadersParams {
fn headers_to_relay(&self) -> HeadersToRelay {
match (self.only_mandatory_headers, self.only_free_headers) {
Expand Down Expand Up @@ -89,4 +107,23 @@ pub trait HeadersRelayer: RelayToRelayHeadersCliBridge {
)
.await
}

/// Relay single header. No checks are made to ensure that transaction will succeed.
async fn relay_header(data: RelayHeaderParams) -> anyhow::Result<()> {
let source_client = data.source.into_client::<Self::Source>().await?;
let target_client = data.target.into_client::<Self::Target>().await?;
let target_transactions_mortality = data.target_sign.target_transactions_mortality;
let target_sign = data.target_sign.to_keypair::<Self::Target>()?;

crate::finality::relay_single_header::<Self::Finality>(
source_client,
target_client,
crate::TransactionParams {
signer: target_sign,
mortality: target_transactions_mortality,
},
data.number.unique_saturated_into(),
)
.await
}
}
37 changes: 35 additions & 2 deletions bridges/relays/lib-substrate-relay/src/finality/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ use crate::{

use async_trait::async_trait;
use bp_header_chain::justification::{GrandpaJustification, JustificationVerificationContext};
use finality_relay::{FinalityPipeline, FinalitySyncPipeline, HeadersToRelay};
use finality_relay::{
FinalityPipeline, FinalitySyncPipeline, HeadersToRelay, SourceClient, TargetClient,
};
use pallet_bridge_grandpa::{Call as BridgeGrandpaCall, Config as BridgeGrandpaConfig};
use relay_substrate_client::{
transaction_stall_timeout, AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain,
ChainWithTransactions, Client, HashOf, HeaderOf, SyncHeader,
};
use relay_utils::metrics::MetricsParams;
use relay_utils::{metrics::MetricsParams, TrackedTransactionStatus, TransactionTracker};
use sp_core::Pair;
use std::{fmt::Debug, marker::PhantomData};

Expand Down Expand Up @@ -274,3 +276,34 @@ pub async fn run<P: SubstrateFinalitySyncPipeline>(
.await
.map_err(|e| anyhow::format_err!("{}", e))
}

/// Relay single header. No checks are made to ensure that transaction will succeed.
pub async fn relay_single_header<P: SubstrateFinalitySyncPipeline>(
source_client: Client<P::SourceChain>,
target_client: Client<P::TargetChain>,
transaction_params: TransactionParams<AccountKeyPairOf<P::TargetChain>>,
header_number: BlockNumberOf<P::SourceChain>,
) -> anyhow::Result<()> {
let finality_source = SubstrateFinalitySource::<P>::new(source_client, None);
let (header, proof) = finality_source.header_and_finality_proof(header_number).await?;
let Some(proof) = proof else {
return Err(anyhow::format_err!(
"Unable to submit {} header #{} to {}: no finality proof",
P::SourceChain::NAME,
header_number,
P::TargetChain::NAME,
));
};

let finality_target = SubstrateFinalityTarget::<P>::new(target_client, transaction_params);
let tx_tracker = finality_target.submit_finality_proof(header, proof, false).await?;
match tx_tracker.wait().await {
TrackedTransactionStatus::Finalized(_) => Ok(()),
TrackedTransactionStatus::Lost => Err(anyhow::format_err!(
"Transaction with {} header #{} is considered lost at {}",
P::SourceChain::NAME,
header_number,
P::TargetChain::NAME,
)),
}
}
Loading