Skip to content

Commit

Permalink
Bridge: add subcommand to relay messages delivery confirmation (parit…
Browse files Browse the repository at this point in the history
…ytech#4453)

related to
paritytech/parity-bridges-common#2962
on top of paritytech#4383

Example:
```sh
RUST_LOG=runtime=trace,rpc=trace,bridge=trace \
        ./target/release/substrate-relay relay-messages-delivery-confirmation bridge-hub-rococo-to-bridge-hub-westend \
        --source-host localhost \
        --source-port 8943 \
        --source-version-mode Auto \
        --source-signer //Eve \
        --source-transactions-mortality 4 \
        --target-host localhost \
        --target-port 8945 \
        --target-version-mode Auto \
        --lane 00000002 \
        --at-target-block 49
```
  • Loading branch information
svyatonik authored and hitchhooker committed Jun 5, 2024
1 parent e629d5a commit a0fc9c4
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 9 deletions.
51 changes: 51 additions & 0 deletions bridges/relays/lib-substrate-relay/src/cli/relay_messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,24 @@ pub struct RelayMessagesRangeParams {
target_sign: TargetSigningParams,
}

/// Messages delivery confirmation relaying params.
#[derive(StructOpt)]
pub struct RelayMessagesDeliveryConfirmationParams {
/// Number of the target chain header that we will use to prepare a messages
/// delivery proof. This header must be previously proved to the source chain.
#[structopt(long)]
at_target_block: u128,
/// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`.
#[structopt(long, default_value = "00000000")]
lane: HexLaneId,
#[structopt(flatten)]
source: SourceConnectionParams,
#[structopt(flatten)]
source_sign: SourceSigningParams,
#[structopt(flatten)]
target: TargetConnectionParams,
}

/// Trait used for relaying messages between 2 chains.
#[async_trait]
pub trait MessagesRelayer: MessagesCliBridge
Expand Down Expand Up @@ -154,4 +172,37 @@ where
)
.await
}

/// Relay a messages delivery confirmation.
async fn relay_messages_delivery_confirmation(
data: RelayMessagesDeliveryConfirmationParams,
) -> anyhow::Result<()> {
let source_client = data.source.into_client::<Self::Source>().await?;
let target_client = data.target.into_client::<Self::Target>().await?;
let source_sign = data.source_sign.to_keypair::<Self::Source>()?;
let source_transactions_mortality = data.source_sign.transactions_mortality()?;

let at_target_block = target_client
.header_by_number(data.at_target_block.unique_saturated_into())
.await
.map_err(|e| {
log::trace!(
target: "bridge",
"Failed to read {} header with number {}: {e:?}",
Self::Target::NAME,
data.at_target_block,
);
anyhow::format_err!("The command has failed")
})?
.id();

crate::messages_lane::relay_messages_delivery_confirmation::<Self::MessagesLane>(
source_client,
target_client,
TransactionParams { signer: source_sign, mortality: source_transactions_mortality },
at_target_block,
data.lane.into(),
)
.await
}
}
42 changes: 40 additions & 2 deletions bridges/relays/lib-substrate-relay/src/messages_lane.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ where
source_client,
params.lane_id,
relayer_id_at_source,
params.target_transaction_params,
Some(params.target_transaction_params),
params.source_to_target_headers_relay,
),
{
Expand Down Expand Up @@ -307,7 +307,7 @@ where
source_client,
lane_id,
relayer_id_at_source,
target_transaction_params,
Some(target_transaction_params),
None,
),
at_source_block,
Expand All @@ -318,6 +318,44 @@ where
.map_err(|_| anyhow::format_err!("The command has failed"))
}

/// Relay messages delivery confirmation of Substrate-to-Substrate messages.
/// No checks are made to ensure that transaction will succeed.
pub async fn relay_messages_delivery_confirmation<P: SubstrateMessageLane>(
source_client: Client<P::SourceChain>,
target_client: Client<P::TargetChain>,
source_transaction_params: TransactionParams<AccountKeyPairOf<P::SourceChain>>,
at_target_block: HeaderIdOf<P::TargetChain>,
lane_id: LaneId,
) -> anyhow::Result<()>
where
AccountIdOf<P::SourceChain>: From<<AccountKeyPairOf<P::SourceChain> as Pair>::Public>,
AccountIdOf<P::TargetChain>: From<<AccountKeyPairOf<P::TargetChain> as Pair>::Public>,
BalanceOf<P::SourceChain>: TryFrom<BalanceOf<P::TargetChain>>,
{
let relayer_id_at_source: AccountIdOf<P::SourceChain> =
source_transaction_params.signer.public().into();
messages_relay::relay_messages_delivery_confirmation(
SubstrateMessagesSource::<P>::new(
source_client.clone(),
target_client.clone(),
lane_id,
source_transaction_params,
None,
),
SubstrateMessagesTarget::<P>::new(
target_client,
source_client,
lane_id,
relayer_id_at_source,
None,
None,
),
at_target_block,
)
.await
.map_err(|_| anyhow::format_err!("The command has failed"))
}

