// Copyright 2019-2022 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Bridges Common is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see .
use async_trait::async_trait;
use std::sync::Arc;
use crate::cli::{
bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge},
relay_headers_and_messages::{Full2WayBridgeBase, Full2WayBridgeCommonParams},
CliChain,
};
use bp_polkadot_core::parachains::ParaHash;
use bp_runtime::BlockNumberOf;
use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber};
use relay_substrate_client::{AccountIdOf, AccountKeyPairOf, Chain, ChainWithTransactions, Client};
use sp_core::Pair;
use substrate_relay_helper::{
finality::SubstrateFinalitySyncPipeline,
on_demand::{
headers::OnDemandHeadersRelay, parachains::OnDemandParachainsRelay, OnDemandRelay,
},
TaggedAccount, TransactionParams,
};
/// A base relay between two parachain from different consensus systems.
///
/// Such relay starts 2 messages relay. It also starts 2 on-demand header relays and 2 on-demand
/// parachain heads relay.
pub struct ParachainToParachainBridge<
L2R: MessagesCliBridge + ParachainToRelayHeadersCliBridge,
R2L: MessagesCliBridge + ParachainToRelayHeadersCliBridge,
> {
/// Parameters that are shared by all bridge types.
pub common:
Full2WayBridgeCommonParams<::Target, ::Target>,
/// Client of the left relay chain.
pub left_relay: Client<::SourceRelay>,
/// Client of the right relay chain.
pub right_relay: Client<::SourceRelay>,
/// Override for right_relay->left headers signer.
pub right_headers_to_left_transaction_params:
TransactionParams::Target>>,
/// Override for left_relay->right headers signer.
pub left_headers_to_right_transaction_params:
TransactionParams::Target>>,
/// Override for right->left parachains signer.
pub right_parachains_to_left_transaction_params:
TransactionParams::Target>>,
/// Override for left->right parachains signer.
pub left_parachains_to_right_transaction_params:
TransactionParams::Target>>,
}
macro_rules! declare_parachain_to_parachain_bridge_schema {
// left-parachain, relay-chain-of-left-parachain, right-parachain, relay-chain-of-right-parachain
($left_parachain:ident, $left_chain:ident, $right_parachain:ident, $right_chain:ident) => {
bp_runtime::paste::item! {
#[doc = $left_parachain ", " $left_chain ", " $right_parachain " and " $right_chain " headers+parachains+messages relay params."]
#[derive(Debug, PartialEq, StructOpt)]
pub struct [<$left_parachain $right_parachain HeadersAndMessages>] {
// shared parameters
#[structopt(flatten)]
shared: HeadersAndMessagesSharedParams,
#[structopt(flatten)]
left: [<$left_parachain ConnectionParams>],
#[structopt(flatten)]
left_relay: [<$left_chain ConnectionParams>],
// default signer, which is always used to sign messages relay transactions on the left chain
#[structopt(flatten)]
left_sign: [<$left_parachain SigningParams>],
// signer used to sign parameter update transactions at the left parachain
#[structopt(flatten)]
left_messages_pallet_owner: [<$left_parachain MessagesPalletOwnerSigningParams>],
#[structopt(flatten)]
right: [<$right_parachain ConnectionParams>],
#[structopt(flatten)]
right_relay: [<$right_chain ConnectionParams>],
// default signer, which is always used to sign messages relay transactions on the right chain
#[structopt(flatten)]
right_sign: [<$right_parachain SigningParams>],
// signer used to sign parameter update transactions at the right parachain
#[structopt(flatten)]
right_messages_pallet_owner: [<$right_parachain MessagesPalletOwnerSigningParams>],
// override for right_relay->left-parachain headers signer
#[structopt(flatten)]
right_relay_headers_to_left_sign_override: [<$right_chain HeadersTo $left_parachain SigningParams>],
// override for left_relay->right-parachain headers signer
#[structopt(flatten)]
left_relay_headers_to_right_sign_override: [<$left_chain HeadersTo $right_parachain SigningParams>],
// override for right->left parachains signer
#[structopt(flatten)]
right_parachains_to_left_sign_override: [<$right_chain ParachainsTo $left_parachain SigningParams>],
// override for left->right parachains signer
#[structopt(flatten)]
left_parachains_to_right_sign_override: [<$left_chain ParachainsTo $right_parachain SigningParams>],
}
impl [<$left_parachain $right_parachain HeadersAndMessages>] {
async fn into_bridge<
Left: ChainWithTransactions + CliChain>,
LeftRelay: CliChain,
Right: ChainWithTransactions + CliChain>,
RightRelay: CliChain,
L2R: CliBridgeBase
+ MessagesCliBridge
+ ParachainToRelayHeadersCliBridge,
R2L: CliBridgeBase
+ MessagesCliBridge
+ ParachainToRelayHeadersCliBridge,
>(
self,
) -> anyhow::Result> {
Ok(ParachainToParachainBridge {
common: Full2WayBridgeCommonParams::new::(
self.shared,
BridgeEndCommonParams {
client: self.left.into_client::().await?,
sign: self.left_sign.to_keypair::()?,
transactions_mortality: self.left_sign.transactions_mortality()?,
messages_pallet_owner: self.left_messages_pallet_owner.to_keypair::()?,
accounts: vec![],
},
BridgeEndCommonParams {
client: self.right.into_client::().await?,
sign: self.right_sign.to_keypair::()?,
transactions_mortality: self.right_sign.transactions_mortality()?,
messages_pallet_owner: self.right_messages_pallet_owner.to_keypair::()?,
accounts: vec![],
},
)?,
left_relay: self.left_relay.into_client::().await?,
right_relay: self.right_relay.into_client::().await?,
right_headers_to_left_transaction_params: self
.right_relay_headers_to_left_sign_override
.transaction_params_or::(&self.left_sign)?,
left_headers_to_right_transaction_params: self
.left_relay_headers_to_right_sign_override
.transaction_params_or::(&self.right_sign)?,
right_parachains_to_left_transaction_params: self
.right_parachains_to_left_sign_override
.transaction_params_or::(&self.left_sign)?,
left_parachains_to_right_transaction_params: self
.left_parachains_to_right_sign_override
.transaction_params_or::(&self.right_sign)?,
})
}
}
}
};
}
#[async_trait]
impl<
Left: Chain + ChainWithTransactions + CliChain>,
Right: Chain
+ ChainWithTransactions
+ CliChain>,
LeftRelay: Chain
+ CliChain,
RightRelay: Chain
+ CliChain,
L2R: CliBridgeBase
+ MessagesCliBridge
+ ParachainToRelayHeadersCliBridge,
R2L: CliBridgeBase
+ MessagesCliBridge
+ ParachainToRelayHeadersCliBridge,
> Full2WayBridgeBase for ParachainToParachainBridge
where
AccountIdOf: From< as Pair>::Public>,
AccountIdOf: From< as Pair>::Public>,
{
type Params = ParachainToParachainBridge;
type Left = Left;
type Right = Right;
fn common(&self) -> &Full2WayBridgeCommonParams {
&self.common
}
fn mut_common(&mut self) -> &mut Full2WayBridgeCommonParams {
&mut self.common
}
async fn start_on_demand_headers_relayers(
&mut self,
) -> anyhow::Result<(
Arc>>,
Arc>>,
)> {
self.common.left.accounts.push(TaggedAccount::Headers {
id: self.right_headers_to_left_transaction_params.signer.public().into(),
bridged_chain: RightRelay::NAME.to_string(),
});
self.common.left.accounts.push(TaggedAccount::Parachains {
id: self.right_parachains_to_left_transaction_params.signer.public().into(),
bridged_chain: RightRelay::NAME.to_string(),
});
self.common.right.accounts.push(TaggedAccount::Headers {
id: self.left_headers_to_right_transaction_params.signer.public().into(),
bridged_chain: Left::NAME.to_string(),
});
self.common.right.accounts.push(TaggedAccount::Parachains {
id: self.left_parachains_to_right_transaction_params.signer.public().into(),
bridged_chain: LeftRelay::NAME.to_string(),
});
::RelayFinality::start_relay_guards(
&self.common.right.client,
&self.left_headers_to_right_transaction_params,
self.common.right.client.can_start_version_guard(),
)
.await?;
::RelayFinality::start_relay_guards(
&self.common.left.client,
&self.right_headers_to_left_transaction_params,
self.common.left.client.can_start_version_guard(),
)
.await?;
let left_relay_to_right_on_demand_headers =
OnDemandHeadersRelay::new::<::RelayFinality>(
self.left_relay.clone(),
self.common.right.client.clone(),
self.left_headers_to_right_transaction_params.clone(),
self.common.shared.only_mandatory_headers,
);
let right_relay_to_left_on_demand_headers =
OnDemandHeadersRelay::new::<::RelayFinality>(
self.right_relay.clone(),
self.common.left.client.clone(),
self.right_headers_to_left_transaction_params.clone(),
self.common.shared.only_mandatory_headers,
);
let left_to_right_on_demand_parachains = OnDemandParachainsRelay::new::<
::ParachainFinality,
>(
self.left_relay.clone(),
self.common.right.client.clone(),
self.left_parachains_to_right_transaction_params.clone(),
Arc::new(left_relay_to_right_on_demand_headers),
);
let right_to_left_on_demand_parachains = OnDemandParachainsRelay::new::<
::ParachainFinality,
>(
self.right_relay.clone(),
self.common.left.client.clone(),
self.right_parachains_to_left_transaction_params.clone(),
Arc::new(right_relay_to_left_on_demand_headers),
);
Ok((
Arc::new(left_to_right_on_demand_parachains),
Arc::new(right_to_left_on_demand_parachains),
))
}
}