// 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 . //! Complex 2-ways headers+messages relays support. //! //! To add new complex relay between `ChainA` and `ChainB`, you must: //! //! 1) ensure that there's a `declare_chain_cli_schema!(...)` for both chains. //! 2) add `declare_chain_to_chain_bridge_schema!(...)` or //! `declare_chain_to_parachain_bridge_schema` for the bridge. //! 3) declare a new struct for the added bridge and implement the `Full2WayBridge` trait for it. use async_trait::async_trait; use structopt::StructOpt; use crate::bridges::{ kusama_polkadot::{ kusama_parachains_to_bridge_hub_polkadot::BridgeHubKusamaToBridgeHubPolkadotCliBridge, polkadot_parachains_to_bridge_hub_kusama::BridgeHubPolkadotToBridgeHubKusamaCliBridge, }, polkadot_bulletin::{ polkadot_bulletin_headers_to_bridge_hub_polkadot::PolkadotBulletinToBridgeHubPolkadotCliBridge, polkadot_parachains_to_polkadot_bulletin::PolkadotToPolkadotBulletinCliBridge, }, rococo_bulletin::{ rococo_bulletin_headers_to_bridge_hub_rococo::RococoBulletinToBridgeHubRococoCliBridge, rococo_parachains_to_rococo_bulletin::RococoToRococoBulletinCliBridge, BridgeHubRococoAsBridgeHubPolkadot, }, rococo_westend::{ rococo_parachains_to_bridge_hub_westend::BridgeHubRococoToBridgeHubWestendCliBridge, westend_parachains_to_bridge_hub_rococo::BridgeHubWestendToBridgeHubRococoCliBridge, }, }; use relay_substrate_client::{ AccountKeyPairOf, ChainRuntimeVersion, ChainWithRuntimeVersion, ChainWithTransactions, Parachain, SimpleRuntimeVersion, }; use substrate_relay_helper::{ cli::{ bridge::{ CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge, RelayToRelayHeadersCliBridge, }, chain_schema::*, relay_headers_and_messages::{ parachain_to_parachain::ParachainToParachainBridge, relay_to_parachain::*, BridgeEndCommonParams, Full2WayBridge, Full2WayBridgeCommonParams, HeadersAndMessagesSharedParams, }, }, declare_chain_cli_schema, declare_parachain_to_parachain_bridge_schema, declare_relay_to_parachain_bridge_schema, TransactionParams, }; // All supported chains. declare_chain_cli_schema!(Rococo, rococo); declare_chain_cli_schema!(BridgeHubRococo, bridge_hub_rococo); declare_chain_cli_schema!(Westend, westend); declare_chain_cli_schema!(BridgeHubWestend, bridge_hub_westend); declare_chain_cli_schema!(Kusama, kusama); declare_chain_cli_schema!(BridgeHubKusama, bridge_hub_kusama); declare_chain_cli_schema!(Polkadot, polkadot); declare_chain_cli_schema!(BridgeHubPolkadot, bridge_hub_polkadot); declare_chain_cli_schema!(PolkadotBulletin, polkadot_bulletin); declare_chain_cli_schema!(RococoBulletin, rococo_bulletin); // Means to override signers of different layer transactions. declare_chain_cli_schema!(RococoHeadersToBridgeHubWestend, rococo_headers_to_bridge_hub_westend); declare_chain_cli_schema!( RococoParachainsToBridgeHubWestend, rococo_parachains_to_bridge_hub_westend ); declare_chain_cli_schema!(WestendHeadersToBridgeHubRococo, westend_headers_to_bridge_hub_rococo); declare_chain_cli_schema!( WestendParachainsToBridgeHubRococo, westend_parachains_to_bridge_hub_rococo ); declare_chain_cli_schema!(KusamaHeadersToBridgeHubPolkadot, kusama_headers_to_bridge_hub_polkadot); declare_chain_cli_schema!( KusamaParachainsToBridgeHubPolkadot, kusama_parachains_to_bridge_hub_polkadot ); declare_chain_cli_schema!(PolkadotHeadersToBridgeHubKusama, polkadot_headers_to_bridge_hub_kusama); declare_chain_cli_schema!( PolkadotParachainsToBridgeHubKusama, polkadot_parachains_to_bridge_hub_kusama ); declare_chain_cli_schema!( PolkadotBulletinHeadersToBridgeHubPolkadot, polkadot_bulletin_headers_to_bridge_hub_polkadot ); declare_chain_cli_schema!( RococoBulletinHeadersToBridgeHubRococo, rococo_bulletin_headers_to_bridge_hub_rococo ); declare_chain_cli_schema!(PolkadotHeadersToPolkadotBulletin, polkadot_headers_to_polkadot_bulletin); declare_chain_cli_schema!(RococoHeadersToRococoBulletin, rococo_headers_to_rococo_bulletin); declare_chain_cli_schema!( PolkadotParachainsToPolkadotBulletin, polkadot_parachains_to_polkadot_bulletin ); declare_chain_cli_schema!(RococoParachainsToRococoBulletin, rococo_parachains_to_rococo_bulletin); // All supported bridges. declare_parachain_to_parachain_bridge_schema!(BridgeHubRococo, Rococo, BridgeHubWestend, Westend); declare_parachain_to_parachain_bridge_schema!(BridgeHubKusama, Kusama, BridgeHubPolkadot, Polkadot); declare_relay_to_parachain_bridge_schema!(PolkadotBulletin, BridgeHubPolkadot, Polkadot); declare_relay_to_parachain_bridge_schema!(RococoBulletin, BridgeHubRococo, Rococo); /// BridgeHubRococo <> BridgeHubWestend complex relay. pub struct BridgeHubRococoBridgeHubWestendFull2WayBridge { base: ::Base, } #[async_trait] impl Full2WayBridge for BridgeHubRococoBridgeHubWestendFull2WayBridge { type Base = ParachainToParachainBridge; type Left = relay_bridge_hub_rococo_client::BridgeHubRococo; type Right = relay_bridge_hub_westend_client::BridgeHubWestend; type L2R = BridgeHubRococoToBridgeHubWestendCliBridge; type R2L = BridgeHubWestendToBridgeHubRococoCliBridge; fn new(base: Self::Base) -> anyhow::Result { Ok(Self { base }) } fn base(&self) -> &Self::Base { &self.base } fn mut_base(&mut self) -> &mut Self::Base { &mut self.base } } /// BridgeHubKusama <> BridgeHubPolkadot complex relay. pub struct BridgeHubKusamaBridgeHubPolkadotFull2WayBridge { base: ::Base, } #[async_trait] impl Full2WayBridge for BridgeHubKusamaBridgeHubPolkadotFull2WayBridge { type Base = ParachainToParachainBridge; type Left = relay_bridge_hub_kusama_client::BridgeHubKusama; type Right = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; type L2R = BridgeHubKusamaToBridgeHubPolkadotCliBridge; type R2L = BridgeHubPolkadotToBridgeHubKusamaCliBridge; fn new(base: Self::Base) -> anyhow::Result { Ok(Self { base }) } fn base(&self) -> &Self::Base { &self.base } fn mut_base(&mut self) -> &mut Self::Base { &mut self.base } } /// `PolkadotBulletin` <> `BridgeHubPolkadot` complex relay. pub struct PolkadotBulletinBridgeHubPolkadotFull2WayBridge { base: ::Base, } #[async_trait] impl Full2WayBridge for PolkadotBulletinBridgeHubPolkadotFull2WayBridge { type Base = RelayToParachainBridge; type Left = relay_polkadot_bulletin_client::PolkadotBulletin; type Right = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; type L2R = PolkadotBulletinToBridgeHubPolkadotCliBridge; type R2L = PolkadotToPolkadotBulletinCliBridge; fn new(base: Self::Base) -> anyhow::Result { Ok(Self { base }) } fn base(&self) -> &Self::Base { &self.base } fn mut_base(&mut self) -> &mut Self::Base { &mut self.base } } /// `RococoBulletin` <> `BridgeHubRococo` complex relay. pub struct RococoBulletinBridgeHubRococoFull2WayBridge { base: ::Base, } #[async_trait] impl Full2WayBridge for RococoBulletinBridgeHubRococoFull2WayBridge { type Base = RelayToParachainBridge; type Left = relay_polkadot_bulletin_client::PolkadotBulletin; type Right = BridgeHubRococoAsBridgeHubPolkadot; type L2R = RococoBulletinToBridgeHubRococoCliBridge; type R2L = RococoToRococoBulletinCliBridge; fn new(base: Self::Base) -> anyhow::Result { Ok(Self { base }) } fn base(&self) -> &Self::Base { &self.base } fn mut_base(&mut self) -> &mut Self::Base { &mut self.base } } /// Complex headers+messages relay. #[derive(Debug, PartialEq, StructOpt)] pub enum RelayHeadersAndMessages { /// BridgeHubKusama <> BridgeHubPolkadot relay. BridgeHubKusamaBridgeHubPolkadot(BridgeHubKusamaBridgeHubPolkadotHeadersAndMessages), /// `PolkadotBulletin` <> `BridgeHubPolkadot` relay. PolkadotBulletinBridgeHubPolkadot(PolkadotBulletinBridgeHubPolkadotHeadersAndMessages), /// `RococoBulletin` <> `BridgeHubRococo` relay. RococoBulletinBridgeHubRococo(RococoBulletinBridgeHubRococoHeadersAndMessages), /// BridgeHubRococo <> BridgeHubWestend relay. BridgeHubRococoBridgeHubWestend(BridgeHubRococoBridgeHubWestendHeadersAndMessages), } impl RelayHeadersAndMessages { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { match self { RelayHeadersAndMessages::BridgeHubRococoBridgeHubWestend(params) => BridgeHubRococoBridgeHubWestendFull2WayBridge::new(params.into_bridge().await?)? .run() .await, RelayHeadersAndMessages::BridgeHubKusamaBridgeHubPolkadot(params) => BridgeHubKusamaBridgeHubPolkadotFull2WayBridge::new(params.into_bridge().await?)? .run() .await, RelayHeadersAndMessages::PolkadotBulletinBridgeHubPolkadot(params) => PolkadotBulletinBridgeHubPolkadotFull2WayBridge::new(params.into_bridge().await?)? .run() .await, RelayHeadersAndMessages::RococoBulletinBridgeHubRococo(params) => RococoBulletinBridgeHubRococoFull2WayBridge::new(params.into_bridge().await?)? .run() .await, } } } #[cfg(test)] mod tests { use super::*; use substrate_relay_helper::cli::{HexLaneId, PrometheusParams}; #[test] fn should_parse_parachain_to_parachain_options() { // when let res = RelayHeadersAndMessages::from_iter(vec![ "relay-headers-and-messages", "bridge-hub-kusama-bridge-hub-polkadot", "--bridge-hub-kusama-host", "bridge-hub-kusama-node-collator1", "--bridge-hub-kusama-port", "9944", "--bridge-hub-kusama-signer", "//Iden", "--bridge-hub-kusama-transactions-mortality", "64", "--kusama-host", "kusama-alice", "--kusama-port", "9944", "--bridge-hub-polkadot-host", "bridge-hub-polkadot-collator1", "--bridge-hub-polkadot-port", "9944", "--bridge-hub-polkadot-signer", "//George", "--bridge-hub-polkadot-transactions-mortality", "64", "--polkadot-host", "polkadot-alice", "--polkadot-port", "9944", "--lane", "00000000", "--prometheus-host", "0.0.0.0", ]); // then assert_eq!( res, RelayHeadersAndMessages::BridgeHubKusamaBridgeHubPolkadot( BridgeHubKusamaBridgeHubPolkadotHeadersAndMessages { shared: HeadersAndMessagesSharedParams { lane: vec![HexLaneId([0x00, 0x00, 0x00, 0x00])], only_mandatory_headers: false, prometheus_params: PrometheusParams { no_prometheus: false, prometheus_host: "0.0.0.0".into(), prometheus_port: 9616, }, }, left_relay: KusamaConnectionParams { kusama_uri: None, kusama_host: "kusama-alice".into(), kusama_port: 9944, kusama_path: None, kusama_secure: false, kusama_runtime_version: KusamaRuntimeVersionParams { kusama_version_mode: RuntimeVersionType::Bundle, kusama_spec_version: None, kusama_transaction_version: None, }, }, left: BridgeHubKusamaConnectionParams { bridge_hub_kusama_uri: None, bridge_hub_kusama_host: "bridge-hub-kusama-node-collator1".into(), bridge_hub_kusama_port: 9944, bridge_hub_kusama_path: None, bridge_hub_kusama_secure: false, bridge_hub_kusama_runtime_version: BridgeHubKusamaRuntimeVersionParams { bridge_hub_kusama_version_mode: RuntimeVersionType::Bundle, bridge_hub_kusama_spec_version: None, bridge_hub_kusama_transaction_version: None, }, }, left_sign: BridgeHubKusamaSigningParams { bridge_hub_kusama_signer: Some("//Iden".into()), bridge_hub_kusama_signer_password: None, bridge_hub_kusama_signer_file: None, bridge_hub_kusama_signer_password_file: None, bridge_hub_kusama_transactions_mortality: Some(64), }, right: BridgeHubPolkadotConnectionParams { bridge_hub_polkadot_uri: None, bridge_hub_polkadot_host: "bridge-hub-polkadot-collator1".into(), bridge_hub_polkadot_port: 9944, bridge_hub_polkadot_path: None, bridge_hub_polkadot_secure: false, bridge_hub_polkadot_runtime_version: BridgeHubPolkadotRuntimeVersionParams { bridge_hub_polkadot_version_mode: RuntimeVersionType::Bundle, bridge_hub_polkadot_spec_version: None, bridge_hub_polkadot_transaction_version: None, }, }, right_sign: BridgeHubPolkadotSigningParams { bridge_hub_polkadot_signer: Some("//George".into()), bridge_hub_polkadot_signer_password: None, bridge_hub_polkadot_signer_file: None, bridge_hub_polkadot_signer_password_file: None, bridge_hub_polkadot_transactions_mortality: Some(64), }, right_relay: PolkadotConnectionParams { polkadot_uri: None, polkadot_host: "polkadot-alice".into(), polkadot_port: 9944, polkadot_path: None, polkadot_secure: false, polkadot_runtime_version: PolkadotRuntimeVersionParams { polkadot_version_mode: RuntimeVersionType::Bundle, polkadot_spec_version: None, polkadot_transaction_version: None, }, }, } ), ); } }