/// Different ways of building `receive_messages_proof` calls.
pub trait ReceiveMessagesProofCallBuilder<P: SubstrateMessageLane> {
/// Given messages proof, build call of `receive_messages_proof` function of bridge
Expand Down
19 changes: 13 additions & 6 deletions bridges/relays/lib-substrate-relay/src/messages_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ use messages_relay::{
message_lane_loop::{NoncesSubmitArtifacts, TargetClient, TargetClientState},
};
use relay_substrate_client::{
AccountIdOf, AccountKeyPairOf, BalanceOf, CallOf, Client, Error as SubstrateError, HashOf,
TransactionEra, TransactionTracker, UnsignedTransaction,
AccountIdOf, AccountKeyPairOf, BalanceOf, CallOf, Chain, Client, Error as SubstrateError,
HashOf, TransactionEra, TransactionTracker, UnsignedTransaction,
};
use relay_utils::relay_loop::Client as RelayClient;
use sp_core::Pair;
Expand All @@ -57,7 +57,7 @@ pub struct SubstrateMessagesTarget<P: SubstrateMessageLane> {
source_client: Client<P::SourceChain>,
lane_id: LaneId,
relayer_id_at_source: AccountIdOf<P::SourceChain>,
transaction_params: TransactionParams<AccountKeyPairOf<P::TargetChain>>,
transaction_params: Option<TransactionParams<AccountKeyPairOf<P::TargetChain>>>,
source_to_target_headers_relay: Option<Arc<dyn OnDemandRelay<P::SourceChain, P::TargetChain>>>,
}

Expand All @@ -68,7 +68,7 @@ impl<P: SubstrateMessageLane> SubstrateMessagesTarget<P> {
source_client: Client<P::SourceChain>,
lane_id: LaneId,
relayer_id_at_source: AccountIdOf<P::SourceChain>,
transaction_params: TransactionParams<AccountKeyPairOf<P::TargetChain>>,
transaction_params: Option<TransactionParams<AccountKeyPairOf<P::TargetChain>>>,
source_to_target_headers_relay: Option<
Arc<dyn OnDemandRelay<P::SourceChain, P::TargetChain>>,
>,
Expand Down Expand Up @@ -249,11 +249,18 @@ where
None => messages_proof_call,
};

let transaction_params = self.transaction_params.clone();
let transaction_params = self.transaction_params.clone().map(Ok).unwrap_or_else(|| {
// this error shall never happen in practice, so it not deserves
// a separate error variant
Err(SubstrateError::Custom(format!(
"Cannot sign transaction of {} chain",
P::TargetChain::NAME,
)))
})?;
let tx_tracker = self
.target_client
.submit_and_watch_signed_extrinsic(
&self.transaction_params.signer,
&transaction_params.signer,
move |best_block_id, transaction_nonce| {
Ok(UnsignedTransaction::new(final_call.into(), transaction_nonce)
.era(TransactionEra::new(best_block_id, transaction_params.mortality)))
Expand Down
1 change: 1 addition & 0 deletions bridges/relays/messages/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ mod message_race_receiving;
mod message_race_strategy;

pub use message_race_delivery::relay_messages_range;
pub use message_race_receiving::relay_messages_delivery_confirmation;
39 changes: 38 additions & 1 deletion bridges/relays/messages/src/message_race_receiving.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use crate::{
use async_trait::async_trait;
use bp_messages::MessageNonce;
use futures::stream::FusedStream;
use relay_utils::FailedClient;
use relay_utils::{FailedClient, TrackedTransactionStatus, TransactionTracker};
use std::{marker::PhantomData, ops::RangeInclusive};

/// Message receiving confirmations delivery strategy.
Expand Down Expand Up @@ -69,6 +69,43 @@ pub async fn run<P: MessageLane>(
.await
}

/// Relay messages delivery confirmation.
pub async fn relay_messages_delivery_confirmation<P: MessageLane>(
source_client: impl MessageLaneSourceClient<P>,
target_client: impl MessageLaneTargetClient<P>,
at: TargetHeaderIdOf<P>,
) -> Result<(), ()> {
// prepare messages delivery proof
let (at, proof) = target_client.prove_messages_receiving(at.clone()).await.map_err(|e| {
log::error!(
target: "bridge",
"Failed to generate messages delivery proof at {:?}: {:?}",
at,
e,
);
})?;
// submit messages delivery proof to the source node
let tx_tracker =
source_client
.submit_messages_receiving_proof(None, at, proof)
.await
.map_err(|e| {
log::error!(
target: "bridge",
"Failed to submit messages delivery proof: {:?}",
e,
);
})?;

match tx_tracker.wait().await {
TrackedTransactionStatus::Finalized(_) => Ok(()),
TrackedTransactionStatus::Lost => {
log::error!("Transaction with messages delivery proof is considered lost");
Err(())
},
}
}

/// Messages receiving confirmations race.
struct ReceivingConfirmationsRace<P>(std::marker::PhantomData<P>);

Expand Down

0 comments on commit a0fc9c4

Please sign in to comment.