// 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), )) } }