From bd87488295d2679ecf5afc05919b03bd256fc660 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 25 Aug 2023 11:14:40 +0300 Subject: [PATCH] Implement additional require primitives for dynamic fees directly for pallet-xcm-bridge-hub (#2261) * added backoff mechanism to inbound bridge queue * impl backpressure in the XcmBlobHaulerAdapter * leave TODOs * BridgeMessageProcessor prototype * another TODO * Revert "also temporary (?) remove BridgesByLocalOrigin because the storage format will likely change to be able to resume bridges from the on_iniitalize/on_idle" This reverts commit bdd7ae11a8942b58c5db6ac6d4e7922aa28cece4. * prototype for QueuePausedQuery * implement ExportXcm and MessageDispatch for pallet-xcm-bridge-hub * spelling * flush * small comments to myself * more backports from dynamic-fees-v1 * use new pallet as exporter and dispatcher in Millau * use new pallet as exporter and dispatcher in Rialto * use new pallet as exporter and dispatcher in RialtoParachain * flush * fix remaining compilation issues * warnings + fmt * fix tests * LocalXcmChannelManager * change lane ids * it works! * remove bp-xcm-bridge-hub-router and use LocalXcmChannelManager everywhere * removed commented code * cleaning up * cleaning up * cleaning up * - separated BridgeId and LaneId - BridgeId now uses versioned universal locations - added missing stuff to exporter.rs * OnMessagesDelivered is back * start using bp-xcm-bridge-hub as OnMessagesDelivered * cleaning up * spelling * fix stupid issues * Backport latest relevant dynamic fees changes from v1 to v2 (#2372) * backport latest relevant dynamic fees changes from v1 to v2 * fix comment --- Cargo.lock | 19 +- Cargo.toml | 1 - README.md | 2 +- bin/millau/node/Cargo.toml | 4 + bin/millau/node/src/chain_spec.rs | 28 ++- bin/millau/runtime/Cargo.toml | 7 +- bin/millau/runtime/src/lib.rs | 81 ++++++- bin/millau/runtime/src/rialto_messages.rs | 54 +---- .../runtime/src/rialto_parachain_messages.rs | 56 +---- bin/millau/runtime/src/xcm_config.rs | 77 ++++--- bin/rialto-parachain/node/Cargo.toml | 1 + bin/rialto-parachain/node/src/chain_spec.rs | 18 +- bin/rialto-parachain/runtime/Cargo.toml | 4 + bin/rialto-parachain/runtime/src/lib.rs | 58 +++-- .../runtime/src/millau_messages.rs | 56 +---- bin/rialto/node/Cargo.toml | 2 + bin/rialto/node/src/chain_spec.rs | 14 +- bin/rialto/runtime/Cargo.toml | 4 + bin/rialto/runtime/src/lib.rs | 32 ++- bin/rialto/runtime/src/millau_messages.rs | 56 +---- bin/rialto/runtime/src/xcm_config.rs | 27 ++- bin/runtime-common/Cargo.toml | 2 + bin/runtime-common/src/integrity.rs | 2 +- bin/runtime-common/src/lib.rs | 3 - bin/runtime-common/src/messages_call_ext.rs | 30 ++- .../src/messages_xcm_extension.rs | 168 -------------- bin/runtime-common/src/mock.rs | 47 +++- .../src/refund_relayer_extension.rs | 18 +- ...y-millau-to-rialto-messages-dashboard.json | 24 +- ...y-rialto-to-millau-messages-dashboard.json | 24 +- .../rialto-millau-maintenance-dashboard.json | 4 +- .../relay-millau-rialto-entrypoint.sh | 2 +- ...o-rialto-parachain-messages-dashboard.json | 24 +- ...arachain-to-millau-messages-dashboard.json | 24 +- ...arachain-millau-maintenance-dashboard.json | 12 +- ...elay-millau-rialto-parachain-entrypoint.sh | 2 +- .../relay-messages-millau-to-rialto.sh | 2 +- .../relay-messages-rialto-to-millau.sh | 2 +- modules/messages/src/lanes_manager.rs | 37 ++- modules/messages/src/lib.rs | 19 +- modules/messages/src/tests/mock.rs | 25 +- modules/messages/src/tests/pallet_tests.rs | 89 ++++++- modules/xcm-bridge-hub-router/Cargo.toml | 4 +- .../xcm-bridge-hub-router/src/benchmarking.rs | 6 +- modules/xcm-bridge-hub-router/src/lib.rs | 156 +++++++++---- modules/xcm-bridge-hub-router/src/mock.rs | 34 ++- modules/xcm-bridge-hub/Cargo.toml | 2 +- modules/xcm-bridge-hub/src/dispatcher.rs | 19 +- modules/xcm-bridge-hub/src/exporter.rs | 189 +++++++++++++-- modules/xcm-bridge-hub/src/lib.rs | 218 +++++++++++++----- modules/xcm-bridge-hub/src/mock.rs | 43 +++- primitives/messages/src/source_chain.rs | 17 +- primitives/messages/src/target_chain.rs | 10 + primitives/xcm-bridge-hub-router/Cargo.toml | 11 - primitives/xcm-bridge-hub-router/src/lib.rs | 31 --- primitives/xcm-bridge-hub/Cargo.toml | 2 + primitives/xcm-bridge-hub/src/lib.rs | 150 ++++++++---- relays/bin-substrate/Cargo.toml | 1 + relays/bin-substrate/src/chains/millau.rs | 2 +- relays/bin-substrate/src/chains/rialto.rs | 7 +- .../src/chains/rialto_parachain.rs | 7 +- 61 files changed, 1282 insertions(+), 788 deletions(-) delete mode 100644 bin/runtime-common/src/messages_xcm_extension.rs delete mode 100644 primitives/xcm-bridge-hub-router/Cargo.toml delete mode 100644 primitives/xcm-bridge-hub-router/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index a6118bd3230..e546ea153db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1255,14 +1255,11 @@ dependencies = [ "frame-support", "parity-scale-codec", "scale-info", + "serde", "sp-std 8.0.0 (git+https://github.com/paritytech/substrate?branch=master)", "xcm", ] -[[package]] -name = "bp-xcm-bridge-hub-router" -version = "0.1.0" - [[package]] name = "bridge-runtime-common" version = "0.1.0" @@ -1274,6 +1271,7 @@ dependencies = [ "bp-relayers", "bp-runtime", "bp-test-utils", + "bp-xcm-bridge-hub", "frame-support", "frame-system", "hash-db", @@ -6179,6 +6177,7 @@ dependencies = [ "sp-timestamp", "substrate-build-script-utils", "substrate-frame-rpc-system", + "xcm", ] [[package]] @@ -6195,7 +6194,7 @@ dependencies = [ "bp-rialto-parachain", "bp-runtime", "bp-westend", - "bp-xcm-bridge-hub-router", + "bp-xcm-bridge-hub", "bridge-runtime-common", "env_logger", "frame-benchmarking", @@ -6222,6 +6221,7 @@ dependencies = [ "pallet-transaction-payment-rpc-runtime-api", "pallet-utility", "pallet-xcm", + "pallet-xcm-bridge-hub", "pallet-xcm-bridge-hub-router", "parity-scale-codec", "scale-info", @@ -7977,7 +7977,7 @@ dependencies = [ name = "pallet-xcm-bridge-hub-router" version = "0.1.0" dependencies = [ - "bp-xcm-bridge-hub-router", + "bp-xcm-bridge-hub", "frame-benchmarking", "frame-support", "frame-system", @@ -10507,6 +10507,7 @@ dependencies = [ "sp-core", "sp-runtime", "substrate-build-script-utils", + "xcm", ] [[package]] @@ -10562,6 +10563,7 @@ dependencies = [ "substrate-build-script-utils", "substrate-frame-rpc-system", "substrate-prometheus-endpoint", + "xcm", ] [[package]] @@ -10574,6 +10576,7 @@ dependencies = [ "bp-relayers", "bp-rialto-parachain", "bp-runtime", + "bp-xcm-bridge-hub", "bridge-runtime-common", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", @@ -10599,6 +10602,7 @@ dependencies = [ "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", "pallet-xcm", + "pallet-xcm-bridge-hub", "parachain-info", "parity-scale-codec", "polkadot-parachain", @@ -10632,6 +10636,7 @@ dependencies = [ "bp-relayers", "bp-rialto", "bp-runtime", + "bp-xcm-bridge-hub", "bridge-runtime-common", "env_logger", "frame-benchmarking", @@ -10659,6 +10664,7 @@ dependencies = [ "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", "pallet-xcm", + "pallet-xcm-bridge-hub", "parity-scale-codec", "polkadot-primitives", "polkadot-runtime-common", @@ -13939,6 +13945,7 @@ dependencies = [ "num-traits", "pallet-bridge-messages", "pallet-bridge-parachains", + "pallet-xcm-bridge-hub", "parachains-relay", "parity-scale-codec", "polkadot-parachain", diff --git a/Cargo.toml b/Cargo.toml index 20cf2e8d6db..5d948cdebf7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,7 +40,6 @@ members = [ "primitives/runtime", "primitives/test-utils", "primitives/xcm-bridge-hub", - "primitives/xcm-bridge-hub-router", "relays/bin-substrate", "relays/client-bridge-hub-kusama", "relays/client-bridge-hub-polkadot", diff --git a/README.md b/README.md index e72d4b2cd44..383e57609d6 100644 --- a/README.md +++ b/README.md @@ -189,7 +189,7 @@ You will also see the message lane relayers listening for new messages. ``` # Message Relayer Logs -[Millau_to_Rialto_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7] [date] DEBUG bridge Asking Millau::ReceivingConfirmationsDelivery about best message nonces +[Millau_to_Rialto_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7] [date] DEBUG bridge Asking Millau::ReceivingConfirmationsDelivery about best message nonces [...] [date] INFO bridge Synced Some(2) of Some(3) nonces in Millau::MessagesDelivery -> Rialto::MessagesDelivery race [...] [date] DEBUG bridge Asking Millau::MessagesDelivery about message nonces [...] [date] DEBUG bridge Received best nonces from Millau::ReceivingConfirmationsDelivery: TargetClientNonces { latest_nonce: 0, nonces_data: () } diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 5b8ddced157..47b00fe1fc4 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -54,6 +54,10 @@ sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "mast substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-network-common = { git = "https://github.com/paritytech/substrate", branch = "master" } +# Polkadot Dependencies + +xcm = { git = "https://github.com/paritytech/polkadot", branch = "master" } + [build-dependencies] substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index ced3f4939cf..8f63d353688 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -14,12 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use bridge_runtime_common::messages_xcm_extension::XcmBlobHauler; use millau_runtime::{ AccountId, AuraConfig, BalancesConfig, BeefyConfig, BridgeRialtoMessagesConfig, BridgeRialtoParachainMessagesConfig, BridgeWestendGrandpaConfig, GrandpaConfig, RuntimeGenesisConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, - WASM_BINARY, + XcmRialtoBridgeHubConfig, XcmRialtoParachainBridgeHubConfig, WASM_BINARY, }; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_consensus_beefy::crypto::AuthorityId as BeefyId; @@ -225,19 +224,34 @@ fn testnet_genesis( }, bridge_rialto_messages: BridgeRialtoMessagesConfig { owner: Some(get_account_id_from_seed::(RIALTO_MESSAGES_PALLET_OWNER)), - opened_lanes: vec![millau_runtime::rialto_messages::ToRialtoXcmBlobHauler::xcm_lane()], + opened_lanes: vec![millau_runtime::rialto_messages::Bridge::get().lane_id()], ..Default::default() }, bridge_rialto_parachain_messages: BridgeRialtoParachainMessagesConfig { owner: Some(get_account_id_from_seed::( RIALTO_PARACHAIN_MESSAGES_PALLET_OWNER, )), - opened_lanes: vec![ - millau_runtime::rialto_parachain_messages::ToRialtoParachainXcmBlobHauler::xcm_lane( - ), - ], + opened_lanes: vec![millau_runtime::rialto_parachain_messages::Bridge::get().lane_id()], ..Default::default() }, xcm_pallet: Default::default(), + xcm_rialto_bridge_hub: XcmRialtoBridgeHubConfig { + opened_bridges: vec![( + xcm::latest::Junctions::Here.into(), + xcm::latest::InteriorMultiLocation::from( + millau_runtime::xcm_config::RialtoNetwork::get(), + ), + )], + ..Default::default() + }, + xcm_rialto_parachain_bridge_hub: XcmRialtoParachainBridgeHubConfig { + opened_bridges: vec![( + xcm::latest::Junctions::Here.into(), + xcm::latest::InteriorMultiLocation::from( + millau_runtime::xcm_config::RialtoParachainNetwork::get(), + ), + )], + ..Default::default() + }, } } diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index ccff85b99eb..4bb32f724f8 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -23,13 +23,14 @@ bp-rialto = { path = "../../../primitives/chain-rialto", default-features = fals bp-rialto-parachain = { path = "../../../primitives/chain-rialto-parachain", default-features = false } bp-runtime = { path = "../../../primitives/runtime", default-features = false } bp-westend = { path = "../../../primitives/chain-westend", default-features = false } -bp-xcm-bridge-hub-router = { path = "../../../primitives/xcm-bridge-hub-router", default-features = false } +bp-xcm-bridge-hub = { path = "../../../primitives/xcm-bridge-hub", default-features = false } bridge-runtime-common = { path = "../../runtime-common", default-features = false } pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../../modules/messages", default-features = false } pallet-bridge-parachains = { path = "../../../modules/parachains", default-features = false } pallet-bridge-relayers = { path = "../../../modules/relayers", default-features = false } pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } +pallet-xcm-bridge-hub = { path = "../../../modules/xcm-bridge-hub", default-features = false } pallet-xcm-bridge-hub-router = { path = "../../../modules/xcm-bridge-hub-router", default-features = false } # Substrate Dependencies @@ -92,7 +93,7 @@ std = [ "bp-rialto-parachain/std", "bp-runtime/std", "bp-westend/std", - "bp-xcm-bridge-hub-router/std", + "bp-xcm-bridge-hub/std", "bridge-runtime-common/std", "codec/std", "frame-executive/std", @@ -117,6 +118,7 @@ std = [ "pallet-transaction-payment/std", "pallet-utility/std", "pallet-xcm/std", + "pallet-xcm-bridge-hub/std", "pallet-xcm-bridge-hub-router/std", "scale-info/std", "sp-api/std", @@ -144,6 +146,7 @@ runtime-benchmarks = [ "pallet-bridge-parachains/runtime-benchmarks", "pallet-bridge-relayers/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", + "pallet-xcm-bridge-hub/runtime-benchmarks", "pallet-xcm-bridge-hub-router/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 22e4e1b7221..b4292e21b10 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -55,6 +55,7 @@ use sp_std::prelude::*; #[cfg(feature = "std")] use sp_version::NativeVersion; use sp_version::RuntimeVersion; +use xcm_builder::NetworkExportTable; // to be able to use Millau runtime in `bridge-runtime-common` tests pub use bridge_runtime_common; @@ -442,8 +443,8 @@ impl pallet_bridge_messages::Config for Runtime { type BridgedChain = bp_rialto::Rialto; type BridgedHeaderChain = BridgeRialtoGrandpa; - type OutboundPayload = bridge_runtime_common::messages_xcm_extension::XcmAsPlainPayload; - type InboundPayload = bridge_runtime_common::messages_xcm_extension::XcmAsPlainPayload; + type OutboundPayload = bp_xcm_bridge_hub::XcmAsPlainPayload; + type InboundPayload = bp_xcm_bridge_hub::XcmAsPlainPayload; type DeliveryPayments = (); type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< @@ -451,8 +452,9 @@ impl pallet_bridge_messages::Config for Runtime { WithRialtoMessagesInstance, frame_support::traits::ConstU64<100_000>, >; + type OnMessagesDelivered = XcmRialtoBridgeHub; - type MessageDispatch = crate::rialto_messages::FromRialtoMessageDispatch; + type MessageDispatch = XcmRialtoBridgeHub; } /// Instance of the messages pallet used to relay messages to/from RialtoParachain chain. @@ -470,8 +472,8 @@ impl pallet_bridge_messages::Config for Run bp_rialto_parachain::RialtoParachain, >; - type OutboundPayload = bridge_runtime_common::messages_xcm_extension::XcmAsPlainPayload; - type InboundPayload = bridge_runtime_common::messages_xcm_extension::XcmAsPlainPayload; + type OutboundPayload = bp_xcm_bridge_hub::XcmAsPlainPayload; + type InboundPayload = bp_xcm_bridge_hub::XcmAsPlainPayload; type DeliveryPayments = (); type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< @@ -479,8 +481,9 @@ impl pallet_bridge_messages::Config for Run WithRialtoParachainMessagesInstance, frame_support::traits::ConstU64<100_000>, >; + type OnMessagesDelivered = XcmRialtoParachainBridgeHub; - type MessageDispatch = crate::rialto_parachain_messages::FromRialtoParachainMessageDispatch; + type MessageDispatch = XcmRialtoParachainBridgeHub; } parameter_types! { @@ -527,21 +530,75 @@ impl pallet_utility::Config for Runtime { // this config is totally incorrect - the pallet is not actually used at this runtime. We need // it only to be able to run benchmarks and make required traits (and default weights for tests). + +parameter_types! { + pub BridgeTable: Vec<(xcm::prelude::NetworkId, xcm::prelude::MultiLocation, Option)> + = vec![( + xcm_config::RialtoNetwork::get(), + xcm_config::TokenLocation::get(), + Some((xcm_config::TokenAssetId::get(), 1_000_000_000_u128).into()), + )]; +} + impl pallet_xcm_bridge_hub_router::Config for Runtime { type WeightInfo = (); type UniversalLocation = xcm_config::UniversalLocation; type SiblingBridgeHubLocation = xcm_config::TokenLocation; type BridgedNetworkId = xcm_config::RialtoNetwork; + type Bridges = NetworkExportTable; type ToBridgeHubSender = xcm_config::XcmRouter; - type WithBridgeHubChannel = xcm_config::EmulatedSiblingXcmpChannel; + type LocalXcmChannelManager = xcm_config::EmulatedSiblingXcmpChannel; - type BaseFee = ConstU128<1_000_000_000>; type ByteFee = ConstU128<1_000>; type FeeAsset = xcm_config::TokenAssetId; } +/// Instance of the XCM bridge hub pallet used to relay messages to/from Rialto chain. +pub type WithRialtoXcmBridgeHubInstance = (); + +impl pallet_xcm_bridge_hub::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + + type UniversalLocation = xcm_config::UniversalLocation; + type BridgedNetworkId = xcm_config::RialtoNetwork; + type BridgeMessagesPalletInstance = WithRialtoMessagesInstance; + + type MaxSuspendedBridges = ConstU32<1>; + type OpenBridgeOrigin = frame_support::traits::NeverEnsureOrigin; + type BridgeOriginAccountIdConverter = xcm_config::SovereignAccountOf; + + type BridgeReserve = ConstU64<1_000_000_000>; + type NativeCurrency = Balances; + + type LocalXcmChannelManager = (); + type BlobDispatcher = xcm_config::OnMillauBlobDispatcher; + type MessageExportPrice = (); +} + +/// Instance of the XCM bridge hub pallet used to relay messages to/from RialtoParachain chain. +pub type WithRialtoParachainXcmBridgeHubInstance = pallet_xcm_bridge_hub::Instance1; + +impl pallet_xcm_bridge_hub::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + + type UniversalLocation = xcm_config::UniversalLocation; + type BridgedNetworkId = xcm_config::RialtoParachainNetwork; + type BridgeMessagesPalletInstance = WithRialtoParachainMessagesInstance; + + type MaxSuspendedBridges = ConstU32<1>; + type OpenBridgeOrigin = frame_support::traits::NeverEnsureOrigin; + type BridgeOriginAccountIdConverter = xcm_config::SovereignAccountOf; + + type BridgeReserve = ConstU64<1_000_000_000>; + type NativeCurrency = Balances; + + type LocalXcmChannelManager = (); + type BlobDispatcher = xcm_config::OnMillauBlobDispatcher; + type MessageExportPrice = (); +} + construct_runtime!( pub enum Runtime { System: frame_system::{Pallet, Call, Config, Storage, Event}, @@ -569,6 +626,7 @@ construct_runtime!( BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event}, BridgeRialtoGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage, Event}, BridgeRialtoMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event, Config}, + XcmRialtoBridgeHub: pallet_xcm_bridge_hub::{Pallet, Call, Storage, Event, Config}, // Westend bridge modules. BridgeWestendGrandpa: pallet_bridge_grandpa::::{Pallet, Call, Config, Storage, Event}, @@ -577,6 +635,7 @@ construct_runtime!( // RialtoParachain bridge modules. BridgeRialtoParachains: pallet_bridge_parachains::{Pallet, Call, Storage, Event}, BridgeRialtoParachainMessages: pallet_bridge_messages::::{Pallet, Call, Storage, Event, Config}, + XcmRialtoParachainBridgeHub: pallet_xcm_bridge_hub::::{Pallet, Call, Storage, Event, Config}, // Pallet for sending XCM. XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event, Origin, Config} = 99, @@ -602,7 +661,11 @@ pub type PriorityBoostPerMessage = ConstU64<351_343_108>; pub type BridgeRefundRialtoParachainMessages = RefundBridgedParachainMessages< Runtime, RefundableParachain, - RefundableMessagesLane, + RefundableMessagesLane< + Runtime, + WithRialtoParachainMessagesInstance, + rialto_parachain_messages::Lane, + >, ActualFeeRefund, PriorityBoostPerMessage, StrBridgeRefundRialtoPara2000Lane0Msgs, diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 7e785703aee..8f186588226 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -16,53 +16,19 @@ //! Everything required to serve Millau <-> Rialto messages. -use crate::{Runtime, WithRialtoMessagesInstance}; +use crate::Runtime; -use bp_messages::LaneId; -use bridge_runtime_common::messages_xcm_extension::{ - LaneIdFromChainId, XcmBlobHauler, XcmBlobHaulerAdapter, -}; +use bp_xcm_bridge_hub::BridgeId; use frame_support::{parameter_types, weights::Weight}; use pallet_bridge_relayers::WeightInfoExt as _; -use sp_core::Get; -use xcm_builder::HaulBlobExporter; - -/// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge -/// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual -/// tests, confirming that we don't break encoding somewhere between. -pub const BASE_XCM_WEIGHT_TWICE: Weight = crate::xcm_config::BaseXcmWeight::get().saturating_mul(2); +use xcm::prelude::*; parameter_types! { - /// Weight credit for our test messages. - /// - /// 2 XCM instructions is for simple `Trap(42)` program, coming through bridge - /// (it is prepended with `UniversalOrigin` instruction). - pub const WeightCredit: Weight = BASE_XCM_WEIGHT_TWICE; -} - -/// Call-dispatch based message dispatch for Rialto -> Millau messages. -pub type FromRialtoMessageDispatch = - bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch< - crate::xcm_config::OnMillauBlobDispatcher, - (), - >; - -/// Export XCM messages to be relayed to Rialto. -pub type ToRialtoBlobExporter = HaulBlobExporter< - XcmBlobHaulerAdapter, - crate::xcm_config::RialtoNetwork, - (), ->; - -/// To-Rialto XCM hauler. -pub struct ToRialtoXcmBlobHauler; - -impl XcmBlobHauler for ToRialtoXcmBlobHauler { - type MessageSender = pallet_bridge_messages::Pallet; - - fn xcm_lane() -> LaneId { - LaneIdFromChainId::::get() - } + /// Bridge identifier that is used to bridge with Rialto. + pub Bridge: BridgeId = BridgeId::new( + &InteriorMultiLocation::from(crate::xcm_config::ThisNetwork::get()).into(), + &InteriorMultiLocation::from(crate::xcm_config::RialtoNetwork::get()).into(), + ); } impl pallet_bridge_messages::WeightInfoExt for crate::weights::RialtoMessagesWeightInfo { @@ -129,8 +95,8 @@ mod tests { // there's nothing criminal if it is changed, but then thou need to fix it across // all deployments scripts, alerts and so on assert_eq!( - *ToRialtoXcmBlobHauler::xcm_lane().as_ref(), - hex_literal::hex!("52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7") + *Bridge::get().lane_id().as_ref(), + hex_literal::hex!("efed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7") .into(), ); } diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs index e13c4c203c4..0b09067b3c5 100644 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -16,54 +16,22 @@ //! Everything required to serve Millau <-> RialtoParachain messages. -use crate::{Runtime, WithRialtoParachainMessagesInstance}; +use crate::Runtime; use bp_messages::LaneId; -use bridge_runtime_common::messages_xcm_extension::{ - LaneIdFromChainId, XcmBlobHauler, XcmBlobHaulerAdapter, -}; +use bp_xcm_bridge_hub::BridgeId; use frame_support::{parameter_types, weights::Weight}; use pallet_bridge_relayers::WeightInfoExt as _; -use sp_core::Get; -use xcm_builder::HaulBlobExporter; - -/// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge -/// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual -/// tests, confirming that we don't break encoding somewhere between. -pub const BASE_XCM_WEIGHT_TWICE: Weight = crate::xcm_config::BaseXcmWeight::get().saturating_mul(2); +use xcm::prelude::*; parameter_types! { - /// Weight credit for our test messages. - /// - /// 2 XCM instructions is for simple `Trap(42)` program, coming through bridge - /// (it is prepended with `UniversalOrigin` instruction). - pub const WeightCredit: Weight = BASE_XCM_WEIGHT_TWICE; -} - -/// Call-dispatch based message dispatch for RialtoParachain -> Millau messages. -pub type FromRialtoParachainMessageDispatch = - bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch< - crate::xcm_config::OnMillauBlobDispatcher, - (), - >; - -/// Export XCM messages to be relayed to Rialto. -pub type ToRialtoParachainBlobExporter = HaulBlobExporter< - XcmBlobHaulerAdapter, - crate::xcm_config::RialtoParachainNetwork, - (), ->; - -/// To-RialtoParachain XCM hauler. -pub struct ToRialtoParachainXcmBlobHauler; - -impl XcmBlobHauler for ToRialtoParachainXcmBlobHauler { - type MessageSender = - pallet_bridge_messages::Pallet; - - fn xcm_lane() -> LaneId { - LaneIdFromChainId::::get() - } + /// Bridge identifier that is used to bridge with RialtoParachain. + pub Bridge: BridgeId = BridgeId::new( + &InteriorMultiLocation::from(crate::xcm_config::ThisNetwork::get()).into(), + &InteriorMultiLocation::from(crate::xcm_config::RialtoParachainNetwork::get()).into(), + ); + /// Lane identifier, used by with-RialtoParachain bridge. + pub Lane: LaneId = Bridge::get().lane_id(); } impl pallet_bridge_messages::WeightInfoExt @@ -142,8 +110,8 @@ mod tests { // there's nothing criminal if it is changed, but then thou need to fix it across // all deployments scripts, alerts and so on assert_eq!( - *ToRialtoParachainXcmBlobHauler::xcm_lane().as_ref(), - hex_literal::hex!("6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de") + *Bridge::get().lane_id().as_ref(), + hex_literal::hex!("ee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c") .into(), ); } diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs index 33307ab9c81..d1c20d1c480 100644 --- a/bin/millau/runtime/src/xcm_config.rs +++ b/bin/millau/runtime/src/xcm_config.rs @@ -17,11 +17,11 @@ //! XCM configurations for the Millau runtime. use super::{ - rialto_messages::ToRialtoBlobExporter, - rialto_parachain_messages::ToRialtoParachainBlobExporter, AccountId, AllPalletsWithSystem, - Balances, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, XcmPallet, + AccountId, AllPalletsWithSystem, Balances, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, + XcmPallet, }; use bp_millau::WeightToFee; +use bp_xcm_bridge_hub::{BridgeId, BridgeLocations}; use bridge_runtime_common::CustomNetworkId; use frame_support::{ parameter_types, @@ -29,11 +29,12 @@ use frame_support::{ weights::Weight, }; use frame_system::EnsureRoot; +use sp_std::prelude::*; use xcm::latest::prelude::*; use xcm_builder::{ - AccountId32Aliases, CurrencyAdapter as XcmCurrencyAdapter, IsConcrete, MintLocation, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, - UsingComponents, + Account32Hash, AccountId32Aliases, CurrencyAdapter as XcmCurrencyAdapter, IsConcrete, + MintLocation, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, + TakeWeightCredit, UsingComponents, }; use xcm_executor::traits::ExportXcm; @@ -64,6 +65,8 @@ parameter_types! { pub type SovereignAccountOf = ( // We can directly alias an `AccountId32` into a local account. AccountId32Aliases, + // Dummy stuff for our tests. + Account32Hash, ); /// Our asset transactor. This is what allows us to interest with the runtime facilities from the @@ -199,7 +202,7 @@ impl pallet_xcm::Config for Runtime { pub struct ToRialtoOrRialtoParachainSwitchExporter; impl ExportXcm for ToRialtoOrRialtoParachainSwitchExporter { - type Ticket = (NetworkId, (sp_std::prelude::Vec, XcmHash)); + type Ticket = (NetworkId, (Box, sp_std::prelude::Vec, XcmHash)); fn validate( network: NetworkId, @@ -209,10 +212,16 @@ impl ExportXcm for ToRialtoOrRialtoParachainSwitchExporter { message: &mut Option>, ) -> SendResult { if network == RialtoNetwork::get() { - ToRialtoBlobExporter::validate(network, channel, universal_source, destination, message) - .map(|result| ((RialtoNetwork::get(), result.0), result.1)) + crate::XcmRialtoBridgeHub::validate( + network, + channel, + universal_source, + destination, + message, + ) + .map(|result| ((RialtoNetwork::get(), result.0), result.1)) } else if network == RialtoParachainNetwork::get() { - ToRialtoParachainBlobExporter::validate( + crate::XcmRialtoParachainBridgeHub::validate( network, channel, universal_source, @@ -228,9 +237,9 @@ impl ExportXcm for ToRialtoOrRialtoParachainSwitchExporter { fn deliver(ticket: Self::Ticket) -> Result { let (network, ticket) = ticket; if network == RialtoNetwork::get() { - ToRialtoBlobExporter::deliver(ticket) + crate::XcmRialtoBridgeHub::deliver(ticket) } else if network == RialtoParachainNetwork::get() { - ToRialtoParachainBlobExporter::deliver(ticket) + crate::XcmRialtoParachainBridgeHub::deliver(ticket) } else { Err(SendError::Unroutable) } @@ -248,26 +257,33 @@ impl EmulatedSiblingXcmpChannel { } } -impl bp_xcm_bridge_hub_router::LocalXcmChannel for EmulatedSiblingXcmpChannel { - fn is_congested() -> bool { +impl bp_xcm_bridge_hub::LocalXcmChannelManager for EmulatedSiblingXcmpChannel { + type Error = (); + + fn is_congested(_with: &MultiLocation) -> bool { frame_support::storage::unhashed::get_or_default(b"EmulatedSiblingXcmpChannel.Congested") } + + fn suspend_bridge(_with: &MultiLocation, _bridge_id: BridgeId) -> Result<(), Self::Error> { + Ok(()) + } + + fn resume_bridge(_with: &MultiLocation, _bridge_id: BridgeId) -> Result<(), Self::Error> { + Ok(()) + } } #[cfg(test)] mod tests { use super::*; use crate::{ - rialto_messages::FromRialtoMessageDispatch, WithRialtoMessagesInstance, - WithRialtoParachainMessagesInstance, + WithRialtoMessagesInstance, WithRialtoParachainMessagesInstance, XcmRialtoBridgeHub, + XcmRialtoParachainBridgeHub, }; use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, LaneId, MessageKey, OutboundLaneData, }; - use bridge_runtime_common::messages_xcm_extension::{ - XcmBlobHauler, XcmBlobMessageDispatchResult, - }; use codec::Encode; use pallet_bridge_messages::OutboundLanes; use sp_runtime::BuildStorage; @@ -292,7 +308,7 @@ mod tests { fn xcm_messages_to_rialto_are_sent_using_bridge_exporter() { new_test_ext().execute_with(|| { // ensure that the there are no messages queued - let lane_id = crate::rialto_messages::ToRialtoXcmBlobHauler::xcm_lane(); + let lane_id = crate::rialto_messages::Bridge::get().lane_id(); OutboundLanes::::insert( lane_id, OutboundLaneData::opened(), @@ -329,8 +345,7 @@ mod tests { fn xcm_messages_to_rialto_parachain_are_sent_using_bridge_exporter() { new_test_ext().execute_with(|| { // ensure that the there are no messages queued - let lane_id = - crate::rialto_parachain_messages::ToRialtoParachainXcmBlobHauler::xcm_lane(); + let lane_id = crate::rialto_parachain_messages::Lane::get(); OutboundLanes::::insert( lane_id, OutboundLaneData::opened(), @@ -378,31 +393,29 @@ mod tests { #[test] fn xcm_messages_from_rialto_are_dispatched() { - let incoming_message = prepare_inbound_bridge_message( - crate::rialto_messages::ToRialtoXcmBlobHauler::xcm_lane(), - ); + let incoming_message = + prepare_inbound_bridge_message(crate::rialto_messages::Bridge::get().lane_id()); // we care only about handing message to the XCM dispatcher, so we don't care about its // actual dispatch - let dispatch_result = FromRialtoMessageDispatch::dispatch(incoming_message); + let dispatch_result = XcmRialtoBridgeHub::dispatch(incoming_message); assert!(matches!( dispatch_result.dispatch_level_result, - XcmBlobMessageDispatchResult::NotDispatched(_), + pallet_xcm_bridge_hub::XcmBlobMessageDispatchResult::NotDispatched(_), )); } #[test] fn xcm_messages_from_rialto_parachain_are_dispatched() { - let incoming_message = prepare_inbound_bridge_message( - crate::rialto_parachain_messages::ToRialtoParachainXcmBlobHauler::xcm_lane(), - ); + let incoming_message = + prepare_inbound_bridge_message(crate::rialto_parachain_messages::Lane::get()); // we care only about handing message to the XCM dispatcher, so we don't care about its // actual dispatch - let dispatch_result = FromRialtoMessageDispatch::dispatch(incoming_message); + let dispatch_result = XcmRialtoParachainBridgeHub::dispatch(incoming_message); assert!(matches!( dispatch_result.dispatch_level_result, - XcmBlobMessageDispatchResult::NotDispatched(_), + pallet_xcm_bridge_hub::XcmBlobMessageDispatchResult::NotDispatched(_), )); } } diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index 4be9ced3d60..5f217b1666c 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -82,3 +82,4 @@ cumulus-relay-chain-interface = { git = "https://github.com/paritytech/cumulus", polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "master" } +xcm = { git = "https://github.com/paritytech/polkadot", branch = "master" } diff --git a/bin/rialto-parachain/node/src/chain_spec.rs b/bin/rialto-parachain/node/src/chain_spec.rs index 2aa7a1c0be2..2b0c76ad81e 100644 --- a/bin/rialto-parachain/node/src/chain_spec.rs +++ b/bin/rialto-parachain/node/src/chain_spec.rs @@ -14,9 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use bridge_runtime_common::messages_xcm_extension::XcmBlobHauler; use cumulus_primitives_core::ParaId; -use rialto_parachain_runtime::{AccountId, AuraId, BridgeMillauMessagesConfig, Signature}; +use rialto_parachain_runtime::{ + AccountId, AuraId, BridgeMillauMessagesConfig, Signature, XcmMillauBridgeHubConfig, +}; use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup}; use sc_service::ChainType; use serde::{Deserialize, Serialize}; @@ -197,9 +198,16 @@ fn testnet_genesis( aura_ext: Default::default(), bridge_millau_messages: BridgeMillauMessagesConfig { owner: Some(get_account_id_from_seed::(MILLAU_MESSAGES_PALLET_OWNER)), - opened_lanes: vec![ - rialto_parachain_runtime::millau_messages::ToMillauXcmBlobHauler::xcm_lane(), - ], + opened_lanes: vec![rialto_parachain_runtime::millau_messages::Bridge::get().lane_id()], + ..Default::default() + }, + xcm_millau_bridge_hub: XcmMillauBridgeHubConfig { + opened_bridges: vec![( + xcm::latest::Junctions::Here.into(), + xcm::latest::InteriorMultiLocation::from( + rialto_parachain_runtime::MillauNetwork::get(), + ), + )], ..Default::default() }, } diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index 1b87205e9e9..0e1fd61b2d7 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -22,10 +22,12 @@ bp-millau = { path = "../../../primitives/chain-millau", default-features = fals bp-relayers = { path = "../../../primitives/relayers", default-features = false } bp-runtime = { path = "../../../primitives/runtime", default-features = false } bp-rialto-parachain = { path = "../../../primitives/chain-rialto-parachain", default-features = false } +bp-xcm-bridge-hub = { path = "../../../primitives/xcm-bridge-hub", default-features = false } bridge-runtime-common = { path = "../../runtime-common", default-features = false } pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../../modules/messages", default-features = false } pallet-bridge-relayers = { path = "../../../modules/relayers", default-features = false } +pallet-xcm-bridge-hub = { path = "../../../modules/xcm-bridge-hub", default-features = false } # Substrate Dependencies ## Substrate Primitive Dependencies @@ -98,6 +100,7 @@ std = [ "bp-relayers/std", "bp-runtime/std", "bp-rialto-parachain/std", + "bp-xcm-bridge-hub/std", "bridge-runtime-common/std", "codec/std", "scale-info/std", @@ -125,6 +128,7 @@ std = [ "pallet-transaction-payment/std", "pallet-transaction-payment-rpc-runtime-api/std", "pallet-xcm/std", + "pallet-xcm-bridge-hub/std", "parachain-info/std", "polkadot-parachain/std", "cumulus-pallet-aura-ext/std", diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 5166ca7ca86..d69dfa7c65d 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -34,7 +34,7 @@ use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, ConstBool, OpaqueMetadata}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, - traits::{AccountIdLookup, Block as BlockT, DispatchInfoOf, SignedExtension}, + traits::{AccountIdLookup, Block as BlockT, ConstU128, DispatchInfoOf, SignedExtension}, transaction_validity::{TransactionSource, TransactionValidity, TransactionValidityError}, ApplyExtrinsicResult, }; @@ -83,10 +83,10 @@ use pallet_xcm::XcmPassthrough; use polkadot_parachain::primitives::Sibling; use xcm::latest::prelude::*; use xcm_builder::{ - AccountId32Aliases, CurrencyAdapter, EnsureXcmOrigin, FixedWeightBounds, IsConcrete, - NativeAsset, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, - SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, + Account32Hash, AccountId32Aliases, CurrencyAdapter, EnsureXcmOrigin, FixedWeightBounds, + IsConcrete, NativeAsset, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, + SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, }; use xcm_executor::{Config, XcmExecutor}; @@ -365,6 +365,8 @@ pub type LocationToAccountId = ( SiblingParachainConvertsVia, // Straight up local `AccountId32` origins just alias directly to `AccountId`. AccountId32Aliases, + // Dummy stuff for our tests. + Account32Hash, ); /// Means for transacting assets on this chain. @@ -455,7 +457,7 @@ impl Config for XcmConfig { type AssetLocker = (); type AssetExchanger = (); type FeeManager = (); - type MessageExporter = millau_messages::ToMillauBlobExporter; + type MessageExporter = XcmMillauBridgeHub; type UniversalAliases = Nothing; type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; @@ -565,8 +567,8 @@ impl pallet_bridge_messages::Config for Runtime { type BridgedChain = bp_millau::Millau; type BridgedHeaderChain = BridgeMillauGrandpa; - type OutboundPayload = bridge_runtime_common::messages_xcm_extension::XcmAsPlainPayload; - type InboundPayload = bridge_runtime_common::messages_xcm_extension::XcmAsPlainPayload; + type OutboundPayload = bp_xcm_bridge_hub::XcmAsPlainPayload; + type InboundPayload = bp_xcm_bridge_hub::XcmAsPlainPayload; type DeliveryPayments = (); type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< @@ -574,8 +576,31 @@ impl pallet_bridge_messages::Config for Runtime { WithMillauMessagesInstance, frame_support::traits::ConstU128<100_000>, >; + type OnMessagesDelivered = XcmMillauBridgeHub; - type MessageDispatch = crate::millau_messages::FromMillauMessageDispatch; + type MessageDispatch = XcmMillauBridgeHub; +} + +/// Instance of the XCM bridge hub pallet used to relay messages to/from Millau chain. +pub type WithMillauXcmBridgeHubInstance = (); + +impl pallet_xcm_bridge_hub::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + + type UniversalLocation = UniversalLocation; + type BridgedNetworkId = MillauNetwork; + type BridgeMessagesPalletInstance = WithMillauMessagesInstance; + + type MaxSuspendedBridges = ConstU32<1>; + type OpenBridgeOrigin = frame_support::traits::NeverEnsureOrigin; + type BridgeOriginAccountIdConverter = LocationToAccountId; + + type BridgeReserve = ConstU128<1_000_000_000>; + type NativeCurrency = Balances; + + type LocalXcmChannelManager = (); + type BlobDispatcher = OnRialtoParachainBlobDispatcher; + type MessageExportPrice = (); } // Create the runtime by composing the FRAME pallets that were previously configured. @@ -604,6 +629,7 @@ construct_runtime!( BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event}, BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage, Event}, BridgeMillauMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event, Config}, + XcmMillauBridgeHub: pallet_xcm_bridge_hub::{Pallet, Call, Storage, Event, Config}, } ); @@ -840,16 +866,12 @@ cumulus_pallet_parachain_system::register_validate_block!( #[cfg(test)] mod tests { use super::*; - use crate::millau_messages::FromMillauMessageDispatch; use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, MessageKey, OutboundLaneData, }; use bp_runtime::Chain; - use bridge_runtime_common::{ - integrity::check_additional_signed, - messages_xcm_extension::{XcmBlobHauler, XcmBlobMessageDispatchResult}, - }; + use bridge_runtime_common::integrity::check_additional_signed; use codec::Encode; use pallet_bridge_messages::OutboundLanes; use sp_runtime::generic::Era; @@ -882,7 +904,7 @@ mod tests { fn xcm_messages_to_millau_are_sent_using_bridge_exporter() { new_test_ext().execute_with(|| { // ensure that the there are no messages queued - let lane_id = crate::millau_messages::ToMillauXcmBlobHauler::xcm_lane(); + let lane_id = crate::millau_messages::Bridge::get().lane_id(); OutboundLanes::::insert( lane_id, OutboundLaneData::opened(), @@ -921,7 +943,7 @@ mod tests { xcm::VersionedInteriorMultiLocation::V3(X1(GlobalConsensus(ThisNetwork::get()))); // this is the `BridgeMessage` from polkadot xcm builder, but it has no constructor // or public fields, so just tuple - let xcm_lane = crate::millau_messages::ToMillauXcmBlobHauler::xcm_lane(); + let xcm_lane = crate::millau_messages::Bridge::get().lane_id(); let bridge_message = (location, xcm).encode(); DispatchMessage { key: MessageKey { lane_id: xcm_lane, nonce: 1 }, @@ -936,10 +958,10 @@ mod tests { // we care only about handing message to the XCM dispatcher, so we don't care about its // actual dispatch - let dispatch_result = FromMillauMessageDispatch::dispatch(incoming_message); + let dispatch_result = XcmMillauBridgeHub::dispatch(incoming_message); assert!(matches!( dispatch_result.dispatch_level_result, - XcmBlobMessageDispatchResult::NotDispatched(_), + pallet_xcm_bridge_hub::XcmBlobMessageDispatchResult::NotDispatched(_), )); }); } diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs index 2eb7c1b8525..cd9bdab5cc2 100644 --- a/bin/rialto-parachain/runtime/src/millau_messages.rs +++ b/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -16,52 +16,16 @@ //! Everything required to serve Millau <-> RialtoParachain messages. -// TODO: this is almost exact copy of `millau_messages.rs` from Rialto runtime. -// Should be extracted to a separate crate and reused here. - -use crate::{Runtime, WithMillauMessagesInstance}; - -use bp_messages::LaneId; -use bridge_runtime_common::messages_xcm_extension::{ - LaneIdFromChainId, XcmBlobHauler, XcmBlobHaulerAdapter, -}; -use frame_support::{parameter_types, weights::Weight}; -use sp_core::Get; -use xcm_builder::HaulBlobExporter; - -/// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge -/// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual -/// tests, confirming that we don't break encoding somewhere between. -pub const BASE_XCM_WEIGHT_TWICE: Weight = crate::UnitWeightCost::get().saturating_mul(2); +use bp_xcm_bridge_hub::BridgeId; +use frame_support::parameter_types; +use xcm::prelude::*; parameter_types! { - /// Weight credit for our test messages. - /// - /// 2 XCM instructions is for simple `Trap(42)` program, coming through bridge - /// (it is prepended with `UniversalOrigin` instruction). - pub const WeightCredit: Weight = BASE_XCM_WEIGHT_TWICE; -} - -/// Call-dispatch based message dispatch for Millau -> RialtoParachain messages. -pub type FromMillauMessageDispatch = - bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch< - crate::OnRialtoParachainBlobDispatcher, - (), - >; - -/// Export XCM messages to be relayed to Millau. -pub type ToMillauBlobExporter = - HaulBlobExporter, crate::MillauNetwork, ()>; - -/// To-Millau XCM hauler. -pub struct ToMillauXcmBlobHauler; - -impl XcmBlobHauler for ToMillauXcmBlobHauler { - type MessageSender = pallet_bridge_messages::Pallet; - - fn xcm_lane() -> LaneId { - LaneIdFromChainId::::get() - } + /// Bridge identifier that is used to bridge with Millau. + pub Bridge: BridgeId = BridgeId::new( + &InteriorMultiLocation::from(crate::ThisNetwork::get()).into(), + &InteriorMultiLocation::from(crate::MillauNetwork::get()).into(), + ); } #[cfg(test)] @@ -117,8 +81,8 @@ mod tests { // there's nothing criminal if it is changed, but then thou need to fix it across // all deployments scripts, alerts and so on assert_eq!( - *ToMillauXcmBlobHauler::xcm_lane().as_ref(), - hex_literal::hex!("6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de") + *Bridge::get().lane_id().as_ref(), + hex_literal::hex!("ee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c") .into(), ); } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 5e158a7f6bd..5d3d707666e 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -35,10 +35,12 @@ sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } # Polkadot Dependencies + polkadot-node-core-pvf = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false, features = [ "full-node", "polkadot-native" ] } +xcm = { git = "https://github.com/paritytech/polkadot", branch = "master" } [build-dependencies] substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 83a9fa2ce22..c2ea60f7ef6 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -14,12 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use bridge_runtime_common::messages_xcm_extension::XcmBlobHauler; use polkadot_primitives::v5::{AssignmentId, ValidatorId}; use rialto_runtime::{ AccountId, BabeConfig, BalancesConfig, BeefyConfig, BridgeMillauMessagesConfig, ConfigurationConfig, GrandpaConfig, RuntimeGenesisConfig, SessionConfig, SessionKeys, - Signature, SudoConfig, SystemConfig, WASM_BINARY, + Signature, SudoConfig, SystemConfig, XcmMillauBridgeHubConfig, WASM_BINARY, }; use serde_json::json; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; @@ -280,9 +279,18 @@ fn testnet_genesis( paras: Default::default(), bridge_millau_messages: BridgeMillauMessagesConfig { owner: Some(get_account_id_from_seed::(MILLAU_MESSAGES_PALLET_OWNER)), - opened_lanes: vec![rialto_runtime::millau_messages::ToMillauXcmBlobHauler::xcm_lane()], + opened_lanes: vec![rialto_runtime::millau_messages::Bridge::get().lane_id()], ..Default::default() }, xcm_pallet: Default::default(), + xcm_millau_bridge_hub: XcmMillauBridgeHubConfig { + opened_bridges: vec![( + xcm::latest::Junctions::Here.into(), + xcm::latest::InteriorMultiLocation::from( + rialto_runtime::xcm_config::MillauNetwork::get(), + ), + )], + ..Default::default() + }, } } diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 0f7c4c0f78b..89479740e56 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -18,12 +18,14 @@ bp-millau = { path = "../../../primitives/chain-millau", default-features = fals bp-relayers = { path = "../../../primitives/relayers", default-features = false } bp-rialto = { path = "../../../primitives/chain-rialto", default-features = false } bp-runtime = { path = "../../../primitives/runtime", default-features = false } +bp-xcm-bridge-hub = { path = "../../../primitives/xcm-bridge-hub", default-features = false } bridge-runtime-common = { path = "../../runtime-common", default-features = false } pallet-bridge-beefy = { path = "../../../modules/beefy", default-features = false } pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../../modules/messages", default-features = false } pallet-bridge-relayers = { path = "../../../modules/relayers", default-features = false } pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } +pallet-xcm-bridge-hub = { path = "../../../modules/xcm-bridge-hub", default-features = false } # Substrate Dependencies @@ -87,6 +89,7 @@ std = [ "bp-relayers/std", "bp-rialto/std", "bp-runtime/std", + "bp-xcm-bridge-hub/std", "bridge-runtime-common/std", "codec/std", "frame-benchmarking/std", @@ -113,6 +116,7 @@ std = [ "pallet-timestamp/std", "pallet-transaction-payment-rpc-runtime-api/std", "pallet-transaction-payment/std", + "pallet-xcm-bridge-hub/std", "polkadot-primitives/std", "polkadot-runtime-common/std", "polkadot-runtime-parachains/std", diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 90887e37d05..caf46fef466 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -43,7 +43,7 @@ use sp_consensus_beefy::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, Va use sp_core::OpaqueMetadata; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, - traits::{AccountIdLookup, Block as BlockT, Keccak256, NumberFor, OpaqueKeys}, + traits::{AccountIdLookup, Block as BlockT, ConstU128, Keccak256, NumberFor, OpaqueKeys}, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, FixedPointNumber, Perquintill, }; @@ -423,8 +423,8 @@ impl pallet_bridge_messages::Config for Runtime { type BridgedChain = bp_millau::Millau; type BridgedHeaderChain = BridgeMillauGrandpa; - type OutboundPayload = bridge_runtime_common::messages_xcm_extension::XcmAsPlainPayload; - type InboundPayload = bridge_runtime_common::messages_xcm_extension::XcmAsPlainPayload; + type OutboundPayload = bp_xcm_bridge_hub::XcmAsPlainPayload; + type InboundPayload = bp_xcm_bridge_hub::XcmAsPlainPayload; type DeliveryPayments = (); type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< @@ -432,8 +432,9 @@ impl pallet_bridge_messages::Config for Runtime { WithMillauMessagesInstance, frame_support::traits::ConstU128<100_000>, >; + type OnMessagesDelivered = XcmMillauBridgeHub; - type MessageDispatch = crate::millau_messages::FromMillauMessageDispatch; + type MessageDispatch = XcmMillauBridgeHub; } pub type MillauBeefyInstance = (); @@ -443,6 +444,28 @@ impl pallet_bridge_beefy::Config for Runtime { type BridgedChain = bp_millau::Millau; } +/// Instance of the XCM bridge hub pallet used to relay messages to/from Millau chain. +pub type WithMillauXcmBridgeHubInstance = (); + +impl pallet_xcm_bridge_hub::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + + type UniversalLocation = xcm_config::UniversalLocation; + type BridgedNetworkId = xcm_config::MillauNetwork; + type BridgeMessagesPalletInstance = WithMillauMessagesInstance; + + type MaxSuspendedBridges = ConstU32<1>; + type OpenBridgeOrigin = frame_support::traits::NeverEnsureOrigin; + type BridgeOriginAccountIdConverter = xcm_config::SovereignAccountOf; + + type BridgeReserve = ConstU128<1_000_000_000>; + type NativeCurrency = Balances; + + type LocalXcmChannelManager = (); + type BlobDispatcher = xcm_config::OnRialtoBlobDispatcher; + type MessageExportPrice = (); +} + construct_runtime!( pub enum Runtime { System: frame_system::{Pallet, Call, Config, Storage, Event}, @@ -470,6 +493,7 @@ construct_runtime!( BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event}, BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage, Event}, BridgeMillauMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event, Config}, + XcmMillauBridgeHub: pallet_xcm_bridge_hub::{Pallet, Call, Storage, Event, Config}, // Millau bridge modules (BEEFY based). BridgeMillauBeefy: pallet_bridge_beefy::{Pallet, Call, Storage}, diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index b8f6fadcad5..a1c3164d68e 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -16,52 +16,16 @@ //! Everything required to serve Millau <-> Rialto messages. -use crate::{Runtime, WithMillauMessagesInstance}; - -use bp_messages::LaneId; -use bridge_runtime_common::messages_xcm_extension::{ - LaneIdFromChainId, XcmBlobHauler, XcmBlobHaulerAdapter, -}; -use frame_support::{parameter_types, weights::Weight}; -use sp_core::Get; -use xcm_builder::HaulBlobExporter; - -/// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge -/// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual -/// tests, confirming that we don't break encoding somewhere between. -pub const BASE_XCM_WEIGHT_TWICE: Weight = crate::xcm_config::BaseXcmWeight::get().saturating_mul(2); +use bp_xcm_bridge_hub::BridgeId; +use frame_support::parameter_types; +use xcm::prelude::*; parameter_types! { - /// Weight credit for our test messages. - /// - /// 2 XCM instructions is for simple `Trap(42)` program, coming through bridge - /// (it is prepended with `UniversalOrigin` instruction). - pub const WeightCredit: Weight = BASE_XCM_WEIGHT_TWICE; -} - -/// Call-dispatch based message dispatch for Millau -> Rialto messages. -pub type FromMillauMessageDispatch = - bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch< - crate::xcm_config::OnRialtoBlobDispatcher, - (), - >; - -/// Export XCM messages to be relayed to Millau. -pub type ToMillauBlobExporter = HaulBlobExporter< - XcmBlobHaulerAdapter, - crate::xcm_config::MillauNetwork, - (), ->; - -/// To-Millau XCM hauler. -pub struct ToMillauXcmBlobHauler; - -impl XcmBlobHauler for ToMillauXcmBlobHauler { - type MessageSender = pallet_bridge_messages::Pallet; - - fn xcm_lane() -> LaneId { - LaneIdFromChainId::::get() - } + /// Bridge identifier that is used to bridge with Millau. + pub Bridge: BridgeId = BridgeId::new( + &InteriorMultiLocation::from(crate::xcm_config::ThisNetwork::get()).into(), + &InteriorMultiLocation::from(crate::xcm_config::MillauNetwork::get()).into(), + ); } #[cfg(test)] @@ -113,8 +77,8 @@ mod tests { // there's nothing criminal if it is changed, but then thou need to fix it across // all deployments scripts, alerts and so on assert_eq!( - *ToMillauXcmBlobHauler::xcm_lane().as_ref(), - hex_literal::hex!("52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7") + *Bridge::get().lane_id().as_ref(), + hex_literal::hex!("efed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7") .into(), ); } diff --git a/bin/rialto/runtime/src/xcm_config.rs b/bin/rialto/runtime/src/xcm_config.rs index 12d8c11a3ec..f846a2fddb6 100644 --- a/bin/rialto/runtime/src/xcm_config.rs +++ b/bin/rialto/runtime/src/xcm_config.rs @@ -17,8 +17,8 @@ //! XCM configurations for the Rialto runtime. use super::{ - millau_messages::ToMillauBlobExporter, AccountId, AllPalletsWithSystem, Balances, Runtime, - RuntimeCall, RuntimeEvent, RuntimeOrigin, XcmPallet, + AccountId, AllPalletsWithSystem, Balances, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, + XcmPallet, }; use bp_rialto::WeightToFee; use bridge_runtime_common::CustomNetworkId; @@ -30,9 +30,9 @@ use frame_support::{ use frame_system::EnsureRoot; use xcm::latest::prelude::*; use xcm_builder::{ - AccountId32Aliases, CurrencyAdapter as XcmCurrencyAdapter, IsConcrete, MintLocation, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, - UsingComponents, + Account32Hash, AccountId32Aliases, CurrencyAdapter as XcmCurrencyAdapter, IsConcrete, + MintLocation, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, + TakeWeightCredit, UsingComponents, }; parameter_types! { @@ -58,6 +58,8 @@ parameter_types! { pub type SovereignAccountOf = ( // We can directly alias an `AccountId32` into a local account. AccountId32Aliases, + // Dummy stuff for our tests. + Account32Hash, ); /// Our asset transactor. This is what allows us to interest with the runtime facilities from the @@ -134,7 +136,7 @@ impl xcm_executor::Config for XcmConfig { type PalletInstancesInfo = AllPalletsWithSystem; type MaxAssetsIntoHolding = ConstU32<64>; type FeeManager = (); - type MessageExporter = ToMillauBlobExporter; + type MessageExporter = crate::XcmMillauBridgeHub; type UniversalAliases = Nothing; type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; @@ -193,14 +195,11 @@ impl pallet_xcm::Config for Runtime { #[cfg(test)] mod tests { use super::*; - use crate::{millau_messages::FromMillauMessageDispatch, WithMillauMessagesInstance}; + use crate::{WithMillauMessagesInstance, XcmMillauBridgeHub}; use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, MessageKey, OutboundLaneData, }; - use bridge_runtime_common::messages_xcm_extension::{ - XcmBlobHauler, XcmBlobMessageDispatchResult, - }; use codec::Encode; use pallet_bridge_messages::OutboundLanes; use sp_runtime::BuildStorage; @@ -225,7 +224,7 @@ mod tests { fn xcm_messages_to_millau_are_sent_using_bridge_exporter() { new_test_ext().execute_with(|| { // ensure that the there are no messages queued - let lane_id = crate::millau_messages::ToMillauXcmBlobHauler::xcm_lane(); + let lane_id = crate::millau_messages::Bridge::get().lane_id(); OutboundLanes::::insert( lane_id, OutboundLaneData::opened(), @@ -265,7 +264,7 @@ mod tests { // this is the `BridgeMessage` from polkadot xcm builder, but it has no constructor // or public fields, so just tuple let bridge_message = (location, xcm).encode(); - let lane_id = crate::millau_messages::ToMillauXcmBlobHauler::xcm_lane(); + let lane_id = crate::millau_messages::Bridge::get().lane_id(); DispatchMessage { key: MessageKey { lane_id, nonce: 1 }, data: DispatchMessageData { payload: Ok(bridge_message) }, @@ -278,10 +277,10 @@ mod tests { // we care only about handing message to the XCM dispatcher, so we don't care about its // actual dispatch - let dispatch_result = FromMillauMessageDispatch::dispatch(incoming_message); + let dispatch_result = XcmMillauBridgeHub::dispatch(incoming_message); assert!(matches!( dispatch_result.dispatch_level_result, - XcmBlobMessageDispatchResult::NotDispatched(_), + pallet_xcm_bridge_hub::XcmBlobMessageDispatchResult::NotDispatched(_), )); } } diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index e1bb263e81d..50df84f0db9 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -21,6 +21,7 @@ bp-parachains = { path = "../../primitives/parachains", default-features = false bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } bp-relayers = { path = "../../primitives/relayers", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } +bp-xcm-bridge-hub = { path = "../../primitives/xcm-bridge-hub", default-features = false } pallet-bridge-grandpa = { path = "../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../modules/messages", default-features = false } pallet-bridge-parachains = { path = "../../modules/parachains", default-features = false } @@ -56,6 +57,7 @@ std = [ "bp-parachains/std", "bp-polkadot-core/std", "bp-runtime/std", + "bp-xcm-bridge-hub/std", "codec/std", "frame-support/std", "frame-system/std", diff --git a/bin/runtime-common/src/integrity.rs b/bin/runtime-common/src/integrity.rs index 739bc9153fc..aaf0810ca4a 100644 --- a/bin/runtime-common/src/integrity.rs +++ b/bin/runtime-common/src/integrity.rs @@ -64,9 +64,9 @@ macro_rules! assert_bridge_messages_pallet_types( // if one of asserts fail, then either bridge isn't configured properly (or alternatively - non-standard // configuration is used), or something has broke existing configuration (meaning that all bridged chains // and relays will stop functioning) - use $crate::messages_xcm_extension::XcmAsPlainPayload; use bp_messages::ChainWithMessages; use bp_runtime::Chain; + use bp_xcm_bridge_hub::XcmAsPlainPayload; use pallet_bridge_messages::Config as MessagesConfig; use static_assertions::assert_type_eq_all; diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index 459466264eb..9a1df7fd311 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -28,7 +28,6 @@ use xcm::v3::NetworkId; pub mod messages_api; pub mod messages_benchmarking; pub mod messages_call_ext; -pub mod messages_xcm_extension; pub mod parachains_benchmarking; pub mod priority_calculator; pub mod refund_relayer_extension; @@ -38,8 +37,6 @@ mod mock; #[cfg(feature = "integrity-test")] pub mod integrity; -const LOG_TARGET_BRIDGE_DISPATCH: &str = "runtime::bridge-dispatch"; - /// A duplication of the `FilterCall` trait. /// /// We need this trait in order to be able to implement it for the messages pallet, diff --git a/bin/runtime-common/src/messages_call_ext.rs b/bin/runtime-common/src/messages_call_ext.rs index daf51e0a334..926aa9fb523 100644 --- a/bin/runtime-common/src/messages_call_ext.rs +++ b/bin/runtime-common/src/messages_call_ext.rs @@ -17,7 +17,9 @@ //! Signed extension for the `pallet-bridge-messages` that is able to reject obsolete //! (and some other invalid) transactions. -use bp_messages::{ChainWithMessages, InboundLaneData, LaneId, MessageNonce}; +use bp_messages::{ + target_chain::MessageDispatch, ChainWithMessages, InboundLaneData, LaneId, MessageNonce, +}; use bp_runtime::AccountIdOf; use frame_support::{dispatch::CallableCallFor, traits::IsSubType, RuntimeDebug}; use pallet_bridge_messages::{BridgedChainOf, Config, Pallet}; @@ -74,7 +76,12 @@ impl ReceiveMessagesProofInfo { /// /// - or there are no bundled messages, but the inbound lane is blocked by too many unconfirmed /// messages and/or unrewarded relayers. - fn is_obsolete(&self) -> bool { + fn is_obsolete(&self, is_dispatcher_active: bool) -> bool { + // if dispatcher is inactive, we don't accept any delivery transactions + if !is_dispatcher_active { + return true + } + // transactions with zero bundled nonces are not allowed, unless they're message // delivery transactions, which brings reward confirmations required to unblock // the lane @@ -271,7 +278,10 @@ impl< fn check_obsolete_call(&self) -> TransactionValidity { match self.call_info() { - Some(CallInfo::ReceiveMessagesProof(proof_info)) if proof_info.is_obsolete() => { + Some(CallInfo::ReceiveMessagesProof(proof_info)) + if proof_info + .is_obsolete(T::MessageDispatch::is_active(proof_info.base.lane_id)) => + { log::trace!( target: pallet_bridge_messages::LOG_TARGET, "Rejecting obsolete messages delivery transaction: {:?}", @@ -320,7 +330,7 @@ mod tests { use super::*; use crate::{ messages_call_ext::MessagesCallSubType, - mock::{BridgedUnderlyingChain, TestRuntime, ThisChainRuntimeCall}, + mock::{BridgedUnderlyingChain, DummyMessageDispatch, TestRuntime, ThisChainRuntimeCall}, }; use bp_messages::{ source_chain::FromBridgedChainMessagesDeliveryProof, @@ -452,6 +462,18 @@ mod tests { }); } + #[test] + fn extension_reject_call_when_dispatcher_is_inactive() { + run_test(|| { + // when current best delivered is message#10 and we're trying to deliver message 11..=15 + // => tx is accepted + deliver_message_10(); + + DummyMessageDispatch::deactivate(test_lane_id()); + assert!(!validate_message_delivery(11, 15)); + }); + } + #[test] fn extension_rejects_empty_delivery_with_rewards_confirmations_if_there_are_free_relayer_and_message_slots( ) { diff --git a/bin/runtime-common/src/messages_xcm_extension.rs b/bin/runtime-common/src/messages_xcm_extension.rs deleted file mode 100644 index 6b412747f68..00000000000 --- a/bin/runtime-common/src/messages_xcm_extension.rs +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright 2023 Parity Technologies (UK) Ltd. -// This file is part of Parity Bridges Common. - -// Parity Bridges Common is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Bridges Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Bridges Common. If not, see . - -//! Module provides utilities for easier XCM handling, e.g: -//! `XcmExecutor` -> `MessageSender` -> `OutboundMessageQueue` -//! | -//! `Relayer` -//! | -//! `XcmRouter` <- `MessageDispatch` <- `InboundMessageQueue` - -use bp_messages::{ - source_chain::MessagesBridge, - target_chain::{DispatchMessage, MessageDispatch}, - LaneId, -}; -use bp_runtime::{messages::MessageDispatchResult, Chain}; -use codec::{Decode, Encode}; -use frame_support::{dispatch::Weight, CloneNoBound, EqNoBound, PartialEqNoBound}; -use pallet_bridge_messages::WeightInfoExt as MessagesPalletWeights; -use scale_info::TypeInfo; -use sp_core::Get; -use sp_runtime::SaturatedConversion; -use sp_std::marker::PhantomData; -use xcm_builder::{DispatchBlob, DispatchBlobError, HaulBlob, HaulBlobError}; - -/// Plain "XCM" payload, which we transfer through bridge -pub type XcmAsPlainPayload = sp_std::prelude::Vec; - -/// Make LaneId from chain identifiers of two bridge endpoints. -// TODO: https://github.com/paritytech/parity-bridges-common/issues/1666: this function -// is a temporary solution, because `ChainId` and will be removed soon. -pub struct LaneIdFromChainId(PhantomData<(R, I)>); - -impl Get for LaneIdFromChainId -where - R: pallet_bridge_messages::Config, - I: 'static, -{ - fn get() -> LaneId { - LaneId::new( - pallet_bridge_messages::ThisChainOf::::ID, - pallet_bridge_messages::BridgedChainOf::::ID, - ) - } -} - -/// Message dispatch result type for single message. -#[derive(CloneNoBound, EqNoBound, PartialEqNoBound, Encode, Decode, Debug, TypeInfo)] -pub enum XcmBlobMessageDispatchResult { - /// We've been unable to decode message payload. - InvalidPayload, - /// Message has been dispatched. - Dispatched, - /// Message has **NOT** been dispatched because of given error. - NotDispatched(#[codec(skip)] Option), -} - -/// [`XcmBlobMessageDispatch`] is responsible for dispatching received messages -pub struct XcmBlobMessageDispatch { - _marker: sp_std::marker::PhantomData<(DispatchBlob, Weights)>, -} - -impl MessageDispatch - for XcmBlobMessageDispatch -{ - type DispatchPayload = XcmAsPlainPayload; - type DispatchLevelResult = XcmBlobMessageDispatchResult; - - fn dispatch_weight(message: &mut DispatchMessage) -> Weight { - match message.data.payload { - Ok(ref payload) => { - let payload_size = payload.encoded_size().saturated_into(); - Weights::message_dispatch_weight(payload_size) - }, - Err(_) => Weight::zero(), - } - } - - fn dispatch( - message: DispatchMessage, - ) -> MessageDispatchResult { - let payload = match message.data.payload { - Ok(payload) => payload, - Err(e) => { - log::error!( - target: crate::LOG_TARGET_BRIDGE_DISPATCH, - "[XcmBlobMessageDispatch] payload error: {:?} - message_nonce: {:?}", - e, - message.key.nonce - ); - return MessageDispatchResult { - unspent_weight: Weight::zero(), - dispatch_level_result: XcmBlobMessageDispatchResult::InvalidPayload, - } - }, - }; - let dispatch_level_result = match BlobDispatcher::dispatch_blob(payload) { - Ok(_) => { - log::debug!( - target: crate::LOG_TARGET_BRIDGE_DISPATCH, - "[XcmBlobMessageDispatch] DispatchBlob::dispatch_blob was ok - message_nonce: {:?}", - message.key.nonce - ); - XcmBlobMessageDispatchResult::Dispatched - }, - Err(e) => { - log::error!( - target: crate::LOG_TARGET_BRIDGE_DISPATCH, - "[XcmBlobMessageDispatch] DispatchBlob::dispatch_blob failed, error: {:?} - message_nonce: {:?}", - e, message.key.nonce - ); - XcmBlobMessageDispatchResult::NotDispatched(Some(e)) - }, - }; - MessageDispatchResult { unspent_weight: Weight::zero(), dispatch_level_result } - } -} - -/// [`XcmBlobHauler`] is responsible for sending messages to the bridge "point-to-point link" from -/// one side, where on the other it can be dispatched by [`XcmBlobMessageDispatch`]. -pub trait XcmBlobHauler { - /// Runtime message sender adapter. - type MessageSender: MessagesBridge; - - /// Return message lane (as "point-to-point link") used to deliver XCM messages. - fn xcm_lane() -> LaneId; -} - -/// XCM bridge adapter which connects [`XcmBlobHauler`] with [`XcmBlobHauler::MessageSender`] and -/// makes sure that XCM blob is sent to the [`pallet_bridge_messages`] queue to be relayed. -pub struct XcmBlobHaulerAdapter(sp_std::marker::PhantomData); -impl HaulBlob for XcmBlobHaulerAdapter { - fn haul_blob(blob: sp_std::prelude::Vec) -> Result<(), HaulBlobError> { - let lane = H::xcm_lane(); - H::MessageSender::send_message(lane, blob) - .map(|artifacts| (lane, artifacts.nonce).using_encoded(sp_io::hashing::blake2_256)) - .map(|result| { - log::info!( - target: crate::LOG_TARGET_BRIDGE_DISPATCH, - "haul_blob result - ok: {:?} on lane: {:?}", - result, - lane - ) - }) - .map_err(|error| { - log::error!( - target: crate::LOG_TARGET_BRIDGE_DISPATCH, - "haul_blob result - error: {:?} on lane: {:?}", - error, - lane - ); - HaulBlobError::Transport("MessageSenderError") - }) - } -} diff --git a/bin/runtime-common/src/mock.rs b/bin/runtime-common/src/mock.rs index ad594831962..194f469b562 100644 --- a/bin/runtime-common/src/mock.rs +++ b/bin/runtime-common/src/mock.rs @@ -23,20 +23,21 @@ #![cfg(test)] -use crate::messages_xcm_extension::XcmAsPlainPayload; - use bp_header_chain::ChainWithGrandpa; -use bp_messages::{target_chain::ForbidInboundMessages, ChainWithMessages, LaneId, MessageNonce}; +use bp_messages::{ + target_chain::{DispatchMessage, MessageDispatch}, + ChainWithMessages, LaneId, MessageNonce, +}; use bp_parachains::SingleParaStoredHeaderDataBuilder; use bp_relayers::PayRewardFromAccount; -use bp_runtime::{Chain, ChainId, Parachain}; +use bp_runtime::{messages::MessageDispatchResult, Chain, ChainId, Parachain}; +use codec::Encode; use frame_support::{ parameter_types, weights::{ConstantMultiplier, IdentityFee, RuntimeDbWeight, Weight}, StateVersion, }; use pallet_transaction_payment::Multiplier; -use sp_core::Get; use sp_runtime::{ testing::H256, traits::{BlakeTwo256, ConstU32, ConstU64, ConstU8, IdentityLookup}, @@ -90,7 +91,7 @@ pub type TestStakeAndSlash = pallet_bridge_relayers::StakeAndSlashNamed< /// Message lane used in tests. pub fn test_lane_id() -> LaneId { - crate::messages_xcm_extension::LaneIdFromChainId::::get() + LaneId::new(1, 2) } /// Bridged chain id used in tests. @@ -217,7 +218,7 @@ impl pallet_bridge_messages::Config for TestRuntime { type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_bridge_messages::weights::BridgeWeight; - type OutboundPayload = XcmAsPlainPayload; + type OutboundPayload = Vec; type InboundPayload = Vec; type DeliveryPayments = (); @@ -227,8 +228,9 @@ impl pallet_bridge_messages::Config for TestRuntime { (), ConstU64<100_000>, >; + type OnMessagesDelivered = (); - type MessageDispatch = ForbidInboundMessages>; + type MessageDispatch = DummyMessageDispatch; type ThisChain = ThisUnderlyingChain; type BridgedChain = BridgedUnderlyingChain; type BridgedHeaderChain = BridgeGrandpa; @@ -242,6 +244,35 @@ impl pallet_bridge_relayers::Config for TestRuntime { type WeightInfo = (); } +/// Dummy message dispatcher. +pub struct DummyMessageDispatch; + +impl DummyMessageDispatch { + pub fn deactivate(lane: LaneId) { + frame_support::storage::unhashed::put(&(b"inactive", lane).encode()[..], &false); + } +} + +impl MessageDispatch for DummyMessageDispatch { + type DispatchPayload = Vec; + type DispatchLevelResult = (); + + fn is_active(lane: LaneId) -> bool { + frame_support::storage::unhashed::take::(&(b"inactive", lane).encode()[..]) != + Some(false) + } + + fn dispatch_weight(_message: &mut DispatchMessage) -> Weight { + Weight::zero() + } + + fn dispatch( + _: DispatchMessage, + ) -> MessageDispatchResult { + MessageDispatchResult { unspent_weight: Weight::zero(), dispatch_level_result: () } + } +} + /// Underlying chain of `ThisChain`. pub struct ThisUnderlyingChain; diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index 0e932ffb5fd..0fca846a848 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -19,11 +19,8 @@ //! with calls that are: delivering new messsage and all necessary underlying headers //! (parachain or relay chain). -use crate::{ - messages_call_ext::{ - CallHelper as MessagesCallHelper, CallInfo as MessagesCallInfo, MessagesCallSubType, - }, - messages_xcm_extension::LaneIdFromChainId, +use crate::messages_call_ext::{ + CallHelper as MessagesCallHelper, CallInfo as MessagesCallInfo, MessagesCallSubType, }; use bp_messages::{ChainWithMessages, LaneId, MessageNonce}; use bp_relayers::{RewardsAccountOwner, RewardsAccountParams}; @@ -105,15 +102,17 @@ pub trait RefundableMessagesLaneId { } /// Default implementation of `RefundableMessagesLaneId`. -pub struct RefundableMessagesLane(PhantomData<(Runtime, Instance)>); +pub struct RefundableMessagesLane(PhantomData<(Runtime, Instance, Lane)>); -impl RefundableMessagesLaneId for RefundableMessagesLane +impl RefundableMessagesLaneId + for RefundableMessagesLane where Runtime: MessagesConfig, Instance: 'static, + Lane: Get, { type Instance = Instance; - type Id = LaneIdFromChainId; + type Id = Lane; } /// Refund calculator. @@ -693,13 +692,14 @@ mod tests { TEST_BRIDGED_CHAIN_ID, RewardsAccountOwner::BridgedChain, ); + pub TestLaneId: LaneId = test_lane_id(); } bp_runtime::generate_static_str_provider!(TestExtension); type TestExtension = RefundBridgedParachainMessages< TestRuntime, DefaultRefundableParachainId<(), TestParachain>, - RefundableMessagesLane, + RefundableMessagesLane, ActualFeeRefund, ConstU64<1>, StrTestExtension, diff --git a/deployments/bridges/rialto-millau/dashboard/grafana/relay-millau-to-rialto-messages-dashboard.json b/deployments/bridges/rialto-millau/dashboard/grafana/relay-millau-to-rialto-messages-dashboard.json index d3c59e98868..44ec8454b32 100644 --- a/deployments/bridges/rialto-millau/dashboard/grafana/relay-millau-to-rialto-messages-dashboard.json +++ b/deployments/bridges/rialto-millau/dashboard/grafana/relay-millau-to-rialto-messages-dashboard.json @@ -63,14 +63,14 @@ "steppedLine": false, "targets": [ { - "expr": "Millau_to_Rialto_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_best_target_block_number", + "expr": "Millau_to_Rialto_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_best_target_block_number", "instant": false, "interval": "", "legendFormat": "At Rialto", "refId": "A" }, { - "expr": "Millau_to_Rialto_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_best_target_at_source_block_number", + "expr": "Millau_to_Rialto_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_best_target_at_source_block_number", "instant": false, "interval": "", "legendFormat": "At Millau", @@ -164,13 +164,13 @@ "steppedLine": false, "targets": [ { - "expr": "Millau_to_Rialto_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_best_source_block_number", + "expr": "Millau_to_Rialto_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_best_source_block_number", "interval": "", "legendFormat": "At Millau", "refId": "A" }, { - "expr": "Millau_to_Rialto_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_best_source_at_target_block_number", + "expr": "Millau_to_Rialto_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_best_source_at_target_block_number", "interval": "", "legendFormat": "At Rialto", "refId": "B" @@ -298,13 +298,13 @@ "steppedLine": false, "targets": [ { - "expr": "label_replace(label_replace(Millau_to_Rialto_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=~\"source_latest_generated|target_latest_received\"}, \"type\", \"Latest message sent from Rialto\", \"type\", \"source_latest_generated\"), \"type\", \"Latest Rialto message received by Millau\", \"type\", \"target_latest_received\")", + "expr": "label_replace(label_replace(Millau_to_Rialto_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=~\"source_latest_generated|target_latest_received\"}, \"type\", \"Latest message sent from Rialto\", \"type\", \"source_latest_generated\"), \"type\", \"Latest Rialto message received by Millau\", \"type\", \"target_latest_received\")", "interval": "", "legendFormat": "{{type}}", "refId": "A" }, { - "expr": "increase(Millau_to_Rialto_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=\"source_latest_generated\"}[10m]) OR on() vector(0)", + "expr": "increase(Millau_to_Rialto_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=\"source_latest_generated\"}[10m]) OR on() vector(0)", "hide": true, "interval": "", "legendFormat": "Messages generated in last 5 minutes (Millau -> Rialto)", @@ -407,7 +407,7 @@ "steppedLine": false, "targets": [ { - "expr": "label_replace(label_replace(Millau_to_Rialto_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=~\"source_latest_confirmed|target_latest_received\"}, \"type\", \"Latest message confirmed by Rialto to Millau\", \"type\", \"source_latest_confirmed\"), \"type\", \"Latest Rialto message received by Millau\", \"type\", \"target_latest_received\")", + "expr": "label_replace(label_replace(Millau_to_Rialto_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=~\"source_latest_confirmed|target_latest_received\"}, \"type\", \"Latest message confirmed by Rialto to Millau\", \"type\", \"source_latest_confirmed\"), \"type\", \"Latest Rialto message received by Millau\", \"type\", \"target_latest_received\")", "interval": "", "legendFormat": "{{type}}", "refId": "A" @@ -535,7 +535,7 @@ "steppedLine": false, "targets": [ { - "expr": "scalar(max_over_time(Millau_to_Rialto_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=\"source_latest_generated\"}[2m])) - scalar(max_over_time(Millau_to_Rialto_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=\"target_latest_received\"}[2m]))", + "expr": "scalar(max_over_time(Millau_to_Rialto_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=\"source_latest_generated\"}[2m])) - scalar(max_over_time(Millau_to_Rialto_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=\"target_latest_received\"}[2m]))", "format": "time_series", "instant": false, "interval": "", @@ -543,7 +543,7 @@ "refId": "A" }, { - "expr": "increase(Millau_to_Rialto_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=\"target_latest_received\"}[5m]) OR on() vector(0)", + "expr": "increase(Millau_to_Rialto_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=\"target_latest_received\"}[5m]) OR on() vector(0)", "interval": "", "legendFormat": "Millau Messages delivered to Rialto in last 5m", "refId": "B" @@ -680,7 +680,7 @@ "steppedLine": false, "targets": [ { - "expr": "scalar(max_over_time(Millau_to_Rialto_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=\"target_latest_received\"}[2m]) OR on() vector(0)) - scalar(max_over_time(Millau_to_Rialto_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=\"source_latest_confirmed\"}[2m]) OR on() vector(0))", + "expr": "scalar(max_over_time(Millau_to_Rialto_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=\"target_latest_received\"}[2m]) OR on() vector(0)) - scalar(max_over_time(Millau_to_Rialto_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=\"source_latest_confirmed\"}[2m]) OR on() vector(0))", "interval": "", "legendFormat": "Unconfirmed messages at Millau", "refId": "A" @@ -817,13 +817,13 @@ "steppedLine": false, "targets": [ { - "expr": "scalar(max_over_time(Millau_to_Rialto_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=\"source_latest_confirmed\"}[2m])) - scalar(max_over_time(Millau_to_Rialto_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=\"target_latest_confirmed\"}[2m]))", + "expr": "scalar(max_over_time(Millau_to_Rialto_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=\"source_latest_confirmed\"}[2m])) - scalar(max_over_time(Millau_to_Rialto_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=\"target_latest_confirmed\"}[2m]))", "interval": "", "legendFormat": "Unconfirmed rewards at Rialto", "refId": "A" }, { - "expr": "(scalar(max_over_time(Millau_to_Rialto_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=\"source_latest_confirmed\"}[2m]) OR on() vector(0)) - scalar(max_over_time(Millau_to_Rialto_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=\"target_latest_confirmed\"}[2m]) OR on() vector(0))) * (max_over_time(Millau_to_Rialto_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=\"target_latest_received\"}[2m]) > bool min_over_time(Millau_to_Rialto_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=\"target_latest_received\"}[2m]))", + "expr": "(scalar(max_over_time(Millau_to_Rialto_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=\"source_latest_confirmed\"}[2m]) OR on() vector(0)) - scalar(max_over_time(Millau_to_Rialto_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=\"target_latest_confirmed\"}[2m]) OR on() vector(0))) * (max_over_time(Millau_to_Rialto_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=\"target_latest_received\"}[2m]) > bool min_over_time(Millau_to_Rialto_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=\"target_latest_received\"}[2m]))", "interval": "", "legendFormat": "Unconfirmed rewards at Millau->Rialto (zero if messages are not being delivered to Rialto)", "refId": "B" diff --git a/deployments/bridges/rialto-millau/dashboard/grafana/relay-rialto-to-millau-messages-dashboard.json b/deployments/bridges/rialto-millau/dashboard/grafana/relay-rialto-to-millau-messages-dashboard.json index 68932a05891..1dec1b688c9 100644 --- a/deployments/bridges/rialto-millau/dashboard/grafana/relay-rialto-to-millau-messages-dashboard.json +++ b/deployments/bridges/rialto-millau/dashboard/grafana/relay-rialto-to-millau-messages-dashboard.json @@ -64,14 +64,14 @@ "steppedLine": false, "targets": [ { - "expr": "Rialto_to_Millau_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_best_target_block_number", + "expr": "Rialto_to_Millau_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_best_target_block_number", "instant": false, "interval": "", "legendFormat": "At Millau", "refId": "A" }, { - "expr": "Rialto_to_Millau_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_best_target_at_source_block_number", + "expr": "Rialto_to_Millau_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_best_target_at_source_block_number", "instant": false, "interval": "", "legendFormat": "At Rialto", @@ -165,13 +165,13 @@ "steppedLine": false, "targets": [ { - "expr": "Rialto_to_Millau_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_best_source_block_number", + "expr": "Rialto_to_Millau_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_best_source_block_number", "interval": "", "legendFormat": "At Rialto", "refId": "A" }, { - "expr": "Rialto_to_Millau_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_best_source_at_target_block_number", + "expr": "Rialto_to_Millau_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_best_source_at_target_block_number", "interval": "", "legendFormat": "At Millau", "refId": "B" @@ -299,13 +299,13 @@ "steppedLine": false, "targets": [ { - "expr": "label_replace(label_replace(Rialto_to_Millau_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=~\"source_latest_generated|target_latest_received\"}, \"type\", \"Latest message sent from Millau\", \"type\", \"source_latest_generated\"), \"type\", \"Latest message received by Rialto\", \"type\", \"target_latest_received\")", + "expr": "label_replace(label_replace(Rialto_to_Millau_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=~\"source_latest_generated|target_latest_received\"}, \"type\", \"Latest message sent from Millau\", \"type\", \"source_latest_generated\"), \"type\", \"Latest message received by Rialto\", \"type\", \"target_latest_received\")", "interval": "", "legendFormat": "{{type}}", "refId": "A" }, { - "expr": "increase(Rialto_to_Millau_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=\"source_latest_generated\"}[10m]) OR on() vector(0)", + "expr": "increase(Rialto_to_Millau_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=\"source_latest_generated\"}[10m]) OR on() vector(0)", "hide": true, "interval": "", "legendFormat": "Messages generated in last 5 minutes (Rialto -> Millau)", @@ -399,7 +399,7 @@ "steppedLine": false, "targets": [ { - "expr": "label_replace(label_replace(Rialto_to_Millau_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=~\"source_latest_confirmed|target_latest_received\"}, \"type\", \"Latest message confirmed by Millau to Rialto\", \"type\", \"source_latest_confirmed\"), \"type\", \"Latest message received by Rialto\", \"type\", \"target_latest_received\")", + "expr": "label_replace(label_replace(Rialto_to_Millau_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=~\"source_latest_confirmed|target_latest_received\"}, \"type\", \"Latest message confirmed by Millau to Rialto\", \"type\", \"source_latest_confirmed\"), \"type\", \"Latest message received by Rialto\", \"type\", \"target_latest_received\")", "interval": "", "legendFormat": "{{type}}", "refId": "A" @@ -527,7 +527,7 @@ "steppedLine": false, "targets": [ { - "expr": "scalar(max_over_time(Rialto_to_Millau_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=\"source_latest_generated\"}[2m])) - scalar(max_over_time(Rialto_to_Millau_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=\"target_latest_received\"}[2m]))", + "expr": "scalar(max_over_time(Rialto_to_Millau_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=\"source_latest_generated\"}[2m])) - scalar(max_over_time(Rialto_to_Millau_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=\"target_latest_received\"}[2m]))", "format": "time_series", "instant": false, "interval": "", @@ -535,7 +535,7 @@ "refId": "A" }, { - "expr": "increase(Rialto_to_Millau_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=\"target_latest_received\"}[5m]) OR on() vector(0)", + "expr": "increase(Rialto_to_Millau_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=\"target_latest_received\"}[5m]) OR on() vector(0)", "interval": "", "legendFormat": "Rialto Messages delivered to Millau in last 5m", "refId": "B" @@ -672,7 +672,7 @@ "steppedLine": false, "targets": [ { - "expr": "scalar(max_over_time(Rialto_to_Millau_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=\"target_latest_received\"}[2m]) OR on() vector(0)) - scalar(max_over_time(Rialto_to_Millau_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=\"source_latest_confirmed\"}[2m]) OR on() vector(0))", + "expr": "scalar(max_over_time(Rialto_to_Millau_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=\"target_latest_received\"}[2m]) OR on() vector(0)) - scalar(max_over_time(Rialto_to_Millau_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=\"source_latest_confirmed\"}[2m]) OR on() vector(0))", "interval": "", "legendFormat": "Unconfirmed messages at Rialto", "refId": "A" @@ -809,13 +809,13 @@ "steppedLine": false, "targets": [ { - "expr": "scalar(max_over_time(Rialto_to_Millau_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=\"source_latest_confirmed\"}[2m])) - scalar(max_over_time(Rialto_to_Millau_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=\"target_latest_confirmed\"}[2m]))", + "expr": "scalar(max_over_time(Rialto_to_Millau_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=\"source_latest_confirmed\"}[2m])) - scalar(max_over_time(Rialto_to_Millau_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=\"target_latest_confirmed\"}[2m]))", "interval": "", "legendFormat": "Unconfirmed rewards at Millau", "refId": "A" }, { - "expr": "(scalar(max_over_time(Rialto_to_Millau_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=\"source_latest_confirmed\"}[2m]) OR on() vector(0)) - scalar(max_over_time(Rialto_to_Millau_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=\"target_latest_confirmed\"}[2m]) OR on() vector(0))) * (max_over_time(Rialto_to_Millau_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=\"target_latest_received\"}[2m]) > bool min_over_time(Rialto_to_Millau_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_lane_state_nonces{type=\"target_latest_received\"}[2m]))", + "expr": "(scalar(max_over_time(Rialto_to_Millau_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=\"source_latest_confirmed\"}[2m]) OR on() vector(0)) - scalar(max_over_time(Rialto_to_Millau_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=\"target_latest_confirmed\"}[2m]) OR on() vector(0))) * (max_over_time(Rialto_to_Millau_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=\"target_latest_received\"}[2m]) > bool min_over_time(Rialto_to_Millau_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_lane_state_nonces{type=\"target_latest_received\"}[2m]))", "interval": "", "legendFormat": "Unconfirmed rewards at Millau (zero if messages are not being delivered to Millau)", "refId": "B" diff --git a/deployments/bridges/rialto-millau/dashboard/grafana/rialto-millau-maintenance-dashboard.json b/deployments/bridges/rialto-millau/dashboard/grafana/rialto-millau-maintenance-dashboard.json index 23a180b17ce..3ce23db4699 100644 --- a/deployments/bridges/rialto-millau/dashboard/grafana/rialto-millau-maintenance-dashboard.json +++ b/deployments/bridges/rialto-millau/dashboard/grafana/rialto-millau-maintenance-dashboard.json @@ -426,7 +426,7 @@ "steppedLine": false, "targets": [ { - "expr": "Rialto_to_Millau_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_is_source_and_source_at_target_using_different_forks OR on() vector(0)", + "expr": "Rialto_to_Millau_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_is_source_and_source_at_target_using_different_forks OR on() vector(0)", "interval": "", "legendFormat": "On different forks?", "refId": "A" @@ -559,7 +559,7 @@ "steppedLine": false, "targets": [ { - "expr": "Millau_to_Rialto_MessageLane_0x52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7_is_source_and_source_at_target_using_different_forks OR on() vector(0)", + "expr": "Millau_to_Rialto_MessageLane_0xefed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7_is_source_and_source_at_target_using_different_forks OR on() vector(0)", "interval": "", "legendFormat": "On different forks?", "refId": "A" diff --git a/deployments/bridges/rialto-millau/entrypoints/relay-millau-rialto-entrypoint.sh b/deployments/bridges/rialto-millau/entrypoints/relay-millau-rialto-entrypoint.sh index 1227c4a4452..5816884c12c 100755 --- a/deployments/bridges/rialto-millau/entrypoints/relay-millau-rialto-entrypoint.sh +++ b/deployments/bridges/rialto-millau/entrypoints/relay-millau-rialto-entrypoint.sh @@ -5,7 +5,7 @@ sleep 15 # see `rialto_millau_bridge_identifier_did_not_changed` test in `millau-runtime` crate for # details on how this lane is computed -MESSAGE_LANE="52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7" +MESSAGE_LANE="efed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7" /home/user/substrate-relay init-bridge millau-to-rialto \ --source-host millau-node-alice \ diff --git a/deployments/bridges/rialto-parachain-millau/dashboard/grafana/relay-millau-to-rialto-parachain-messages-dashboard.json b/deployments/bridges/rialto-parachain-millau/dashboard/grafana/relay-millau-to-rialto-parachain-messages-dashboard.json index d4feb6a4c7e..80bb7917c09 100644 --- a/deployments/bridges/rialto-parachain-millau/dashboard/grafana/relay-millau-to-rialto-parachain-messages-dashboard.json +++ b/deployments/bridges/rialto-parachain-millau/dashboard/grafana/relay-millau-to-rialto-parachain-messages-dashboard.json @@ -63,14 +63,14 @@ "steppedLine": false, "targets": [ { - "expr": "Millau_to_RialtoParachain_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_best_target_block_number{instance=\"relay-millau-rialto-parachain-1:9616\"}", + "expr": "Millau_to_RialtoParachain_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_best_target_block_number{instance=\"relay-millau-rialto-parachain-1:9616\"}", "instant": false, "interval": "", "legendFormat": "At RialtoParachain", "refId": "A" }, { - "expr": "Millau_to_RialtoParachain_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_best_target_at_source_block_number{instance=\"relay-millau-rialto-parachain-1:9616\"}", + "expr": "Millau_to_RialtoParachain_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_best_target_at_source_block_number{instance=\"relay-millau-rialto-parachain-1:9616\"}", "instant": false, "interval": "", "legendFormat": "At Millau", @@ -164,13 +164,13 @@ "steppedLine": false, "targets": [ { - "expr": "Millau_to_RialtoParachain_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_best_source_block_number{instance=\"relay-millau-rialto-parachain-1:9616\"}", + "expr": "Millau_to_RialtoParachain_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_best_source_block_number{instance=\"relay-millau-rialto-parachain-1:9616\"}", "interval": "", "legendFormat": "At Millau", "refId": "A" }, { - "expr": "Millau_to_RialtoParachain_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_best_source_at_target_block_number{instance=\"relay-millau-rialto-parachain-1:9616\"}", + "expr": "Millau_to_RialtoParachain_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_best_source_at_target_block_number{instance=\"relay-millau-rialto-parachain-1:9616\"}", "interval": "", "legendFormat": "At RialtoParachain", "refId": "B" @@ -298,13 +298,13 @@ "steppedLine": false, "targets": [ { - "expr": "label_replace(label_replace(Millau_to_RialtoParachain_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=~\"source_latest_generated|target_latest_received\"}, \"type\", \"Latest message sent from RialtoParachain\", \"type\", \"source_latest_generated\"), \"type\", \"Latest RialtoParachain message received by Millau\", \"type\", \"target_latest_received\")", + "expr": "label_replace(label_replace(Millau_to_RialtoParachain_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=~\"source_latest_generated|target_latest_received\"}, \"type\", \"Latest message sent from RialtoParachain\", \"type\", \"source_latest_generated\"), \"type\", \"Latest RialtoParachain message received by Millau\", \"type\", \"target_latest_received\")", "interval": "", "legendFormat": "{{type}}", "refId": "A" }, { - "expr": "increase(Millau_to_RialtoParachain_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"source_latest_generated\"}[10m]) OR on() vector(0)", + "expr": "increase(Millau_to_RialtoParachain_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"source_latest_generated\"}[10m]) OR on() vector(0)", "hide": true, "interval": "", "legendFormat": "Messages generated in last 5 minutes (Millau -> RialtoParachain)", @@ -407,7 +407,7 @@ "steppedLine": false, "targets": [ { - "expr": "label_replace(label_replace(Millau_to_RialtoParachain_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=~\"source_latest_confirmed|target_latest_received\"}, \"type\", \"Latest message confirmed by RialtoParachain to Millau\", \"type\", \"source_latest_confirmed\"), \"type\", \"Latest RialtoParachain message received by Millau\", \"type\", \"target_latest_received\")", + "expr": "label_replace(label_replace(Millau_to_RialtoParachain_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=~\"source_latest_confirmed|target_latest_received\"}, \"type\", \"Latest message confirmed by RialtoParachain to Millau\", \"type\", \"source_latest_confirmed\"), \"type\", \"Latest RialtoParachain message received by Millau\", \"type\", \"target_latest_received\")", "interval": "", "legendFormat": "{{type}}", "refId": "A" @@ -535,7 +535,7 @@ "steppedLine": false, "targets": [ { - "expr": "scalar(max_over_time(Millau_to_RialtoParachain_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"source_latest_generated\"}[2m])) - scalar(max_over_time(Millau_to_RialtoParachain_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_received\"}[2m]))", + "expr": "scalar(max_over_time(Millau_to_RialtoParachain_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"source_latest_generated\"}[2m])) - scalar(max_over_time(Millau_to_RialtoParachain_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_received\"}[2m]))", "format": "time_series", "instant": false, "interval": "", @@ -543,7 +543,7 @@ "refId": "A" }, { - "expr": "increase(Millau_to_RialtoParachain_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_received\"}[5m]) OR on() vector(0)", + "expr": "increase(Millau_to_RialtoParachain_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_received\"}[5m]) OR on() vector(0)", "interval": "", "legendFormat": "Millau Messages delivered to RialtoParachain in last 5m", "refId": "B" @@ -679,7 +679,7 @@ "steppedLine": false, "targets": [ { - "expr": "scalar(max_over_time(Millau_to_RialtoParachain_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_received\"}[2m]) OR on() vector(0)) - scalar(max_over_time(Millau_to_RialtoParachain_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"source_latest_confirmed\"}[2m]) OR on() vector(0))", + "expr": "scalar(max_over_time(Millau_to_RialtoParachain_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_received\"}[2m]) OR on() vector(0)) - scalar(max_over_time(Millau_to_RialtoParachain_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"source_latest_confirmed\"}[2m]) OR on() vector(0))", "interval": "", "legendFormat": "Unconfirmed messages at Millau", "refId": "A" @@ -815,13 +815,13 @@ "steppedLine": false, "targets": [ { - "expr": "scalar(max_over_time(Millau_to_RialtoParachain_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"source_latest_confirmed\"}[2m])) - scalar(max_over_time(Millau_to_RialtoParachain_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_confirmed\"}[2m]))", + "expr": "scalar(max_over_time(Millau_to_RialtoParachain_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"source_latest_confirmed\"}[2m])) - scalar(max_over_time(Millau_to_RialtoParachain_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_confirmed\"}[2m]))", "interval": "", "legendFormat": "Unconfirmed rewards at RialtoParachain", "refId": "A" }, { - "expr": "(scalar(max_over_time(Millau_to_RialtoParachain_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"source_latest_confirmed\"}[2m]) OR on() vector(0)) - scalar(max_over_time(Millau_to_RialtoParachain_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_confirmed\"}[2m]) OR on() vector(0))) * (max_over_time(Millau_to_RialtoParachain_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_received\"}[2m]) > bool min_over_time(Millau_to_RialtoParachain_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_received\"}[2m]))", + "expr": "(scalar(max_over_time(Millau_to_RialtoParachain_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"source_latest_confirmed\"}[2m]) OR on() vector(0)) - scalar(max_over_time(Millau_to_RialtoParachain_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_confirmed\"}[2m]) OR on() vector(0))) * (max_over_time(Millau_to_RialtoParachain_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_received\"}[2m]) > bool min_over_time(Millau_to_RialtoParachain_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_received\"}[2m]))", "interval": "", "legendFormat": "Unconfirmed rewards at Millau->RaltoParachain (zero if messages are not being delivered to RialtoParachain)", "refId": "B" diff --git a/deployments/bridges/rialto-parachain-millau/dashboard/grafana/relay-rialto-parachain-to-millau-messages-dashboard.json b/deployments/bridges/rialto-parachain-millau/dashboard/grafana/relay-rialto-parachain-to-millau-messages-dashboard.json index 10c8fcd3928..9d252b17f5e 100644 --- a/deployments/bridges/rialto-parachain-millau/dashboard/grafana/relay-rialto-parachain-to-millau-messages-dashboard.json +++ b/deployments/bridges/rialto-parachain-millau/dashboard/grafana/relay-rialto-parachain-to-millau-messages-dashboard.json @@ -63,14 +63,14 @@ "steppedLine": false, "targets": [ { - "expr": "RialtoParachain_to_Millau_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_best_target_block_number{instance=\"relay-millau-rialto-parachain-1:9616\"}", + "expr": "RialtoParachain_to_Millau_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_best_target_block_number{instance=\"relay-millau-rialto-parachain-1:9616\"}", "instant": false, "interval": "", "legendFormat": "At Millau", "refId": "A" }, { - "expr": "RialtoParachain_to_Millau_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_best_target_at_source_block_number{instance=\"relay-millau-rialto-parachain-1:9616\"}", + "expr": "RialtoParachain_to_Millau_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_best_target_at_source_block_number{instance=\"relay-millau-rialto-parachain-1:9616\"}", "instant": false, "interval": "", "legendFormat": "At RialtoParachain", @@ -164,13 +164,13 @@ "steppedLine": false, "targets": [ { - "expr": "RialtoParachain_to_Millau_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_best_source_block_number{instance=\"relay-millau-rialto-parachain-1:9616\"}", + "expr": "RialtoParachain_to_Millau_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_best_source_block_number{instance=\"relay-millau-rialto-parachain-1:9616\"}", "interval": "", "legendFormat": "At RialtoParachain", "refId": "A" }, { - "expr": "RialtoParachain_to_Millau_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_best_source_at_target_block_number{instance=\"relay-millau-rialto-parachain-1:9616\"}", + "expr": "RialtoParachain_to_Millau_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_best_source_at_target_block_number{instance=\"relay-millau-rialto-parachain-1:9616\"}", "interval": "", "legendFormat": "At Millau", "refId": "B" @@ -298,13 +298,13 @@ "steppedLine": false, "targets": [ { - "expr": "label_replace(label_replace(RialtoParachain_to_Millau_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=~\"source_latest_generated|target_latest_received\"}, \"type\", \"Latest message sent from Millau\", \"type\", \"source_latest_generated\"), \"type\", \"Latest Millau message received by RialtoParachain\", \"type\", \"target_latest_received\")", + "expr": "label_replace(label_replace(RialtoParachain_to_Millau_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=~\"source_latest_generated|target_latest_received\"}, \"type\", \"Latest message sent from Millau\", \"type\", \"source_latest_generated\"), \"type\", \"Latest Millau message received by RialtoParachain\", \"type\", \"target_latest_received\")", "interval": "", "legendFormat": "{{type}}", "refId": "A" }, { - "expr": "increase(RialtoParachain_to_Millau_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"source_latest_generated\"}[10m]) OR on() vector(0)", + "expr": "increase(RialtoParachain_to_Millau_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"source_latest_generated\"}[10m]) OR on() vector(0)", "hide": true, "interval": "", "legendFormat": "Messages generated in last 5 minutes (RialtoParachain -> Millau)", @@ -406,7 +406,7 @@ "steppedLine": false, "targets": [ { - "expr": "label_replace(label_replace(RialtoParachain_to_Millau_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=~\"source_latest_confirmed|target_latest_received\"}, \"type\", \"Latest message confirmed by Millau to RialtoParachain\", \"type\", \"source_latest_confirmed\"), \"type\", \"Latest Millau message received by RialtoParachain\", \"type\", \"target_latest_received\")", + "expr": "label_replace(label_replace(RialtoParachain_to_Millau_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=~\"source_latest_confirmed|target_latest_received\"}, \"type\", \"Latest message confirmed by Millau to RialtoParachain\", \"type\", \"source_latest_confirmed\"), \"type\", \"Latest Millau message received by RialtoParachain\", \"type\", \"target_latest_received\")", "interval": "", "legendFormat": "{{type}}", "refId": "A" @@ -534,7 +534,7 @@ "steppedLine": false, "targets": [ { - "expr": "scalar(max_over_time(RialtoParachain_to_Millau_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"source_latest_generated\"}[2m])) - scalar(max_over_time(RialtoParachain_to_Millau_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_received\"}[2m]))", + "expr": "scalar(max_over_time(RialtoParachain_to_Millau_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"source_latest_generated\"}[2m])) - scalar(max_over_time(RialtoParachain_to_Millau_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_received\"}[2m]))", "format": "time_series", "instant": false, "interval": "", @@ -542,7 +542,7 @@ "refId": "A" }, { - "expr": "increase(RialtoParachain_to_Millau_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_received\"}[5m]) OR on() vector(0)", + "expr": "increase(RialtoParachain_to_Millau_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_received\"}[5m]) OR on() vector(0)", "interval": "", "legendFormat": "RialtoParachain Messages delivered to Millau in last 5m", "refId": "B" @@ -678,7 +678,7 @@ "steppedLine": false, "targets": [ { - "expr": "scalar(max_over_time(RialtoParachain_to_Millau_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_received\"}[2m]) OR on() vector(0)) - scalar(max_over_time(RialtoParachain_to_Millau_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"source_latest_confirmed\"}[2m]) OR on() vector(0))", + "expr": "scalar(max_over_time(RialtoParachain_to_Millau_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_received\"}[2m]) OR on() vector(0)) - scalar(max_over_time(RialtoParachain_to_Millau_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"source_latest_confirmed\"}[2m]) OR on() vector(0))", "interval": "", "legendFormat": "Unconfirmed messages at RialtoParachain", "refId": "A" @@ -814,13 +814,13 @@ "steppedLine": false, "targets": [ { - "expr": "scalar(max_over_time(RialtoParachain_to_Millau_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"source_latest_confirmed\"}[2m])) - scalar(max_over_time(RialtoParachain_to_Millau_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_confirmed\"}[2m]))", + "expr": "scalar(max_over_time(RialtoParachain_to_Millau_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"source_latest_confirmed\"}[2m])) - scalar(max_over_time(RialtoParachain_to_Millau_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_confirmed\"}[2m]))", "interval": "", "legendFormat": "Unconfirmed rewards at Millau", "refId": "A" }, { - "expr": "(scalar(max_over_time(RialtoParachain_to_Millau_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"source_latest_confirmed\"}[2m]) OR on() vector(0)) - scalar(max_over_time(RialtoParachain_to_Millau_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_confirmed\"}[2m]) OR on() vector(0))) * (max_over_time(RialtoParachain_to_Millau_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_received\"}[2m]) > bool min_over_time(RialtoParachain_to_Millau_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_received\"}[2m]))", + "expr": "(scalar(max_over_time(RialtoParachain_to_Millau_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"source_latest_confirmed\"}[2m]) OR on() vector(0)) - scalar(max_over_time(RialtoParachain_to_Millau_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_confirmed\"}[2m]) OR on() vector(0))) * (max_over_time(RialtoParachain_to_Millau_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_received\"}[2m]) > bool min_over_time(RialtoParachain_to_Millau_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_lane_state_nonces{instance=\"relay-millau-rialto-parachain-1:9616\",type=\"target_latest_received\"}[2m]))", "interval": "", "legendFormat": "Unconfirmed rewards at Millau (zero if messages are not being delivered to Millau)", "refId": "B" diff --git a/deployments/bridges/rialto-parachain-millau/dashboard/grafana/rialto-parachain-millau-maintenance-dashboard.json b/deployments/bridges/rialto-parachain-millau/dashboard/grafana/rialto-parachain-millau-maintenance-dashboard.json index d3cd10f5a80..cfdeacfa7bf 100644 --- a/deployments/bridges/rialto-parachain-millau/dashboard/grafana/rialto-parachain-millau-maintenance-dashboard.json +++ b/deployments/bridges/rialto-parachain-millau/dashboard/grafana/rialto-parachain-millau-maintenance-dashboard.json @@ -111,7 +111,7 @@ }, { "exemplar": true, - "expr": "at_RialtoParachain_relay_MillauMessages_reward_for_msgs_from_Millau_on_lane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de{instance=\"relay-millau-rialto-parachain-1:9616\"} + at_RialtoParachain_relay_MillauMessages_reward_for_msgs_to_Millau_on_lane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de{instance=\"relay-millau-rialto-parachain-1:9616\"}", + "expr": "at_RialtoParachain_relay_MillauMessages_reward_for_msgs_from_Millau_on_lane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c{instance=\"relay-millau-rialto-parachain-1:9616\"} + at_RialtoParachain_relay_MillauMessages_reward_for_msgs_to_Millau_on_lane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c{instance=\"relay-millau-rialto-parachain-1:9616\"}", "hide": false, "instant": false, "interval": "", @@ -120,7 +120,7 @@ }, { "exemplar": true, - "expr": "at_RialtoParachain_relay_MillauMessages_balance{instance=\"relay-millau-rialto-parachain-1:9616\"} + at_RialtoParachain_relay_MillauMessages_reward_for_msgs_from_Millau_on_lane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de{instance=\"relay-millau-rialto-parachain-1:9616\"} + at_RialtoParachain_relay_MillauMessages_reward_for_msgs_to_Millau_on_lane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de{instance=\"relay-millau-rialto-parachain-1:9616\"}", + "expr": "at_RialtoParachain_relay_MillauMessages_balance{instance=\"relay-millau-rialto-parachain-1:9616\"} + at_RialtoParachain_relay_MillauMessages_reward_for_msgs_from_Millau_on_lane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c{instance=\"relay-millau-rialto-parachain-1:9616\"} + at_RialtoParachain_relay_MillauMessages_reward_for_msgs_to_Millau_on_lane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c{instance=\"relay-millau-rialto-parachain-1:9616\"}", "hide": false, "interval": "", "legendFormat": "With-Millau relay account total balance (balance + reward)", @@ -262,7 +262,7 @@ }, { "exemplar": true, - "expr": "at_Millau_relay_RialtoParachainMessages_reward_for_msgs_from_RialtoParachain_on_lane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de{instance=\"relay-millau-rialto-parachain-1:9616\"} + at_Millau_relay_RialtoParachainMessages_reward_for_msgs_to_RialtoParachain_on_lane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de{instance=\"relay-millau-rialto-parachain-1:9616\"}", + "expr": "at_Millau_relay_RialtoParachainMessages_reward_for_msgs_from_RialtoParachain_on_lane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c{instance=\"relay-millau-rialto-parachain-1:9616\"} + at_Millau_relay_RialtoParachainMessages_reward_for_msgs_to_RialtoParachain_on_lane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c{instance=\"relay-millau-rialto-parachain-1:9616\"}", "hide": false, "interval": "", "legendFormat": "With-Rialto relay account reward", @@ -270,7 +270,7 @@ }, { "exemplar": true, - "expr": "at_Millau_relay_RialtoParachainMessages_balance{instance=\"relay-millau-rialto-parachain-1:9616\"} + at_Millau_relay_RialtoParachainMessages_reward_for_msgs_from_RialtoParachain_on_lane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de{instance=\"relay-millau-rialto-parachain-1:9616\"} + at_Millau_relay_RialtoParachainMessages_reward_for_msgs_to_RialtoParachain_on_lane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de{instance=\"relay-millau-rialto-parachain-1:9616\"}", + "expr": "at_Millau_relay_RialtoParachainMessages_balance{instance=\"relay-millau-rialto-parachain-1:9616\"} + at_Millau_relay_RialtoParachainMessages_reward_for_msgs_from_RialtoParachain_on_lane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c{instance=\"relay-millau-rialto-parachain-1:9616\"} + at_Millau_relay_RialtoParachainMessages_reward_for_msgs_to_RialtoParachain_on_lane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c{instance=\"relay-millau-rialto-parachain-1:9616\"}", "hide": false, "interval": "", "legendFormat": "With-Rialto relay account total balance (balance + reward)", @@ -404,7 +404,7 @@ "steppedLine": false, "targets": [ { - "expr": "RialtoParachain_to_Millau_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_is_source_and_source_at_target_using_different_forks{instance=\"relay-millau-rialto-parachain-1:9616\"} OR on() vector(0)", + "expr": "RialtoParachain_to_Millau_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_is_source_and_source_at_target_using_different_forks{instance=\"relay-millau-rialto-parachain-1:9616\"} OR on() vector(0)", "instant": false, "interval": "", "legendFormat": "On different forks?", @@ -538,7 +538,7 @@ "steppedLine": false, "targets": [ { - "expr": "Millau_to_RialtoParachain_MessageLane_0x6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de_is_source_and_source_at_target_using_different_forks{instance=\"relay-millau-rialto-parachain-1:9616\"} OR on() vector(0)", + "expr": "Millau_to_RialtoParachain_MessageLane_0xee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c_is_source_and_source_at_target_using_different_forks{instance=\"relay-millau-rialto-parachain-1:9616\"} OR on() vector(0)", "interval": "", "legendFormat": "On different forks?", "refId": "A" diff --git a/deployments/bridges/rialto-parachain-millau/entrypoints/relay-millau-rialto-parachain-entrypoint.sh b/deployments/bridges/rialto-parachain-millau/entrypoints/relay-millau-rialto-parachain-entrypoint.sh index caa3ebb7ceb..613e99d1b3f 100755 --- a/deployments/bridges/rialto-parachain-millau/entrypoints/relay-millau-rialto-parachain-entrypoint.sh +++ b/deployments/bridges/rialto-parachain-millau/entrypoints/relay-millau-rialto-parachain-entrypoint.sh @@ -9,7 +9,7 @@ RIALTO_PARACHAIN_RELAY_ACCOUNT=${EXT_RIALTO_PARACHAIN_RELAY_ACCOUNT:-//Millau.He # see `rialto_parachain_millau_bridge_identifier_did_not_changed` test in `millau-runtime` crate for # details on how this lane is computed -MESSAGE_LANE="6aa61bff567db6b5d5f0cb815ee6d8f5ac630e222a95700cb3d594134e3805de" +MESSAGE_LANE="ee7158d2a51c3c43853ced550cc25bd00eb2662b231b1ddbb92e495ec882969c" /home/user/substrate-relay init-bridge millau-to-rialto-parachain \ --source-host millau-node-alice \ diff --git a/deployments/local-scripts/relay-messages-millau-to-rialto.sh b/deployments/local-scripts/relay-messages-millau-to-rialto.sh index 90f9c8c9dd7..eca1052a7f0 100755 --- a/deployments/local-scripts/relay-messages-millau-to-rialto.sh +++ b/deployments/local-scripts/relay-messages-millau-to-rialto.sh @@ -10,7 +10,7 @@ RIALTO_PORT="${RIALTO_PORT:-9944}" RUST_LOG=bridge=debug \ ./target/debug/substrate-relay relay-messages millau-to-rialto \ - --lane "52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7" \ + --lane "efed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7" \ --source-host localhost \ --source-port $MILLAU_PORT \ --source-signer //Bob \ diff --git a/deployments/local-scripts/relay-messages-rialto-to-millau.sh b/deployments/local-scripts/relay-messages-rialto-to-millau.sh index 03791d41352..455fffa242b 100755 --- a/deployments/local-scripts/relay-messages-rialto-to-millau.sh +++ b/deployments/local-scripts/relay-messages-rialto-to-millau.sh @@ -10,7 +10,7 @@ RIALTO_PORT="${RIALTO_PORT:-9944}" RUST_LOG=bridge=debug \ ./target/debug/substrate-relay relay-messages rialto-to-millau \ - --lane "52011894c856c0c613a2ad2395dfbb509090f6b7a6aef9359adb75aa26a586c7" \ + --lane "efed785b626e94da3969257012f506524bcec78867420e26ff8c55ddcdb0f7b7" \ --source-host localhost \ --source-port $RIALTO_PORT \ --source-signer //Bob \ diff --git a/modules/messages/src/lanes_manager.rs b/modules/messages/src/lanes_manager.rs index 11b03ed8432..da6967368e5 100644 --- a/modules/messages/src/lanes_manager.rs +++ b/modules/messages/src/lanes_manager.rs @@ -21,8 +21,8 @@ use crate::{ }; use bp_messages::{ - ChainWithMessages, InboundLaneData, LaneId, LaneState, MessageKey, MessageNonce, - MessagePayload, OutboundLaneData, VerificationError, + target_chain::MessageDispatch, ChainWithMessages, InboundLaneData, LaneId, LaneState, + MessageKey, MessageNonce, MessagePayload, OutboundLaneData, VerificationError, }; use bp_runtime::AccountIdOf; use codec::{Decode, Encode, MaxEncodedLen}; @@ -45,6 +45,9 @@ pub enum LanesManagerError { ClosedInboundLane, /// Outbound lane with given id is closed. ClosedOutboundLane, + /// Message dispatcher is inactive at given inbound lane. This is logical equivalent + /// of the [`Self::ClosedInboundLane`] variant. + LaneDispatcherInactive, } /// Message lanes manager. @@ -145,10 +148,32 @@ impl, I: 'static> RuntimeInboundLaneStorage { ) -> Result, LanesManagerError> { let cached_data = InboundLanes::::get(lane_id).ok_or(LanesManagerError::UnknownInboundLane)?; - ensure!( - !check_active || cached_data.state.is_active(), - LanesManagerError::ClosedInboundLane - ); + + if check_active { + // check that the lane is not explicitly closed + ensure!(cached_data.state.is_active(), LanesManagerError::ClosedInboundLane); + // apart from the explicit closure, the lane may be unable to receive any messages. + // Right now we do an additional check here, but it may be done later (e.g. by + // explicitly closing the lane and reopening it from + // `pallet-xcm-bridge-hub::on-initialize`) + // + // The fact that we only check it here, means that the `MessageDispatch` may switch + // to inactive state during some message dispatch in the middle of message delivery + // transaction. But we treat result of `MessageDispatch::is_active()` as a hint, so + // we know that it won't drop messages - just it experiences problems with processing. + // This would allow us to check that in our signed extensions, and invalidate + // transaction early, thus avoiding losing honest relayers funds. This problem should + // gone with relayers coordination protocol. + // + // There's a limit on number of messages in the message delivery transaction, so even + // if we dispatch (enqueue) some additional messages, we'll know the maximal queue + // length; + ensure!( + T::MessageDispatch::is_active(lane_id), + LanesManagerError::LaneDispatcherInactive + ); + } + Ok(RuntimeInboundLaneStorage { lane_id, cached_data: cached_data.into(), diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 410e54908fd..b6b99ab854c 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -53,7 +53,8 @@ pub use weights_ext::{ use bp_header_chain::HeaderChain; use bp_messages::{ source_chain::{ - DeliveryConfirmationPayments, FromBridgedChainMessagesDeliveryProof, SendMessageArtifacts, + DeliveryConfirmationPayments, FromBridgedChainMessagesDeliveryProof, OnMessagesDelivered, + SendMessageArtifacts, }, target_chain::{ DeliveryPayments, DispatchMessage, FromBridgedChainMessagesProof, MessageDispatch, @@ -64,7 +65,8 @@ use bp_messages::{ OutboundMessageDetails, UnrewardedRelayersState, VerificationError, }; use bp_runtime::{ - AccountIdOf, BasicOperatingMode, HashOf, OwnedBridgeModule, PreComputedSize, Size, + AccountIdOf, BasicOperatingMode, HashOf, OwnedBridgeModule, PreComputedSize, RangeInclusiveExt, + Size, }; use codec::{Decode, Encode}; use frame_support::{dispatch::PostDispatchInfo, ensure, fail, traits::Get, DefaultNoBound}; @@ -124,6 +126,8 @@ pub mod pallet { /// Handler for relayer payments that happen during message delivery confirmation /// transaction. type DeliveryConfirmationPayments: DeliveryConfirmationPayments; + /// Delivery confirmation callback. + type OnMessagesDelivered: OnMessagesDelivered; /// Message dispatch handler. type MessageDispatch: MessageDispatch; @@ -409,6 +413,12 @@ pub mod pallet { lane_id, ); + // notify others about messages delivery + T::OnMessagesDelivered::on_messages_delivered( + lane_id, + lane.queued_messages().saturating_len(), + ); + // because of lags, the inbound lane state (`lane_data`) may have entries for // already rewarded relayers and messages (if all entries are duplicated, then // this transaction must be filtered out by our signed extension) @@ -616,6 +626,9 @@ fn send_message, I: 'static>( .send_message(encoded_payload) .map_err(Error::::MessageRejectedByPallet)?; + // return number of messages in the queue to let sender know about its state + let enqueued_messages = lane.queued_messages().saturating_len(); + log::trace!( target: LOG_TARGET, "Accepted message {} to lane {:?}. Message size: {:?}", @@ -626,7 +639,7 @@ fn send_message, I: 'static>( Pallet::::deposit_event(Event::MessageAccepted { lane_id, nonce }); - Ok(SendMessageArtifacts { nonce }) + Ok(SendMessageArtifacts { nonce, enqueued_messages }) } /// Ensure that the pallet is in normal operational mode. diff --git a/modules/messages/src/tests/mock.rs b/modules/messages/src/tests/mock.rs index 6e78be63697..84725219335 100644 --- a/modules/messages/src/tests/mock.rs +++ b/modules/messages/src/tests/mock.rs @@ -220,11 +220,6 @@ impl pallet_bridge_grandpa::Config for TestRuntime { type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } -parameter_types! { - pub const MaxMessagesToPruneAtOnce: u64 = 10; - pub const TestBridgedChainId: bp_runtime::ChainId = *b"test"; -} - /// weights of messages pallet calls we use in tests. pub type TestWeightInfo = (); @@ -242,6 +237,7 @@ impl Config for TestRuntime { type DeliveryPayments = TestDeliveryPayments; type DeliveryConfirmationPayments = TestDeliveryConfirmationPayments; + type OnMessagesDelivered = (); type MessageDispatch = TestMessageDispatch; } @@ -381,10 +377,24 @@ impl DeliveryConfirmationPayments for TestDeliveryConfirmationPayment #[derive(Debug)] pub struct TestMessageDispatch; +impl TestMessageDispatch { + pub fn emulate_enqueued_message(lane: LaneId) { + let key = (b"dispatched", lane).encode(); + let dispatched = frame_support::storage::unhashed::get_or_default::(&key[..]); + frame_support::storage::unhashed::put(&key[..], &(dispatched + 1)); + } +} + impl MessageDispatch for TestMessageDispatch { type DispatchPayload = TestPayload; type DispatchLevelResult = TestDispatchLevelResult; + fn is_active(lane: LaneId) -> bool { + frame_support::storage::unhashed::get_or_default::( + &(b"dispatched", lane).encode()[..], + ) <= BridgedChain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX + } + fn dispatch_weight(message: &mut DispatchMessage) -> Weight { match message.data.payload.as_ref() { Ok(payload) => payload.declared_weight, @@ -396,7 +406,10 @@ impl MessageDispatch for TestMessageDispatch { message: DispatchMessage, ) -> MessageDispatchResult { match message.data.payload.as_ref() { - Ok(payload) => payload.dispatch_result.clone(), + Ok(payload) => { + Self::emulate_enqueued_message(message.key.lane_id); + payload.dispatch_result.clone() + }, Err(_) => dispatch_result(0), } } diff --git a/modules/messages/src/tests/pallet_tests.rs b/modules/messages/src/tests/pallet_tests.rs index b2686b8b0c3..22b2cdf1ff4 100644 --- a/modules/messages/src/tests/pallet_tests.rs +++ b/modules/messages/src/tests/pallet_tests.rs @@ -26,10 +26,11 @@ use crate::{ use bp_messages::{ source_chain::FromBridgedChainMessagesDeliveryProof, - target_chain::FromBridgedChainMessagesProof, BridgeMessagesCall, ChainWithMessages, - DeliveredMessages, InboundLaneData, InboundMessageDetails, LaneId, LaneState, MessageKey, - MessageNonce, MessagesOperatingMode, OutboundLaneData, OutboundMessageDetails, - UnrewardedRelayer, UnrewardedRelayersState, VerificationError, + target_chain::{FromBridgedChainMessagesProof, MessageDispatch}, + BridgeMessagesCall, ChainWithMessages, DeliveredMessages, InboundLaneData, + InboundMessageDetails, LaneId, LaneState, MessageKey, MessageNonce, MessagesOperatingMode, + OutboundLaneData, OutboundMessageDetails, UnrewardedRelayer, UnrewardedRelayersState, + VerificationError, }; use bp_runtime::{BasicOperatingMode, PreComputedSize, Size}; use bp_test_utils::generate_owned_bridge_module_tests; @@ -322,6 +323,86 @@ fn receive_messages_proof_updates_confirmed_message_nonce() { }); } +#[test] +fn receive_messages_proof_fails_when_dispatcher_is_inactive() { + run_test(|| { + // "enqueue" enough (to deactivate dispatcher) messages at dispatcher + let latest_received_nonce = BridgedChain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX + 1; + for _ in 1..=latest_received_nonce { + TestMessageDispatch::emulate_enqueued_message(test_lane_id()); + } + assert!(!TestMessageDispatch::is_active(test_lane_id())); + InboundLanes::::insert( + test_lane_id(), + InboundLaneData { + state: LaneState::Opened, + last_confirmed_nonce: latest_received_nonce, + relayers: vec![].into(), + }, + ); + + // try to delvier next message - it should fail because dispatcher is in "suspended" state + // at the beginning of the call + let messages_proof = + prepare_messages_proof(vec![message(latest_received_nonce + 1, REGULAR_PAYLOAD)], None); + assert_noop!( + Pallet::::receive_messages_proof( + RuntimeOrigin::signed(1), + TEST_RELAYER_A, + messages_proof, + 1, + REGULAR_PAYLOAD.declared_weight, + ), + Error::::LanesManager(LanesManagerError::LaneDispatcherInactive) + ); + assert!(!TestMessageDispatch::is_active(test_lane_id())); + }); +} + +#[test] +fn receive_messages_succeeds_when_dispatcher_becomes_inactive_in_the_middle_of_transaction() { + run_test(|| { + // "enqueue" enough (to deactivate dispatcher) messages at dispatcher + let latest_received_nonce = BridgedChain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX / 2; + for _ in 1..=latest_received_nonce { + TestMessageDispatch::emulate_enqueued_message(test_lane_id()); + } + assert!(TestMessageDispatch::is_active(test_lane_id())); + InboundLanes::::insert( + test_lane_id(), + InboundLaneData { + state: LaneState::Opened, + last_confirmed_nonce: latest_received_nonce, + relayers: vec![].into(), + }, + ); + + // try to delvier next `BridgedChain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX` messages + // - it will lead to dispatcher deactivation, but the transaction shall not fail and all + // messages must be delivered + let messages_begin = latest_received_nonce + 1; + let messages_end = + messages_begin + BridgedChain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + let messages_range = messages_begin..messages_end; + let messages_count = BridgedChain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + assert_ok!(Pallet::::receive_messages_proof( + RuntimeOrigin::signed(1), + TEST_RELAYER_A, + prepare_messages_proof( + messages_range.map(|nonce| message(nonce, REGULAR_PAYLOAD)).collect(), + None, + ), + messages_count as _, + REGULAR_PAYLOAD.declared_weight * messages_count, + ),); + assert_eq!( + inbound_unrewarded_relayers_state(test_lane_id()).last_delivered_nonce, + messages_end - 1, + ); + assert!(!TestMessageDispatch::is_active(test_lane_id())); + }); +} + #[test] fn receive_messages_proof_does_not_accept_message_if_dispatch_weight_is_not_enough() { run_test(|| { diff --git a/modules/xcm-bridge-hub-router/Cargo.toml b/modules/xcm-bridge-hub-router/Cargo.toml index 72699580d18..965e3ef23d3 100644 --- a/modules/xcm-bridge-hub-router/Cargo.toml +++ b/modules/xcm-bridge-hub-router/Cargo.toml @@ -13,7 +13,7 @@ scale-info = { version = "2.8.0", default-features = false, features = ["bit-vec # Bridge dependencies -bp-xcm-bridge-hub-router = { path = "../../primitives/xcm-bridge-hub-router", default-features = false } +bp-xcm-bridge-hub = { path = "../../primitives/xcm-bridge-hub", default-features = false } # Substrate Dependencies @@ -36,7 +36,7 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] default = ["std"] std = [ - "bp-xcm-bridge-hub-router/std", + "bp-xcm-bridge-hub/std", "codec/std", "frame-benchmarking/std", "frame-support/std", diff --git a/modules/xcm-bridge-hub-router/src/benchmarking.rs b/modules/xcm-bridge-hub-router/src/benchmarking.rs index 1a4338a6fc9..84be404b478 100644 --- a/modules/xcm-bridge-hub-router/src/benchmarking.rs +++ b/modules/xcm-bridge-hub-router/src/benchmarking.rs @@ -18,7 +18,7 @@ #![cfg(feature = "runtime-benchmarks")] -use crate::{DeliveryFeeFactor, InitialFactor}; +use crate::{DeliveryFeeFactor, InitialFactor, MINIMAL_DELIVERY_FEE_FACTOR}; use frame_benchmarking::benchmarks_instance_pallet; use frame_support::traits::{Get, Hooks}; @@ -35,13 +35,13 @@ pub trait Config: crate::Config { benchmarks_instance_pallet! { on_initialize_when_non_congested { - DeliveryFeeFactor::::put(InitialFactor::get() + InitialFactor::get()); + DeliveryFeeFactor::::put(MINIMAL_DELIVERY_FEE_FACTOR + MINIMAL_DELIVERY_FEE_FACTOR); }: { crate::Pallet::::on_initialize(Zero::zero()) } on_initialize_when_congested { - DeliveryFeeFactor::::put(InitialFactor::get() + InitialFactor::get()); + DeliveryFeeFactor::::put(MINIMAL_DELIVERY_FEE_FACTOR + MINIMAL_DELIVERY_FEE_FACTOR); T::make_congested(); }: { crate::Pallet::::on_initialize(Zero::zero()) diff --git a/modules/xcm-bridge-hub-router/src/lib.rs b/modules/xcm-bridge-hub-router/src/lib.rs index 24615474857..8081338a806 100644 --- a/modules/xcm-bridge-hub-router/src/lib.rs +++ b/modules/xcm-bridge-hub-router/src/lib.rs @@ -22,13 +22,18 @@ //! All other bridge hub queues offer some backpressure mechanisms. So if at least one //! of all queues is congested, it will eventually lead to the growth of the queue at //! this chain. +//! +//! **A note on terminology**: when we mention the bridge hub here, we mean the chain that +//! has the messages pallet deployed (`pallet-bridge-grandpa`, `pallet-bridge-messages`, +//! `pallet-xcm-bridge-hub`, ...). It may be the system bridge hub parachain or any other +//! chain. #![cfg_attr(not(feature = "std"), no_std)] -use bp_xcm_bridge_hub_router::LocalXcmChannel; +use bp_xcm_bridge_hub::LocalXcmChannelManager; use codec::Encode; use frame_support::traits::Get; -use sp_runtime::{traits::One, FixedPointNumber, FixedU128, Saturating}; +use sp_runtime::{FixedPointNumber, FixedU128, Saturating}; use xcm::prelude::*; use xcm_builder::{ExporterFor, SovereignPaidRemoteExporter}; @@ -40,6 +45,9 @@ pub mod weights; mod mock; +/// Minimal delivery fee factor. +pub const MINIMAL_DELIVERY_FEE_FACTOR: FixedU128 = FixedU128::from_u32(1); + /// The factor that is used to increase current message fee factor when bridge experiencing /// some lags. const EXPONENTIAL_FEE_BASE: FixedU128 = FixedU128::from_rational(105, 100); // 1.05 @@ -75,17 +83,20 @@ pub mod pallet { type UniversalLocation: Get; /// Relative location of the sibling bridge hub. type SiblingBridgeHubLocation: Get; - /// The bridged network that this config is for. + /// The bridged network that this config is for if specified. + /// Also used for filtering `Bridges` by `BridgedNetworkId`. + /// If not specified, allows all networks pass through. type BridgedNetworkId: Get; + /// Configuration for supported **bridged networks/locations** with **bridge location** and + /// **possible fee**. Allows to externalize better control over allowed **bridged + /// networks/locations**. + type Bridges: ExporterFor; /// Actual message sender (`HRMP` or `DMP`) to the sibling bridge hub location. type ToBridgeHubSender: SendXcm; - /// Underlying channel with the sibling bridge hub. It must match the channel, used - /// by the `Self::ToBridgeHubSender`. - type WithBridgeHubChannel: LocalXcmChannel; + /// Local XCM channel manager. + type LocalXcmChannelManager: LocalXcmChannelManager; - /// Base bridge fee that is paid for every outbound message. - type BaseFee: Get; /// Additional fee that is paid for every byte of the outbound message. type ByteFee: Get; /// Asset that is used to paid bridge fee. @@ -98,37 +109,36 @@ pub mod pallet { #[pallet::hooks] impl, I: 'static> Hooks> for Pallet { fn on_initialize(_n: BlockNumberFor) -> Weight { - // if XCM queue is still congested, we don't change anything - if T::WithBridgeHubChannel::is_congested() { + // if XCM channel is still congested, we don't change anything + if T::LocalXcmChannelManager::is_congested(&T::SiblingBridgeHubLocation::get()) { return T::WeightInfo::on_initialize_when_congested() } - DeliveryFeeFactor::::mutate(|f| { - let previous_factor = *f; - *f = InitialFactor::get().max(*f / EXPONENTIAL_FEE_BASE); - if previous_factor != *f { - log::info!( - target: LOG_TARGET, - "Bridge queue is uncongested. Decreased fee factor from {} to {}", - previous_factor, - f, - ); + // if we can't decrease the delivery fee factor anymore, we don't change anything + let mut delivery_fee_factor = Self::delivery_fee_factor(); + if delivery_fee_factor == MINIMAL_DELIVERY_FEE_FACTOR { + return T::WeightInfo::on_initialize_when_congested() + } - T::WeightInfo::on_initialize_when_non_congested() - } else { - // we have not actually updated the `DeliveryFeeFactor`, so we may deduct - // single db write from maximal weight - T::WeightInfo::on_initialize_when_non_congested() - .saturating_sub(T::DbWeight::get().writes(1)) - } - }) + let previous_factor = delivery_fee_factor; + delivery_fee_factor = + MINIMAL_DELIVERY_FEE_FACTOR.max(delivery_fee_factor / EXPONENTIAL_FEE_BASE); + log::info!( + target: LOG_TARGET, + "Bridge channel is uncongested. Decreased fee factor from {} to {}", + previous_factor, + delivery_fee_factor, + ); + + DeliveryFeeFactor::::put(delivery_fee_factor); + T::WeightInfo::on_initialize_when_non_congested() } } /// Initialization value for the delivery fee factor. #[pallet::type_value] pub fn InitialFactor() -> FixedU128 { - FixedU128::one() + MINIMAL_DELIVERY_FEE_FACTOR } /// The number to multiply the base delivery fee by. @@ -169,8 +179,8 @@ pub mod pallet { impl, I: 'static> Pallet { /// Called when new message is sent (queued to local outbound XCM queue) over the bridge. pub(crate) fn on_message_sent_to_bridge(message_size: u32) { - // if outbound queue is not congested, do nothing - if !T::WithBridgeHubChannel::is_congested() { + // if outbound channel is not congested, do nothing + if !T::LocalXcmChannelManager::is_congested(&T::SiblingBridgeHubLocation::get()) { return } @@ -183,7 +193,7 @@ pub mod pallet { *f = f.saturating_mul(total_factor); log::info!( target: LOG_TARGET, - "Bridge queue is congested. Increased fee factor from {} to {}", + "Bridge channel is congested. Increased fee factor from {} to {}", previous_factor, f, ); @@ -206,32 +216,89 @@ type ViaBridgeHubExporter = SovereignPaidRemoteExporter< impl, I: 'static> ExporterFor for Pallet { fn exporter_for( network: &NetworkId, - _remote_location: &InteriorMultiLocation, + remote_location: &InteriorMultiLocation, message: &Xcm<()>, ) -> Option<(MultiLocation, Option)> { - // ensure that the message is sent to the expected bridged network + // ensure that the message is sent to the expected bridged network (if specified). if *network != T::BridgedNetworkId::get() { + log::trace!( + target: LOG_TARGET, + "Router with bridged_network_id {:?} does not support bridging to network {:?}!", + T::BridgedNetworkId::get(), + network, + ); return None } + // ensure that the message is sent to the expected bridged network and location. + let Some((bridge_hub_location, maybe_payment)) = + T::Bridges::exporter_for(network, remote_location, message) + else { + log::trace!( + target: LOG_TARGET, + "Router with bridged_network_id {:?} does not support bridging to network {:?} \ + and remote_location {:?}!", + T::BridgedNetworkId::get(), + network, + remote_location, + ); + return None + }; + + // ensure that the bridge hub location is the expected one + if bridge_hub_location != T::SiblingBridgeHubLocation::get() { + log::trace!( + target: LOG_TARGET, + "Router with bridged_network_id {:?} is configured to use different bridge hub \ + router {:?}. Expected: {:?}", + T::BridgedNetworkId::get(), + bridge_hub_location, + T::SiblingBridgeHubLocation::get(), + ); + return None + } + + // take `base_fee` from `T::Brides`, but it has to be the same `T::FeeAsset` + let base_fee = match maybe_payment { + Some(payment) => match payment { + MultiAsset { fun: Fungible(amount), id } if id.eq(&T::FeeAsset::get()) => amount, + invalid_asset => { + log::error!( + target: LOG_TARGET, + "Router with bridged_network_id {:?} is configured for `T::FeeAsset` {:?} \ + which is not compatible with {:?} for bridge_hub_location: {:?} for bridging to {:?}/{:?}!", + T::BridgedNetworkId::get(), + T::FeeAsset::get(), + invalid_asset, + bridge_hub_location, + network, + remote_location, + ); + return None + }, + }, + None => 0, + }; + // compute fee amount. Keep in mind that this is only the bridge fee. The fee for sending // message from this chain to child/sibling bridge hub is determined by the // `Config::ToBridgeHubSender` let message_size = message.encoded_size(); let message_fee = (message_size as u128).saturating_mul(T::ByteFee::get()); - let fee_sum = T::BaseFee::get().saturating_add(message_fee); + let fee_sum = base_fee.saturating_add(message_fee); let fee_factor = Self::delivery_fee_factor(); let fee = fee_factor.saturating_mul_int(fee_sum); + let fee = if fee > 0 { Some((T::FeeAsset::get(), fee).into()) } else { None }; log::info!( target: LOG_TARGET, - "Going to send message ({} bytes) over bridge. Computed bridge fee {} using fee factor {}", + "Going to send message ({} bytes) over bridge. Computed bridge fee {:?} using fee factor {}", + message_size, fee, fee_factor, - message_size, ); - Some((T::SiblingBridgeHubLocation::get(), Some((T::FeeAsset::get(), fee).into()))) + Some((bridge_hub_location, fee)) } } @@ -272,7 +339,7 @@ impl, I: 'static> SendXcm for Pallet { // use router to enqueue message to the sibling/child bridge hub. This also should handle // payment for passing through this queue. let (message_size, ticket) = ticket; - let xcm_hash = T::ToBridgeHubSender::deliver(ticket)?; + let xcm_hash = ViaBridgeHubExporter::::deliver(ticket)?; // increase delivery fee factor if required Self::on_message_sent_to_bridge(message_size); @@ -287,11 +354,12 @@ mod tests { use mock::*; use frame_support::traits::Hooks; + use sp_runtime::traits::One; #[test] fn initial_fee_factor_is_one() { run_test(|| { - assert_eq!(DeliveryFeeFactor::::get(), FixedU128::one()); + assert_eq!(DeliveryFeeFactor::::get(), MINIMAL_DELIVERY_FEE_FACTOR); }) } @@ -299,7 +367,7 @@ mod tests { fn fee_factor_is_not_decreased_from_on_initialize_when_queue_is_congested() { run_test(|| { DeliveryFeeFactor::::put(FixedU128::from_rational(125, 100)); - TestWithBridgeHubChannel::make_congested(); + TestLocalXcmChannelManager::make_congested(); // it should not decrease, because queue is congested let old_delivery_fee_factor = XcmBridgeHubRouter::delivery_fee_factor(); @@ -314,13 +382,13 @@ mod tests { DeliveryFeeFactor::::put(FixedU128::from_rational(125, 100)); // it shold eventually decreased to one - while XcmBridgeHubRouter::delivery_fee_factor() > FixedU128::one() { + while XcmBridgeHubRouter::delivery_fee_factor() > MINIMAL_DELIVERY_FEE_FACTOR { XcmBridgeHubRouter::on_initialize(One::one()); } // verify that it doesn't decreases anymore XcmBridgeHubRouter::on_initialize(One::one()); - assert_eq!(XcmBridgeHubRouter::delivery_fee_factor(), FixedU128::one()); + assert_eq!(XcmBridgeHubRouter::delivery_fee_factor(), MINIMAL_DELIVERY_FEE_FACTOR); }) } @@ -407,7 +475,7 @@ mod tests { #[test] fn sent_message_increases_factor_if_queue_is_congested() { run_test(|| { - TestWithBridgeHubChannel::make_congested(); + TestLocalXcmChannelManager::make_congested(); let old_delivery_fee_factor = XcmBridgeHubRouter::delivery_fee_factor(); assert_eq!( diff --git a/modules/xcm-bridge-hub-router/src/mock.rs b/modules/xcm-bridge-hub-router/src/mock.rs index 04540158e65..27565532780 100644 --- a/modules/xcm-bridge-hub-router/src/mock.rs +++ b/modules/xcm-bridge-hub-router/src/mock.rs @@ -18,7 +18,7 @@ use crate as pallet_xcm_bridge_hub_router; -use bp_xcm_bridge_hub_router::LocalXcmChannel; +use bp_xcm_bridge_hub::{BridgeId, LocalXcmChannelManager}; use frame_support::{construct_runtime, parameter_types}; use sp_core::H256; use sp_runtime::{ @@ -26,6 +26,7 @@ use sp_runtime::{ BuildStorage, }; use xcm::prelude::*; +use xcm_builder::NetworkExportTable; pub type AccountId = u64; type Block = frame_system::mocking::MockBlock; @@ -51,6 +52,11 @@ parameter_types! { pub UniversalLocation: InteriorMultiLocation = X2(GlobalConsensus(ThisNetworkId::get()), Parachain(1000)); pub SiblingBridgeHubLocation: MultiLocation = ParentThen(X1(Parachain(1002))).into(); pub BridgeFeeAsset: AssetId = MultiLocation::parent().into(); + pub BridgeTable: Vec<(NetworkId, MultiLocation, Option)> = vec![( + BridgedNetworkId::get(), + SiblingBridgeHubLocation::get(), + Some((BridgeFeeAsset::get(), BASE_FEE).into()), + )]; } impl frame_system::Config for TestRuntime { @@ -85,11 +91,11 @@ impl pallet_xcm_bridge_hub_router::Config<()> for TestRuntime { type UniversalLocation = UniversalLocation; type SiblingBridgeHubLocation = SiblingBridgeHubLocation; type BridgedNetworkId = BridgedNetworkId; + type Bridges = NetworkExportTable; type ToBridgeHubSender = TestToBridgeHubSender; - type WithBridgeHubChannel = TestWithBridgeHubChannel; + type LocalXcmChannelManager = TestLocalXcmChannelManager; - type BaseFee = ConstU128; type ByteFee = ConstU128; type FeeAsset = BridgeFeeAsset; } @@ -118,17 +124,27 @@ impl SendXcm for TestToBridgeHubSender { } } -pub struct TestWithBridgeHubChannel; +pub struct TestLocalXcmChannelManager; -impl TestWithBridgeHubChannel { +impl TestLocalXcmChannelManager { pub fn make_congested() { - frame_support::storage::unhashed::put(b"TestWithBridgeHubChannel.Congested", &true); + frame_support::storage::unhashed::put(b"TestLocalXcmChannelManager.Congested", &true); } } -impl LocalXcmChannel for TestWithBridgeHubChannel { - fn is_congested() -> bool { - frame_support::storage::unhashed::get_or_default(b"TestWithBridgeHubChannel.Congested") +impl LocalXcmChannelManager for TestLocalXcmChannelManager { + type Error = (); + + fn is_congested(_with: &MultiLocation) -> bool { + frame_support::storage::unhashed::get_or_default(b"TestLocalXcmChannelManager.Congested") + } + + fn suspend_bridge(_with: &MultiLocation, _bridge: BridgeId) -> Result<(), Self::Error> { + Ok(()) + } + + fn resume_bridge(_with: &MultiLocation, _bridge: BridgeId) -> Result<(), Self::Error> { + Ok(()) } } diff --git a/modules/xcm-bridge-hub/Cargo.toml b/modules/xcm-bridge-hub/Cargo.toml index 815054fd73d..4cf457da7fb 100644 --- a/modules/xcm-bridge-hub/Cargo.toml +++ b/modules/xcm-bridge-hub/Cargo.toml @@ -29,7 +29,7 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d # Polkadot Dependencies xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } -xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "master" } +xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } [dev-dependencies] diff --git a/modules/xcm-bridge-hub/src/dispatcher.rs b/modules/xcm-bridge-hub/src/dispatcher.rs index 0d0662fdc19..5898e1b67d5 100644 --- a/modules/xcm-bridge-hub/src/dispatcher.rs +++ b/modules/xcm-bridge-hub/src/dispatcher.rs @@ -18,16 +18,23 @@ //! bridge messages dispatcher. Internally, it just forwards inbound blob to the //! XCM-level blob dispatcher, which pushes message to some other queue (e.g. //! to HRMP queue with the sibling target chain). +//! +//! This code is executed at the target bridge hub. -use crate::{Config, Pallet, XcmAsPlainPayload, LOG_TARGET}; +use crate::{Config, Pallet, LOG_TARGET}; -use bp_messages::target_chain::{DispatchMessage, MessageDispatch}; +use bp_messages::{ + target_chain::{DispatchMessage, MessageDispatch}, + LaneId, +}; use bp_runtime::messages::MessageDispatchResult; +use bp_xcm_bridge_hub::{BridgeId, LocalXcmChannelManager, XcmAsPlainPayload}; use codec::{Decode, Encode}; use frame_support::{dispatch::Weight, CloneNoBound, EqNoBound, PartialEqNoBound}; use pallet_bridge_messages::{Config as BridgeMessagesConfig, WeightInfoExt}; use scale_info::TypeInfo; use sp_runtime::SaturatedConversion; +use xcm::prelude::*; use xcm_builder::{DispatchBlob, DispatchBlobError}; /// Message dispatch result type for single message. @@ -52,6 +59,14 @@ where type DispatchPayload = XcmAsPlainPayload; type DispatchLevelResult = XcmBlobMessageDispatchResult; + fn is_active(lane: LaneId) -> bool { + let bridge_id = BridgeId::from_lane_id(lane); + Pallet::::bridge(bridge_id) + .and_then(|bridge| bridge.bridge_origin_relative_location.try_as().cloned().ok()) + .map(|recipient: MultiLocation| !T::LocalXcmChannelManager::is_congested(&recipient)) + .unwrap_or(false) + } + fn dispatch_weight(message: &mut DispatchMessage) -> Weight { match message.data.payload { Ok(ref payload) => { diff --git a/modules/xcm-bridge-hub/src/exporter.rs b/modules/xcm-bridge-hub/src/exporter.rs index 5eab79b38ac..d42ba7523b4 100644 --- a/modules/xcm-bridge-hub/src/exporter.rs +++ b/modules/xcm-bridge-hub/src/exporter.rs @@ -17,16 +17,31 @@ //! The code that allows to use the pallet (`pallet-xcm-bridge-hub`) as XCM message //! exporter at the sending bridge hub. Internally, it just enqueues outbound blob //! in the messages pallet queue. +//! +//! This code is executed at the source bridge hub. -use crate::{Config, Pallet, XcmAsPlainPayload, LOG_TARGET}; +use crate::{Config, Pallet, SuspendedBridges, LOG_TARGET}; -use bp_messages::{source_chain::MessagesBridge, LaneId}; +use bp_messages::{ + source_chain::{MessagesBridge, OnMessagesDelivered}, + LaneId, MessageNonce, +}; +use bp_xcm_bridge_hub::{BridgeId, BridgeLocations, LocalXcmChannelManager, XcmAsPlainPayload}; use frame_support::traits::Get; use pallet_bridge_messages::{Config as BridgeMessagesConfig, Pallet as BridgeMessagesPallet}; +use sp_std::boxed::Box; use xcm::prelude::*; use xcm_builder::{HaulBlob, HaulBlobError, HaulBlobExporter}; use xcm_executor::traits::ExportXcm; +/// Maximal number of messages in the outbound bridge queue. Once we reach this limit, we +/// suspend a bridge. +const OUTBOUND_LANE_CONGESTED_THRESHOLD: MessageNonce = 8_192; + +/// After we have suspended the bridge, we wait until number of messages in the outbound bridge +/// queue drops to this count, before sending resuming the bridge. +const OUTBOUND_LANE_UNCONGESTED_THRESHOLD: MessageNonce = 1_024; + // An easy way to access `HaulBlobExporter`. type PalletAsHaulBlobExporter = HaulBlobExporter< DummyHaulBlob, @@ -43,7 +58,7 @@ where OutboundPayload = XcmAsPlainPayload, >, { - type Ticket = (LaneId, XcmAsPlainPayload, XcmHash); + type Ticket = (Box, XcmAsPlainPayload, XcmHash); fn validate( network: NetworkId, @@ -83,37 +98,40 @@ where bridge_origin_universal_location.relative_to(&T::UniversalLocation::get()); // then we are able to compute the lane id used to send messages - let bridge_locations = Self::bridge_locations( + let locations = Self::bridge_locations( Box::new(bridge_origin_relative_location), Box::new(bridge_destination_universal_location.into()), ) .map_err(|_| SendError::Unroutable)?; - Ok(((bridge_locations.lane_id, blob, id), price)) + Ok(((locations, blob, id), price)) } fn deliver( - (lane_id, blob, id): (LaneId, XcmAsPlainPayload, XcmHash), + (locations, blob, id): (Box, XcmAsPlainPayload, XcmHash), ) -> Result { - let send_result = MessagesPallet::::send_message(lane_id, blob); + let send_result = MessagesPallet::::send_message(locations.bridge_id.lane_id(), blob); match send_result { Ok(artifacts) => { log::info!( target: LOG_TARGET, - "XCM message {:?} has been enqueued at lane {:?} with nonce {}", + "XCM message {:?} has been enqueued at bridge {:?} with nonce {}", id, - lane_id, + locations.bridge_id, artifacts.nonce, ); + + // maybe we need switch to congested state + Self::on_bridge_message_enqueued(locations, artifacts.enqueued_messages); }, Err(error) => { log::debug!( target: LOG_TARGET, - "XCM message {:?} has been dropped because of bridge error {:?} on lane {:?}", + "XCM message {:?} has been dropped because of bridge error {:?} on bridge {:?}", id, error, - lane_id, + locations.bridge_id, ); return Err(SendError::Transport("BridgeSendError")) }, @@ -123,6 +141,149 @@ where } } +impl, I: 'static> OnMessagesDelivered for Pallet { + fn on_messages_delivered(lane_id: LaneId, enqueued_messages: MessageNonce) { + Self::on_bridge_messages_delivered(lane_id, enqueued_messages); + } +} + +impl, I: 'static> Pallet { + /// Called when new message is pushed onto outbound bridge queue. + fn on_bridge_message_enqueued( + locations: Box, + enqueued_messages: MessageNonce, + ) { + // if the bridge queue is not congested, we don't want to do anything + let is_congested = enqueued_messages > OUTBOUND_LANE_CONGESTED_THRESHOLD; + if !is_congested { + return + } + + // TODO: https://github.com/paritytech/parity-bridges-common/issues/2006 we either need fishermens + // to watch thsi rule violation (suspended, but keep sending new messages), or we need a + // hard limit for that like other XCM queues have + + // check if the lane is already suspended. If it is, do nothing. We still accept new + // messages to the suspended bridge, hoping that it'll be actually suspended soon + let is_already_congested = SuspendedBridges::::get().contains(&locations.bridge_id); + if is_already_congested { + return + } + + // else - suspend the bridge + let suspend_result = T::LocalXcmChannelManager::suspend_bridge( + &locations.bridge_origin_relative_location, + locations.bridge_id, + ); + match suspend_result { + Ok(_) => { + log::debug!( + target: LOG_TARGET, + "Suspended the bridge {:?}, originated by the {:?}", + locations.bridge_id, + locations.bridge_origin_relative_location, + ); + }, + Err(e) => { + log::debug!( + target: LOG_TARGET, + "Failed to suspended the bridge {:?}, originated by the {:?}: {:?}", + locations.bridge_id, + locations.bridge_origin_relative_location, + e, + ); + + return + }, + } + + // and remember that we have suspended the bridge + SuspendedBridges::::mutate(|suspended_bridges| { + let maybe_error = suspended_bridges.try_push(locations.bridge_id); + if let Err(e) = maybe_error { + // TODO: https://github.com/paritytech/parity-bridges-common/issues/2006 + // we've sent the suspend signal, but failed to remember that => we'll keep + // up sending the signal on every further message, effectively blocking the XCM + // lane. We need some limit on total number of bridges so that this call won't ever + // fail. + + log::debug!( + target: LOG_TARGET, + "Failed to remember the suspended bridge {:?}, originated by the {:?}: {:?}", + locations.bridge_id, + locations.bridge_origin_relative_location, + e, + ); + } + }); + } + + /// Must be called whenever we receive a message delivery confirmation. + fn on_bridge_messages_delivered(lane_id: LaneId, enqueued_messages: MessageNonce) { + // if the bridge queue is still congested, we don't want to do anything + let is_congested = enqueued_messages > OUTBOUND_LANE_UNCONGESTED_THRESHOLD; + if is_congested { + return + } + + // if we have not suspended the bridge before, we don't want to do anything + let bridge_id = BridgeId::from_lane_id(lane_id); + if !SuspendedBridges::::get().contains(&bridge_id) { + return + } + + // else - resume the bridge + if let Some(bridge) = Self::bridge(bridge_id) { + let bridge_origin_relative_location = + (*bridge.bridge_origin_relative_location).try_into(); + let bridge_origin_relative_location = match bridge_origin_relative_location { + Ok(bridge_origin_relative_location) => bridge_origin_relative_location, + Err(e) => { + log::debug!( + target: LOG_TARGET, + "Failed to convert the bridge {:?} location: {:?}", + lane_id, + e, + ); + + return + }, + }; + + let resume_result = T::LocalXcmChannelManager::resume_bridge( + &bridge_origin_relative_location, + bridge_id, + ); + match resume_result { + Ok(_) => { + log::debug!( + target: LOG_TARGET, + "Resumed the bridge {:?}, originated by the {:?}", + lane_id, + bridge_origin_relative_location, + ); + }, + Err(e) => { + log::debug!( + target: LOG_TARGET, + "Failed to resume the bridge {:?}, originated by the {:?}: {:?}", + lane_id, + bridge_origin_relative_location, + e, + ); + + return + }, + } + } + + // and forget that we have previously suspended the bridge + SuspendedBridges::::mutate(|suspended_bridges| { + suspended_bridges.retain(|b| *b != bridge_id); + }); + } +} + /// Dummy implementation of the `HaulBlob` trait that is never called. /// /// We are using `HaulBlobExporter`, which requires `HaulBlob` implementation. It assumes that @@ -155,9 +316,9 @@ mod tests { XcmOverBridge::bridge_locations_from_origin(origin, Box::new(with.into())).unwrap(); let lanes_manager = LanesManagerOf::::new(); - lanes_manager.create_outbound_lane(locations.lane_id).unwrap(); + lanes_manager.create_outbound_lane(locations.bridge_id.lane_id()).unwrap(); assert!(lanes_manager - .active_outbound_lane(locations.lane_id) + .active_outbound_lane(locations.bridge_id.lane_id()) .unwrap() .queued_messages() .is_empty()); @@ -175,7 +336,7 @@ mod tests { // double check that the message has been pushed to the expected lane // (it should already been checked during `send_message` call) assert!(!lanes_manager - .active_outbound_lane(locations.lane_id) + .active_outbound_lane(locations.bridge_id.lane_id()) .unwrap() .queued_messages() .is_empty()); diff --git a/modules/xcm-bridge-hub/src/lib.rs b/modules/xcm-bridge-hub/src/lib.rs index 8fe956e75b5..c2ade2bcb56 100644 --- a/modules/xcm-bridge-hub/src/lib.rs +++ b/modules/xcm-bridge-hub/src/lib.rs @@ -51,15 +51,20 @@ #![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] -use bp_messages::{LaneId, LaneState, MessageNonce}; +use bp_messages::{LaneState, MessageNonce}; use bp_runtime::{AccountIdOf, BalanceOf, BlockNumberOf, RangeInclusiveExt}; use bp_xcm_bridge_hub::{ - bridge_locations, Bridge, BridgeLocations, BridgeLocationsError, BridgeState, + bridge_locations, Bridge, BridgeId, BridgeLocations, BridgeLocationsError, BridgeState, + LocalXcmChannelManager, +}; +use frame_support::{ + traits::{Currency, ReservableCurrency}, + DefaultNoBound, }; -use frame_support::traits::{Currency, ReservableCurrency}; use frame_system::Config as SystemConfig; use pallet_bridge_messages::{Config as BridgeMessagesConfig, LanesManagerError}; use sp_runtime::traits::{Header as HeaderT, HeaderProvider, Zero}; +use sp_std::{boxed::Box, vec::Vec}; use xcm::prelude::*; use xcm_builder::DispatchBlob; use xcm_executor::traits::ConvertLocation; @@ -71,10 +76,6 @@ mod dispatcher; mod exporter; mod mock; -/// Encoded XCM blob. We expect the bridge messages pallet to use this blobtype for both inbound -/// and outbound payloads. -pub type XcmAsPlainPayload = Vec; - /// The target that will be used when publishing logs related to this pallet. pub const LOG_TARGET: &str = "runtime::bridge-xcm"; @@ -105,6 +106,10 @@ pub mod pallet { /// `BridgedNetworkId` consensus. type BridgeMessagesPalletInstance: 'static; + /// Maximal number of suspended bridges. + #[pallet::constant] + type MaxSuspendedBridges: Get; + /// A set of XCM locations within local consensus system that are allowed to open /// bridges with remote destinations. // TODO: there's only one impl of `EnsureOrigin` - @@ -124,9 +129,11 @@ pub mod pallet { /// Currency used to pay for bridge registration. type NativeCurrency: ReservableCurrency; + /// Local XCM channel manager. + type LocalXcmChannelManager: LocalXcmChannelManager; /// XCM-level dispatcher for inbound bridge messages. type BlobDispatcher: DispatchBlob; - /// Price of single message export. + /// Price of single message export to the bridged consensus (`Self::BridgedNetworkId`). type MessageExportPrice: Get; } @@ -181,7 +188,7 @@ pub mod pallet { .map_err(|_| Error::::FailedToReserveBridgeReserve)?; // save bridge metadata - Bridges::::try_mutate(locations.lane_id, |bridge| match bridge { + Bridges::::try_mutate(locations.bridge_id, |bridge| match bridge { Some(_) => Err(Error::::BridgeAlreadyExists), None => { *bridge = Some(BridgeOf:: { @@ -199,24 +206,24 @@ pub mod pallet { // create new lanes. Under normal circumstances, following calls shall never fail let lanes_manager = LanesManagerOf::::new(); lanes_manager - .create_inbound_lane(locations.lane_id) + .create_inbound_lane(locations.bridge_id.lane_id()) .map_err(Error::::LanesManager)?; lanes_manager - .create_outbound_lane(locations.lane_id) + .create_outbound_lane(locations.bridge_id.lane_id()) .map_err(Error::::LanesManager)?; // write something to log log::trace!( target: LOG_TARGET, "Bridge {:?} between {:?} and {:?} has been opened", - locations.lane_id, + locations.bridge_id, locations.bridge_origin_universal_location, locations.bridge_destination_universal_location, ); // deposit `BridgeOpened` event Self::deposit_event(Event::::BridgeOpened { - lane_id: locations.lane_id, + bridge_id: locations.bridge_id, local_endpoint: Box::new(locations.bridge_origin_universal_location), remote_endpoint: Box::new(locations.bridge_destination_universal_location), }); @@ -257,7 +264,7 @@ pub mod pallet { // update bridge metadata - this also guarantees that the bridge is in the proper state let bridge = - Bridges::::try_mutate_exists(locations.lane_id, |bridge| match bridge { + Bridges::::try_mutate_exists(locations.bridge_id, |bridge| match bridge { Some(bridge) => { bridge.state = BridgeState::Closed; Ok(bridge.clone()) @@ -268,10 +275,10 @@ pub mod pallet { // close inbound and outbound lanes let lanes_manager = LanesManagerOf::::new(); let mut inbound_lane = lanes_manager - .any_state_inbound_lane(locations.lane_id) + .any_state_inbound_lane(locations.bridge_id.lane_id()) .map_err(Error::::LanesManager)?; let mut outbound_lane = lanes_manager - .any_state_outbound_lane(locations.lane_id) + .any_state_outbound_lane(locations.bridge_id.lane_id()) .map_err(Error::::LanesManager)?; // now prune queued messages @@ -296,7 +303,7 @@ pub mod pallet { log::trace!( target: LOG_TARGET, "Bridge {:?} between {:?} and {:?} is closing. {} messages remaining", - locations.lane_id, + locations.bridge_id, locations.bridge_origin_universal_location, locations.bridge_destination_universal_location, enqueued_messages, @@ -304,7 +311,7 @@ pub mod pallet { // deposit the `ClosingBridge` event Self::deposit_event(Event::::ClosingBridge { - lane_id: locations.lane_id, + bridge_id: locations.bridge_id, pruned_messages, enqueued_messages, }); @@ -315,7 +322,11 @@ pub mod pallet { // else we have pruned all messages, so lanes and the bridge itself may gone inbound_lane.purge(); outbound_lane.purge(); - Bridges::::remove(locations.lane_id); + Bridges::::remove(locations.bridge_id); + SuspendedBridges::::mutate(|suspended_bridges| { + suspended_bridges.retain(|b| *b != locations.bridge_id); + // TODO: https://github.com/paritytech/parity-bridges-common/issues/2006 send resume signal or not??? + }); // unreserve remaining amount let failed_to_unreserve = @@ -327,7 +338,7 @@ pub mod pallet { target: LOG_TARGET, "Failed to unreserve {:?} during ridge {:?} closure", failed_to_unreserve, - locations.lane_id, + locations.bridge_id, ); } @@ -335,14 +346,14 @@ pub mod pallet { log::trace!( target: LOG_TARGET, "Bridge {:?} between {:?} and {:?} has been closed", - locations.lane_id, + locations.bridge_id, locations.bridge_origin_universal_location, locations.bridge_destination_universal_location, ); // deposit the `BridgePruned` event Self::deposit_event(Event::::BridgePruned { - lane_id: locations.lane_id, + bridge_id: locations.bridge_id, pruned_messages, }); @@ -385,8 +396,62 @@ pub mod pallet { /// All registered bridges. #[pallet::storage] + #[pallet::getter(fn bridge)] pub type Bridges, I: 'static = ()> = - StorageMap<_, Identity, LaneId, BridgeOf>; + StorageMap<_, Identity, BridgeId, BridgeOf>; + + /// All currently suspended bridges. + #[pallet::storage] + #[pallet::getter(fn bridges_by_local_origin)] + pub type SuspendedBridges, I: 'static = ()> = + StorageValue<_, BoundedVec, ValueQuery>; + + #[pallet::genesis_config] + #[derive(DefaultNoBound)] + pub struct GenesisConfig, I: 'static = ()> { + /// Opened bridges. + /// + /// Keep in mind that we are **NOT** reserving any amount for the bridges, opened at + /// genesis. We are **NOT** opening lanes, used by this bridge. It all must be done using + /// other pallets genesis configuration or some other means. + pub opened_bridges: Vec<(MultiLocation, InteriorMultiLocation)>, + /// Dummy marker. + pub phantom: sp_std::marker::PhantomData<(T, I)>, + } + + #[pallet::genesis_build] + impl, I: 'static> BuildGenesisConfig for GenesisConfig + where + T: frame_system::Config>>, + { + fn build(&self) { + for (bridge_origin_relative_location, bridge_destination_universal_location) in + &self.opened_bridges + { + let locations = Pallet::::bridge_locations( + Box::new(*bridge_origin_relative_location), + Box::new((*bridge_destination_universal_location).into()), + ) + .expect("Invalid genesis configuration"); + let bridge_owner_account = T::BridgeOriginAccountIdConverter::convert_location( + &locations.bridge_origin_relative_location, + ) + .expect("Invalid genesis configuration"); + + Bridges::::insert( + locations.bridge_id, + Bridge { + bridge_origin_relative_location: Box::new( + locations.bridge_origin_relative_location.into(), + ), + state: BridgeState::Opened, + bridge_owner_account, + reserve: Zero::zero(), + }, + ); + } + } + } #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] @@ -397,13 +462,13 @@ pub mod pallet { local_endpoint: Box, /// Universal location of remote bridge endpoint. remote_endpoint: Box, - /// Bridge and its lane identifier. - lane_id: LaneId, + /// Bridge identifier. + bridge_id: BridgeId, }, /// Bridge is going to be closed, but not yet fully pruned from the runtime storage. ClosingBridge { - /// Bridge and its lane identifier. - lane_id: LaneId, + /// Bridge identifier. + bridge_id: BridgeId, /// Number of pruned messages during the close call. pruned_messages: MessageNonce, /// Number of enqueued messages that need to be pruned in follow up calls. @@ -412,8 +477,8 @@ pub mod pallet { /// Bridge has been closed and pruned from the runtime storage. It now may be reopened /// again by any participant. BridgePruned { - /// Bridge and its lane identifier. - lane_id: LaneId, + /// Bridge identifier. + bridge_id: BridgeId, /// Number of pruned messages during the close call. pruned_messages: MessageNonce, }, @@ -427,6 +492,8 @@ pub mod pallet { InvalidBridgeOriginAccount, /// The bridge is already registered in this pallet. BridgeAlreadyExists, + /// The local origin already owns a maximal number of bridges. + TooManyBridgesForLocalOrigin, /// Trying to close already closed bridge. BridgeAlreadyClosed, /// Lanes manager error. @@ -445,6 +512,7 @@ mod tests { use super::*; use mock::*; + use bp_messages::LaneId; use frame_support::{assert_noop, assert_ok, traits::fungible::Mutate}; use frame_system::{EventRecord, Phase}; @@ -475,11 +543,11 @@ mod tests { bridge_owner_account, reserve, }; - Bridges::::insert(locations.lane_id, bridge.clone()); + Bridges::::insert(locations.bridge_id, bridge.clone()); let lanes_manager = LanesManagerOf::::new(); - lanes_manager.create_inbound_lane(locations.lane_id).unwrap(); - lanes_manager.create_outbound_lane(locations.lane_id).unwrap(); + lanes_manager.create_inbound_lane(locations.bridge_id.lane_id()).unwrap(); + lanes_manager.create_outbound_lane(locations.bridge_id.lane_id()).unwrap(); (bridge, *locations) } @@ -615,7 +683,7 @@ mod tests { ); Bridges::::insert( - locations.lane_id, + locations.bridge_id, Bridge { bridge_origin_relative_location: Box::new( locations.bridge_origin_relative_location.into(), @@ -649,7 +717,7 @@ mod tests { let lanes_manager = LanesManagerOf::::new(); - lanes_manager.create_inbound_lane(locations.lane_id).unwrap(); + lanes_manager.create_inbound_lane(locations.bridge_id.lane_id()).unwrap(); assert_noop!( XcmOverBridge::open_bridge( origin.clone(), @@ -658,8 +726,11 @@ mod tests { Error::::LanesManager(LanesManagerError::InboundLaneAlreadyExists), ); - lanes_manager.active_inbound_lane(locations.lane_id).unwrap().purge(); - lanes_manager.create_outbound_lane(locations.lane_id).unwrap(); + lanes_manager + .active_inbound_lane(locations.bridge_id.lane_id()) + .unwrap() + .purge(); + lanes_manager.create_outbound_lane(locations.bridge_id.lane_id()).unwrap(); assert_noop!( XcmOverBridge::open_bridge(origin, Box::new(bridged_asset_hub_location().into()),), Error::::LanesManager( @@ -696,13 +767,13 @@ mod tests { .unwrap(); // ensure that there's no bridge and lanes in the storage - assert_eq!(Bridges::::get(locations.lane_id), None); + assert_eq!(Bridges::::get(locations.bridge_id), None); assert_eq!( - lanes_manager.active_inbound_lane(locations.lane_id).map(drop), + lanes_manager.active_inbound_lane(locations.bridge_id.lane_id()).map(drop), Err(LanesManagerError::UnknownInboundLane) ); assert_eq!( - lanes_manager.active_outbound_lane(locations.lane_id).map(drop), + lanes_manager.active_outbound_lane(locations.bridge_id.lane_id()).map(drop), Err(LanesManagerError::UnknownOutboundLane) ); @@ -725,7 +796,7 @@ mod tests { // ensure that everything has been set up in the runtime storage assert_eq!( - Bridges::::get(locations.lane_id), + Bridges::::get(locations.bridge_id), Some(Bridge { bridge_origin_relative_location: Box::new( locations.bridge_origin_relative_location.into() @@ -736,11 +807,15 @@ mod tests { }), ); assert_eq!( - lanes_manager.active_inbound_lane(locations.lane_id).map(|l| l.state()), + lanes_manager + .active_inbound_lane(locations.bridge_id.lane_id()) + .map(|l| l.state()), Ok(LaneState::Opened) ); assert_eq!( - lanes_manager.active_outbound_lane(locations.lane_id).map(|l| l.state()), + lanes_manager + .active_outbound_lane(locations.bridge_id.lane_id()) + .map(|l| l.state()), Ok(LaneState::Opened) ); assert_eq!(Balances::free_balance(&bridge_owner_account), existential_deposit); @@ -752,7 +827,7 @@ mod tests { Some(&EventRecord { phase: Phase::Initialization, event: RuntimeEvent::XcmOverBridge(Event::BridgeOpened { - lane_id: locations.lane_id, + bridge_id: locations.bridge_id, local_endpoint: Box::new(locations.bridge_origin_universal_location), remote_endpoint: Box::new( locations.bridge_destination_universal_location @@ -813,7 +888,10 @@ mod tests { let (_, locations) = mock_open_bridge_from(origin.clone()); let lanes_manager = LanesManagerOf::::new(); - lanes_manager.any_state_inbound_lane(locations.lane_id).unwrap().purge(); + lanes_manager + .any_state_inbound_lane(locations.bridge_id.lane_id()) + .unwrap() + .purge(); assert_noop!( XcmOverBridge::close_bridge( origin.clone(), @@ -822,10 +900,16 @@ mod tests { ), Error::::LanesManager(LanesManagerError::UnknownInboundLane), ); - lanes_manager.any_state_outbound_lane(locations.lane_id).unwrap().purge(); + lanes_manager + .any_state_outbound_lane(locations.bridge_id.lane_id()) + .unwrap() + .purge(); let (_, locations) = mock_open_bridge_from(origin.clone()); - lanes_manager.any_state_outbound_lane(locations.lane_id).unwrap().purge(); + lanes_manager + .any_state_outbound_lane(locations.bridge_id.lane_id()) + .unwrap() + .purge(); assert_noop!( XcmOverBridge::close_bridge( origin, @@ -850,7 +934,7 @@ mod tests { // enqueue some messages for _ in 0..32 { - enqueue_message(locations.lane_id); + enqueue_message(locations.bridge_id.lane_id()); } // now call the `close_bridge`, which will only partially prune messages @@ -864,20 +948,26 @@ mod tests { // are pruned, but funds are not unreserved let lanes_manager = LanesManagerOf::::new(); assert_eq!( - Bridges::::get(locations.lane_id).map(|b| b.state), + Bridges::::get(locations.bridge_id).map(|b| b.state), Some(BridgeState::Closed) ); assert_eq!( - lanes_manager.any_state_inbound_lane(locations.lane_id).unwrap().state(), + lanes_manager + .any_state_inbound_lane(locations.bridge_id.lane_id()) + .unwrap() + .state(), LaneState::Closed ); assert_eq!( - lanes_manager.any_state_outbound_lane(locations.lane_id).unwrap().state(), + lanes_manager + .any_state_outbound_lane(locations.bridge_id.lane_id()) + .unwrap() + .state(), LaneState::Closed ); assert_eq!( lanes_manager - .any_state_outbound_lane(locations.lane_id) + .any_state_outbound_lane(locations.bridge_id.lane_id()) .unwrap() .queued_messages() .checked_len(), @@ -890,7 +980,7 @@ mod tests { Some(&EventRecord { phase: Phase::Initialization, event: RuntimeEvent::XcmOverBridge(Event::ClosingBridge { - lane_id: locations.lane_id, + bridge_id: locations.bridge_id, pruned_messages: 16, enqueued_messages: 16, }), @@ -907,20 +997,26 @@ mod tests { // nothing is changed (apart from the pruned messages) assert_eq!( - Bridges::::get(locations.lane_id).map(|b| b.state), + Bridges::::get(locations.bridge_id).map(|b| b.state), Some(BridgeState::Closed) ); assert_eq!( - lanes_manager.any_state_inbound_lane(locations.lane_id).unwrap().state(), + lanes_manager + .any_state_inbound_lane(locations.bridge_id.lane_id()) + .unwrap() + .state(), LaneState::Closed ); assert_eq!( - lanes_manager.any_state_outbound_lane(locations.lane_id).unwrap().state(), + lanes_manager + .any_state_outbound_lane(locations.bridge_id.lane_id()) + .unwrap() + .state(), LaneState::Closed ); assert_eq!( lanes_manager - .any_state_outbound_lane(locations.lane_id) + .any_state_outbound_lane(locations.bridge_id.lane_id()) .unwrap() .queued_messages() .checked_len(), @@ -933,7 +1029,7 @@ mod tests { Some(&EventRecord { phase: Phase::Initialization, event: RuntimeEvent::XcmOverBridge(Event::ClosingBridge { - lane_id: locations.lane_id, + bridge_id: locations.bridge_id, pruned_messages: 8, enqueued_messages: 8, }), @@ -950,13 +1046,13 @@ mod tests { ),); // there's no traces of bridge in the runtime storage and funds are unreserved - assert_eq!(Bridges::::get(locations.lane_id).map(|b| b.state), None); + assert_eq!(Bridges::::get(locations.bridge_id).map(|b| b.state), None); assert_eq!( - lanes_manager.any_state_inbound_lane(locations.lane_id).map(drop), + lanes_manager.any_state_inbound_lane(locations.bridge_id.lane_id()).map(drop), Err(LanesManagerError::UnknownInboundLane) ); assert_eq!( - lanes_manager.any_state_outbound_lane(locations.lane_id).map(drop), + lanes_manager.any_state_outbound_lane(locations.bridge_id.lane_id()).map(drop), Err(LanesManagerError::UnknownOutboundLane) ); assert_eq!( @@ -969,7 +1065,7 @@ mod tests { Some(&EventRecord { phase: Phase::Initialization, event: RuntimeEvent::XcmOverBridge(Event::BridgePruned { - lane_id: locations.lane_id, + bridge_id: locations.bridge_id, pruned_messages: 8, }), topics: vec![], diff --git a/modules/xcm-bridge-hub/src/mock.rs b/modules/xcm-bridge-hub/src/mock.rs index 79d96a29d03..c3c8ad3deef 100644 --- a/modules/xcm-bridge-hub/src/mock.rs +++ b/modules/xcm-bridge-hub/src/mock.rs @@ -18,8 +18,11 @@ use crate as pallet_xcm_bridge_hub; -use bp_messages::{target_chain::ForbidInboundMessages, ChainWithMessages, MessageNonce}; -use bp_runtime::{Chain, ChainId}; +use bp_messages::{ + target_chain::{DispatchMessage, MessageDispatch}, + ChainWithMessages, LaneId, MessageNonce, +}; +use bp_runtime::{messages::MessageDispatchResult, Chain, ChainId}; use codec::Encode; use frame_support::{ parameter_types, @@ -114,7 +117,8 @@ impl pallet_bridge_messages::Config for TestRuntime { type InboundPayload = Vec; type DeliveryPayments = (); type DeliveryConfirmationPayments = (); - type MessageDispatch = ForbidInboundMessages>; + type MessageDispatch = TestMessageDispatch; + type OnMessagesDelivered = (); } parameter_types! { @@ -126,6 +130,8 @@ parameter_types! { GlobalConsensus(RelayNetwork::get()), Parachain(THIS_BRIDGE_HUB_ID), ); + pub const MaxSuspendedBridges: u32 = 2; + pub const Penalty: Balance = 1_000; } /// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used @@ -214,12 +220,14 @@ impl pallet_xcm_bridge_hub::Config for TestRuntime { type BridgedNetworkId = BridgedRelayNetwork; type BridgeMessagesPalletInstance = (); + type MaxSuspendedBridges = MaxSuspendedBridges; type OpenBridgeOrigin = OpenBridgeOrigin; type BridgeOriginAccountIdConverter = LocationToAccountId; type BridgeReserve = BridgeReserve; type NativeCurrency = Balances; + type LocalXcmChannelManager = (); type BlobDispatcher = TestBlobDispatcher; type MessageExportPrice = (); } @@ -295,6 +303,35 @@ impl ChainWithMessages for BridgedChain { const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 128; } +/// Test message dispatcher. +pub struct TestMessageDispatch; + +impl TestMessageDispatch { + pub fn deactivate(lane: LaneId) { + frame_support::storage::unhashed::put(&(b"inactive", lane).encode()[..], &false); + } +} + +impl MessageDispatch for TestMessageDispatch { + type DispatchPayload = Vec; + type DispatchLevelResult = (); + + fn is_active(lane: LaneId) -> bool { + frame_support::storage::unhashed::take::(&(b"inactive", lane).encode()[..]) != + Some(false) + } + + fn dispatch_weight(_message: &mut DispatchMessage) -> Weight { + Weight::zero() + } + + fn dispatch( + _: DispatchMessage, + ) -> MessageDispatchResult { + MessageDispatchResult { unspent_weight: Weight::zero(), dispatch_level_result: () } + } +} + /// Location of bridged asset hub. pub fn bridged_asset_hub_location() -> InteriorMultiLocation { X2(GlobalConsensus(BridgedRelayNetwork::get()), Parachain(BRIDGED_ASSET_HUB_ID)) diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index cd529ce1383..290216c8023 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -91,11 +91,26 @@ impl DeliveryConfirmationPayments for () { } } +/// Callback that is called at the source chain (bridge hub) when we get delivery confirmation +/// for new messages. +pub trait OnMessagesDelivered { + /// New messages delivery has been confirmed. + /// + /// The only argument of the function is the number of yet undelivered messages + fn on_messages_delivered(lane: LaneId, enqueued_messages: MessageNonce); +} + +impl OnMessagesDelivered for () { + fn on_messages_delivered(_lane: LaneId, _enqueued_messages: MessageNonce) {} +} + /// Send message artifacts. #[derive(Eq, RuntimeDebug, PartialEq)] pub struct SendMessageArtifacts { /// Nonce of the message. pub nonce: MessageNonce, + /// Number of enqueued messages at the lane, after the message is sent. + pub enqueued_messages: MessageNonce, } /// Messages bridge API to be used from other pallets. @@ -117,7 +132,7 @@ impl MessagesBridge for NoopMessagesBridge { type Error = &'static str; fn send_message(_lane: LaneId, _message: Payload) -> Result { - Ok(SendMessageArtifacts { nonce: 0 }) + Ok(SendMessageArtifacts { nonce: 0, enqueued_messages: 0 }) } } diff --git a/primitives/messages/src/target_chain.rs b/primitives/messages/src/target_chain.rs index 0fc70ad00cf..51484e1e32e 100644 --- a/primitives/messages/src/target_chain.rs +++ b/primitives/messages/src/target_chain.rs @@ -94,6 +94,12 @@ pub trait MessageDispatch { /// Fine-grained result of single message dispatch (for better diagnostic purposes) type DispatchLevelResult: Clone + sp_std::fmt::Debug + Eq; + /// Returns `true` if dispatcher for given lane is ready to accept additional messages. The + /// `false` should be treated as a hint by both dispatcher and its consumers - i.e. dispatcher + /// shall not simply drop messages if it returns `false`. The consumer may still call the + /// `dispatch` if dispatcher has returned `false`. + fn is_active(lane: LaneId) -> bool; + /// Estimate dispatch weight. /// /// This function must return correct upper bound of dispatch weight. The return value @@ -168,6 +174,10 @@ impl MessageDispatch for ForbidInboundMessages bool { + false + } + fn dispatch_weight(_message: &mut DispatchMessage) -> Weight { Weight::MAX } diff --git a/primitives/xcm-bridge-hub-router/Cargo.toml b/primitives/xcm-bridge-hub-router/Cargo.toml deleted file mode 100644 index 95b232fffdb..00000000000 --- a/primitives/xcm-bridge-hub-router/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "bp-xcm-bridge-hub-router" -description = "Primitives of the xcm-bridge-hub fee pallet." -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[features] -default = ["std"] -std = [] diff --git a/primitives/xcm-bridge-hub-router/src/lib.rs b/primitives/xcm-bridge-hub-router/src/lib.rs deleted file mode 100644 index e3d627660a6..00000000000 --- a/primitives/xcm-bridge-hub-router/src/lib.rs +++ /dev/null @@ -1,31 +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 . - -//! Primitives of the `xcm-bridge-hub-router` pallet. - -#![cfg_attr(not(feature = "std"), no_std)] - -/// Local XCM channel that may report whether it is congested or not. -pub trait LocalXcmChannel { - /// Returns true if the queue is currently congested. - fn is_congested() -> bool; -} - -impl LocalXcmChannel for () { - fn is_congested() -> bool { - false - } -} diff --git a/primitives/xcm-bridge-hub/Cargo.toml b/primitives/xcm-bridge-hub/Cargo.toml index 5eda536f76e..25760dcf07e 100644 --- a/primitives/xcm-bridge-hub/Cargo.toml +++ b/primitives/xcm-bridge-hub/Cargo.toml @@ -9,6 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } +serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } # Bridge Dependencies @@ -32,6 +33,7 @@ std = [ "codec/std", "frame-support/std", "scale-info/std", + "serde/std", "sp-std/std", "xcm/std", ] diff --git a/primitives/xcm-bridge-hub/src/lib.rs b/primitives/xcm-bridge-hub/src/lib.rs index a9f3b88c9ba..e62d5a46e32 100644 --- a/primitives/xcm-bridge-hub/src/lib.rs +++ b/primitives/xcm-bridge-hub/src/lib.rs @@ -26,58 +26,112 @@ use frame_support::{ ensure, CloneNoBound, PalletError, PartialEqNoBound, RuntimeDebug, RuntimeDebugNoBound, }; use scale_info::TypeInfo; +use serde::{Deserialize, Serialize}; use sp_std::boxed::Box; -use xcm::{latest::prelude::*, VersionedMultiLocation}; +use xcm::{latest::prelude::*, VersionedInteriorMultiLocation, VersionedMultiLocation}; -/// A manager of XCM communication channels between the bridge hub and parent/sibling chains -/// that have opened bridges at this bridge hub. -/// -/// We use this interface to suspend and resume channels programmatically to implement backpressure -/// mechanism for bridge queues. -#[allow(clippy::result_unit_err)] // XCM uses `Result<(), ()>` everywhere -pub trait LocalXcmChannelManager { - // TODO: https://github.com/paritytech/parity-bridges-common/issues/2255 - // check following assumptions. They are important at least for following cases: - // 1) we now close the associated outbound lane when misbehavior is reported. If we'll keep - // handling inbound XCM messages after the `suspend_inbound_channel`, they will be dropped - // 2) the sender will be able to enqueue message to othe lanes if we won't stop handling inbound - // XCM immediately. He even may open additional bridges - - /// Stop handling new incoming XCM messages from given bridge `owner` (parent/sibling chain). - /// - /// We assume that the channel will be suspended immediately, but we don't mind if inbound - /// messages will keep piling up here for some time. Once this is communicated to the - /// `owner` chain (in any form), we expect it to stop sending messages to us and queue - /// messages at that `owner` chain instead. - /// - /// We expect that: +/// Encoded XCM blob. We expect the bridge messages pallet to use this blob type for both inbound +/// and outbound payloads. +pub type XcmAsPlainPayload = sp_std::vec::Vec; + +/// Bridge identifier. +#[derive( + Clone, + Copy, + Decode, + Default, + Encode, + Eq, + Ord, + PartialOrd, + PartialEq, + RuntimeDebug, + TypeInfo, + MaxEncodedLen, + Serialize, + Deserialize, +)] +pub struct BridgeId(LaneId); + +impl BridgeId { + /// Create bridge identifier from two universal locations. /// - /// - no more incoming XCM messages from the `owner` will be processed until further - /// `resume_inbound_channel` call; + /// The fact that we are using versioned locations here means that XCM version upgrades must + /// be coordinated at all involved chains (at source and target chains + at bridge hubs). + /// Otherwise messages may simply be dropped anywhere on its path to the target chain. + pub fn new( + universal_location1: &VersionedInteriorMultiLocation, + universal_location2: &VersionedInteriorMultiLocation, + ) -> Self { + // a tricky helper struct that adds required `Ord` support for + // `VersionedInteriorMultiLocation` + #[derive(Eq, PartialEq, Ord, PartialOrd)] + struct EncodedVersionedInteriorMultiLocation(sp_std::vec::Vec); + + impl Encode for EncodedVersionedInteriorMultiLocation { + fn encode(&self) -> sp_std::vec::Vec { + self.0.clone() + } + } + + Self(LaneId::new( + EncodedVersionedInteriorMultiLocation(universal_location1.encode()), + EncodedVersionedInteriorMultiLocation(universal_location2.encode()), + )) + } + + /// Creates bridge id using lane id. /// - /// - soon after the call, the channel will switch to the state when incoming messages are - /// piling up at the sending chain, not at the bridge hub. + /// **ATTENTION**: this function may be removed in the future. + pub fn from_lane_id(lane_id: LaneId) -> Self { + // in the future we may want to keep using the same lane identifiers if we'll be upgrading + // the XCM version (and `VersionedInteriorMultiLocation` will change) + Self(lane_id) + } + + /// Return lane id, used by this bridge. + pub fn lane_id(&self) -> LaneId { + self.0 + } +} + +/// Local XCM channel manager. +pub trait LocalXcmChannelManager { + /// Error that may be returned when suspending/resuming the bridge. + type Error: sp_std::fmt::Debug; + + /// Returns true if the channel with given location is currently congested. /// - /// This method shall not fail if the channel is already suspended. - fn suspend_inbound_channel(owner: MultiLocation) -> Result<(), ()>; + /// The `with` is guaranteed to be in the same consensus. However, it may point to something + /// below the chain level - like the constract or pallet instance, for example. + fn is_congested(with: &MultiLocation) -> bool; - /// Start handling incoming messages from from given bridge `owner` (parent/sibling chain) - /// again. + /// Suspend the bridge, opened by given origin. /// - /// The channel is assumed to be suspended by the previous `suspend_inbound_channel` call, - /// however we don't check it anywhere. + /// The `local_origin` is guaranteed to be in the same consensus. However, it may point to + /// something below the chain level - like the constract or pallet instance, for example. + fn suspend_bridge(local_origin: &MultiLocation, bridge: BridgeId) -> Result<(), Self::Error>; + + /// Resume the previously suspended bridge, opened by given origin. /// - /// This method shall not fail if the channel is already resumed. - fn resume_inbound_channel(owner: MultiLocation) -> Result<(), ()>; + /// The `local_origin` is guaranteed to be in the same consensus. However, it may point to + /// something below the chain level - like the constract or pallet instance, for example. + fn resume_bridge(local_origin: &MultiLocation, bridge: BridgeId) -> Result<(), Self::Error>; } impl LocalXcmChannelManager for () { - fn suspend_inbound_channel(_owner: MultiLocation) -> Result<(), ()> { + type Error = (); + + fn is_congested(_with: &MultiLocation) -> bool { + false + } + + fn suspend_bridge(_local_origin: &MultiLocation, _bridge: BridgeId) -> Result<(), Self::Error> { Ok(()) } - fn resume_inbound_channel(_owner: MultiLocation) -> Result<(), ()> { - Err(()) + fn resume_bridge(_local_origin: &MultiLocation, _bridge: BridgeId) -> Result<(), Self::Error> { + Ok(()) } } @@ -117,7 +171,7 @@ pub struct BridgeLocations { /// Universal (unique) location of other side of the bridge. pub bridge_destination_universal_location: InteriorMultiLocation, /// An identifier of the dedicated bridge message lane. - pub lane_id: LaneId, + pub bridge_id: BridgeId, } /// Errors that may happen when we check bridge locations. @@ -212,14 +266,16 @@ pub fn bridge_locations( // `GlobalConsensus` and we know that the `bridge_origin_universal_location` // is also within the `GlobalConsensus`. So we know that the lane id will be // the same on both ends of the bridge - let lane_id = - LaneId::new(bridge_origin_universal_location, bridge_destination_universal_location); + let bridge_id = BridgeId::new( + &bridge_origin_universal_location.into(), + &bridge_destination_universal_location.into(), + ); Ok(Box::new(BridgeLocations { bridge_origin_relative_location: *bridge_origin_relative_location, bridge_origin_universal_location, bridge_destination_universal_location, - lane_id, + bridge_id, })) } @@ -255,9 +311,9 @@ mod tests { bridge_origin_relative_location: test.bridge_origin_relative_location, bridge_origin_universal_location: test.bridge_origin_universal_location, bridge_destination_universal_location: test.bridge_destination_universal_location, - lane_id: LaneId::new( - test.bridge_origin_universal_location, - test.bridge_destination_universal_location, + bridge_id: BridgeId::new( + &test.bridge_origin_universal_location.into(), + &test.bridge_destination_universal_location.into(), ), })), ); @@ -410,7 +466,7 @@ mod tests { bridge_destination_universal_location: X1(GlobalConsensus(REMOTE_NETWORK)), }); - assert_eq!(locations1.lane_id, locations2.lane_id); + assert_eq!(locations1.bridge_id, locations2.bridge_id); } #[test] @@ -430,7 +486,7 @@ mod tests { bridge_destination_universal_location: X1(GlobalConsensus(REMOTE_NETWORK)), }); - assert_eq!(locations1.lane_id, locations2.lane_id); + assert_eq!(locations1.bridge_id, locations2.bridge_id); } // negative tests diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index a7153daf5ba..8ee7f58b974 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -35,6 +35,7 @@ bridge-runtime-common = { path = "../../bin/runtime-common" } millau-runtime = { path = "../../bin/millau/runtime" } pallet-bridge-parachains = { path = "../../modules/parachains" } pallet-bridge-messages = { path = "../../modules/messages" } +pallet-xcm-bridge-hub = { path = "../../modules/xcm-bridge-hub" } parachains-relay = { path = "../parachains" } relay-millau-client = { path = "../client-millau" } relay-rialto-client = { path = "../client-rialto" } diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index 4cee26255d3..3d4a72f6609 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -47,7 +47,7 @@ impl CliEncodeMessage for Millau { .map_err(|e| anyhow::format_err!("Failed to prepare outbound message: {:?}", e))? .0 .1 - .0) + .1) } fn encode_execute_xcm( diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs index 30bc7eb13ca..31c3912cc0c 100644 --- a/relays/bin-substrate/src/chains/rialto.rs +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -33,7 +33,10 @@ impl CliEncodeMessage for Rialto { anyhow::format_err!("Unsupported target chain: {:?}", target) ); - Ok(rialto_runtime::millau_messages::ToMillauBlobExporter::validate( + Ok(pallet_xcm_bridge_hub::Pallet::< + rialto_runtime::Runtime, + rialto_runtime::WithMillauXcmBridgeHubInstance, + >::validate( target, 0, &mut Some(Self::dummy_universal_source()?), @@ -42,7 +45,7 @@ impl CliEncodeMessage for Rialto { ) .map_err(|e| anyhow::format_err!("Failed to prepare outbound message: {:?}", e))? .0 - .0) + .1) } fn encode_execute_xcm( diff --git a/relays/bin-substrate/src/chains/rialto_parachain.rs b/relays/bin-substrate/src/chains/rialto_parachain.rs index 872d96981d0..de6c78cc229 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -33,7 +33,10 @@ impl CliEncodeMessage for RialtoParachain { anyhow::format_err!("Unsupported target chain: {:?}", target) ); - Ok(rialto_parachain_runtime::millau_messages::ToMillauBlobExporter::validate( + Ok(pallet_xcm_bridge_hub::Pallet::< + rialto_parachain_runtime::Runtime, + rialto_parachain_runtime::WithMillauXcmBridgeHubInstance, + >::validate( target, 0, &mut Some(Self::dummy_universal_source()?), @@ -42,7 +45,7 @@ impl CliEncodeMessage for RialtoParachain { ) .map_err(|e| anyhow::format_err!("Failed to prepare outbound message: {:?}", e))? .0 - .0) + .1) } fn encode_execute_xcm(