Move generic CLI logic to different crate (#2885)

* Move generic CLI logic to separate crate

* Move and rename `CliChain` trait definition

Move it to `relay-substrate-client`

* Move generic cli logic to substrate-relay-helper

* Fix docs warnings
This commit is contained in:
Serban Iorga
2024-03-20 09:45:43 +01:00
committed by Bastian Köcher
parent bfce7a250f
commit 3643f721d4
63 changed files with 1746 additions and 1438 deletions
@@ -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 {}
@@ -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 {}
@@ -16,7 +16,7 @@
//! Kusama-to-BridgeHubPolkadot headers sync entrypoint.
use crate::cli::bridge::{
use substrate_relay_helper::cli::bridge::{
CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge,
};
@@ -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.
@@ -16,7 +16,7 @@
//! Polkadot-to-KusamaBridgeHub headers sync entrypoint.
use crate::cli::bridge::{
use substrate_relay_helper::cli::bridge::{
CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge,
};
@@ -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.
@@ -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 {}
@@ -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;
@@ -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 {}
@@ -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;
@@ -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;
@@ -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 {}
@@ -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<SimpleRuntimeVersion> = 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<SimpleRuntimeVersion> =
Some(SimpleRuntimeVersion { spec_version: 1_003_000, transaction_version: 3 });
}
@@ -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;
@@ -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 {}
@@ -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;
@@ -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},
};
@@ -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 {}
@@ -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 {}
@@ -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;
@@ -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.
@@ -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;
@@ -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.
@@ -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 <http://www.gnu.org/licenses/>.
//! 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<SimpleRuntimeVersion> =
Some(SimpleRuntimeVersion { spec_version: 1_001_002, transaction_version: 25 });
}
impl CliChain for BridgeHubKusama {
const RUNTIME_VERSION: Option<SimpleRuntimeVersion> =
Some(SimpleRuntimeVersion { spec_version: 1_001_000, transaction_version: 4 });
}
@@ -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 <http://www.gnu.org/licenses/>.
//! Chain-specific relayer configuration.
mod kusama;
mod polkadot;
mod polkadot_bulletin;
mod rococo;
mod westend;
@@ -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 <http://www.gnu.org/licenses/>.
//! 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<SimpleRuntimeVersion> =
Some(SimpleRuntimeVersion { spec_version: 1_001_002, transaction_version: 25 });
}
impl CliChain for BridgeHubPolkadot {
const RUNTIME_VERSION: Option<SimpleRuntimeVersion> =
Some(SimpleRuntimeVersion { spec_version: 1_001_000, transaction_version: 3 });
}
@@ -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 <http://www.gnu.org/licenses/>.
//! 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<SimpleRuntimeVersion> =
Some(SimpleRuntimeVersion { spec_version: 100, transaction_version: 1 });
}
@@ -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 <http://www.gnu.org/licenses/>.
//! 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<SimpleRuntimeVersion> =
Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 24 });
}
impl CliChain for BridgeHubRococo {
const RUNTIME_VERSION: Option<SimpleRuntimeVersion> =
Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 4 });
}
@@ -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 <http://www.gnu.org/licenses/>.
//! 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<SimpleRuntimeVersion> =
Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 24 });
}
impl CliChain for BridgeHubWestend {
const RUNTIME_VERSION: Option<SimpleRuntimeVersion> =
Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 4 });
}
@@ -1,121 +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 <http://www.gnu.org/licenses/>.
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::{
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,
}
/// 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;
/// The target chain.
type Target: ChainWithTransactions + CliChain;
}
/// Bridge representation that can be used from the CLI for relaying headers
/// from a relay chain to a relay chain.
pub trait RelayToRelayHeadersCliBridge: CliBridgeBase {
/// Finality proofs synchronization pipeline.
type Finality: SubstrateFinalitySyncPipeline<
SourceChain = Self::Source,
TargetChain = Self::Target,
>;
}
/// Convenience trait that adds bounds to `CliBridgeBase`.
pub trait RelayToRelayEquivocationDetectionCliBridgeBase: CliBridgeBase {
type BoundedSource: ChainWithTransactions;
}
impl<T> RelayToRelayEquivocationDetectionCliBridgeBase for T
where
T: CliBridgeBase,
T::Source: ChainWithTransactions,
{
type BoundedSource = T::Source;
}
/// Bridge representation that can be used from the CLI for detecting equivocations
/// in the headers synchronized from a relay chain to a relay chain.
pub trait RelayToRelayEquivocationDetectionCliBridge:
RelayToRelayEquivocationDetectionCliBridgeBase
{
/// Equivocation detection pipeline.
type Equivocation: SubstrateEquivocationDetectionPipeline<
SourceChain = Self::Source,
TargetChain = Self::Target,
>;
}
/// Bridge representation that can be used from the CLI for relaying headers
/// from a parachain to a relay chain.
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.
type SourceRelay: Chain<BlockNumber = RelayBlockNumber, Hash = RelayBlockHash, Hasher = RelayBlockHasher>
+ CliChain
+ RelayChain;
/// Finality proofs synchronization pipeline (source parachain -> target).
type ParachainFinality: SubstrateParachainsPipeline<
SourceRelayChain = Self::SourceRelay,
SourceParachain = Self::Source,
TargetChain = Self::Target,
>;
/// Finality proofs synchronization pipeline (source relay chain -> target).
type RelayFinality: SubstrateFinalitySyncPipeline<
SourceChain = Self::SourceRelay,
TargetChain = Self::Target,
>;
}
/// Bridge representation that can be used from the CLI for relaying messages.
pub trait MessagesCliBridge: CliBridgeBase {
/// The Source -> Destination messages synchronization pipeline.
type MessagesLane: SubstrateMessageLane<SourceChain = Self::Source, TargetChain = Self::Target>;
/// Optional messages delivery transaction limits that the messages relay is going
/// to use. If it returns `None`, limits are estimated using `TransactionPayment` API
/// at the target chain.
fn maybe_messages_limits() -> Option<MessagesRelayLimits> {
None
}
}
@@ -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 <http://www.gnu.org/licenses/>.
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<u32>,
#[doc = "The custom transaction_version for chain " $chain]
#[structopt(long)]
pub [<$chain_prefix _transaction_version>]: Option<u32>,
}
impl [<$chain RuntimeVersionParams>] {
/// Converts self into `ChainRuntimeVersion`.
pub fn into_runtime_version(
self,
bundle_runtime_version: Option<SimpleRuntimeVersion>,
) -> anyhow::Result<ChainRuntimeVersion> {
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<Chain: CliChain>(
self,
) -> anyhow::Result<relay_substrate_client::Client<Chain>> {
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<String>,
#[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<String>,
#[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<std::path::PathBuf>,
#[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<std::path::PathBuf>,
#[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<u32>,
}
impl [<$chain SigningParams>] {
/// Return transactions mortality.
#[allow(dead_code)]
pub fn transactions_mortality(&self) -> anyhow::Result<Option<u32>> {
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<Chain: ChainWithTransactions>(&self) -> anyhow::Result<AccountKeyPairOf<Chain>> {
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::<Chain>::from_string(
&suri,
suri_password.as_deref()
).map_err(|e| anyhow::format_err!("{:?}", e))
}
/// Return transaction parameters.
#[allow(dead_code)]
pub fn transaction_params<Chain: ChainWithTransactions>(
&self,
) -> anyhow::Result<TransactionParams<AccountKeyPairOf<Chain>>> {
Ok(TransactionParams {
mortality: self.transactions_mortality()?,
signer: self.to_keypair::<Chain>()?,
})
}
}
}
};
}
/// 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() {
@@ -14,25 +14,23 @@
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
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::<Self::Source>().await?;
Self::Equivocation::start_relay_guards(
&source_client,
source_client.can_start_version_guard(),
)
.await?;
equivocation::run::<Self::Equivocation>(
source_client,
data.target.into_client::<Self::Target>().await?,
data.source_sign.transaction_params::<Self::Source>()?,
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
}
@@ -14,107 +14,31 @@
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
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
<Self::Target as ChainBase>::AccountId: From<<AccountKeyPairOf<Self::Target> as Pair>::Public>,
{
type Engine: Engine<Self::Source>;
/// Get the encoded call to init the bridge.
fn encode_init_bridge(
init_data: <Self::Engine as Engine<Self::Source>>::InitializationData,
) -> <Self::Target as Chain>::Call;
/// Initialize the bridge.
async fn init_bridge(data: InitBridge) -> anyhow::Result<()> {
let source_client = data.source.into_client::<Self::Source>().await?;
let target_client = data.target.into_client::<Self::Target>().await?;
let target_sign = data.target_sign.to_keypair::<Self::Target>()?;
let dry_run = data.dry_run;
substrate_relay_helper::finality::initialize::initialize::<Self::Engine, _, _, _>(
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<Self::Source>;
@@ -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
}
+11 -197
View File
@@ -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<relay_headers_and_messages::RelayHeadersAndMessages>),
/// 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<SimpleRuntimeVersion>;
}
/// Lane id.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HexLaneId(pub [u8; 4]);
impl From<HexLaneId> 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<Self, Self::Err> {
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<u8>);
impl std::str::FromStr for HexBytes {
type Err = hex::FromHexError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
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 `<short-sha-(clean|dirty)>`.
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<relay_utils::metrics::MetricsParams> {
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<V> {
/// User has explicitly specified argument value.
Explicit(V),
/// Maximal allowed value for this argument.
Maximal,
}
impl<V: std::str::FromStr> std::str::FromStr for ExplicitOrMaximal<V>
where
V::Err: std::fmt::Debug,
{
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
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);
}
}
@@ -14,7 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
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::<Self::Source>().await?;
let target_client = data.target.into_client::<Self::Target>().await?;
let target_transactions_mortality = data.target_sign.target_transactions_mortality;
let target_sign = data.target_sign.to_keypair::<Self::Target>()?;
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::<Self::Finality>(
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
}
@@ -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<HexLaneId>,
/// 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<Left>,
/// Parameters of the right chain.
pub right: BridgeEndCommonParams<Right>,
/// Common metric parameters.
pub metrics_params: MetricsParams,
}
impl<Left: ChainWithTransactions + CliChain, Right: ChainWithTransactions + CliChain>
Full2WayBridgeCommonParams<Left, Right>
{
/// Creates new bridge parameters from its components.
pub fn new<L2R: MessagesCliBridge<Source = Left, Target = Right>>(
shared: HeadersAndMessagesSharedParams,
left: BridgeEndCommonParams<Left>,
right: BridgeEndCommonParams<Right>,
) -> anyhow::Result<Self> {
// 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: ChainWithTransactions + CliChain> {
/// Chain client.
pub client: Client<Chain>,
/// Params used for sending transactions to the chain.
pub tx_params: TransactionParams<AccountKeyPairOf<Chain>>,
/// Accounts, which balances are exposed as metrics by the relay process.
pub accounts: Vec<TaggedAccount<AccountIdOf<Chain>>>,
}
/// All data of the bidirectional complex relay.
struct FullBridge<
'a,
Source: ChainWithTransactions + CliChain,
Target: ChainWithTransactions + CliChain,
Bridge: MessagesCliBridge<Source = Source, Target = Target>,
> {
source: &'a mut BridgeEndCommonParams<Source>,
target: &'a mut BridgeEndCommonParams<Target>,
metrics_params: &'a MetricsParams,
_phantom_data: PhantomData<Bridge>,
}
impl<
'a,
Source: ChainWithTransactions + CliChain,
Target: ChainWithTransactions + CliChain,
Bridge: MessagesCliBridge<Source = Source, Target = Target>,
> FullBridge<'a, Source, Target, Bridge>
where
AccountIdOf<Source>: From<<AccountKeyPairOf<Source> as Pair>::Public>,
AccountIdOf<Target>: From<<AccountKeyPairOf<Target> as Pair>::Public>,
BalanceOf<Source>: TryFrom<BalanceOf<Target>> + Into<u128>,
{
/// Construct complex relay given it components.
fn new(
source: &'a mut BridgeEndCommonParams<Source>,
target: &'a mut BridgeEndCommonParams<Target>,
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<dyn OnDemandRelay<Source, Target>>,
target_to_source_headers_relay: Arc<dyn OnDemandRelay<Target, Source>>,
lane_id: LaneId,
maybe_limits: Option<MessagesRelayLimits>,
) -> MessagesRelayParams<Bridge::MessagesLane> {
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<Self::Left, Self::Right>;
/// Mutable reference to common relay parameters.
fn mut_common(&mut self) -> &mut Full2WayBridgeCommonParams<Self::Left, Self::Right>;
/// Start on-demand headers relays.
async fn start_on_demand_headers_relayers(
&mut self,
) -> anyhow::Result<(
Arc<dyn OnDemandRelay<Self::Left, Self::Right>>,
Arc<dyn OnDemandRelay<Self::Right, Self::Left>>,
)>;
}
/// Bidirectional complex relay.
#[async_trait]
trait Full2WayBridge: Sized + Sync
where
AccountIdOf<Self::Left>: From<<AccountKeyPairOf<Self::Left> as Pair>::Public>,
AccountIdOf<Self::Right>: From<<AccountKeyPairOf<Self::Right> as Pair>::Public>,
BalanceOf<Self::Left>: TryFrom<BalanceOf<Self::Right>> + Into<u128>,
BalanceOf<Self::Right>: TryFrom<BalanceOf<Self::Left>> + Into<u128>,
{
/// Base portion of the bidirectional complex relay.
type Base: Full2WayBridgeBase<Left = Self::Left, Right = Self::Right>;
/// 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<Source = Self::Left, Target = Self::Right>;
/// Right to Left bridge
type R2L: MessagesCliBridge<Source = Self::Right, Target = Self::Left>;
/// Construct new bridge.
fn new(params: <Self::Base as Full2WayBridgeBase>::Params) -> anyhow::Result<Self>;
/// 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<Self::Left, Self::Right, Self::L2R> {
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<Self::Right, Self::Left, Self::R2L> {
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::<Vec<_>>();
{
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::<
<Self::L2R as MessagesCliBridge>::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::<
<Self::R2L as MessagesCliBridge>::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: <Self as Full2WayBridge>::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() {
@@ -1,213 +0,0 @@
// 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 <http://www.gnu.org/licenses/>.
use async_trait::async_trait;
use std::sync::Arc;
use crate::cli::{
bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge},
relay_headers_and_messages::{Full2WayBridgeBase, Full2WayBridgeCommonParams},
CliChain,
};
use bp_polkadot_core::parachains::ParaHash;
use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber};
use relay_substrate_client::{
AccountIdOf, AccountKeyPairOf, Chain, 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.
///
/// Such relay starts 2 messages relay. It also starts 2 on-demand header relays and 2 on-demand
/// parachain heads relay.
pub struct ParachainToParachainBridge<
L2R: MessagesCliBridge + ParachainToRelayHeadersCliBridge,
R2L: MessagesCliBridge + ParachainToRelayHeadersCliBridge,
> where
<L2R as CliBridgeBase>::Source: Parachain,
<R2L as CliBridgeBase>::Source: Parachain,
{
/// Parameters that are shared by all bridge types.
pub common:
Full2WayBridgeCommonParams<<R2L as CliBridgeBase>::Target, <L2R as CliBridgeBase>::Target>,
/// Client of the left relay chain.
pub left_relay: Client<<L2R as ParachainToRelayHeadersCliBridge>::SourceRelay>,
/// Client of the right relay chain.
pub right_relay: Client<<R2L as ParachainToRelayHeadersCliBridge>::SourceRelay>,
}
macro_rules! declare_parachain_to_parachain_bridge_schema {
// left-parachain, relay-chain-of-left-parachain, right-parachain, relay-chain-of-right-parachain
($left_parachain:ident, $left_chain:ident, $right_parachain:ident, $right_chain:ident) => {
bp_runtime::paste::item! {
#[doc = $left_parachain ", " $left_chain ", " $right_parachain " and " $right_chain " headers+parachains+messages relay params."]
#[derive(Debug, PartialEq, StructOpt)]
pub struct [<$left_parachain $right_parachain HeadersAndMessages>] {
// shared parameters
#[structopt(flatten)]
shared: HeadersAndMessagesSharedParams,
#[structopt(flatten)]
left: [<$left_parachain ConnectionParams>],
// default signer, which is always used to sign messages relay transactions on the left chain
#[structopt(flatten)]
left_sign: [<$left_parachain SigningParams>],
#[structopt(flatten)]
left_relay: [<$left_chain ConnectionParams>],
#[structopt(flatten)]
right: [<$right_parachain ConnectionParams>],
// default signer, which is always used to sign messages relay transactions on the right chain
#[structopt(flatten)]
right_sign: [<$right_parachain SigningParams>],
#[structopt(flatten)]
right_relay: [<$right_chain ConnectionParams>],
}
impl [<$left_parachain $right_parachain HeadersAndMessages>] {
async fn into_bridge<
Left: ChainWithTransactions + CliChain + Parachain,
LeftRelay: CliChain,
Right: ChainWithTransactions + CliChain + Parachain,
RightRelay: CliChain,
L2R: CliBridgeBase<Source = Left, Target = Right>
+ MessagesCliBridge
+ ParachainToRelayHeadersCliBridge<SourceRelay = LeftRelay>,
R2L: CliBridgeBase<Source = Right, Target = Left>
+ MessagesCliBridge
+ ParachainToRelayHeadersCliBridge<SourceRelay = RightRelay>,
>(
self,
) -> anyhow::Result<ParachainToParachainBridge<L2R, R2L>> {
Ok(ParachainToParachainBridge {
common: Full2WayBridgeCommonParams::new::<L2R>(
self.shared,
BridgeEndCommonParams {
client: self.left.into_client::<Left>().await?,
tx_params: self.left_sign.transaction_params::<Left>()?,
accounts: vec![],
},
BridgeEndCommonParams {
client: self.right.into_client::<Right>().await?,
tx_params: self.right_sign.transaction_params::<Right>()?,
accounts: vec![],
},
)?,
left_relay: self.left_relay.into_client::<LeftRelay>().await?,
right_relay: self.right_relay.into_client::<RightRelay>().await?,
})
}
}
}
};
}
#[async_trait]
impl<
Left: Chain<Hash = ParaHash> + ChainWithTransactions + CliChain + Parachain,
Right: Chain<Hash = ParaHash> + ChainWithTransactions + CliChain + Parachain,
LeftRelay: Chain<BlockNumber = RelayBlockNumber, Hash = RelayBlockHash, Hasher = RelayBlockHasher>
+ CliChain,
RightRelay: Chain<BlockNumber = RelayBlockNumber, Hash = RelayBlockHash, Hasher = RelayBlockHasher>
+ CliChain,
L2R: CliBridgeBase<Source = Left, Target = Right>
+ MessagesCliBridge
+ ParachainToRelayHeadersCliBridge<SourceRelay = LeftRelay>,
R2L: CliBridgeBase<Source = Right, Target = Left>
+ MessagesCliBridge
+ ParachainToRelayHeadersCliBridge<SourceRelay = RightRelay>,
> Full2WayBridgeBase for ParachainToParachainBridge<L2R, R2L>
where
AccountIdOf<Left>: From<<AccountKeyPairOf<Left> as Pair>::Public>,
AccountIdOf<Right>: From<<AccountKeyPairOf<Right> as Pair>::Public>,
{
type Params = ParachainToParachainBridge<L2R, R2L>;
type Left = Left;
type Right = Right;
fn common(&self) -> &Full2WayBridgeCommonParams<Left, Right> {
&self.common
}
fn mut_common(&mut self) -> &mut Full2WayBridgeCommonParams<Self::Left, Self::Right> {
&mut self.common
}
async fn start_on_demand_headers_relayers(
&mut self,
) -> anyhow::Result<(
Arc<dyn OnDemandRelay<Self::Left, Self::Right>>,
Arc<dyn OnDemandRelay<Self::Right, Self::Left>>,
)> {
<L2R as ParachainToRelayHeadersCliBridge>::RelayFinality::start_relay_guards(
&self.common.right.client,
self.common.right.client.can_start_version_guard(),
)
.await?;
<R2L as ParachainToRelayHeadersCliBridge>::RelayFinality::start_relay_guards(
&self.common.left.client,
self.common.left.client.can_start_version_guard(),
)
.await?;
let left_relay_to_right_on_demand_headers =
OnDemandHeadersRelay::<<L2R as ParachainToRelayHeadersCliBridge>::RelayFinality>::new(
self.left_relay.clone(),
self.common.right.client.clone(),
self.common.right.tx_params.clone(),
self.common.shared.only_mandatory_headers,
Some(self.common.metrics_params.clone()),
);
let right_relay_to_left_on_demand_headers =
OnDemandHeadersRelay::<<R2L as ParachainToRelayHeadersCliBridge>::RelayFinality>::new(
self.right_relay.clone(),
self.common.left.client.clone(),
self.common.left.tx_params.clone(),
self.common.shared.only_mandatory_headers,
Some(self.common.metrics_params.clone()),
);
let left_to_right_on_demand_parachains = OnDemandParachainsRelay::<
<L2R as ParachainToRelayHeadersCliBridge>::ParachainFinality,
>::new(
self.left_relay.clone(),
self.common.right.client.clone(),
self.common.right.tx_params.clone(),
Arc::new(left_relay_to_right_on_demand_headers),
);
let right_to_left_on_demand_parachains = OnDemandParachainsRelay::<
<R2L as ParachainToRelayHeadersCliBridge>::ParachainFinality,
>::new(
self.right_relay.clone(),
self.common.left.client.clone(),
self.common.left.tx_params.clone(),
Arc::new(right_relay_to_left_on_demand_headers),
);
Ok((
Arc::new(left_to_right_on_demand_parachains),
Arc::new(right_to_left_on_demand_parachains),
))
}
}
@@ -1,195 +0,0 @@
// 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 <http://www.gnu.org/licenses/>.
use async_trait::async_trait;
use std::sync::Arc;
use crate::cli::{
bridge::{
CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge,
RelayToRelayHeadersCliBridge,
},
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,
};
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.
///
/// Such relay starts 2 messages relay. It also starts 2 on-demand header relays and 1 on-demand
/// parachain heads relay.
pub struct RelayToParachainBridge<
L2R: MessagesCliBridge + RelayToRelayHeadersCliBridge,
R2L: MessagesCliBridge + ParachainToRelayHeadersCliBridge,
> where
<R2L as CliBridgeBase>::Source: Parachain,
{
/// Parameters that are shared by all bridge types.
pub common:
Full2WayBridgeCommonParams<<R2L as CliBridgeBase>::Target, <L2R as CliBridgeBase>::Target>,
/// Client of the right relay chain.
pub right_relay: Client<<R2L as ParachainToRelayHeadersCliBridge>::SourceRelay>,
}
macro_rules! declare_relay_to_parachain_bridge_schema {
// chain, parachain, relay-chain-of-parachain
($left_chain:ident, $right_parachain:ident, $right_chain:ident) => {
bp_runtime::paste::item! {
#[doc = $left_chain ", " $right_parachain " and " $right_chain " headers+parachains+messages relay params."]
#[derive(Debug, PartialEq, StructOpt)]
pub struct [<$left_chain $right_parachain HeadersAndMessages>] {
// shared parameters
#[structopt(flatten)]
shared: HeadersAndMessagesSharedParams,
#[structopt(flatten)]
left: [<$left_chain ConnectionParams>],
// default signer, which is always used to sign messages relay transactions on the left chain
#[structopt(flatten)]
left_sign: [<$left_chain SigningParams>],
#[structopt(flatten)]
right: [<$right_parachain ConnectionParams>],
// default signer, which is always used to sign messages relay transactions on the right chain
#[structopt(flatten)]
right_sign: [<$right_parachain SigningParams>],
#[structopt(flatten)]
right_relay: [<$right_chain ConnectionParams>],
}
impl [<$left_chain $right_parachain HeadersAndMessages>] {
async fn into_bridge<
Left: ChainWithTransactions + CliChain,
Right: ChainWithTransactions + CliChain + Parachain,
RightRelay: CliChain,
L2R: CliBridgeBase<Source = Left, Target = Right> + MessagesCliBridge + RelayToRelayHeadersCliBridge,
R2L: CliBridgeBase<Source = Right, Target = Left>
+ MessagesCliBridge
+ ParachainToRelayHeadersCliBridge<SourceRelay = RightRelay>,
>(
self,
) -> anyhow::Result<RelayToParachainBridge<L2R, R2L>> {
Ok(RelayToParachainBridge {
common: Full2WayBridgeCommonParams::new::<L2R>(
self.shared,
BridgeEndCommonParams {
client: self.left.into_client::<Left>().await?,
tx_params: self.left_sign.transaction_params::<Left>()?,
accounts: vec![],
},
BridgeEndCommonParams {
client: self.right.into_client::<Right>().await?,
tx_params: self.right_sign.transaction_params::<Right>()?,
accounts: vec![],
},
)?,
right_relay: self.right_relay.into_client::<RightRelay>().await?,
})
}
}
}
};
}
#[async_trait]
impl<
Left: ChainWithTransactions + CliChain,
Right: Chain<Hash = ParaHash> + ChainWithTransactions + CliChain + Parachain,
RightRelay: Chain<BlockNumber = RelayBlockNumber, Hash = RelayBlockHash, Hasher = RelayBlockHasher>
+ CliChain,
L2R: CliBridgeBase<Source = Left, Target = Right>
+ MessagesCliBridge
+ RelayToRelayHeadersCliBridge,
R2L: CliBridgeBase<Source = Right, Target = Left>
+ MessagesCliBridge
+ ParachainToRelayHeadersCliBridge<SourceRelay = RightRelay>,
> Full2WayBridgeBase for RelayToParachainBridge<L2R, R2L>
where
AccountIdOf<Left>: From<<AccountKeyPairOf<Left> as Pair>::Public>,
AccountIdOf<Right>: From<<AccountKeyPairOf<Right> as Pair>::Public>,
{
type Params = RelayToParachainBridge<L2R, R2L>;
type Left = Left;
type Right = Right;
fn common(&self) -> &Full2WayBridgeCommonParams<Left, Right> {
&self.common
}
fn mut_common(&mut self) -> &mut Full2WayBridgeCommonParams<Self::Left, Self::Right> {
&mut self.common
}
async fn start_on_demand_headers_relayers(
&mut self,
) -> anyhow::Result<(
Arc<dyn OnDemandRelay<Self::Left, Self::Right>>,
Arc<dyn OnDemandRelay<Self::Right, Self::Left>>,
)> {
<L2R as RelayToRelayHeadersCliBridge>::Finality::start_relay_guards(
&self.common.right.client,
self.common.right.client.can_start_version_guard(),
)
.await?;
<R2L as ParachainToRelayHeadersCliBridge>::RelayFinality::start_relay_guards(
&self.common.left.client,
self.common.left.client.can_start_version_guard(),
)
.await?;
let left_to_right_on_demand_headers =
OnDemandHeadersRelay::<<L2R as RelayToRelayHeadersCliBridge>::Finality>::new(
self.common.left.client.clone(),
self.common.right.client.clone(),
self.common.right.tx_params.clone(),
self.common.shared.only_mandatory_headers,
None,
);
let right_relay_to_left_on_demand_headers =
OnDemandHeadersRelay::<<R2L as ParachainToRelayHeadersCliBridge>::RelayFinality>::new(
self.right_relay.clone(),
self.common.left.client.clone(),
self.common.left.tx_params.clone(),
self.common.shared.only_mandatory_headers,
Some(self.common.metrics_params.clone()),
);
let right_to_left_on_demand_parachains = OnDemandParachainsRelay::<
<R2L as ParachainToRelayHeadersCliBridge>::ParachainFinality,
>::new(
self.right_relay.clone(),
self.common.left.client.clone(),
self.common.left.tx_params.clone(),
Arc::new(right_relay_to_left_on_demand_headers),
);
Ok((
Arc::new(left_to_right_on_demand_headers),
Arc::new(right_to_left_on_demand_parachains),
))
}
}
@@ -1,165 +0,0 @@
// 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 <http://www.gnu.org/licenses/>.
// we don't have any relay/standalone <> relay/standalone chain bridges, but we may need it in a
// future
#![allow(unused_macros)]
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::{
finality::SubstrateFinalitySyncPipeline,
on_demand::{headers::OnDemandHeadersRelay, OnDemandRelay},
};
/// A base relay between two standalone (relay) chains.
///
/// Such relay starts 2 messages relay and 2 on-demand header relays.
pub struct RelayToRelayBridge<
L2R: MessagesCliBridge + RelayToRelayHeadersCliBridge,
R2L: MessagesCliBridge + RelayToRelayHeadersCliBridge,
> {
/// Parameters that are shared by all bridge types.
pub common:
Full2WayBridgeCommonParams<<R2L as CliBridgeBase>::Target, <L2R as CliBridgeBase>::Target>,
}
macro_rules! declare_relay_to_relay_bridge_schema {
($left_chain:ident, $right_chain:ident) => {
bp_runtime::paste::item! {
#[doc = $left_chain " and " $right_chain " headers+messages relay params."]
#[derive(Debug, PartialEq, StructOpt)]
pub struct [<$left_chain $right_chain HeadersAndMessages>] {
#[structopt(flatten)]
shared: HeadersAndMessagesSharedParams,
#[structopt(flatten)]
left: [<$left_chain ConnectionParams>],
// default signer, which is always used to sign messages relay transactions on the left chain
#[structopt(flatten)]
left_sign: [<$left_chain SigningParams>],
#[structopt(flatten)]
right: [<$right_chain ConnectionParams>],
#[structopt(flatten)]
// default signer, which is always used to sign messages relay transactions on the right chain
right_sign: [<$right_chain SigningParams>],
}
impl [<$left_chain $right_chain HeadersAndMessages>] {
async fn into_bridge<
Left: ChainWithTransactions + CliChain,
Right: ChainWithTransactions + CliChain,
L2R: CliBridgeBase<Source = Left, Target = Right> + MessagesCliBridge + RelayToRelayHeadersCliBridge,
R2L: CliBridgeBase<Source = Right, Target = Left> + MessagesCliBridge + RelayToRelayHeadersCliBridge,
>(
self,
) -> anyhow::Result<RelayToRelayBridge<L2R, R2L>> {
Ok(RelayToRelayBridge {
common: Full2WayBridgeCommonParams::new::<L2R>(
self.shared,
BridgeEndCommonParams {
client: self.left.into_client::<Left>().await?,
tx_params: self.left_sign.transaction_params::<Left>()?,
accounts: vec![],
},
BridgeEndCommonParams {
client: self.right.into_client::<Right>().await?,
tx_params: self.right_sign.transaction_params::<Right>()?,
accounts: vec![],
},
)?,
right_to_left_transaction_params: self.left_sign.transaction_params::<Left>(),
left_to_right_transaction_params: self.right_sign.transaction_params::<Right>(),
})
}
}
}
};
}
#[async_trait]
impl<
Left: ChainWithTransactions + CliChain,
Right: ChainWithTransactions + CliChain,
L2R: CliBridgeBase<Source = Left, Target = Right>
+ MessagesCliBridge
+ RelayToRelayHeadersCliBridge,
R2L: CliBridgeBase<Source = Right, Target = Left>
+ MessagesCliBridge
+ RelayToRelayHeadersCliBridge,
> Full2WayBridgeBase for RelayToRelayBridge<L2R, R2L>
where
AccountIdOf<Left>: From<<AccountKeyPairOf<Left> as Pair>::Public>,
AccountIdOf<Right>: From<<AccountKeyPairOf<Right> as Pair>::Public>,
{
type Params = RelayToRelayBridge<L2R, R2L>;
type Left = Left;
type Right = Right;
fn common(&self) -> &Full2WayBridgeCommonParams<Left, Right> {
&self.common
}
fn mut_common(&mut self) -> &mut Full2WayBridgeCommonParams<Self::Left, Self::Right> {
&mut self.common
}
async fn start_on_demand_headers_relayers(
&mut self,
) -> anyhow::Result<(
Arc<dyn OnDemandRelay<Self::Left, Self::Right>>,
Arc<dyn OnDemandRelay<Self::Right, Self::Left>>,
)> {
<L2R as RelayToRelayHeadersCliBridge>::Finality::start_relay_guards(
&self.common.right.client,
self.common.right.client.can_start_version_guard(),
)
.await?;
<R2L as RelayToRelayHeadersCliBridge>::Finality::start_relay_guards(
&self.common.left.client,
self.common.left.client.can_start_version_guard(),
)
.await?;
let left_to_right_on_demand_headers =
OnDemandHeadersRelay::<<L2R as RelayToRelayHeadersCliBridge>::Finality>::new(
self.common.left.client.clone(),
self.common.right.client.clone(),
self.common.right.tx_params.clone(),
self.common.shared.only_mandatory_headers,
None,
);
let right_to_left_on_demand_headers =
OnDemandHeadersRelay::<<R2L as RelayToRelayHeadersCliBridge>::Finality>::new(
self.common.right.client.clone(),
self.common.left.client.clone(),
self.common.left.tx_params.clone(),
self.common.shared.only_mandatory_headers,
None,
);
Ok((Arc::new(left_to_right_on_demand_headers), Arc::new(right_to_left_on_demand_headers)))
}
}
@@ -14,10 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
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<Self::Source>: From<<AccountKeyPairOf<Self::Source> as Pair>::Public>,
AccountIdOf<Self::Target>: From<<AccountKeyPairOf<Self::Target> as Pair>::Public>,
BalanceOf<Self::Source>: TryFrom<BalanceOf<Self::Target>>,
{
async fn relay_messages(data: RelayMessages) -> anyhow::Result<()> {
let source_client = data.source.into_client::<Self::Source>().await?;
let source_sign = data.source_sign.to_keypair::<Self::Source>()?;
let source_transactions_mortality = data.source_sign.transactions_mortality()?;
let target_client = data.target.into_client::<Self::Target>().await?;
let target_sign = data.target_sign.to_keypair::<Self::Target>()?;
let target_transactions_mortality = data.target_sign.transactions_mortality()?;
substrate_relay_helper::messages_lane::run::<Self::MessagesLane>(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
}
@@ -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<Self::ParachainFinality>:
SourceClient<ParachainsPipelineAdapter<Self::ParachainFinality>>,
ParachainsTarget<Self::ParachainFinality>:
TargetClient<ParachainsPipelineAdapter<Self::ParachainFinality>>,
<Self as CliBridgeBase>::Source: Parachain,
{
async fn relay_parachains(data: RelayParachains) -> anyhow::Result<()> {
let source_client = data.source.into_client::<Self::SourceRelay>().await?;
let source_client = ParachainsSource::<Self::ParachainFinality>::new(
source_client,
Arc::new(Mutex::new(AvailableHeader::Missing)),
);
let target_transaction_params = TransactionParams {
signer: data.target_sign.to_keypair::<Self::Target>()?,
mortality: data.target_sign.target_transactions_mortality,
};
let target_client = data.target.into_client::<Self::Target>().await?;
let target_client = ParachainsTarget::<Self::ParachainFinality>::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
}
-1
View File
@@ -19,7 +19,6 @@
#![warn(missing_docs)]
mod bridges;
mod chains;
mod cli;
fn main() {