diff --git a/Cargo.lock b/Cargo.lock index 347da03ae46..5ae38806bdb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9109,6 +9109,7 @@ dependencies = [ "pallet-transaction-payment", "parachains-relay", "parity-scale-codec", + "rbtag", "relay-bridge-hub-rococo-client", "relay-bridge-hub-westend-client", "relay-rococo-client", @@ -9117,6 +9118,8 @@ dependencies = [ "sp-consensus-grandpa", "sp-core", "sp-runtime", + "structopt", + "strum 0.26.2", "thiserror", ] diff --git a/Cargo.toml b/Cargo.toml index f866e6827e5..b7119995932 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,7 +53,7 @@ members = [ "relays/lib-substrate-relay", "relays/messages", "relays/parachains", - "relays/utils", + "relays/utils" ] # Setup clippy lints as `polkadot-sdk`, diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_kusama_messages_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_kusama_messages_to_bridge_hub_polkadot.rs index e5730231556..fc239ca1ed3 100644 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_kusama_messages_to_bridge_hub_polkadot.rs +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_kusama_messages_to_bridge_hub_polkadot.rs @@ -16,10 +16,13 @@ //! BridgeHubKusama-to-BridgeHubPolkadot messages sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; use relay_bridge_hub_kusama_client::BridgeHubKusama; use relay_bridge_hub_polkadot_client::BridgeHubPolkadot; -use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; +use substrate_relay_helper::{ + cli::bridge::{CliBridgeBase, MessagesCliBridge}, + messages_lane::SubstrateMessageLane, + UtilityPalletBatchCallBuilder, +}; /// BridgeHubKusama-to-BridgeHubPolkadot messages bridge. pub struct BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge {} diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_polkadot_messages_to_bridge_hub_kusama.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_polkadot_messages_to_bridge_hub_kusama.rs index 0a1b21cd112..8d8e5e0c35e 100644 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_polkadot_messages_to_bridge_hub_kusama.rs +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_polkadot_messages_to_bridge_hub_kusama.rs @@ -16,10 +16,13 @@ //! BridgeHubPolkadot-to-BridgeHubKusama messages sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; use relay_bridge_hub_kusama_client::BridgeHubKusama; use relay_bridge_hub_polkadot_client::BridgeHubPolkadot; -use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; +use substrate_relay_helper::{ + cli::bridge::{CliBridgeBase, MessagesCliBridge}, + messages_lane::SubstrateMessageLane, + UtilityPalletBatchCallBuilder, +}; /// BridgeHubPolkadot-to-BridgeHubKusama messages bridge. pub struct BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge {} diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs index dafb5f56826..196a22cd70d 100644 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs @@ -16,7 +16,7 @@ //! Kusama-to-BridgeHubPolkadot headers sync entrypoint. -use crate::cli::bridge::{ +use substrate_relay_helper::cli::bridge::{ CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, }; diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_parachains_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_parachains_to_bridge_hub_polkadot.rs index 9b76cdbfa63..b39b9700805 100644 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_parachains_to_bridge_hub_polkadot.rs +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_parachains_to_bridge_hub_polkadot.rs @@ -16,11 +16,11 @@ //! Kusama-to-BridgeHubPolkadot parachains sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use relay_substrate_client::{CallOf, HeaderIdOf}; -use substrate_relay_helper::parachains::{ - SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, +use substrate_relay_helper::{ + cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}, + parachains::{SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline}, }; /// Kusama-to-BridgeHubPolkadot parachain sync description. diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs index 019afab0bb3..d96326a288d 100644 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs @@ -16,7 +16,7 @@ //! Polkadot-to-KusamaBridgeHub headers sync entrypoint. -use crate::cli::bridge::{ +use substrate_relay_helper::cli::bridge::{ CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, }; diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_parachains_to_bridge_hub_kusama.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_parachains_to_bridge_hub_kusama.rs index 439eddaa1a6..25ce53cb599 100644 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_parachains_to_bridge_hub_kusama.rs +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_parachains_to_bridge_hub_kusama.rs @@ -16,11 +16,11 @@ //! Polkadot-to-BridgeHubKusama parachains sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use relay_substrate_client::{CallOf, HeaderIdOf}; -use substrate_relay_helper::parachains::{ - SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, +use substrate_relay_helper::{ + cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}, + parachains::{SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline}, }; /// Polkadot-to-BridgeHubKusama parachain sync description. diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/bridge_hub_polkadot_messages_to_polkadot_bulletin.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/bridge_hub_polkadot_messages_to_polkadot_bulletin.rs index ba177271db1..8114d23296f 100644 --- a/relays/bin-substrate/src/bridges/polkadot_bulletin/bridge_hub_polkadot_messages_to_polkadot_bulletin.rs +++ b/relays/bin-substrate/src/bridges/polkadot_bulletin/bridge_hub_polkadot_messages_to_polkadot_bulletin.rs @@ -16,10 +16,13 @@ //! BridgeHubPolkadot-to-PolkadotBulletin messages sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; use relay_bridge_hub_polkadot_client::BridgeHubPolkadot; use relay_polkadot_bulletin_client::PolkadotBulletin; -use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; +use substrate_relay_helper::{ + cli::bridge::{CliBridgeBase, MessagesCliBridge}, + messages_lane::SubstrateMessageLane, + UtilityPalletBatchCallBuilder, +}; /// BridgeHubPolkadot-to-PolkadotBulletin messages bridge. pub struct BridgeHubPolkadotToPolkadotBulletinMessagesCliBridge {} diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_headers_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_headers_to_bridge_hub_polkadot.rs index 7019a6b55a3..eb63785d3bb 100644 --- a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_headers_to_bridge_hub_polkadot.rs +++ b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_headers_to_bridge_hub_polkadot.rs @@ -16,11 +16,6 @@ //! PolkadotBulletin-to-BridgeHubPolkadot headers sync entrypoint. -use crate::cli::bridge::{ - CliBridgeBase, MessagesCliBridge, RelayToRelayEquivocationDetectionCliBridge, - RelayToRelayHeadersCliBridge, -}; - use async_trait::async_trait; use substrate_relay_helper::{ equivocation::SubstrateEquivocationDetectionPipeline, @@ -28,6 +23,11 @@ use substrate_relay_helper::{ finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, }; +use substrate_relay_helper::cli::bridge::{ + CliBridgeBase, MessagesCliBridge, RelayToRelayEquivocationDetectionCliBridge, + RelayToRelayHeadersCliBridge, +}; + /// Description of `PolkadotBulletin` -> `PolkadotBridgeHub` finalized headers bridge. #[derive(Clone, Debug)] pub struct PolkadotBulletinFinalityToBridgeHubPolkadot; diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_messages_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_messages_to_bridge_hub_polkadot.rs index 1b5f3e5f69e..1c04f878810 100644 --- a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_messages_to_bridge_hub_polkadot.rs +++ b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_messages_to_bridge_hub_polkadot.rs @@ -16,10 +16,13 @@ //! PolkadotBulletin-to-BridgeHubPolkadot messages sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; use relay_bridge_hub_polkadot_client::BridgeHubPolkadot; use relay_polkadot_bulletin_client::PolkadotBulletin; -use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; +use substrate_relay_helper::{ + cli::bridge::{CliBridgeBase, MessagesCliBridge}, + messages_lane::SubstrateMessageLane, + UtilityPalletBatchCallBuilder, +}; /// PolkadotBulletin-to-BridgeHubPolkadot messages bridge. pub struct PolkadotBulletinToBridgeHubPolkadotMessagesCliBridge {} diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_headers_to_polkadot_bulletin.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_headers_to_polkadot_bulletin.rs index 897c2ac884f..7996d1613c8 100644 --- a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_headers_to_polkadot_bulletin.rs +++ b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_headers_to_polkadot_bulletin.rs @@ -16,10 +16,6 @@ //! Polkadot-to-PolkadotBulletin headers sync entrypoint. -use crate::cli::bridge::{ - CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, -}; - use async_trait::async_trait; use substrate_relay_helper::{ equivocation::SubstrateEquivocationDetectionPipeline, @@ -27,6 +23,10 @@ use substrate_relay_helper::{ finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, }; +use substrate_relay_helper::cli::bridge::{ + CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, +}; + /// Description of Polkadot -> `PolkadotBulletin` finalized headers bridge. #[derive(Clone, Debug)] pub struct PolkadotFinalityToPolkadotBulletin; diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_parachains_to_polkadot_bulletin.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_parachains_to_polkadot_bulletin.rs index 674c84adb39..0bfce11ba71 100644 --- a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_parachains_to_polkadot_bulletin.rs +++ b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_parachains_to_polkadot_bulletin.rs @@ -16,7 +16,9 @@ //! Polkadot-to-PolkadotBulletin parachains sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; +use substrate_relay_helper::cli::bridge::{ + CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge, +}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use bp_runtime::Chain; diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/bridge_hub_rococo_messages_to_rococo_bulletin.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/bridge_hub_rococo_messages_to_rococo_bulletin.rs index a2de83831c9..b8e95556bff 100644 --- a/relays/bin-substrate/src/bridges/rococo_bulletin/bridge_hub_rococo_messages_to_rococo_bulletin.rs +++ b/relays/bin-substrate/src/bridges/rococo_bulletin/bridge_hub_rococo_messages_to_rococo_bulletin.rs @@ -17,9 +17,12 @@ //! BridgeHubRococo-to-RococoBulletin messages sync entrypoint. use super::BridgeHubRococoAsBridgeHubPolkadot; -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; use relay_polkadot_bulletin_client::PolkadotBulletin as RococoBulletin; -use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; +use substrate_relay_helper::{ + cli::bridge::{CliBridgeBase, MessagesCliBridge}, + messages_lane::SubstrateMessageLane, + UtilityPalletBatchCallBuilder, +}; /// BridgeHubRococo-to-RococoBulletin messages bridge. pub struct BridgeHubRococoToRococoBulletinMessagesCliBridge {} diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs index 2d7b5aec1fd..738fea8c528 100644 --- a/relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs +++ b/relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs @@ -16,8 +16,6 @@ //! Declaration of all bridges between Rococo Bulletin Chain and Rococo Bridge Hub. -use crate::cli::CliChain; - use bp_messages::MessageNonce; use bp_runtime::{ AccountIdOf, BalanceOf, BlockNumberOf, ChainId, HashOf, HasherOf, HeaderOf, NonceOf, @@ -25,7 +23,8 @@ use bp_runtime::{ }; use frame_support::pallet_prelude::Weight; use relay_substrate_client::{ - Error as SubstrateError, SignParam, SimpleRuntimeVersion, UnsignedTransaction, + ChainWithRuntimeVersion, Error as SubstrateError, SignParam, SimpleRuntimeVersion, + UnsignedTransaction, }; use sp_core::storage::StorageKey; use std::time::Duration; @@ -127,7 +126,7 @@ impl relay_substrate_client::ChainWithTransactions for RococoAsPolkadot { } } -impl CliChain for RococoAsPolkadot { +impl ChainWithRuntimeVersion for RococoAsPolkadot { const RUNTIME_VERSION: Option = None; } @@ -232,7 +231,7 @@ impl relay_substrate_client::ChainWithMessages for BridgeHubRococoAsBridgeHubPol relay_bridge_hub_polkadot_client::BridgeHubPolkadot::FROM_CHAIN_MESSAGE_DETAILS_METHOD; } -impl CliChain for BridgeHubRococoAsBridgeHubPolkadot { +impl ChainWithRuntimeVersion for BridgeHubRococoAsBridgeHubPolkadot { const RUNTIME_VERSION: Option = Some(SimpleRuntimeVersion { spec_version: 1_003_000, transaction_version: 3 }); } diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_headers_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_headers_to_bridge_hub_rococo.rs index e897cd85967..0d54fd21018 100644 --- a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_headers_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_headers_to_bridge_hub_rococo.rs @@ -17,10 +17,6 @@ //! RococoBulletin-to-BridgeHubRococo headers sync entrypoint. use super::BridgeHubRococoAsBridgeHubPolkadot; -use crate::cli::bridge::{ - CliBridgeBase, MessagesCliBridge, RelayToRelayEquivocationDetectionCliBridge, - RelayToRelayHeadersCliBridge, -}; use async_trait::async_trait; use substrate_relay_helper::{ @@ -29,6 +25,11 @@ use substrate_relay_helper::{ finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, }; +use substrate_relay_helper::cli::bridge::{ + CliBridgeBase, MessagesCliBridge, RelayToRelayEquivocationDetectionCliBridge, + RelayToRelayHeadersCliBridge, +}; + /// Description of `RococoBulletin` -> `RococoBridgeHub` finalized headers bridge. #[derive(Clone, Debug)] pub struct RococoBulletinFinalityToBridgeHubRococo; diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_messages_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_messages_to_bridge_hub_rococo.rs index 856be9cf6f2..d192ec0381e 100644 --- a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_messages_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_messages_to_bridge_hub_rococo.rs @@ -17,9 +17,12 @@ //! RococoBulletin-to-BridgeHubRococo messages sync entrypoint. use super::BridgeHubRococoAsBridgeHubPolkadot; -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; use relay_polkadot_bulletin_client::PolkadotBulletin as RococoBulletin; -use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; +use substrate_relay_helper::{ + cli::bridge::{CliBridgeBase, MessagesCliBridge}, + messages_lane::SubstrateMessageLane, + UtilityPalletBatchCallBuilder, +}; /// RococoBulletin-to-BridgeHubRococo messages bridge. pub struct RococoBulletinToBridgeHubRococoMessagesCliBridge {} diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_headers_to_rococo_bulletin.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_headers_to_rococo_bulletin.rs index 8a4b44eec27..45c890267ff 100644 --- a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_headers_to_rococo_bulletin.rs +++ b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_headers_to_rococo_bulletin.rs @@ -17,9 +17,6 @@ //! Rococo-to-RococoBulletin headers sync entrypoint. use super::RococoAsPolkadot; -use crate::cli::bridge::{ - CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, -}; use async_trait::async_trait; use substrate_relay_helper::{ @@ -28,6 +25,10 @@ use substrate_relay_helper::{ finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, }; +use substrate_relay_helper::cli::bridge::{ + CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, +}; + /// Description of Rococo -> `RococoBulletin` finalized headers bridge. #[derive(Clone, Debug)] pub struct RococoFinalityToRococoBulletin; diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_parachains_to_rococo_bulletin.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_parachains_to_rococo_bulletin.rs index ee44bad523b..d14a133d23c 100644 --- a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_parachains_to_rococo_bulletin.rs +++ b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_parachains_to_rococo_bulletin.rs @@ -17,12 +17,12 @@ //! Rococo-to-RococoBulletin parachains sync entrypoint. use super::{BridgeHubRococoAsBridgeHubPolkadot, RococoAsPolkadot}; -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use bp_runtime::Chain; use relay_substrate_client::{CallOf, HeaderIdOf}; use substrate_relay_helper::{ + cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}, messages_lane::MessagesRelayLimits, parachains::{SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline}, }; diff --git a/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_rococo_messages_to_bridge_hub_westend.rs b/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_rococo_messages_to_bridge_hub_westend.rs index cbf122a2d4b..ec6b07d982a 100644 --- a/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_rococo_messages_to_bridge_hub_westend.rs +++ b/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_rococo_messages_to_bridge_hub_westend.rs @@ -16,10 +16,13 @@ //! BridgeHubRococo-to-BridgeHubWestend messages sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; use relay_bridge_hub_rococo_client::BridgeHubRococo; use relay_bridge_hub_westend_client::BridgeHubWestend; -use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; +use substrate_relay_helper::{ + cli::bridge::{CliBridgeBase, MessagesCliBridge}, + messages_lane::SubstrateMessageLane, + UtilityPalletBatchCallBuilder, +}; pub struct BridgeHubRococoToBridgeHubWestendMessagesCliBridge {} diff --git a/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_westend_messages_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_westend_messages_to_bridge_hub_rococo.rs index bb823981bf8..4e978cd8356 100644 --- a/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_westend_messages_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_westend_messages_to_bridge_hub_rococo.rs @@ -16,10 +16,13 @@ //! BridgeHubWestend-to-BridgeHubRococo messages sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; use relay_bridge_hub_rococo_client::BridgeHubRococo; use relay_bridge_hub_westend_client::BridgeHubWestend; -use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; +use substrate_relay_helper::{ + cli::bridge::{CliBridgeBase, MessagesCliBridge}, + messages_lane::SubstrateMessageLane, + UtilityPalletBatchCallBuilder, +}; pub struct BridgeHubWestendToBridgeHubRococoMessagesCliBridge {} diff --git a/relays/bin-substrate/src/bridges/rococo_westend/rococo_headers_to_bridge_hub_westend.rs b/relays/bin-substrate/src/bridges/rococo_westend/rococo_headers_to_bridge_hub_westend.rs index 6e6661d5417..bf30a87bf2d 100644 --- a/relays/bin-substrate/src/bridges/rococo_westend/rococo_headers_to_bridge_hub_westend.rs +++ b/relays/bin-substrate/src/bridges/rococo_westend/rococo_headers_to_bridge_hub_westend.rs @@ -16,10 +16,6 @@ //! Rococo-to-Westend bridge hubs headers sync entrypoint. -use crate::cli::bridge::{ - CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, -}; - use async_trait::async_trait; use substrate_relay_helper::{ equivocation::SubstrateEquivocationDetectionPipeline, @@ -27,6 +23,10 @@ use substrate_relay_helper::{ finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, }; +use substrate_relay_helper::cli::bridge::{ + CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, +}; + /// Description of Rococo -> Westend finalized headers bridge. #[derive(Clone, Debug)] pub struct RococoFinalityToBridgeHubWestend; diff --git a/relays/bin-substrate/src/bridges/rococo_westend/rococo_parachains_to_bridge_hub_westend.rs b/relays/bin-substrate/src/bridges/rococo_westend/rococo_parachains_to_bridge_hub_westend.rs index 16b646233ee..31de8c4d1d1 100644 --- a/relays/bin-substrate/src/bridges/rococo_westend/rococo_parachains_to_bridge_hub_westend.rs +++ b/relays/bin-substrate/src/bridges/rococo_westend/rococo_parachains_to_bridge_hub_westend.rs @@ -16,11 +16,11 @@ //! Westend-to-Rococo parachains sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use relay_substrate_client::{CallOf, HeaderIdOf}; -use substrate_relay_helper::parachains::{ - SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, +use substrate_relay_helper::{ + cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}, + parachains::{SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline}, }; /// BridgeHub-to-BridgeHub parachain sync description. diff --git a/relays/bin-substrate/src/bridges/rococo_westend/westend_headers_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_westend/westend_headers_to_bridge_hub_rococo.rs index 6f4ebb84a83..4a1419f06dc 100644 --- a/relays/bin-substrate/src/bridges/rococo_westend/westend_headers_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_westend/westend_headers_to_bridge_hub_rococo.rs @@ -16,10 +16,6 @@ //! Westend-to-Rococo bridge hubs headers sync entrypoint. -use crate::cli::bridge::{ - CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, -}; - use async_trait::async_trait; use substrate_relay_helper::{ equivocation::SubstrateEquivocationDetectionPipeline, @@ -27,6 +23,10 @@ use substrate_relay_helper::{ finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, }; +use substrate_relay_helper::cli::bridge::{ + CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, +}; + /// Description of Westend -> Rococo finalized headers bridge. #[derive(Clone, Debug)] pub struct WestendFinalityToBridgeHubRococo; diff --git a/relays/bin-substrate/src/bridges/rococo_westend/westend_parachains_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_westend/westend_parachains_to_bridge_hub_rococo.rs index dac915dc3ba..fc6f6532836 100644 --- a/relays/bin-substrate/src/bridges/rococo_westend/westend_parachains_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_westend/westend_parachains_to_bridge_hub_rococo.rs @@ -16,11 +16,11 @@ //! Rococo-to-Westend parachains sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use relay_substrate_client::{CallOf, HeaderIdOf}; -use substrate_relay_helper::parachains::{ - SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, +use substrate_relay_helper::{ + cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}, + parachains::{SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline}, }; /// BridgeHub-to-BridgeHub parachain sync description. diff --git a/relays/bin-substrate/src/chains/kusama.rs b/relays/bin-substrate/src/chains/kusama.rs deleted file mode 100644 index 80ffdfed003..00000000000 --- a/relays/bin-substrate/src/chains/kusama.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 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 . - -//! Kusama + Kusama parachains specification for CLI. - -use crate::cli::CliChain; -use relay_bridge_hub_kusama_client::BridgeHubKusama; -use relay_kusama_client::Kusama; -use relay_substrate_client::SimpleRuntimeVersion; - -impl CliChain for Kusama { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_001_002, transaction_version: 25 }); -} - -impl CliChain for BridgeHubKusama { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_001_000, transaction_version: 4 }); -} diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs deleted file mode 100644 index ab15a9e679c..00000000000 --- a/relays/bin-substrate/src/chains/mod.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2019-2021 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 . - -//! Chain-specific relayer configuration. - -mod kusama; -mod polkadot; -mod polkadot_bulletin; -mod rococo; -mod westend; diff --git a/relays/bin-substrate/src/chains/polkadot.rs b/relays/bin-substrate/src/chains/polkadot.rs deleted file mode 100644 index 1f1c607916a..00000000000 --- a/relays/bin-substrate/src/chains/polkadot.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 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 . - -//! Polkadot + Polkadot parachains specification for CLI. - -use crate::cli::CliChain; -use relay_bridge_hub_polkadot_client::BridgeHubPolkadot; -use relay_polkadot_client::Polkadot; -use relay_substrate_client::SimpleRuntimeVersion; - -impl CliChain for Polkadot { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_001_002, transaction_version: 25 }); -} - -impl CliChain for BridgeHubPolkadot { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_001_000, transaction_version: 3 }); -} diff --git a/relays/bin-substrate/src/chains/polkadot_bulletin.rs b/relays/bin-substrate/src/chains/polkadot_bulletin.rs deleted file mode 100644 index ee7edbd9f42..00000000000 --- a/relays/bin-substrate/src/chains/polkadot_bulletin.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 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 . - -//! Polkadot + Polkadot parachains specification for CLI. - -use crate::cli::CliChain; -use relay_polkadot_bulletin_client::PolkadotBulletin; -use relay_substrate_client::SimpleRuntimeVersion; - -impl CliChain for PolkadotBulletin { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 100, transaction_version: 1 }); -} diff --git a/relays/bin-substrate/src/chains/rococo.rs b/relays/bin-substrate/src/chains/rococo.rs deleted file mode 100644 index 0640447fdc5..00000000000 --- a/relays/bin-substrate/src/chains/rococo.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 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 . - -//! Rococo + Rococo parachains specification for CLI. - -use crate::cli::CliChain; -use relay_bridge_hub_rococo_client::BridgeHubRococo; -use relay_rococo_client::Rococo; -use relay_substrate_client::SimpleRuntimeVersion; - -impl CliChain for Rococo { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 24 }); -} - -impl CliChain for BridgeHubRococo { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 4 }); -} diff --git a/relays/bin-substrate/src/chains/westend.rs b/relays/bin-substrate/src/chains/westend.rs deleted file mode 100644 index 41f5fc4e96c..00000000000 --- a/relays/bin-substrate/src/chains/westend.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2019-2021 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 . - -//! Westend chain specification for CLI. - -use crate::cli::CliChain; -use relay_bridge_hub_westend_client::BridgeHubWestend; -use relay_substrate_client::SimpleRuntimeVersion; -use relay_westend_client::Westend; - -impl CliChain for Westend { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 24 }); -} - -impl CliChain for BridgeHubWestend { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 4 }); -} diff --git a/relays/bin-substrate/src/cli/chain_schema.rs b/relays/bin-substrate/src/cli/chain_schema.rs index 65559397ac2..4422332a593 100644 --- a/relays/bin-substrate/src/cli/chain_schema.rs +++ b/relays/bin-substrate/src/cli/chain_schema.rs @@ -12,248 +12,12 @@ // 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 relay_substrate_client::{AccountKeyPairOf, ChainWithTransactions}; -use structopt::StructOpt; -use strum::{EnumString, VariantNames}; - -use crate::cli::CliChain; -pub use relay_substrate_client::{ChainRuntimeVersion, SimpleRuntimeVersion}; -use substrate_relay_helper::TransactionParams; - -#[doc = "Runtime version params."] -#[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy, EnumString, VariantNames)] -pub enum RuntimeVersionType { - /// Auto query version from chain - Auto, - /// Custom `spec_version` and `transaction_version` - Custom, - /// Read version from bundle dependencies directly. - Bundle, -} - -/// Create chain-specific set of runtime version parameters. -#[macro_export] -macro_rules! declare_chain_runtime_version_params_cli_schema { - ($chain:ident, $chain_prefix:ident) => { - bp_runtime::paste::item! { - #[doc = $chain " runtime version params."] - #[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy)] - pub struct [<$chain RuntimeVersionParams>] { - #[doc = "The type of runtime version for chain " $chain] - #[structopt(long, default_value = "Bundle")] - pub [<$chain_prefix _version_mode>]: RuntimeVersionType, - #[doc = "The custom sepc_version for chain " $chain] - #[structopt(long)] - pub [<$chain_prefix _spec_version>]: Option, - #[doc = "The custom transaction_version for chain " $chain] - #[structopt(long)] - pub [<$chain_prefix _transaction_version>]: Option, - } - - impl [<$chain RuntimeVersionParams>] { - /// Converts self into `ChainRuntimeVersion`. - pub fn into_runtime_version( - self, - bundle_runtime_version: Option, - ) -> anyhow::Result { - Ok(match self.[<$chain_prefix _version_mode>] { - RuntimeVersionType::Auto => ChainRuntimeVersion::Auto, - RuntimeVersionType::Custom => { - let custom_spec_version = self.[<$chain_prefix _spec_version>] - .ok_or_else(|| anyhow::Error::msg(format!("The {}-spec-version is required when choose custom mode", stringify!($chain_prefix))))?; - let custom_transaction_version = self.[<$chain_prefix _transaction_version>] - .ok_or_else(|| anyhow::Error::msg(format!("The {}-transaction-version is required when choose custom mode", stringify!($chain_prefix))))?; - ChainRuntimeVersion::Custom( - SimpleRuntimeVersion { - spec_version: custom_spec_version, - transaction_version: custom_transaction_version - } - ) - }, - RuntimeVersionType::Bundle => match bundle_runtime_version { - Some(runtime_version) => ChainRuntimeVersion::Custom(runtime_version), - None => { - return Err(anyhow::format_err!("Cannot use bundled runtime version of {}: it is not known to the relay", stringify!($chain_prefix))); - } - }, - }) - } - } - } - }; -} - -/// Create chain-specific set of runtime version parameters. -#[macro_export] -macro_rules! declare_chain_connection_params_cli_schema { - ($chain:ident, $chain_prefix:ident) => { - bp_runtime::paste::item! { - #[doc = $chain " connection params."] - #[derive(StructOpt, Debug, PartialEq, Eq, Clone)] - pub struct [<$chain ConnectionParams>] { - #[doc = "Connect to " $chain " node at given host."] - #[structopt(long, default_value = "127.0.0.1")] - pub [<$chain_prefix _host>]: String, - #[doc = "Connect to " $chain " node websocket server at given port."] - #[structopt(long, default_value = "9944")] - pub [<$chain_prefix _port>]: u16, - #[doc = "Use secure websocket connection."] - #[structopt(long)] - pub [<$chain_prefix _secure>]: bool, - #[doc = "Custom runtime version"] - #[structopt(flatten)] - pub [<$chain_prefix _runtime_version>]: [<$chain RuntimeVersionParams>], - } - - impl [<$chain ConnectionParams>] { - /// Convert connection params into Substrate client. - #[allow(dead_code)] - pub async fn into_client( - self, - ) -> anyhow::Result> { - let chain_runtime_version = self - .[<$chain_prefix _runtime_version>] - .into_runtime_version(Chain::RUNTIME_VERSION)?; - Ok(relay_substrate_client::Client::new(relay_substrate_client::ConnectionParams { - host: self.[<$chain_prefix _host>], - port: self.[<$chain_prefix _port>], - secure: self.[<$chain_prefix _secure>], - chain_runtime_version, - }) - .await - ) - } - } - } - }; -} - -/// Create chain-specific set of signing parameters. -#[macro_export] -macro_rules! declare_chain_signing_params_cli_schema { - ($chain:ident, $chain_prefix:ident) => { - bp_runtime::paste::item! { - #[doc = $chain " signing params."] - #[derive(StructOpt, Debug, PartialEq, Eq, Clone)] - pub struct [<$chain SigningParams>] { - #[doc = "The SURI of secret key to use when transactions are submitted to the " $chain " node."] - #[structopt(long)] - pub [<$chain_prefix _signer>]: Option, - #[doc = "The password for the SURI of secret key to use when transactions are submitted to the " $chain " node."] - #[structopt(long)] - pub [<$chain_prefix _signer_password>]: Option, - - #[doc = "Path to the file, that contains SURI of secret key to use when transactions are submitted to the " $chain " node. Can be overridden with " $chain_prefix "_signer option."] - #[structopt(long)] - pub [<$chain_prefix _signer_file>]: Option, - #[doc = "Path to the file, that password for the SURI of secret key to use when transactions are submitted to the " $chain " node. Can be overridden with " $chain_prefix "_signer_password option."] - #[structopt(long)] - pub [<$chain_prefix _signer_password_file>]: Option, - - #[doc = "Transactions mortality period, in blocks. MUST be a power of two in [4; 65536] range. MAY NOT be larger than `BlockHashCount` parameter of the chain system module."] - #[structopt(long)] - pub [<$chain_prefix _transactions_mortality>]: Option, - } - - impl [<$chain SigningParams>] { - /// Return transactions mortality. - #[allow(dead_code)] - pub fn transactions_mortality(&self) -> anyhow::Result> { - self.[<$chain_prefix _transactions_mortality>] - .map(|transactions_mortality| { - if !(4..=65536).contains(&transactions_mortality) - || !transactions_mortality.is_power_of_two() - { - Err(anyhow::format_err!( - "Transactions mortality {} is not a power of two in a [4; 65536] range", - transactions_mortality, - )) - } else { - Ok(transactions_mortality) - } - }) - .transpose() - } - - /// Parse signing params into chain-specific KeyPair. - #[allow(dead_code)] - pub fn to_keypair(&self) -> anyhow::Result> { - let suri = match (self.[<$chain_prefix _signer>].as_ref(), self.[<$chain_prefix _signer_file>].as_ref()) { - (Some(suri), _) => suri.to_owned(), - (None, Some(suri_file)) => std::fs::read_to_string(suri_file) - .map_err(|err| anyhow::format_err!( - "Failed to read SURI from file {:?}: {}", - suri_file, - err, - ))?, - (None, None) => return Err(anyhow::format_err!( - "One of options must be specified: '{}' or '{}'", - stringify!([<$chain_prefix _signer>]), - stringify!([<$chain_prefix _signer_file>]), - )), - }; - - let suri_password = match ( - self.[<$chain_prefix _signer_password>].as_ref(), - self.[<$chain_prefix _signer_password_file>].as_ref(), - ) { - (Some(suri_password), _) => Some(suri_password.to_owned()), - (None, Some(suri_password_file)) => std::fs::read_to_string(suri_password_file) - .map(Some) - .map_err(|err| anyhow::format_err!( - "Failed to read SURI password from file {:?}: {}", - suri_password_file, - err, - ))?, - _ => None, - }; - - use sp_core::crypto::Pair; - - AccountKeyPairOf::::from_string( - &suri, - suri_password.as_deref() - ).map_err(|e| anyhow::format_err!("{:?}", e)) - } - - /// Return transaction parameters. - #[allow(dead_code)] - pub fn transaction_params( - &self, - ) -> anyhow::Result>> { - Ok(TransactionParams { - mortality: self.transactions_mortality()?, - signer: self.to_keypair::()?, - }) - } - } - } - }; -} - -/// Create chain-specific set of configuration objects: connection parameters, -/// signing parameters and bridge initialization parameters. -#[macro_export] -macro_rules! declare_chain_cli_schema { - ($chain:ident, $chain_prefix:ident) => { - $crate::declare_chain_runtime_version_params_cli_schema!($chain, $chain_prefix); - $crate::declare_chain_connection_params_cli_schema!($chain, $chain_prefix); - $crate::declare_chain_signing_params_cli_schema!($chain, $chain_prefix); - }; -} - -declare_chain_cli_schema!(Source, source); -declare_chain_cli_schema!(Target, target); -declare_chain_cli_schema!(Relaychain, relaychain); -declare_chain_cli_schema!(Parachain, parachain); - #[cfg(test)] mod tests { - use super::*; use sp_core::Pair; + use substrate_relay_helper::cli::chain_schema::TargetSigningParams; #[test] fn reads_suri_from_file() { diff --git a/relays/bin-substrate/src/cli/detect_equivocations.rs b/relays/bin-substrate/src/cli/detect_equivocations.rs index a8f1ed35f3a..7717b501537 100644 --- a/relays/bin-substrate/src/cli/detect_equivocations.rs +++ b/relays/bin-substrate/src/cli/detect_equivocations.rs @@ -14,25 +14,23 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::{ - bridges::{ - kusama_polkadot::{ - kusama_headers_to_bridge_hub_polkadot::KusamaToBridgeHubPolkadotCliBridge, - polkadot_headers_to_bridge_hub_kusama::PolkadotToBridgeHubKusamaCliBridge, - }, - rococo_westend::{ - rococo_headers_to_bridge_hub_westend::RococoToBridgeHubWestendCliBridge, - westend_headers_to_bridge_hub_rococo::WestendToBridgeHubRococoCliBridge, - }, +use crate::bridges::{ + kusama_polkadot::{ + kusama_headers_to_bridge_hub_polkadot::KusamaToBridgeHubPolkadotCliBridge, + polkadot_headers_to_bridge_hub_kusama::PolkadotToBridgeHubKusamaCliBridge, + }, + rococo_westend::{ + rococo_headers_to_bridge_hub_westend::RococoToBridgeHubWestendCliBridge, + westend_headers_to_bridge_hub_rococo::WestendToBridgeHubRococoCliBridge, }, - cli::{bridge::*, chain_schema::*, PrometheusParams}, }; -use async_trait::async_trait; -use relay_substrate_client::ChainWithTransactions; use structopt::StructOpt; use strum::{EnumString, VariantNames}; -use substrate_relay_helper::{equivocation, equivocation::SubstrateEquivocationDetectionPipeline}; + +use substrate_relay_helper::cli::detect_equivocations::{ + DetectEquivocationsParams, EquivocationsDetector, +}; /// Start equivocation detection loop. #[derive(StructOpt)] @@ -40,13 +38,7 @@ pub struct DetectEquivocations { #[structopt(possible_values = DetectEquivocationsBridge::VARIANTS, case_insensitive = true)] bridge: DetectEquivocationsBridge, #[structopt(flatten)] - source: SourceConnectionParams, - #[structopt(flatten)] - source_sign: SourceSigningParams, - #[structopt(flatten)] - target: TargetConnectionParams, - #[structopt(flatten)] - prometheus_params: PrometheusParams, + params: DetectEquivocationsParams, } #[derive(Debug, EnumString, VariantNames)] @@ -59,29 +51,6 @@ pub enum DetectEquivocationsBridge { WestendToBridgeHubRococo, } -#[async_trait] -trait EquivocationsDetector: RelayToRelayEquivocationDetectionCliBridge -where - Self::Source: ChainWithTransactions, -{ - async fn start(data: DetectEquivocations) -> anyhow::Result<()> { - let source_client = data.source.into_client::().await?; - Self::Equivocation::start_relay_guards( - &source_client, - source_client.can_start_version_guard(), - ) - .await?; - - equivocation::run::( - source_client, - data.target.into_client::().await?, - data.source_sign.transaction_params::()?, - data.prometheus_params.into_metrics_params()?, - ) - .await - } -} - impl EquivocationsDetector for KusamaToBridgeHubPolkadotCliBridge {} impl EquivocationsDetector for PolkadotToBridgeHubKusamaCliBridge {} impl EquivocationsDetector for RococoToBridgeHubWestendCliBridge {} @@ -92,13 +61,13 @@ impl DetectEquivocations { pub async fn run(self) -> anyhow::Result<()> { match self.bridge { DetectEquivocationsBridge::KusamaToBridgeHubPolkadot => - KusamaToBridgeHubPolkadotCliBridge::start(self), + KusamaToBridgeHubPolkadotCliBridge::start(self.params), DetectEquivocationsBridge::PolkadotToBridgeHubKusama => - PolkadotToBridgeHubKusamaCliBridge::start(self), + PolkadotToBridgeHubKusamaCliBridge::start(self.params), DetectEquivocationsBridge::RococoToBridgeHubWestend => - RococoToBridgeHubWestendCliBridge::start(self), + RococoToBridgeHubWestendCliBridge::start(self.params), DetectEquivocationsBridge::WestendToBridgeHubRococo => - WestendToBridgeHubRococoCliBridge::start(self), + WestendToBridgeHubRococoCliBridge::start(self.params), } .await } diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 0b2f9aa7e1e..441487b35a9 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -14,107 +14,31 @@ // 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 codec::Encode; - -use crate::{ - bridges::{ - kusama_polkadot::{ - kusama_headers_to_bridge_hub_polkadot::KusamaToBridgeHubPolkadotCliBridge, - polkadot_headers_to_bridge_hub_kusama::PolkadotToBridgeHubKusamaCliBridge, - }, - polkadot_bulletin::{ - polkadot_bulletin_headers_to_bridge_hub_polkadot::PolkadotBulletinToBridgeHubPolkadotCliBridge, - polkadot_headers_to_polkadot_bulletin::PolkadotToPolkadotBulletinCliBridge, - }, - rococo_bulletin::{ - rococo_bulletin_headers_to_bridge_hub_rococo::RococoBulletinToBridgeHubRococoCliBridge, - rococo_headers_to_rococo_bulletin::RococoToRococoBulletinCliBridge, - }, - rococo_westend::{ - rococo_headers_to_bridge_hub_westend::RococoToBridgeHubWestendCliBridge, - westend_headers_to_bridge_hub_rococo::WestendToBridgeHubRococoCliBridge, - }, +use crate::bridges::{ + kusama_polkadot::{ + kusama_headers_to_bridge_hub_polkadot::KusamaToBridgeHubPolkadotCliBridge, + polkadot_headers_to_bridge_hub_kusama::PolkadotToBridgeHubKusamaCliBridge, + }, + polkadot_bulletin::{ + polkadot_bulletin_headers_to_bridge_hub_polkadot::PolkadotBulletinToBridgeHubPolkadotCliBridge, + polkadot_headers_to_polkadot_bulletin::PolkadotToPolkadotBulletinCliBridge, + }, + rococo_bulletin::{ + rococo_bulletin_headers_to_bridge_hub_rococo::RococoBulletinToBridgeHubRococoCliBridge, + rococo_headers_to_rococo_bulletin::RococoToRococoBulletinCliBridge, + }, + rococo_westend::{ + rococo_headers_to_bridge_hub_westend::RococoToBridgeHubWestendCliBridge, + westend_headers_to_bridge_hub_rococo::WestendToBridgeHubRococoCliBridge, }, - cli::{bridge::CliBridgeBase, chain_schema::*}, }; -use bp_runtime::Chain as ChainBase; -use relay_substrate_client::{AccountKeyPairOf, Chain, UnsignedTransaction}; -use sp_core::Pair; +use relay_substrate_client::Chain; use structopt::StructOpt; use strum::{EnumString, VariantNames}; -use substrate_relay_helper::finality_base::engine::{Engine, Grandpa as GrandpaFinalityEngine}; - -/// Initialize bridge pallet. -#[derive(StructOpt)] -pub struct InitBridge { - /// A bridge instance to initialize. - #[structopt(possible_values = InitBridgeName::VARIANTS, case_insensitive = true)] - bridge: InitBridgeName, - #[structopt(flatten)] - source: SourceConnectionParams, - #[structopt(flatten)] - target: TargetConnectionParams, - #[structopt(flatten)] - target_sign: TargetSigningParams, - /// Generates all required data, but does not submit extrinsic - #[structopt(long)] - dry_run: bool, -} - -#[derive(Debug, EnumString, VariantNames)] -#[strum(serialize_all = "kebab_case")] -/// Bridge to initialize. -pub enum InitBridgeName { - KusamaToBridgeHubPolkadot, - PolkadotToBridgeHubKusama, - PolkadotToPolkadotBulletin, - PolkadotBulletinToBridgeHubPolkadot, - RococoToRococoBulletin, - RococoBulletinToBridgeHubRococo, - RococoToBridgeHubWestend, - WestendToBridgeHubRococo, -} - -#[async_trait] -trait BridgeInitializer: CliBridgeBase -where - ::AccountId: From< as Pair>::Public>, -{ - type Engine: Engine; - - /// Get the encoded call to init the bridge. - fn encode_init_bridge( - init_data: >::InitializationData, - ) -> ::Call; - - /// Initialize the bridge. - async fn init_bridge(data: InitBridge) -> anyhow::Result<()> { - let source_client = data.source.into_client::().await?; - let target_client = data.target.into_client::().await?; - let target_sign = data.target_sign.to_keypair::()?; - let dry_run = data.dry_run; - - substrate_relay_helper::finality::initialize::initialize::( - source_client, - target_client.clone(), - target_sign, - move |transaction_nonce, initialization_data| { - let call = Self::encode_init_bridge(initialization_data); - log::info!( - target: "bridge", - "Initialize bridge call encoded as hex string: {:?}", - format!("0x{}", hex::encode(call.encode())) - ); - Ok(UnsignedTransaction::new(call.into(), transaction_nonce)) - }, - dry_run, - ) - .await; - - Ok(()) - } -} +use substrate_relay_helper::{ + cli::init_bridge::{BridgeInitializer, InitBridgeParams}, + finality_base::engine::{Engine, Grandpa as GrandpaFinalityEngine}, +}; impl BridgeInitializer for RococoToBridgeHubWestendCliBridge { type Engine = GrandpaFinalityEngine; @@ -225,26 +149,50 @@ impl BridgeInitializer for RococoBulletinToBridgeHubRococoCliBridge { } } +/// Initialize bridge pallet. +#[derive(StructOpt)] +pub struct InitBridge { + /// A bridge instance to initialize. + #[structopt(possible_values = InitBridgeName::VARIANTS, case_insensitive = true)] + bridge: InitBridgeName, + #[structopt(flatten)] + params: InitBridgeParams, +} + +#[derive(Debug, EnumString, VariantNames)] +#[strum(serialize_all = "kebab_case")] +/// Bridge to initialize. +pub enum InitBridgeName { + KusamaToBridgeHubPolkadot, + PolkadotToBridgeHubKusama, + PolkadotToPolkadotBulletin, + PolkadotBulletinToBridgeHubPolkadot, + RococoToRococoBulletin, + RococoBulletinToBridgeHubRococo, + RococoToBridgeHubWestend, + WestendToBridgeHubRococo, +} + impl InitBridge { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { match self.bridge { InitBridgeName::KusamaToBridgeHubPolkadot => - KusamaToBridgeHubPolkadotCliBridge::init_bridge(self), + KusamaToBridgeHubPolkadotCliBridge::init_bridge(self.params), InitBridgeName::PolkadotToBridgeHubKusama => - PolkadotToBridgeHubKusamaCliBridge::init_bridge(self), + PolkadotToBridgeHubKusamaCliBridge::init_bridge(self.params), InitBridgeName::PolkadotToPolkadotBulletin => - PolkadotToPolkadotBulletinCliBridge::init_bridge(self), + PolkadotToPolkadotBulletinCliBridge::init_bridge(self.params), InitBridgeName::PolkadotBulletinToBridgeHubPolkadot => - PolkadotBulletinToBridgeHubPolkadotCliBridge::init_bridge(self), + PolkadotBulletinToBridgeHubPolkadotCliBridge::init_bridge(self.params), InitBridgeName::RococoToRococoBulletin => - RococoToRococoBulletinCliBridge::init_bridge(self), + RococoToRococoBulletinCliBridge::init_bridge(self.params), InitBridgeName::RococoBulletinToBridgeHubRococo => - RococoBulletinToBridgeHubRococoCliBridge::init_bridge(self), + RococoBulletinToBridgeHubRococoCliBridge::init_bridge(self.params), InitBridgeName::RococoToBridgeHubWestend => - RococoToBridgeHubWestendCliBridge::init_bridge(self), + RococoToBridgeHubWestendCliBridge::init_bridge(self.params), InitBridgeName::WestendToBridgeHubRococo => - WestendToBridgeHubRococoCliBridge::init_bridge(self), + WestendToBridgeHubRococoCliBridge::init_bridge(self.params), } .await } diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 6d799023cdb..504058894c2 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -17,18 +17,10 @@ //! Deal with CLI args of substrate-to-substrate relay. use async_std::prelude::*; -use codec::{Decode, Encode}; use futures::{select, FutureExt}; -use rbtag::BuildInfo; use signal_hook::consts::*; use signal_hook_async_std::Signals; -use structopt::{clap::arg_enum, StructOpt}; -use strum::{EnumString, VariantNames}; - -use bp_messages::LaneId; -use relay_substrate_client::SimpleRuntimeVersion; - -pub(crate) mod bridge; +use structopt::StructOpt; mod chain_schema; mod detect_equivocations; @@ -50,11 +42,17 @@ pub fn parse_args() -> Command { #[derive(StructOpt)] #[structopt(about = "Substrate-to-Substrate relay")] pub enum Command { + /// Initialize on-chain bridge pallet with current header data. + /// + /// Sends initialization transaction to bootstrap the bridge with current finalized block data. + InitBridge(init_bridge::InitBridge), /// Start headers relay between two chains. /// /// The on-chain bridge component should have been already initialized with /// `init-bridge` sub-command. RelayHeaders(relay_headers::RelayHeaders), + /// Relay parachain heads. + RelayParachains(relay_parachains::RelayParachains), /// Start messages relay between two chains. /// /// Ties up to `Messages` pallets on both chains and starts relaying messages. @@ -67,12 +65,6 @@ pub enum Command { /// the message relays - i.e. when there are messages or confirmations that needs to be /// relayed between chains. RelayHeadersAndMessages(Box), - /// Initialize on-chain bridge pallet with current header data. - /// - /// Sends initialization transaction to bootstrap the bridge with current finalized block data. - InitBridge(init_bridge::InitBridge), - /// Relay parachain heads. - RelayParachains(relay_parachains::RelayParachains), /// Detect and report equivocations. /// /// Parses the source chain headers that were synchronized with the target chain looking for @@ -86,10 +78,10 @@ impl Command { use relay_utils::initialize::{initialize_logger, initialize_relay}; match self { + Self::InitBridge(_) | Self::RelayHeaders(_) | Self::RelayMessages(_) | - Self::RelayHeadersAndMessages(_) | - Self::InitBridge(_) => { + Self::RelayHeadersAndMessages(_) => { initialize_relay(); }, _ => { @@ -101,11 +93,11 @@ impl Command { /// Run the command. async fn do_run(self) -> anyhow::Result<()> { match self { + Self::InitBridge(arg) => arg.run().await?, Self::RelayHeaders(arg) => arg.run().await?, + Self::RelayParachains(arg) => arg.run().await?, Self::RelayMessages(arg) => arg.run().await?, Self::RelayHeadersAndMessages(arg) => arg.run().await?, - Self::InitBridge(arg) => arg.run().await?, - Self::RelayParachains(arg) => arg.run().await?, Self::DetectEquivocations(arg) => arg.run().await?, } Ok(()) @@ -137,181 +129,3 @@ impl Command { } } } - -arg_enum! { - #[derive(Debug)] - /// The origin to use when dispatching the message on the target chain. - /// - /// - `Target` uses account existing on the target chain (requires target private key). - /// - `Origin` uses account derived from the source-chain account. - pub enum Origins { - Target, - Source, - } -} - -/// Bridge-supported network definition. -/// -/// Used to abstract away CLI commands. -pub trait CliChain: relay_substrate_client::Chain { - /// Current version of the chain runtime, known to relay. - /// - /// can be `None` if relay is not going to submit transactions to that chain. - const RUNTIME_VERSION: Option; -} - -/// Lane id. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct HexLaneId(pub [u8; 4]); - -impl From for LaneId { - fn from(lane_id: HexLaneId) -> LaneId { - LaneId(lane_id.0) - } -} - -impl std::str::FromStr for HexLaneId { - type Err = hex::FromHexError; - - fn from_str(s: &str) -> Result { - let mut lane_id = [0u8; 4]; - hex::decode_to_slice(s, &mut lane_id)?; - Ok(HexLaneId(lane_id)) - } -} - -/// Nicer formatting for raw bytes vectors. -#[derive(Default, Encode, Decode, PartialEq, Eq)] -pub struct HexBytes(pub Vec); - -impl std::str::FromStr for HexBytes { - type Err = hex::FromHexError; - - fn from_str(s: &str) -> Result { - Ok(Self(hex::decode(s)?)) - } -} - -impl std::fmt::Debug for HexBytes { - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(fmt, "0x{self}") - } -} - -impl std::fmt::Display for HexBytes { - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(fmt, "{}", hex::encode(&self.0)) - } -} - -/// Prometheus metrics params. -#[derive(Clone, Debug, PartialEq, StructOpt)] -pub struct PrometheusParams { - /// Do not expose a Prometheus metric endpoint. - #[structopt(long)] - pub no_prometheus: bool, - /// Expose Prometheus endpoint at given interface. - #[structopt(long, default_value = "127.0.0.1")] - pub prometheus_host: String, - /// Expose Prometheus endpoint at given port. - #[structopt(long, default_value = "9616")] - pub prometheus_port: u16, -} - -/// Struct to get git commit info and build time. -#[derive(BuildInfo)] -struct SubstrateRelayBuildInfo; - -impl SubstrateRelayBuildInfo { - /// Get git commit in form ``. - pub fn get_git_commit() -> String { - // on gitlab we use images without git installed, so we can't use `rbtag` there - // locally we don't have `CI_*` env variables, so we can't rely on them - // => we are using `CI_*` env variables or else `rbtag` - let maybe_sha_from_ci = option_env!("CI_COMMIT_SHORT_SHA"); - maybe_sha_from_ci - .map(|short_sha| { - // we assume that on CI the copy is always clean - format!("{short_sha}-clean") - }) - .unwrap_or_else(|| SubstrateRelayBuildInfo.get_build_commit().into()) - } -} - -impl PrometheusParams { - /// Tries to convert CLI metrics params into metrics params, used by the relay. - pub fn into_metrics_params(self) -> anyhow::Result { - let metrics_address = if !self.no_prometheus { - Some(relay_utils::metrics::MetricsAddress { - host: self.prometheus_host, - port: self.prometheus_port, - }) - } else { - None - }; - - let relay_version = option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"); - let relay_commit = SubstrateRelayBuildInfo::get_git_commit(); - relay_utils::metrics::MetricsParams::new( - metrics_address, - relay_version.into(), - relay_commit, - ) - .map_err(|e| anyhow::format_err!("{:?}", e)) - } -} - -/// Either explicit or maximal allowed value. -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum ExplicitOrMaximal { - /// User has explicitly specified argument value. - Explicit(V), - /// Maximal allowed value for this argument. - Maximal, -} - -impl std::str::FromStr for ExplicitOrMaximal -where - V::Err: std::fmt::Debug, -{ - type Err = String; - - fn from_str(s: &str) -> Result { - if s.to_lowercase() == "max" { - return Ok(ExplicitOrMaximal::Maximal) - } - - V::from_str(s) - .map(ExplicitOrMaximal::Explicit) - .map_err(|e| format!("Failed to parse '{e:?}'. Expected 'max' or explicit value")) - } -} - -#[doc = "Runtime version params."] -#[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy, EnumString, VariantNames)] -pub enum RuntimeVersionType { - /// Auto query version from chain - Auto, - /// Custom `spec_version` and `transaction_version` - Custom, - /// Read version from bundle dependencies directly. - Bundle, -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn hex_bytes_display_matches_from_str_for_clap() { - // given - let hex = HexBytes(vec![1, 2, 3, 4]); - let display = format!("{hex}"); - - // when - let hex2: HexBytes = display.parse().unwrap(); - - // then - assert_eq!(hex.0, hex2.0); - } -} diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index a3b5c4c9f82..e244d0e9a24 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -14,7 +14,6 @@ // 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 structopt::StructOpt; use strum::{EnumString, VariantNames}; @@ -32,10 +31,8 @@ use crate::bridges::{ rococo_headers_to_rococo_bulletin::RococoToRococoBulletinCliBridge, }, }; -use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; -use substrate_relay_helper::finality::SubstrateFinalitySyncPipeline; -use crate::cli::{bridge::*, chain_schema::*, PrometheusParams}; +use substrate_relay_helper::cli::relay_headers::{HeadersRelayer, RelayHeadersParams}; /// Start headers relayer process. #[derive(StructOpt)] @@ -43,18 +40,8 @@ pub struct RelayHeaders { /// A bridge instance to relay headers for. #[structopt(possible_values = RelayHeadersBridge::VARIANTS, case_insensitive = true)] bridge: RelayHeadersBridge, - /// If passed, only mandatory headers (headers that are changing the GRANDPA authorities set) - /// are relayed. - #[structopt(long)] - only_mandatory_headers: bool, #[structopt(flatten)] - source: SourceConnectionParams, - #[structopt(flatten)] - target: TargetConnectionParams, - #[structopt(flatten)] - target_sign: TargetSigningParams, - #[structopt(flatten)] - prometheus_params: PrometheusParams, + params: RelayHeadersParams, } #[derive(Debug, EnumString, VariantNames)] @@ -69,37 +56,6 @@ pub enum RelayHeadersBridge { RococoBulletinToBridgeHubRococo, } -#[async_trait] -trait HeadersRelayer: RelayToRelayHeadersCliBridge { - /// Relay headers. - async fn relay_headers(data: RelayHeaders) -> anyhow::Result<()> { - let source_client = data.source.into_client::().await?; - let target_client = data.target.into_client::().await?; - let target_transactions_mortality = data.target_sign.target_transactions_mortality; - let target_sign = data.target_sign.to_keypair::()?; - - let metrics_params: relay_utils::metrics::MetricsParams = - data.prometheus_params.into_metrics_params()?; - GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?; - - let target_transactions_params = substrate_relay_helper::TransactionParams { - signer: target_sign, - mortality: target_transactions_mortality, - }; - Self::Finality::start_relay_guards(&target_client, target_client.can_start_version_guard()) - .await?; - - substrate_relay_helper::finality::run::( - source_client, - target_client, - data.only_mandatory_headers, - target_transactions_params, - metrics_params, - ) - .await - } -} - impl HeadersRelayer for KusamaToBridgeHubPolkadotCliBridge {} impl HeadersRelayer for PolkadotToBridgeHubKusamaCliBridge {} impl HeadersRelayer for PolkadotToPolkadotBulletinCliBridge {} @@ -112,17 +68,17 @@ impl RelayHeaders { pub async fn run(self) -> anyhow::Result<()> { match self.bridge { RelayHeadersBridge::KusamaToBridgeHubPolkadot => - KusamaToBridgeHubPolkadotCliBridge::relay_headers(self), + KusamaToBridgeHubPolkadotCliBridge::relay_headers(self.params), RelayHeadersBridge::PolkadotToBridgeHubKusama => - PolkadotToBridgeHubKusamaCliBridge::relay_headers(self), + PolkadotToBridgeHubKusamaCliBridge::relay_headers(self.params), RelayHeadersBridge::PolkadotToPolkadotBulletin => - PolkadotToPolkadotBulletinCliBridge::relay_headers(self), + PolkadotToPolkadotBulletinCliBridge::relay_headers(self.params), RelayHeadersBridge::PolkadotBulletinToBridgeHubPolkadot => - PolkadotBulletinToBridgeHubPolkadotCliBridge::relay_headers(self), + PolkadotBulletinToBridgeHubPolkadotCliBridge::relay_headers(self.params), RelayHeadersBridge::RococoToRococoBulletin => - RococoToRococoBulletinCliBridge::relay_headers(self), + RococoToRococoBulletinCliBridge::relay_headers(self.params), RelayHeadersBridge::RococoBulletinToBridgeHubRococo => - RococoBulletinToBridgeHubRococoCliBridge::relay_headers(self), + RococoBulletinToBridgeHubRococoCliBridge::relay_headers(self.params), } .await } diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs similarity index 52% rename from relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs rename to relays/bin-substrate/src/cli/relay_headers_and_messages.rs index c445bdddcc9..229661748ed 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -23,176 +23,48 @@ //! `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. -#[macro_use] -mod parachain_to_parachain; -#[macro_use] -mod relay_to_relay; -#[macro_use] -mod relay_to_parachain; - use async_trait::async_trait; -use std::{marker::PhantomData, sync::Arc}; use structopt::StructOpt; -use futures::{FutureExt, TryFutureExt}; -use relay_to_parachain::*; - -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 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, - CliChain, HexLaneId, PrometheusParams, + relay_headers_and_messages::{ + parachain_to_parachain::ParachainToParachainBridge, relay_to_parachain::*, + BridgeEndCommonParams, Full2WayBridge, Full2WayBridgeCommonParams, + HeadersAndMessagesSharedParams, + }, }, - declare_chain_cli_schema, + declare_chain_cli_schema, declare_parachain_to_parachain_bridge_schema, + declare_relay_to_parachain_bridge_schema, TransactionParams, }; -use bp_messages::LaneId; -use bp_runtime::BalanceOf; -use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, Chain, ChainWithBalances, ChainWithMessages, - ChainWithTransactions, Client, Parachain, -}; -use relay_utils::metrics::MetricsParams; -use sp_core::Pair; -use substrate_relay_helper::{ - messages_lane::{MessagesRelayLimits, MessagesRelayParams}, - on_demand::OnDemandRelay, - TaggedAccount, TransactionParams, -}; - -/// Parameters that have the same names across all bridges. -#[derive(Debug, PartialEq, StructOpt)] -pub struct HeadersAndMessagesSharedParams { - /// Hex-encoded lane identifiers that should be served by the complex relay. - #[structopt(long, default_value = "00000000")] - pub lane: Vec, - /// If passed, only mandatory headers (headers that are changing the GRANDPA authorities set) - /// are relayed. - #[structopt(long)] - pub only_mandatory_headers: bool, - #[structopt(flatten)] - pub prometheus_params: PrometheusParams, -} - -/// Bridge parameters, shared by all bridge types. -pub struct Full2WayBridgeCommonParams< - Left: ChainWithTransactions + CliChain, - Right: ChainWithTransactions + CliChain, -> { - /// Shared parameters. - pub shared: HeadersAndMessagesSharedParams, - /// Parameters of the left chain. - pub left: BridgeEndCommonParams, - /// Parameters of the right chain. - pub right: BridgeEndCommonParams, - - /// Common metric parameters. - pub metrics_params: MetricsParams, -} - -impl - Full2WayBridgeCommonParams -{ - /// Creates new bridge parameters from its components. - pub fn new>( - shared: HeadersAndMessagesSharedParams, - left: BridgeEndCommonParams, - right: BridgeEndCommonParams, - ) -> anyhow::Result { - // Create metrics registry. - let metrics_params = shared.prometheus_params.clone().into_metrics_params()?; - let metrics_params = relay_utils::relay_metrics(metrics_params).into_params(); - - Ok(Self { shared, left, right, metrics_params }) - } -} - -/// Parameters that are associated with one side of the bridge. -pub struct BridgeEndCommonParams { - /// Chain client. - pub client: Client, - /// Params used for sending transactions to the chain. - pub tx_params: TransactionParams>, - /// Accounts, which balances are exposed as metrics by the relay process. - pub accounts: Vec>>, -} - -/// All data of the bidirectional complex relay. -struct FullBridge< - 'a, - Source: ChainWithTransactions + CliChain, - Target: ChainWithTransactions + CliChain, - Bridge: MessagesCliBridge, -> { - source: &'a mut BridgeEndCommonParams, - target: &'a mut BridgeEndCommonParams, - metrics_params: &'a MetricsParams, - _phantom_data: PhantomData, -} - -impl< - 'a, - Source: ChainWithTransactions + CliChain, - Target: ChainWithTransactions + CliChain, - Bridge: MessagesCliBridge, - > FullBridge<'a, Source, Target, Bridge> -where - AccountIdOf: From< as Pair>::Public>, - AccountIdOf: From< as Pair>::Public>, - BalanceOf: TryFrom> + Into, -{ - /// Construct complex relay given it components. - fn new( - source: &'a mut BridgeEndCommonParams, - target: &'a mut BridgeEndCommonParams, - metrics_params: &'a MetricsParams, - ) -> Self { - Self { source, target, metrics_params, _phantom_data: Default::default() } - } - - /// Returns message relay parameters. - fn messages_relay_params( - &self, - source_to_target_headers_relay: Arc>, - target_to_source_headers_relay: Arc>, - lane_id: LaneId, - maybe_limits: Option, - ) -> MessagesRelayParams { - MessagesRelayParams { - source_client: self.source.client.clone(), - source_transaction_params: self.source.tx_params.clone(), - target_client: self.target.client.clone(), - target_transaction_params: self.target.tx_params.clone(), - source_to_target_headers_relay: Some(source_to_target_headers_relay), - target_to_source_headers_relay: Some(target_to_source_headers_relay), - lane_id, - limits: maybe_limits, - metrics_params: self.metrics_params.clone().disable(), - } - } -} // All supported chains. declare_chain_cli_schema!(Rococo, rococo); @@ -247,171 +119,6 @@ declare_parachain_to_parachain_bridge_schema!(BridgeHubKusama, Kusama, BridgeHub declare_relay_to_parachain_bridge_schema!(PolkadotBulletin, BridgeHubPolkadot, Polkadot); declare_relay_to_parachain_bridge_schema!(RococoBulletin, BridgeHubRococo, Rococo); -/// Base portion of the bidirectional complex relay. -/// -/// This main purpose of extracting this trait is that in different relays the implementation -/// of `start_on_demand_headers_relayers` method will be different. But the number of -/// implementations is limited to relay <> relay, parachain <> relay and parachain <> parachain. -/// This trait allows us to reuse these implementations in different bridges. -#[async_trait] -trait Full2WayBridgeBase: Sized + Send + Sync { - /// The CLI params for the bridge. - type Params; - /// The left relay chain. - type Left: ChainWithTransactions + CliChain; - /// The right destination chain (it can be a relay or a parachain). - type Right: ChainWithTransactions + CliChain; - - /// Reference to common relay parameters. - fn common(&self) -> &Full2WayBridgeCommonParams; - - /// Mutable reference to common relay parameters. - fn mut_common(&mut self) -> &mut Full2WayBridgeCommonParams; - - /// Start on-demand headers relays. - async fn start_on_demand_headers_relayers( - &mut self, - ) -> anyhow::Result<( - Arc>, - Arc>, - )>; -} - -/// Bidirectional complex relay. -#[async_trait] -trait Full2WayBridge: Sized + Sync -where - AccountIdOf: From< as Pair>::Public>, - AccountIdOf: From< as Pair>::Public>, - BalanceOf: TryFrom> + Into, - BalanceOf: TryFrom> + Into, -{ - /// Base portion of the bidirectional complex relay. - type Base: Full2WayBridgeBase; - - /// The left relay chain. - type Left: ChainWithTransactions + ChainWithBalances + ChainWithMessages + CliChain; - /// The right relay chain. - type Right: ChainWithTransactions + ChainWithBalances + ChainWithMessages + CliChain; - - /// Left to Right bridge. - type L2R: MessagesCliBridge; - /// Right to Left bridge - type R2L: MessagesCliBridge; - - /// Construct new bridge. - fn new(params: ::Params) -> anyhow::Result; - - /// Reference to the base relay portion. - fn base(&self) -> &Self::Base; - - /// Mutable reference to the base relay portion. - fn mut_base(&mut self) -> &mut Self::Base; - - /// Creates and returns Left to Right complex relay. - fn left_to_right(&mut self) -> FullBridge { - let common = self.mut_base().mut_common(); - FullBridge::<_, _, Self::L2R>::new( - &mut common.left, - &mut common.right, - &common.metrics_params, - ) - } - - /// Creates and returns Right to Left complex relay. - fn right_to_left(&mut self) -> FullBridge { - let common = self.mut_base().mut_common(); - FullBridge::<_, _, Self::R2L>::new( - &mut common.right, - &mut common.left, - &common.metrics_params, - ) - } - - /// Start complex relay. - async fn run(&mut self) -> anyhow::Result<()> { - // Register standalone metrics. - { - let common = self.mut_base().mut_common(); - common.left.accounts.push(TaggedAccount::Messages { - id: common.left.tx_params.signer.public().into(), - bridged_chain: Self::Right::NAME.to_string(), - }); - common.right.accounts.push(TaggedAccount::Messages { - id: common.right.tx_params.signer.public().into(), - bridged_chain: Self::Left::NAME.to_string(), - }); - } - - // start on-demand header relays - let (left_to_right_on_demand_headers, right_to_left_on_demand_headers) = - self.mut_base().start_on_demand_headers_relayers().await?; - - // add balance-related metrics - let lanes = self - .base() - .common() - .shared - .lane - .iter() - .cloned() - .map(Into::into) - .collect::>(); - { - let common = self.mut_base().mut_common(); - substrate_relay_helper::messages_metrics::add_relay_balances_metrics::<_, Self::Right>( - common.left.client.clone(), - &common.metrics_params, - &common.left.accounts, - &lanes, - ) - .await?; - substrate_relay_helper::messages_metrics::add_relay_balances_metrics::<_, Self::Left>( - common.right.client.clone(), - &common.metrics_params, - &common.right.accounts, - &lanes, - ) - .await?; - } - - // Need 2x capacity since we consider both directions for each lane - let mut message_relays = Vec::with_capacity(lanes.len() * 2); - for lane in lanes { - let left_to_right_messages = substrate_relay_helper::messages_lane::run::< - ::MessagesLane, - >(self.left_to_right().messages_relay_params( - left_to_right_on_demand_headers.clone(), - right_to_left_on_demand_headers.clone(), - lane, - Self::L2R::maybe_messages_limits(), - )) - .map_err(|e| anyhow::format_err!("{}", e)) - .boxed(); - message_relays.push(left_to_right_messages); - - let right_to_left_messages = substrate_relay_helper::messages_lane::run::< - ::MessagesLane, - >(self.right_to_left().messages_relay_params( - right_to_left_on_demand_headers.clone(), - left_to_right_on_demand_headers.clone(), - lane, - Self::R2L::maybe_messages_limits(), - )) - .map_err(|e| anyhow::format_err!("{}", e)) - .boxed(); - message_relays.push(right_to_left_messages); - } - - relay_utils::relay_metrics(self.base().common().metrics_params.clone()) - .expose() - .await - .map_err(|e| anyhow::format_err!("{}", e))?; - - futures::future::select_all(message_relays).await.0 - } -} - /// BridgeHubRococo <> BridgeHubWestend complex relay. pub struct BridgeHubRococoBridgeHubWestendFull2WayBridge { base: ::Base, @@ -556,6 +263,7 @@ impl RelayHeadersAndMessages { #[cfg(test)] mod tests { use super::*; + use substrate_relay_helper::cli::{HexLaneId, PrometheusParams}; #[test] fn should_parse_parachain_to_parachain_options() { diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index b20725b53c7..92b98f4d983 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -14,10 +14,8 @@ // 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 sp_core::Pair; use structopt::StructOpt; -use strum::VariantNames; +use strum::{EnumString, VariantNames}; use crate::bridges::{ kusama_polkadot::{ @@ -37,10 +35,21 @@ use crate::bridges::{ bridge_hub_westend_messages_to_bridge_hub_rococo::BridgeHubWestendToBridgeHubRococoMessagesCliBridge, }, }; -use relay_substrate_client::{AccountIdOf, AccountKeyPairOf, BalanceOf, ChainWithTransactions}; -use substrate_relay_helper::{messages_lane::MessagesRelayParams, TransactionParams}; +use substrate_relay_helper::cli::relay_messages::{MessagesRelayer, RelayMessagesParams}; -use crate::cli::{bridge::*, chain_schema::*, CliChain, HexLaneId, PrometheusParams}; +#[derive(Debug, PartialEq, Eq, EnumString, VariantNames)] +#[strum(serialize_all = "kebab_case")] +/// Supported full bridges (headers + messages). +pub enum FullBridge { + BridgeHubRococoToBridgeHubWestend, + BridgeHubWestendToBridgeHubRococo, + BridgeHubKusamaToBridgeHubPolkadot, + BridgeHubPolkadotToBridgeHubKusama, + PolkadotBulletinToBridgeHubPolkadot, + BridgeHubPolkadotToPolkadotBulletin, + RococoBulletinToBridgeHubRococo, + BridgeHubRococoToRococoBulletin, +} /// Start messages relayer process. #[derive(StructOpt)] @@ -48,57 +57,8 @@ pub struct RelayMessages { /// A bridge instance to relay messages for. #[structopt(possible_values = FullBridge::VARIANTS, case_insensitive = true)] bridge: FullBridge, - /// 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, - #[structopt(flatten)] - target_sign: TargetSigningParams, #[structopt(flatten)] - prometheus_params: PrometheusParams, -} - -#[async_trait] -trait MessagesRelayer: MessagesCliBridge -where - Self::Source: ChainWithTransactions + CliChain, - AccountIdOf: From< as Pair>::Public>, - AccountIdOf: From< as Pair>::Public>, - BalanceOf: TryFrom>, -{ - async fn relay_messages(data: RelayMessages) -> anyhow::Result<()> { - let source_client = data.source.into_client::().await?; - let source_sign = data.source_sign.to_keypair::()?; - let source_transactions_mortality = data.source_sign.transactions_mortality()?; - let target_client = data.target.into_client::().await?; - let target_sign = data.target_sign.to_keypair::()?; - let target_transactions_mortality = data.target_sign.transactions_mortality()?; - - substrate_relay_helper::messages_lane::run::(MessagesRelayParams { - source_client, - source_transaction_params: TransactionParams { - signer: source_sign, - mortality: source_transactions_mortality, - }, - target_client, - target_transaction_params: TransactionParams { - signer: target_sign, - mortality: target_transactions_mortality, - }, - source_to_target_headers_relay: None, - target_to_source_headers_relay: None, - lane_id: data.lane.into(), - limits: Self::maybe_messages_limits(), - metrics_params: data.prometheus_params.into_metrics_params()?, - }) - .await - .map_err(|e| anyhow::format_err!("{}", e)) - } + params: RelayMessagesParams, } impl MessagesRelayer for BridgeHubRococoToBridgeHubWestendMessagesCliBridge {} @@ -115,21 +75,21 @@ impl RelayMessages { pub async fn run(self) -> anyhow::Result<()> { match self.bridge { FullBridge::BridgeHubRococoToBridgeHubWestend => - BridgeHubRococoToBridgeHubWestendMessagesCliBridge::relay_messages(self), + BridgeHubRococoToBridgeHubWestendMessagesCliBridge::relay_messages(self.params), FullBridge::BridgeHubWestendToBridgeHubRococo => - BridgeHubWestendToBridgeHubRococoMessagesCliBridge::relay_messages(self), + BridgeHubWestendToBridgeHubRococoMessagesCliBridge::relay_messages(self.params), FullBridge::BridgeHubKusamaToBridgeHubPolkadot => - BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge::relay_messages(self), + BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge::relay_messages(self.params), FullBridge::BridgeHubPolkadotToBridgeHubKusama => - BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge::relay_messages(self), + BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge::relay_messages(self.params), FullBridge::PolkadotBulletinToBridgeHubPolkadot => - PolkadotBulletinToBridgeHubPolkadotMessagesCliBridge::relay_messages(self), + PolkadotBulletinToBridgeHubPolkadotMessagesCliBridge::relay_messages(self.params), FullBridge::BridgeHubPolkadotToPolkadotBulletin => - BridgeHubPolkadotToPolkadotBulletinMessagesCliBridge::relay_messages(self), + BridgeHubPolkadotToPolkadotBulletinMessagesCliBridge::relay_messages(self.params), FullBridge::RococoBulletinToBridgeHubRococo => - RococoBulletinToBridgeHubRococoMessagesCliBridge::relay_messages(self), + RococoBulletinToBridgeHubRococoMessagesCliBridge::relay_messages(self.params), FullBridge::BridgeHubRococoToRococoBulletin => - BridgeHubRococoToRococoBulletinMessagesCliBridge::relay_messages(self), + BridgeHubRococoToRococoBulletinMessagesCliBridge::relay_messages(self.params), } .await } diff --git a/relays/bin-substrate/src/cli/relay_parachains.rs b/relays/bin-substrate/src/cli/relay_parachains.rs index dc1c5ad362f..65382d1ca11 100644 --- a/relays/bin-substrate/src/cli/relay_parachains.rs +++ b/relays/bin-substrate/src/cli/relay_parachains.rs @@ -26,24 +26,9 @@ use crate::bridges::{ westend_parachains_to_bridge_hub_rococo::BridgeHubWestendToBridgeHubRococoCliBridge, }, }; -use async_std::sync::Mutex; -use async_trait::async_trait; -use parachains_relay::parachains_loop::{AvailableHeader, SourceClient, TargetClient}; -use relay_substrate_client::Parachain; -use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; -use std::sync::Arc; use structopt::StructOpt; use strum::{EnumString, VariantNames}; -use substrate_relay_helper::{ - parachains::{source::ParachainsSource, target::ParachainsTarget, ParachainsPipelineAdapter}, - TransactionParams, -}; - -use crate::cli::{ - bridge::{CliBridgeBase, ParachainToRelayHeadersCliBridge}, - chain_schema::*, - PrometheusParams, -}; +use substrate_relay_helper::cli::relay_parachains::{ParachainsRelayer, RelayParachainsParams}; /// Start parachain heads relayer process. #[derive(StructOpt)] @@ -52,13 +37,7 @@ pub struct RelayParachains { #[structopt(possible_values = RelayParachainsBridge::VARIANTS, case_insensitive = true)] bridge: RelayParachainsBridge, #[structopt(flatten)] - source: SourceConnectionParams, - #[structopt(flatten)] - target: TargetConnectionParams, - #[structopt(flatten)] - target_sign: TargetSigningParams, - #[structopt(flatten)] - prometheus_params: PrometheusParams, + params: RelayParachainsParams, } /// Parachain heads relay bridge. @@ -73,47 +52,6 @@ pub enum RelayParachainsBridge { WestendToBridgeHubRococo, } -#[async_trait] -trait ParachainsRelayer: ParachainToRelayHeadersCliBridge -where - ParachainsSource: - SourceClient>, - ParachainsTarget: - TargetClient>, - ::Source: Parachain, -{ - async fn relay_parachains(data: RelayParachains) -> anyhow::Result<()> { - let source_client = data.source.into_client::().await?; - let source_client = ParachainsSource::::new( - source_client, - Arc::new(Mutex::new(AvailableHeader::Missing)), - ); - - let target_transaction_params = TransactionParams { - signer: data.target_sign.to_keypair::()?, - mortality: data.target_sign.target_transactions_mortality, - }; - let target_client = data.target.into_client::().await?; - let target_client = ParachainsTarget::::new( - target_client.clone(), - target_transaction_params, - ); - - let metrics_params: relay_utils::metrics::MetricsParams = - data.prometheus_params.into_metrics_params()?; - GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?; - - parachains_relay::parachains_loop::run( - source_client, - target_client, - metrics_params, - futures::future::pending(), - ) - .await - .map_err(|e| anyhow::format_err!("{}", e)) - } -} - impl ParachainsRelayer for BridgeHubRococoToBridgeHubWestendCliBridge {} impl ParachainsRelayer for BridgeHubWestendToBridgeHubRococoCliBridge {} impl ParachainsRelayer for BridgeHubKusamaToBridgeHubPolkadotCliBridge {} @@ -126,17 +64,17 @@ impl RelayParachains { pub async fn run(self) -> anyhow::Result<()> { match self.bridge { RelayParachainsBridge::RococoToBridgeHubWestend => - BridgeHubRococoToBridgeHubWestendCliBridge::relay_parachains(self), + BridgeHubRococoToBridgeHubWestendCliBridge::relay_parachains(self.params), RelayParachainsBridge::WestendToBridgeHubRococo => - BridgeHubWestendToBridgeHubRococoCliBridge::relay_parachains(self), + BridgeHubWestendToBridgeHubRococoCliBridge::relay_parachains(self.params), RelayParachainsBridge::KusamaToBridgeHubPolkadot => - BridgeHubKusamaToBridgeHubPolkadotCliBridge::relay_parachains(self), + BridgeHubKusamaToBridgeHubPolkadotCliBridge::relay_parachains(self.params), RelayParachainsBridge::PolkadotToBridgeHubKusama => - BridgeHubPolkadotToBridgeHubKusamaCliBridge::relay_parachains(self), + BridgeHubPolkadotToBridgeHubKusamaCliBridge::relay_parachains(self.params), RelayParachainsBridge::PolkadotToPolkadotBulletin => - PolkadotToPolkadotBulletinCliBridge::relay_parachains(self), + PolkadotToPolkadotBulletinCliBridge::relay_parachains(self.params), RelayParachainsBridge::RococoToRococoBulletin => - RococoToRococoBulletinCliBridge::relay_parachains(self), + RococoToRococoBulletinCliBridge::relay_parachains(self.params), } .await } diff --git a/relays/bin-substrate/src/main.rs b/relays/bin-substrate/src/main.rs index 33a423b0766..214bfa60e24 100644 --- a/relays/bin-substrate/src/main.rs +++ b/relays/bin-substrate/src/main.rs @@ -19,7 +19,6 @@ #![warn(missing_docs)] mod bridges; -mod chains; mod cli; fn main() { diff --git a/relays/client-bridge-hub-kusama/src/lib.rs b/relays/client-bridge-hub-kusama/src/lib.rs index 4ad6d2e2fb7..80f621dee30 100644 --- a/relays/client-bridge-hub-kusama/src/lib.rs +++ b/relays/client-bridge-hub-kusama/src/lib.rs @@ -23,8 +23,9 @@ use bp_polkadot::SuffixedCommonTransactionExtensionExt; use codec::Encode; use relay_substrate_client::{ calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages, - ChainWithTransactions, ChainWithUtilityPallet, Error as SubstrateError, - MockedRuntimeUtilityPallet, SignParam, UnderlyingChainProvider, UnsignedTransaction, + ChainWithRuntimeVersion, ChainWithTransactions, ChainWithUtilityPallet, + Error as SubstrateError, MockedRuntimeUtilityPallet, SignParam, SimpleRuntimeVersion, + UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -120,3 +121,8 @@ impl ChainWithMessages for BridgeHubKusama { const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_bridge_hub_kusama::FROM_BRIDGE_HUB_KUSAMA_MESSAGE_DETAILS_METHOD; } + +impl ChainWithRuntimeVersion for BridgeHubKusama { + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 1_001_000, transaction_version: 4 }); +} diff --git a/relays/client-bridge-hub-polkadot/src/lib.rs b/relays/client-bridge-hub-polkadot/src/lib.rs index 8ac6569210a..ed147e92d5b 100644 --- a/relays/client-bridge-hub-polkadot/src/lib.rs +++ b/relays/client-bridge-hub-polkadot/src/lib.rs @@ -23,8 +23,9 @@ use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; use codec::Encode; use relay_substrate_client::{ calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages, - ChainWithTransactions, ChainWithUtilityPallet, Error as SubstrateError, - MockedRuntimeUtilityPallet, SignParam, UnderlyingChainProvider, UnsignedTransaction, + ChainWithRuntimeVersion, ChainWithTransactions, ChainWithUtilityPallet, + Error as SubstrateError, MockedRuntimeUtilityPallet, SignParam, SimpleRuntimeVersion, + UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -124,3 +125,8 @@ impl ChainWithMessages for BridgeHubPolkadot { const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_bridge_hub_polkadot::FROM_BRIDGE_HUB_POLKADOT_MESSAGE_DETAILS_METHOD; } + +impl ChainWithRuntimeVersion for BridgeHubPolkadot { + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 1_001_000, transaction_version: 3 }); +} diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs index 7ec58453474..169135646d9 100644 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -23,8 +23,9 @@ use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; use codec::Encode; use relay_substrate_client::{ calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages, - ChainWithTransactions, ChainWithUtilityPallet, Error as SubstrateError, - MockedRuntimeUtilityPallet, SignParam, UnderlyingChainProvider, UnsignedTransaction, + ChainWithRuntimeVersion, ChainWithTransactions, ChainWithUtilityPallet, + Error as SubstrateError, MockedRuntimeUtilityPallet, SignParam, SimpleRuntimeVersion, + UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -122,3 +123,8 @@ impl ChainWithMessages for BridgeHubRococo { const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_bridge_hub_rococo::FROM_BRIDGE_HUB_ROCOCO_MESSAGE_DETAILS_METHOD; } + +impl ChainWithRuntimeVersion for BridgeHubRococo { + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 4 }); +} diff --git a/relays/client-bridge-hub-westend/src/lib.rs b/relays/client-bridge-hub-westend/src/lib.rs index c6bf1b45dd1..5e4462f863a 100644 --- a/relays/client-bridge-hub-westend/src/lib.rs +++ b/relays/client-bridge-hub-westend/src/lib.rs @@ -23,8 +23,9 @@ use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; use codec::Encode; use relay_substrate_client::{ calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages, - ChainWithTransactions, ChainWithUtilityPallet, Error as SubstrateError, - MockedRuntimeUtilityPallet, SignParam, UnderlyingChainProvider, UnsignedTransaction, + ChainWithRuntimeVersion, ChainWithTransactions, ChainWithUtilityPallet, + Error as SubstrateError, MockedRuntimeUtilityPallet, SignParam, SimpleRuntimeVersion, + UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -120,3 +121,8 @@ impl ChainWithMessages for BridgeHubWestend { const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_bridge_hub_westend::FROM_BRIDGE_HUB_WESTEND_MESSAGE_DETAILS_METHOD; } + +impl ChainWithRuntimeVersion for BridgeHubWestend { + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 4 }); +} diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 0f412284e79..a953a383e12 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -22,8 +22,9 @@ use bp_kusama::{AccountInfoStorageMapKeyProvider, KUSAMA_SYNCED_HEADERS_GRANDPA_ use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; use codec::Encode; use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithGrandpa, ChainWithTransactions, Error as SubstrateError, - RelayChain, SignParam, UnderlyingChainProvider, UnsignedTransaction, + Chain, ChainWithBalances, ChainWithGrandpa, ChainWithRuntimeVersion, ChainWithTransactions, + Error as SubstrateError, RelayChain, SignParam, SimpleRuntimeVersion, UnderlyingChainProvider, + UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount, MultiAddress}; @@ -114,3 +115,8 @@ impl ChainWithTransactions for Kusama { )) } } + +impl ChainWithRuntimeVersion for Kusama { + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 1_001_002, transaction_version: 25 }); +} diff --git a/relays/client-polkadot-bulletin/src/lib.rs b/relays/client-polkadot-bulletin/src/lib.rs index b5bbeda8025..a6cdd8ee675 100644 --- a/relays/client-polkadot-bulletin/src/lib.rs +++ b/relays/client-polkadot-bulletin/src/lib.rs @@ -21,8 +21,9 @@ mod codegen_runtime; use bp_polkadot_bulletin::POLKADOT_BULLETIN_SYNCED_HEADERS_GRANDPA_INFO_METHOD; use codec::Encode; use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, ChainWithTransactions, - Error as SubstrateError, SignParam, UnderlyingChainProvider, UnsignedTransaction, + Chain, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, ChainWithRuntimeVersion, + ChainWithTransactions, Error as SubstrateError, SignParam, SimpleRuntimeVersion, + UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount, MultiAddress}; @@ -131,3 +132,8 @@ impl ChainWithTransactions for PolkadotBulletin { )) } } + +impl ChainWithRuntimeVersion for PolkadotBulletin { + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 100, transaction_version: 1 }); +} diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index 638e01d1b6a..af75f0dbb87 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -22,8 +22,9 @@ use bp_polkadot::{AccountInfoStorageMapKeyProvider, POLKADOT_SYNCED_HEADERS_GRAN use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; use codec::Encode; use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithGrandpa, ChainWithTransactions, Error as SubstrateError, - RelayChain, SignParam, UnderlyingChainProvider, UnsignedTransaction, + Chain, ChainWithBalances, ChainWithGrandpa, ChainWithRuntimeVersion, ChainWithTransactions, + Error as SubstrateError, RelayChain, SignParam, SimpleRuntimeVersion, UnderlyingChainProvider, + UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount, MultiAddress}; @@ -114,3 +115,8 @@ impl ChainWithTransactions for Polkadot { )) } } + +impl ChainWithRuntimeVersion for Polkadot { + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 1_001_002, transaction_version: 25 }); +} diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index 7843af241c1..5fad80d5c98 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -22,8 +22,9 @@ use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; use bp_rococo::ROCOCO_SYNCED_HEADERS_GRANDPA_INFO_METHOD; use codec::Encode; use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithGrandpa, ChainWithTransactions, Error as SubstrateError, - RelayChain, SignParam, UnderlyingChainProvider, UnsignedTransaction, + Chain, ChainWithBalances, ChainWithGrandpa, ChainWithRuntimeVersion, ChainWithTransactions, + Error as SubstrateError, RelayChain, SignParam, SimpleRuntimeVersion, UnderlyingChainProvider, + UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount, MultiAddress}; @@ -114,3 +115,8 @@ impl ChainWithTransactions for Rococo { )) } } + +impl ChainWithRuntimeVersion for Rococo { + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 24 }); +} diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 4f9467ec59d..2aba5f5674d 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -16,6 +16,7 @@ use crate::calls::UtilityCall; +use crate::SimpleRuntimeVersion; use bp_header_chain::ChainWithGrandpa as ChainWithGrandpaBase; use bp_messages::ChainWithMessages as ChainWithMessagesBase; use bp_runtime::{ @@ -58,6 +59,16 @@ pub trait Chain: ChainBase + Clone { type Call: Clone + Codec + Debug + Send + Sync; } +/// Bridge-supported network definition. +/// +/// Used to abstract away CLI commands. +pub trait ChainWithRuntimeVersion: Chain { + /// Current version of the chain runtime, known to relay. + /// + /// can be `None` if relay is not going to submit transactions to that chain. + const RUNTIME_VERSION: Option; +} + /// Substrate-based relay chain that supports parachains. /// /// We assume that the parachains are supported using `runtime_parachains::paras` pallet. diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index 84c2ad10cf8..6c62b8e1cd5 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -35,9 +35,9 @@ use std::time::Duration; pub use crate::{ chain::{ AccountKeyPairOf, BlockWithJustification, CallOf, Chain, ChainWithBalances, - ChainWithGrandpa, ChainWithMessages, ChainWithTransactions, ChainWithUtilityPallet, - FullRuntimeUtilityPallet, MockedRuntimeUtilityPallet, Parachain, RelayChain, SignParam, - TransactionStatusOf, UnsignedTransaction, UtilityPallet, + ChainWithGrandpa, ChainWithMessages, ChainWithRuntimeVersion, ChainWithTransactions, + ChainWithUtilityPallet, FullRuntimeUtilityPallet, MockedRuntimeUtilityPallet, Parachain, + RelayChain, SignParam, TransactionStatusOf, UnsignedTransaction, UtilityPallet, }, client::{ is_ancient_block, ChainRuntimeVersion, Client, OpaqueGrandpaAuthoritiesSet, diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index 8067f67a2bb..737c6c08519 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -22,8 +22,9 @@ use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; use bp_westend::WESTEND_SYNCED_HEADERS_GRANDPA_INFO_METHOD; use codec::Encode; use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithGrandpa, ChainWithTransactions, Error as SubstrateError, - RelayChain, SignParam, UnderlyingChainProvider, UnsignedTransaction, + Chain, ChainWithBalances, ChainWithGrandpa, ChainWithRuntimeVersion, ChainWithTransactions, + Error as SubstrateError, RelayChain, SignParam, SimpleRuntimeVersion, UnderlyingChainProvider, + UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount, MultiAddress}; @@ -114,3 +115,8 @@ impl ChainWithTransactions for Westend { )) } } + +impl ChainWithRuntimeVersion for Westend { + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 24 }); +} diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 161548ac4d5..d85e2762a4e 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -10,14 +10,17 @@ workspace = true [dependencies] anyhow = "1.0" -thiserror = { workspace = true } async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } futures = "0.3.30" hex = "0.4" -num-traits = "0.2" log = { workspace = true } +num-traits = "0.2" +rbtag = "0.3" +structopt = "0.3" +strum = { version = "0.26.2", features = ["derive"] } +thiserror = { workspace = true } # Bridge dependencies diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/lib-substrate-relay/src/cli/bridge.rs similarity index 81% rename from relays/bin-substrate/src/cli/bridge.rs rename to relays/lib-substrate-relay/src/cli/bridge.rs index 9457dfa5c06..316f59a2b0c 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/lib-substrate-relay/src/cli/bridge.rs @@ -14,38 +14,26 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::cli::CliChain; -use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; -use relay_substrate_client::{Chain, ChainWithTransactions, Parachain, RelayChain}; -use strum::{EnumString, VariantNames}; -use substrate_relay_helper::{ +//! Basic traits for exposing bridges in the CLI. + +use crate::{ equivocation::SubstrateEquivocationDetectionPipeline, finality::SubstrateFinalitySyncPipeline, messages_lane::{MessagesRelayLimits, SubstrateMessageLane}, parachains::SubstrateParachainsPipeline, }; - -#[derive(Debug, PartialEq, Eq, EnumString, VariantNames)] -#[strum(serialize_all = "kebab_case")] -/// Supported full bridges (headers + messages). -pub enum FullBridge { - BridgeHubRococoToBridgeHubWestend, - BridgeHubWestendToBridgeHubRococo, - BridgeHubKusamaToBridgeHubPolkadot, - BridgeHubPolkadotToBridgeHubKusama, - PolkadotBulletinToBridgeHubPolkadot, - BridgeHubPolkadotToPolkadotBulletin, - RococoBulletinToBridgeHubRococo, - BridgeHubRococoToRococoBulletin, -} +use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; +use relay_substrate_client::{ + Chain, ChainWithRuntimeVersion, ChainWithTransactions, Parachain, RelayChain, +}; /// Minimal bridge representation that can be used from the CLI. /// It connects a source chain to a target chain. pub trait CliBridgeBase: Sized { /// The source chain. - type Source: Chain + CliChain; + type Source: Chain + ChainWithRuntimeVersion; /// The target chain. - type Target: ChainWithTransactions + CliChain; + type Target: ChainWithTransactions + ChainWithRuntimeVersion; } /// Bridge representation that can be used from the CLI for relaying headers @@ -60,6 +48,7 @@ pub trait RelayToRelayHeadersCliBridge: CliBridgeBase { /// Convenience trait that adds bounds to `CliBridgeBase`. pub trait RelayToRelayEquivocationDetectionCliBridgeBase: CliBridgeBase { + /// The source chain with extra bounds. type BoundedSource: ChainWithTransactions; } @@ -89,10 +78,10 @@ pub trait ParachainToRelayHeadersCliBridge: CliBridgeBase where Self::Source: Parachain, { - // The `CliBridgeBase` type represents the parachain in this situation. - // We need to add an extra type for the relay chain. + /// The `CliBridgeBase` type represents the parachain in this situation. + /// We need to add an extra type for the relay chain. type SourceRelay: Chain - + CliChain + + ChainWithRuntimeVersion + RelayChain; /// Finality proofs synchronization pipeline (source parachain -> target). type ParachainFinality: SubstrateParachainsPipeline< diff --git a/relays/lib-substrate-relay/src/cli/chain_schema.rs b/relays/lib-substrate-relay/src/cli/chain_schema.rs new file mode 100644 index 00000000000..c5b802173ad --- /dev/null +++ b/relays/lib-substrate-relay/src/cli/chain_schema.rs @@ -0,0 +1,250 @@ +// 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 . + +//! Primitives related to chain CLI options. + +use relay_substrate_client::{AccountKeyPairOf, ChainWithTransactions}; +use structopt::StructOpt; +use strum::{EnumString, VariantNames}; + +use relay_substrate_client::{ChainRuntimeVersion, ChainWithRuntimeVersion, SimpleRuntimeVersion}; + +use crate::TransactionParams; + +#[doc = "Runtime version params."] +#[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy, EnumString, VariantNames)] +pub enum RuntimeVersionType { + /// Auto query version from chain + Auto, + /// Custom `spec_version` and `transaction_version` + Custom, + /// Read version from bundle dependencies directly. + Bundle, +} + +/// Create chain-specific set of runtime version parameters. +#[macro_export] +macro_rules! declare_chain_runtime_version_params_cli_schema { + ($chain:ident, $chain_prefix:ident) => { + bp_runtime::paste::item! { + #[doc = $chain " runtime version params."] + #[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy)] + pub struct [<$chain RuntimeVersionParams>] { + #[doc = "The type of runtime version for chain " $chain] + #[structopt(long, default_value = "Bundle")] + pub [<$chain_prefix _version_mode>]: RuntimeVersionType, + #[doc = "The custom sepc_version for chain " $chain] + #[structopt(long)] + pub [<$chain_prefix _spec_version>]: Option, + #[doc = "The custom transaction_version for chain " $chain] + #[structopt(long)] + pub [<$chain_prefix _transaction_version>]: Option, + } + + impl [<$chain RuntimeVersionParams>] { + /// Converts self into `ChainRuntimeVersion`. + pub fn into_runtime_version( + self, + bundle_runtime_version: Option, + ) -> anyhow::Result { + Ok(match self.[<$chain_prefix _version_mode>] { + RuntimeVersionType::Auto => ChainRuntimeVersion::Auto, + RuntimeVersionType::Custom => { + let custom_spec_version = self.[<$chain_prefix _spec_version>] + .ok_or_else(|| anyhow::Error::msg(format!("The {}-spec-version is required when choose custom mode", stringify!($chain_prefix))))?; + let custom_transaction_version = self.[<$chain_prefix _transaction_version>] + .ok_or_else(|| anyhow::Error::msg(format!("The {}-transaction-version is required when choose custom mode", stringify!($chain_prefix))))?; + ChainRuntimeVersion::Custom( + SimpleRuntimeVersion { + spec_version: custom_spec_version, + transaction_version: custom_transaction_version + } + ) + }, + RuntimeVersionType::Bundle => match bundle_runtime_version { + Some(runtime_version) => ChainRuntimeVersion::Custom(runtime_version), + None => { + return Err(anyhow::format_err!("Cannot use bundled runtime version of {}: it is not known to the relay", stringify!($chain_prefix))); + } + }, + }) + } + } + } + }; +} + +/// Create chain-specific set of runtime version parameters. +#[macro_export] +macro_rules! declare_chain_connection_params_cli_schema { + ($chain:ident, $chain_prefix:ident) => { + bp_runtime::paste::item! { + #[doc = $chain " connection params."] + #[derive(StructOpt, Debug, PartialEq, Eq, Clone)] + pub struct [<$chain ConnectionParams>] { + #[doc = "Connect to " $chain " node at given host."] + #[structopt(long, default_value = "127.0.0.1")] + pub [<$chain_prefix _host>]: String, + #[doc = "Connect to " $chain " node websocket server at given port."] + #[structopt(long, default_value = "9944")] + pub [<$chain_prefix _port>]: u16, + #[doc = "Use secure websocket connection."] + #[structopt(long)] + pub [<$chain_prefix _secure>]: bool, + #[doc = "Custom runtime version"] + #[structopt(flatten)] + pub [<$chain_prefix _runtime_version>]: [<$chain RuntimeVersionParams>], + } + + impl [<$chain ConnectionParams>] { + /// Convert connection params into Substrate client. + #[allow(dead_code)] + pub async fn into_client( + self, + ) -> anyhow::Result> { + let chain_runtime_version = self + .[<$chain_prefix _runtime_version>] + .into_runtime_version(Chain::RUNTIME_VERSION)?; + Ok(relay_substrate_client::Client::new(relay_substrate_client::ConnectionParams { + host: self.[<$chain_prefix _host>], + port: self.[<$chain_prefix _port>], + secure: self.[<$chain_prefix _secure>], + chain_runtime_version, + }) + .await + ) + } + } + } + }; +} + +/// Create chain-specific set of signing parameters. +#[macro_export] +macro_rules! declare_chain_signing_params_cli_schema { + ($chain:ident, $chain_prefix:ident) => { + bp_runtime::paste::item! { + #[doc = $chain " signing params."] + #[derive(StructOpt, Debug, PartialEq, Eq, Clone)] + pub struct [<$chain SigningParams>] { + #[doc = "The SURI of secret key to use when transactions are submitted to the " $chain " node."] + #[structopt(long)] + pub [<$chain_prefix _signer>]: Option, + #[doc = "The password for the SURI of secret key to use when transactions are submitted to the " $chain " node."] + #[structopt(long)] + pub [<$chain_prefix _signer_password>]: Option, + + #[doc = "Path to the file, that contains SURI of secret key to use when transactions are submitted to the " $chain " node. Can be overridden with " $chain_prefix "_signer option."] + #[structopt(long)] + pub [<$chain_prefix _signer_file>]: Option, + #[doc = "Path to the file, that password for the SURI of secret key to use when transactions are submitted to the " $chain " node. Can be overridden with " $chain_prefix "_signer_password option."] + #[structopt(long)] + pub [<$chain_prefix _signer_password_file>]: Option, + + #[doc = "Transactions mortality period, in blocks. MUST be a power of two in [4; 65536] range. MAY NOT be larger than `BlockHashCount` parameter of the chain system module."] + #[structopt(long)] + pub [<$chain_prefix _transactions_mortality>]: Option, + } + + impl [<$chain SigningParams>] { + /// Return transactions mortality. + #[allow(dead_code)] + pub fn transactions_mortality(&self) -> anyhow::Result> { + self.[<$chain_prefix _transactions_mortality>] + .map(|transactions_mortality| { + if !(4..=65536).contains(&transactions_mortality) + || !transactions_mortality.is_power_of_two() + { + Err(anyhow::format_err!( + "Transactions mortality {} is not a power of two in a [4; 65536] range", + transactions_mortality, + )) + } else { + Ok(transactions_mortality) + } + }) + .transpose() + } + + /// Parse signing params into chain-specific KeyPair. + #[allow(dead_code)] + pub fn to_keypair(&self) -> anyhow::Result> { + let suri = match (self.[<$chain_prefix _signer>].as_ref(), self.[<$chain_prefix _signer_file>].as_ref()) { + (Some(suri), _) => suri.to_owned(), + (None, Some(suri_file)) => std::fs::read_to_string(suri_file) + .map_err(|err| anyhow::format_err!( + "Failed to read SURI from file {:?}: {}", + suri_file, + err, + ))?, + (None, None) => return Err(anyhow::format_err!( + "One of options must be specified: '{}' or '{}'", + stringify!([<$chain_prefix _signer>]), + stringify!([<$chain_prefix _signer_file>]), + )), + }; + + let suri_password = match ( + self.[<$chain_prefix _signer_password>].as_ref(), + self.[<$chain_prefix _signer_password_file>].as_ref(), + ) { + (Some(suri_password), _) => Some(suri_password.to_owned()), + (None, Some(suri_password_file)) => std::fs::read_to_string(suri_password_file) + .map(Some) + .map_err(|err| anyhow::format_err!( + "Failed to read SURI password from file {:?}: {}", + suri_password_file, + err, + ))?, + _ => None, + }; + + use sp_core::crypto::Pair; + + AccountKeyPairOf::::from_string( + &suri, + suri_password.as_deref() + ).map_err(|e| anyhow::format_err!("{:?}", e)) + } + + /// Return transaction parameters. + #[allow(dead_code)] + pub fn transaction_params( + &self, + ) -> anyhow::Result>> { + Ok(TransactionParams { + mortality: self.transactions_mortality()?, + signer: self.to_keypair::()?, + }) + } + } + } + }; +} + +/// Create chain-specific set of configuration objects: connection parameters, +/// signing parameters and bridge initialization parameters. +#[macro_export] +macro_rules! declare_chain_cli_schema { + ($chain:ident, $chain_prefix:ident) => { + $crate::declare_chain_runtime_version_params_cli_schema!($chain, $chain_prefix); + $crate::declare_chain_connection_params_cli_schema!($chain, $chain_prefix); + $crate::declare_chain_signing_params_cli_schema!($chain, $chain_prefix); + }; +} + +declare_chain_cli_schema!(Source, source); +declare_chain_cli_schema!(Target, target); diff --git a/relays/lib-substrate-relay/src/cli/detect_equivocations.rs b/relays/lib-substrate-relay/src/cli/detect_equivocations.rs new file mode 100644 index 00000000000..b98e41b2a43 --- /dev/null +++ b/relays/lib-substrate-relay/src/cli/detect_equivocations.rs @@ -0,0 +1,65 @@ +// Copyright 2019-2023 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 . + +//! Primitives for exposing the equivocation detection functionality in the CLI. + +use crate::{ + cli::{bridge::*, chain_schema::*, PrometheusParams}, + equivocation, + equivocation::SubstrateEquivocationDetectionPipeline, +}; + +use async_trait::async_trait; +use relay_substrate_client::ChainWithTransactions; +use structopt::StructOpt; + +/// Start equivocation detection loop. +#[derive(StructOpt)] +pub struct DetectEquivocationsParams { + #[structopt(flatten)] + source: SourceConnectionParams, + #[structopt(flatten)] + source_sign: SourceSigningParams, + #[structopt(flatten)] + target: TargetConnectionParams, + #[structopt(flatten)] + prometheus_params: PrometheusParams, +} + +/// Trait used for starting the equivocation detection loop between 2 chains. +#[async_trait] +pub trait EquivocationsDetector: RelayToRelayEquivocationDetectionCliBridge +where + Self::Source: ChainWithTransactions, +{ + /// Start the equivocation detection loop. + async fn start(data: DetectEquivocationsParams) -> anyhow::Result<()> { + let source_client = data.source.into_client::().await?; + Self::Equivocation::start_relay_guards( + &source_client, + source_client.can_start_version_guard(), + ) + .await?; + + equivocation::run::( + source_client, + data.target.into_client::().await?, + data.source_sign.transaction_params::()?, + data.prometheus_params.into_metrics_params()?, + ) + .await + } +} diff --git a/relays/lib-substrate-relay/src/cli/init_bridge.rs b/relays/lib-substrate-relay/src/cli/init_bridge.rs new file mode 100644 index 00000000000..bf7c86437ba --- /dev/null +++ b/relays/lib-substrate-relay/src/cli/init_bridge.rs @@ -0,0 +1,85 @@ +// Copyright 2019-2021 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 . + +//! Primitives for exposing the bridge initialization functionality in the CLI. + +use async_trait::async_trait; +use codec::Encode; + +use crate::{ + cli::{bridge::CliBridgeBase, chain_schema::*}, + finality_base::engine::Engine, +}; +use bp_runtime::Chain as ChainBase; +use relay_substrate_client::{AccountKeyPairOf, Chain, UnsignedTransaction}; +use sp_core::Pair; +use structopt::StructOpt; + +/// Bridge initialization params. +#[derive(StructOpt)] +pub struct InitBridgeParams { + #[structopt(flatten)] + source: SourceConnectionParams, + #[structopt(flatten)] + target: TargetConnectionParams, + #[structopt(flatten)] + target_sign: TargetSigningParams, + /// Generates all required data, but does not submit extrinsic + #[structopt(long)] + dry_run: bool, +} + +/// Trait used for bridge initializing. +#[async_trait] +pub trait BridgeInitializer: CliBridgeBase +where + ::AccountId: From< as Pair>::Public>, +{ + /// The finality engine used by the source chain. + type Engine: Engine; + + /// Get the encoded call to init the bridge. + fn encode_init_bridge( + init_data: >::InitializationData, + ) -> ::Call; + + /// Initialize the bridge. + async fn init_bridge(data: InitBridgeParams) -> anyhow::Result<()> { + let source_client = data.source.into_client::().await?; + let target_client = data.target.into_client::().await?; + let target_sign = data.target_sign.to_keypair::()?; + let dry_run = data.dry_run; + + crate::finality::initialize::initialize::( + source_client, + target_client.clone(), + target_sign, + move |transaction_nonce, initialization_data| { + let call = Self::encode_init_bridge(initialization_data); + log::info!( + target: "bridge", + "Initialize bridge call encoded as hex string: {:?}", + format!("0x{}", hex::encode(call.encode())) + ); + Ok(UnsignedTransaction::new(call.into(), transaction_nonce)) + }, + dry_run, + ) + .await; + + Ok(()) + } +} diff --git a/relays/lib-substrate-relay/src/cli/mod.rs b/relays/lib-substrate-relay/src/cli/mod.rs new file mode 100644 index 00000000000..0dd0d5474b3 --- /dev/null +++ b/relays/lib-substrate-relay/src/cli/mod.rs @@ -0,0 +1,192 @@ +// Copyright 2019-2021 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 . + +//! Deal with CLI args of substrate-to-substrate relay. + +use codec::{Decode, Encode}; +use rbtag::BuildInfo; +use structopt::StructOpt; +use strum::{EnumString, VariantNames}; + +use bp_messages::LaneId; + +pub mod bridge; +pub mod chain_schema; +pub mod detect_equivocations; +pub mod init_bridge; +pub mod relay_headers; +pub mod relay_headers_and_messages; +pub mod relay_messages; +pub mod relay_parachains; + +/// The target that will be used when publishing logs related to this pallet. +pub const LOG_TARGET: &str = "bridge"; + +/// Lane id. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct HexLaneId(pub [u8; 4]); + +impl From for LaneId { + fn from(lane_id: HexLaneId) -> LaneId { + LaneId(lane_id.0) + } +} + +impl std::str::FromStr for HexLaneId { + type Err = hex::FromHexError; + + fn from_str(s: &str) -> Result { + let mut lane_id = [0u8; 4]; + hex::decode_to_slice(s, &mut lane_id)?; + Ok(HexLaneId(lane_id)) + } +} + +/// Nicer formatting for raw bytes vectors. +#[derive(Default, Encode, Decode, PartialEq, Eq)] +pub struct HexBytes(pub Vec); + +impl std::str::FromStr for HexBytes { + type Err = hex::FromHexError; + + fn from_str(s: &str) -> Result { + Ok(Self(hex::decode(s)?)) + } +} + +impl std::fmt::Debug for HexBytes { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(fmt, "0x{self}") + } +} + +impl std::fmt::Display for HexBytes { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(fmt, "{}", hex::encode(&self.0)) + } +} + +/// Prometheus metrics params. +#[derive(Clone, Debug, PartialEq, StructOpt)] +pub struct PrometheusParams { + /// Do not expose a Prometheus metric endpoint. + #[structopt(long)] + pub no_prometheus: bool, + /// Expose Prometheus endpoint at given interface. + #[structopt(long, default_value = "127.0.0.1")] + pub prometheus_host: String, + /// Expose Prometheus endpoint at given port. + #[structopt(long, default_value = "9616")] + pub prometheus_port: u16, +} + +/// Struct to get git commit info and build time. +#[derive(BuildInfo)] +struct SubstrateRelayBuildInfo; + +impl SubstrateRelayBuildInfo { + /// Get git commit in form ``. + pub fn get_git_commit() -> String { + // on gitlab we use images without git installed, so we can't use `rbtag` there + // locally we don't have `CI_*` env variables, so we can't rely on them + // => we are using `CI_*` env variables or else `rbtag` + let maybe_sha_from_ci = option_env!("CI_COMMIT_SHORT_SHA"); + maybe_sha_from_ci + .map(|short_sha| { + // we assume that on CI the copy is always clean + format!("{short_sha}-clean") + }) + .unwrap_or_else(|| SubstrateRelayBuildInfo.get_build_commit().into()) + } +} + +impl PrometheusParams { + /// Tries to convert CLI metrics params into metrics params, used by the relay. + pub fn into_metrics_params(self) -> anyhow::Result { + let metrics_address = if !self.no_prometheus { + Some(relay_utils::metrics::MetricsAddress { + host: self.prometheus_host, + port: self.prometheus_port, + }) + } else { + None + }; + + let relay_version = option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"); + let relay_commit = SubstrateRelayBuildInfo::get_git_commit(); + relay_utils::metrics::MetricsParams::new( + metrics_address, + relay_version.into(), + relay_commit, + ) + .map_err(|e| anyhow::format_err!("{:?}", e)) + } +} + +/// Either explicit or maximal allowed value. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ExplicitOrMaximal { + /// User has explicitly specified argument value. + Explicit(V), + /// Maximal allowed value for this argument. + Maximal, +} + +impl std::str::FromStr for ExplicitOrMaximal +where + V::Err: std::fmt::Debug, +{ + type Err = String; + + fn from_str(s: &str) -> Result { + if s.to_lowercase() == "max" { + return Ok(ExplicitOrMaximal::Maximal) + } + + V::from_str(s) + .map(ExplicitOrMaximal::Explicit) + .map_err(|e| format!("Failed to parse '{e:?}'. Expected 'max' or explicit value")) + } +} + +#[doc = "Runtime version params."] +#[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy, EnumString, VariantNames)] +pub enum RuntimeVersionType { + /// Auto query version from chain + Auto, + /// Custom `spec_version` and `transaction_version` + Custom, + /// Read version from bundle dependencies directly. + Bundle, +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn hex_bytes_display_matches_from_str_for_clap() { + // given + let hex = HexBytes(vec![1, 2, 3, 4]); + let display = format!("{hex}"); + + // when + let hex2: HexBytes = display.parse().unwrap(); + + // then + assert_eq!(hex.0, hex2.0); + } +} diff --git a/relays/lib-substrate-relay/src/cli/relay_headers.rs b/relays/lib-substrate-relay/src/cli/relay_headers.rs new file mode 100644 index 00000000000..90558ed4613 --- /dev/null +++ b/relays/lib-substrate-relay/src/cli/relay_headers.rs @@ -0,0 +1,76 @@ +// Copyright 2019-2021 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 . + +//! Primitives for exposing the headers relaying functionality in the CLI. + +use async_trait::async_trait; +use structopt::StructOpt; + +use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; + +use crate::{ + cli::{bridge::*, chain_schema::*, PrometheusParams}, + finality::SubstrateFinalitySyncPipeline, +}; + +/// Chain headers relaying params. +#[derive(StructOpt)] +pub struct RelayHeadersParams { + /// If passed, only mandatory headers (headers that are changing the GRANDPA authorities set) + /// are relayed. + #[structopt(long)] + only_mandatory_headers: bool, + #[structopt(flatten)] + source: SourceConnectionParams, + #[structopt(flatten)] + target: TargetConnectionParams, + #[structopt(flatten)] + target_sign: TargetSigningParams, + #[structopt(flatten)] + prometheus_params: PrometheusParams, +} + +/// Trait used for relaying headers between 2 chains. +#[async_trait] +pub trait HeadersRelayer: RelayToRelayHeadersCliBridge { + /// Relay headers. + async fn relay_headers(data: RelayHeadersParams) -> anyhow::Result<()> { + let source_client = data.source.into_client::().await?; + let target_client = data.target.into_client::().await?; + let target_transactions_mortality = data.target_sign.target_transactions_mortality; + let target_sign = data.target_sign.to_keypair::()?; + + let metrics_params: relay_utils::metrics::MetricsParams = + data.prometheus_params.into_metrics_params()?; + GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?; + + let target_transactions_params = crate::TransactionParams { + signer: target_sign, + mortality: target_transactions_mortality, + }; + Self::Finality::start_relay_guards(&target_client, target_client.can_start_version_guard()) + .await?; + + crate::finality::run::( + source_client, + target_client, + data.only_mandatory_headers, + target_transactions_params, + metrics_params, + ) + .await + } +} diff --git a/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/mod.rs b/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/mod.rs new file mode 100644 index 00000000000..d404f714b58 --- /dev/null +++ b/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/mod.rs @@ -0,0 +1,484 @@ +// 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. + +#[macro_use] +pub mod parachain_to_parachain; +#[macro_use] +pub mod relay_to_relay; +#[macro_use] +pub mod relay_to_parachain; + +use async_trait::async_trait; +use std::{marker::PhantomData, sync::Arc}; +use structopt::StructOpt; + +use futures::{FutureExt, TryFutureExt}; + +use crate::{ + cli::{bridge::MessagesCliBridge, HexLaneId, PrometheusParams}, + messages_lane::{MessagesRelayLimits, MessagesRelayParams}, + on_demand::OnDemandRelay, + TaggedAccount, TransactionParams, +}; +use bp_messages::LaneId; +use bp_runtime::BalanceOf; +use relay_substrate_client::{ + AccountIdOf, AccountKeyPairOf, Chain, ChainWithBalances, ChainWithMessages, + ChainWithRuntimeVersion, ChainWithTransactions, Client, +}; +use relay_utils::metrics::MetricsParams; +use sp_core::Pair; + +/// Parameters that have the same names across all bridges. +#[derive(Debug, PartialEq, StructOpt)] +pub struct HeadersAndMessagesSharedParams { + /// Hex-encoded lane identifiers that should be served by the complex relay. + #[structopt(long, default_value = "00000000")] + pub lane: Vec, + /// If passed, only mandatory headers (headers that are changing the GRANDPA authorities set) + /// are relayed. + #[structopt(long)] + pub only_mandatory_headers: bool, + #[structopt(flatten)] + /// Prometheus metrics params. + pub prometheus_params: PrometheusParams, +} + +/// Bridge parameters, shared by all bridge types. +pub struct Full2WayBridgeCommonParams< + Left: ChainWithTransactions + ChainWithRuntimeVersion, + Right: ChainWithTransactions + ChainWithRuntimeVersion, +> { + /// Shared parameters. + pub shared: HeadersAndMessagesSharedParams, + /// Parameters of the left chain. + pub left: BridgeEndCommonParams, + /// Parameters of the right chain. + pub right: BridgeEndCommonParams, + + /// Common metric parameters. + pub metrics_params: MetricsParams, +} + +impl< + Left: ChainWithTransactions + ChainWithRuntimeVersion, + Right: ChainWithTransactions + ChainWithRuntimeVersion, + > Full2WayBridgeCommonParams +{ + /// Creates new bridge parameters from its components. + pub fn new>( + shared: HeadersAndMessagesSharedParams, + left: BridgeEndCommonParams, + right: BridgeEndCommonParams, + ) -> anyhow::Result { + // Create metrics registry. + let metrics_params = shared.prometheus_params.clone().into_metrics_params()?; + let metrics_params = relay_utils::relay_metrics(metrics_params).into_params(); + + Ok(Self { shared, left, right, metrics_params }) + } +} + +/// Parameters that are associated with one side of the bridge. +pub struct BridgeEndCommonParams { + /// Chain client. + pub client: Client, + /// Params used for sending transactions to the chain. + pub tx_params: TransactionParams>, + /// Accounts, which balances are exposed as metrics by the relay process. + pub accounts: Vec>>, +} + +/// All data of the bidirectional complex relay. +pub struct FullBridge< + 'a, + Source: ChainWithTransactions + ChainWithRuntimeVersion, + Target: ChainWithTransactions + ChainWithRuntimeVersion, + Bridge: MessagesCliBridge, +> { + source: &'a mut BridgeEndCommonParams, + target: &'a mut BridgeEndCommonParams, + metrics_params: &'a MetricsParams, + _phantom_data: PhantomData, +} + +impl< + 'a, + Source: ChainWithTransactions + ChainWithRuntimeVersion, + Target: ChainWithTransactions + ChainWithRuntimeVersion, + Bridge: MessagesCliBridge, + > FullBridge<'a, Source, Target, Bridge> +where + AccountIdOf: From< as Pair>::Public>, + AccountIdOf: From< as Pair>::Public>, + BalanceOf: TryFrom> + Into, +{ + /// Construct complex relay given it components. + fn new( + source: &'a mut BridgeEndCommonParams, + target: &'a mut BridgeEndCommonParams, + metrics_params: &'a MetricsParams, + ) -> Self { + Self { source, target, metrics_params, _phantom_data: Default::default() } + } + + /// Returns message relay parameters. + fn messages_relay_params( + &self, + source_to_target_headers_relay: Arc>, + target_to_source_headers_relay: Arc>, + lane_id: LaneId, + maybe_limits: Option, + ) -> MessagesRelayParams { + MessagesRelayParams { + source_client: self.source.client.clone(), + source_transaction_params: self.source.tx_params.clone(), + target_client: self.target.client.clone(), + target_transaction_params: self.target.tx_params.clone(), + source_to_target_headers_relay: Some(source_to_target_headers_relay), + target_to_source_headers_relay: Some(target_to_source_headers_relay), + lane_id, + limits: maybe_limits, + metrics_params: self.metrics_params.clone().disable(), + } + } +} + +/// Base portion of the bidirectional complex relay. +/// +/// This main purpose of extracting this trait is that in different relays the implementation +/// of `start_on_demand_headers_relayers` method will be different. But the number of +/// implementations is limited to relay <> relay, parachain <> relay and parachain <> parachain. +/// This trait allows us to reuse these implementations in different bridges. +#[async_trait] +pub trait Full2WayBridgeBase: Sized + Send + Sync { + /// The CLI params for the bridge. + type Params; + /// The left relay chain. + type Left: ChainWithTransactions + ChainWithRuntimeVersion; + /// The right destination chain (it can be a relay or a parachain). + type Right: ChainWithTransactions + ChainWithRuntimeVersion; + + /// Reference to common relay parameters. + fn common(&self) -> &Full2WayBridgeCommonParams; + + /// Mutable reference to common relay parameters. + fn mut_common(&mut self) -> &mut Full2WayBridgeCommonParams; + + /// Start on-demand headers relays. + async fn start_on_demand_headers_relayers( + &mut self, + ) -> anyhow::Result<( + Arc>, + Arc>, + )>; +} + +/// Bidirectional complex relay. +#[async_trait] +pub trait Full2WayBridge: Sized + Sync +where + AccountIdOf: From< as Pair>::Public>, + AccountIdOf: From< as Pair>::Public>, + BalanceOf: TryFrom> + Into, + BalanceOf: TryFrom> + Into, +{ + /// Base portion of the bidirectional complex relay. + type Base: Full2WayBridgeBase; + + /// The left relay chain. + type Left: ChainWithTransactions + + ChainWithBalances + + ChainWithMessages + + ChainWithRuntimeVersion; + /// The right relay chain. + type Right: ChainWithTransactions + + ChainWithBalances + + ChainWithMessages + + ChainWithRuntimeVersion; + + /// Left to Right bridge. + type L2R: MessagesCliBridge; + /// Right to Left bridge + type R2L: MessagesCliBridge; + + /// Construct new bridge. + fn new(params: ::Params) -> anyhow::Result; + + /// Reference to the base relay portion. + fn base(&self) -> &Self::Base; + + /// Mutable reference to the base relay portion. + fn mut_base(&mut self) -> &mut Self::Base; + + /// Creates and returns Left to Right complex relay. + fn left_to_right(&mut self) -> FullBridge { + let common = self.mut_base().mut_common(); + FullBridge::<_, _, Self::L2R>::new( + &mut common.left, + &mut common.right, + &common.metrics_params, + ) + } + + /// Creates and returns Right to Left complex relay. + fn right_to_left(&mut self) -> FullBridge { + let common = self.mut_base().mut_common(); + FullBridge::<_, _, Self::R2L>::new( + &mut common.right, + &mut common.left, + &common.metrics_params, + ) + } + + /// Start complex relay. + async fn run(&mut self) -> anyhow::Result<()> { + // Register standalone metrics. + { + let common = self.mut_base().mut_common(); + common.left.accounts.push(TaggedAccount::Messages { + id: common.left.tx_params.signer.public().into(), + bridged_chain: Self::Right::NAME.to_string(), + }); + common.right.accounts.push(TaggedAccount::Messages { + id: common.right.tx_params.signer.public().into(), + bridged_chain: Self::Left::NAME.to_string(), + }); + } + + // start on-demand header relays + let (left_to_right_on_demand_headers, right_to_left_on_demand_headers) = + self.mut_base().start_on_demand_headers_relayers().await?; + + // add balance-related metrics + let lanes = self + .base() + .common() + .shared + .lane + .iter() + .cloned() + .map(Into::into) + .collect::>(); + { + let common = self.mut_base().mut_common(); + crate::messages_metrics::add_relay_balances_metrics::<_, Self::Right>( + common.left.client.clone(), + &common.metrics_params, + &common.left.accounts, + &lanes, + ) + .await?; + crate::messages_metrics::add_relay_balances_metrics::<_, Self::Left>( + common.right.client.clone(), + &common.metrics_params, + &common.right.accounts, + &lanes, + ) + .await?; + } + + // Need 2x capacity since we consider both directions for each lane + let mut message_relays = Vec::with_capacity(lanes.len() * 2); + for lane in lanes { + let left_to_right_messages = crate::messages_lane::run::< + ::MessagesLane, + >(self.left_to_right().messages_relay_params( + left_to_right_on_demand_headers.clone(), + right_to_left_on_demand_headers.clone(), + lane, + Self::L2R::maybe_messages_limits(), + )) + .map_err(|e| anyhow::format_err!("{}", e)) + .boxed(); + message_relays.push(left_to_right_messages); + + let right_to_left_messages = crate::messages_lane::run::< + ::MessagesLane, + >(self.right_to_left().messages_relay_params( + right_to_left_on_demand_headers.clone(), + left_to_right_on_demand_headers.clone(), + lane, + Self::R2L::maybe_messages_limits(), + )) + .map_err(|e| anyhow::format_err!("{}", e)) + .boxed(); + message_relays.push(right_to_left_messages); + } + + relay_utils::relay_metrics(self.base().common().metrics_params.clone()) + .expose() + .await + .map_err(|e| anyhow::format_err!("{}", e))?; + + futures::future::select_all(message_relays).await.0 + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{cli::chain_schema::RuntimeVersionType, declare_chain_cli_schema}; + + use relay_substrate_client::{ChainRuntimeVersion, Parachain, SimpleRuntimeVersion}; + + #[test] + // We need `#[allow(dead_code)]` because some of the methods generated by the macros + // are not used. + #[allow(dead_code)] + fn should_parse_parachain_to_parachain_options() { + // Chains. + 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); + // Means to override signers of different layer transactions. + 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 + ); + // Bridges. + declare_parachain_to_parachain_bridge_schema!( + BridgeHubKusama, + Kusama, + BridgeHubPolkadot, + Polkadot + ); + + let res = BridgeHubKusamaBridgeHubPolkadotHeadersAndMessages::from_iter(vec![ + "bridge-hub-kusama-bridge-hub-polkadot-headers-and-messages", + "--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, + 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: BridgeHubKusamaConnectionParams { + bridge_hub_kusama_host: "bridge-hub-kusama-node-collator1".into(), + bridge_hub_kusama_port: 9944, + 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), + }, + left_relay: KusamaConnectionParams { + kusama_host: "kusama-alice".into(), + kusama_port: 9944, + kusama_secure: false, + kusama_runtime_version: KusamaRuntimeVersionParams { + kusama_version_mode: RuntimeVersionType::Bundle, + kusama_spec_version: None, + kusama_transaction_version: None, + }, + }, + right: BridgeHubPolkadotConnectionParams { + bridge_hub_polkadot_host: "bridge-hub-polkadot-collator1".into(), + bridge_hub_polkadot_port: 9944, + 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_host: "polkadot-alice".into(), + polkadot_port: 9944, + polkadot_secure: false, + polkadot_runtime_version: PolkadotRuntimeVersionParams { + polkadot_version_mode: RuntimeVersionType::Bundle, + polkadot_spec_version: None, + polkadot_transaction_version: None, + }, + }, + } + ); + } +} diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs b/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/parachain_to_parachain.rs similarity index 82% rename from relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs rename to relays/lib-substrate-relay/src/cli/relay_headers_and_messages/parachain_to_parachain.rs index 32ba6b3ddad..76accfa2905 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs +++ b/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/parachain_to_parachain.rs @@ -14,26 +14,28 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +//! Parachain to parachain relayer CLI primitives. + use async_trait::async_trait; use std::sync::Arc; -use crate::cli::{ - bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}, - relay_headers_and_messages::{Full2WayBridgeBase, Full2WayBridgeCommonParams}, - CliChain, +use crate::{ + cli::{ + bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}, + relay_headers_and_messages::{Full2WayBridgeBase, Full2WayBridgeCommonParams}, + }, + finality::SubstrateFinalitySyncPipeline, + on_demand::{ + headers::OnDemandHeadersRelay, parachains::OnDemandParachainsRelay, OnDemandRelay, + }, }; use bp_polkadot_core::parachains::ParaHash; use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, Chain, ChainWithTransactions, Client, Parachain, + AccountIdOf, AccountKeyPairOf, Chain, ChainWithRuntimeVersion, ChainWithTransactions, Client, + Parachain, }; use sp_core::Pair; -use substrate_relay_helper::{ - finality::SubstrateFinalitySyncPipeline, - on_demand::{ - headers::OnDemandHeadersRelay, parachains::OnDemandParachainsRelay, OnDemandRelay, - }, -}; /// A base relay between two parachain from different consensus systems. /// @@ -55,6 +57,8 @@ pub struct ParachainToParachainBridge< pub right_relay: Client<::SourceRelay>, } +/// Create set of configuration objects specific to parachain-to-parachain relayer. +#[macro_export] 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) => { @@ -87,20 +91,20 @@ macro_rules! declare_parachain_to_parachain_bridge_schema { impl [<$left_parachain $right_parachain HeadersAndMessages>] { async fn into_bridge< - Left: ChainWithTransactions + CliChain + Parachain, - LeftRelay: CliChain, - Right: ChainWithTransactions + CliChain + Parachain, - RightRelay: CliChain, - L2R: CliBridgeBase + Left: ChainWithTransactions + ChainWithRuntimeVersion + Parachain, + LeftRelay: ChainWithRuntimeVersion, + Right: ChainWithTransactions + ChainWithRuntimeVersion + Parachain, + RightRelay: ChainWithRuntimeVersion, + L2R: $crate::cli::bridge::CliBridgeBase + MessagesCliBridge - + ParachainToRelayHeadersCliBridge, - R2L: CliBridgeBase + + $crate::cli::bridge::ParachainToRelayHeadersCliBridge, + R2L: $crate::cli::bridge::CliBridgeBase + MessagesCliBridge - + ParachainToRelayHeadersCliBridge, + + $crate::cli::bridge::ParachainToRelayHeadersCliBridge, >( self, - ) -> anyhow::Result> { - Ok(ParachainToParachainBridge { + ) -> anyhow::Result<$crate::cli::relay_headers_and_messages::parachain_to_parachain::ParachainToParachainBridge> { + Ok($crate::cli::relay_headers_and_messages::parachain_to_parachain::ParachainToParachainBridge { common: Full2WayBridgeCommonParams::new::( self.shared, BridgeEndCommonParams { @@ -125,12 +129,12 @@ macro_rules! declare_parachain_to_parachain_bridge_schema { #[async_trait] impl< - Left: Chain + ChainWithTransactions + CliChain + Parachain, - Right: Chain + ChainWithTransactions + CliChain + Parachain, + Left: Chain + ChainWithTransactions + ChainWithRuntimeVersion + Parachain, + Right: Chain + ChainWithTransactions + ChainWithRuntimeVersion + Parachain, LeftRelay: Chain - + CliChain, + + ChainWithRuntimeVersion, RightRelay: Chain - + CliChain, + + ChainWithRuntimeVersion, L2R: CliBridgeBase + MessagesCliBridge + ParachainToRelayHeadersCliBridge, diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs b/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/relay_to_parachain.rs similarity index 88% rename from relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs rename to relays/lib-substrate-relay/src/cli/relay_headers_and_messages/relay_to_parachain.rs index fd885b6ea6c..b75ac3e60c2 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs +++ b/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/relay_to_parachain.rs @@ -14,29 +14,31 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +//! Relay chain to parachain relayer CLI primitives. + use async_trait::async_trait; use std::sync::Arc; -use crate::cli::{ - bridge::{ - CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge, - RelayToRelayHeadersCliBridge, +use crate::{ + cli::{ + bridge::{ + CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge, + RelayToRelayHeadersCliBridge, + }, + relay_headers_and_messages::{Full2WayBridgeBase, Full2WayBridgeCommonParams}, + }, + finality::SubstrateFinalitySyncPipeline, + on_demand::{ + headers::OnDemandHeadersRelay, parachains::OnDemandParachainsRelay, OnDemandRelay, }, - relay_headers_and_messages::{Full2WayBridgeBase, Full2WayBridgeCommonParams}, - CliChain, }; use bp_polkadot_core::parachains::ParaHash; use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, Chain, ChainWithTransactions, Client, Parachain, + AccountIdOf, AccountKeyPairOf, Chain, ChainWithRuntimeVersion, ChainWithTransactions, Client, + Parachain, }; use sp_core::Pair; -use substrate_relay_helper::{ - finality::SubstrateFinalitySyncPipeline, - on_demand::{ - headers::OnDemandHeadersRelay, parachains::OnDemandParachainsRelay, OnDemandRelay, - }, -}; /// A base relay between standalone (relay) chain and a parachain from another consensus system. /// @@ -55,6 +57,8 @@ pub struct RelayToParachainBridge< pub right_relay: Client<::SourceRelay>, } +/// Create set of configuration objects specific to relay-to-parachain relayer. +#[macro_export] macro_rules! declare_relay_to_parachain_bridge_schema { // chain, parachain, relay-chain-of-parachain ($left_chain:ident, $right_parachain:ident, $right_chain:ident) => { @@ -84,9 +88,9 @@ macro_rules! declare_relay_to_parachain_bridge_schema { impl [<$left_chain $right_parachain HeadersAndMessages>] { async fn into_bridge< - Left: ChainWithTransactions + CliChain, - Right: ChainWithTransactions + CliChain + Parachain, - RightRelay: CliChain, + Left: ChainWithTransactions + ChainWithRuntimeVersion, + Right: ChainWithTransactions + ChainWithRuntimeVersion + Parachain, + RightRelay: ChainWithRuntimeVersion, L2R: CliBridgeBase + MessagesCliBridge + RelayToRelayHeadersCliBridge, R2L: CliBridgeBase + MessagesCliBridge @@ -118,10 +122,10 @@ macro_rules! declare_relay_to_parachain_bridge_schema { #[async_trait] impl< - Left: ChainWithTransactions + CliChain, - Right: Chain + ChainWithTransactions + CliChain + Parachain, + Left: ChainWithTransactions + ChainWithRuntimeVersion, + Right: Chain + ChainWithTransactions + ChainWithRuntimeVersion + Parachain, RightRelay: Chain - + CliChain, + + ChainWithRuntimeVersion, L2R: CliBridgeBase + MessagesCliBridge + RelayToRelayHeadersCliBridge, diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs b/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/relay_to_relay.rs similarity index 91% rename from relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs rename to relays/lib-substrate-relay/src/cli/relay_headers_and_messages/relay_to_relay.rs index 11425035de2..b397ff50a20 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs +++ b/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/relay_to_relay.rs @@ -18,20 +18,23 @@ // future #![allow(unused_macros)] +//! Relay chain to Relay chain relayer CLI primitives. + use async_trait::async_trait; use std::sync::Arc; -use crate::cli::{ - bridge::{CliBridgeBase, MessagesCliBridge, RelayToRelayHeadersCliBridge}, - relay_headers_and_messages::{Full2WayBridgeBase, Full2WayBridgeCommonParams}, - CliChain, -}; -use relay_substrate_client::{AccountIdOf, AccountKeyPairOf, ChainWithTransactions}; -use sp_core::Pair; -use substrate_relay_helper::{ +use crate::{ + cli::{ + bridge::{CliBridgeBase, MessagesCliBridge, RelayToRelayHeadersCliBridge}, + relay_headers_and_messages::{Full2WayBridgeBase, Full2WayBridgeCommonParams}, + }, finality::SubstrateFinalitySyncPipeline, on_demand::{headers::OnDemandHeadersRelay, OnDemandRelay}, }; +use relay_substrate_client::{ + AccountIdOf, AccountKeyPairOf, ChainWithRuntimeVersion, ChainWithTransactions, +}; +use sp_core::Pair; /// A base relay between two standalone (relay) chains. /// @@ -45,6 +48,7 @@ pub struct RelayToRelayBridge< Full2WayBridgeCommonParams<::Target, ::Target>, } +/// Create set of configuration objects specific to relay-to-relay relayer. macro_rules! declare_relay_to_relay_bridge_schema { ($left_chain:ident, $right_chain:ident) => { bp_runtime::paste::item! { @@ -101,8 +105,8 @@ macro_rules! declare_relay_to_relay_bridge_schema { #[async_trait] impl< - Left: ChainWithTransactions + CliChain, - Right: ChainWithTransactions + CliChain, + Left: ChainWithTransactions + ChainWithRuntimeVersion, + Right: ChainWithTransactions + ChainWithRuntimeVersion, L2R: CliBridgeBase + MessagesCliBridge + RelayToRelayHeadersCliBridge, diff --git a/relays/lib-substrate-relay/src/cli/relay_messages.rs b/relays/lib-substrate-relay/src/cli/relay_messages.rs new file mode 100644 index 00000000000..b672bd4f9b8 --- /dev/null +++ b/relays/lib-substrate-relay/src/cli/relay_messages.rs @@ -0,0 +1,89 @@ +// Copyright 2019-2021 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 . + +//! Primitives for exposing the messages relaying functionality in the CLI. + +use crate::{ + cli::{bridge::*, chain_schema::*, HexLaneId, PrometheusParams}, + messages_lane::MessagesRelayParams, + TransactionParams, +}; + +use async_trait::async_trait; +use sp_core::Pair; +use structopt::StructOpt; + +use relay_substrate_client::{ + AccountIdOf, AccountKeyPairOf, BalanceOf, ChainWithRuntimeVersion, ChainWithTransactions, +}; + +/// Messages relaying params. +#[derive(StructOpt)] +pub struct RelayMessagesParams { + /// 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, + #[structopt(flatten)] + target_sign: TargetSigningParams, + #[structopt(flatten)] + prometheus_params: PrometheusParams, +} + +/// Trait used for relaying messages between 2 chains. +#[async_trait] +pub trait MessagesRelayer: MessagesCliBridge +where + Self::Source: ChainWithTransactions + ChainWithRuntimeVersion, + AccountIdOf: From< as Pair>::Public>, + AccountIdOf: From< as Pair>::Public>, + BalanceOf: TryFrom>, +{ + /// Start relaying messages. + async fn relay_messages(data: RelayMessagesParams) -> anyhow::Result<()> { + let source_client = data.source.into_client::().await?; + let source_sign = data.source_sign.to_keypair::()?; + let source_transactions_mortality = data.source_sign.transactions_mortality()?; + let target_client = data.target.into_client::().await?; + let target_sign = data.target_sign.to_keypair::()?; + let target_transactions_mortality = data.target_sign.transactions_mortality()?; + + crate::messages_lane::run::(MessagesRelayParams { + source_client, + source_transaction_params: TransactionParams { + signer: source_sign, + mortality: source_transactions_mortality, + }, + target_client, + target_transaction_params: TransactionParams { + signer: target_sign, + mortality: target_transactions_mortality, + }, + source_to_target_headers_relay: None, + target_to_source_headers_relay: None, + lane_id: data.lane.into(), + limits: Self::maybe_messages_limits(), + metrics_params: data.prometheus_params.into_metrics_params()?, + }) + .await + .map_err(|e| anyhow::format_err!("{}", e)) + } +} diff --git a/relays/lib-substrate-relay/src/cli/relay_parachains.rs b/relays/lib-substrate-relay/src/cli/relay_parachains.rs new file mode 100644 index 00000000000..e5a52349469 --- /dev/null +++ b/relays/lib-substrate-relay/src/cli/relay_parachains.rs @@ -0,0 +1,91 @@ +// Copyright 2019-2021 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 . + +//! Primitives for exposing the parachains finality relaying functionality in the CLI. + +use async_std::sync::Mutex; +use async_trait::async_trait; +use parachains_relay::parachains_loop::{AvailableHeader, SourceClient, TargetClient}; +use relay_substrate_client::Parachain; +use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; +use std::sync::Arc; +use structopt::StructOpt; + +use crate::{ + cli::{ + bridge::{CliBridgeBase, ParachainToRelayHeadersCliBridge}, + chain_schema::*, + PrometheusParams, + }, + parachains::{source::ParachainsSource, target::ParachainsTarget, ParachainsPipelineAdapter}, + TransactionParams, +}; + +/// Parachains heads relaying params. +#[derive(StructOpt)] +pub struct RelayParachainsParams { + #[structopt(flatten)] + source: SourceConnectionParams, + #[structopt(flatten)] + target: TargetConnectionParams, + #[structopt(flatten)] + target_sign: TargetSigningParams, + #[structopt(flatten)] + prometheus_params: PrometheusParams, +} + +/// Trait used for relaying parachains finality between 2 chains. +#[async_trait] +pub trait ParachainsRelayer: ParachainToRelayHeadersCliBridge +where + ParachainsSource: + SourceClient>, + ParachainsTarget: + TargetClient>, + ::Source: Parachain, +{ + /// Start relaying parachains finality. + async fn relay_parachains(data: RelayParachainsParams) -> anyhow::Result<()> { + let source_client = data.source.into_client::().await?; + let source_client = ParachainsSource::::new( + source_client, + Arc::new(Mutex::new(AvailableHeader::Missing)), + ); + + let target_transaction_params = TransactionParams { + signer: data.target_sign.to_keypair::()?, + mortality: data.target_sign.target_transactions_mortality, + }; + let target_client = data.target.into_client::().await?; + let target_client = ParachainsTarget::::new( + target_client.clone(), + target_transaction_params, + ); + + let metrics_params: relay_utils::metrics::MetricsParams = + data.prometheus_params.into_metrics_params()?; + GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?; + + parachains_relay::parachains_loop::run( + source_client, + target_client, + metrics_params, + futures::future::pending(), + ) + .await + .map_err(|e| anyhow::format_err!("{}", e)) + } +} diff --git a/relays/lib-substrate-relay/src/lib.rs b/relays/lib-substrate-relay/src/lib.rs index 6e620386651..b90453ae0db 100644 --- a/relays/lib-substrate-relay/src/lib.rs +++ b/relays/lib-substrate-relay/src/lib.rs @@ -22,6 +22,7 @@ use relay_substrate_client::{Chain, ChainWithUtilityPallet, UtilityPallet}; use std::marker::PhantomData; +pub mod cli; pub mod equivocation; pub mod error; pub mod finality;