From 4af6519d678841fbb822e6791df90357b0d07d09 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Mon, 4 Sep 2023 12:48:07 +0200 Subject: [PATCH] Extended Kusama/Polkadot BridgeHub with dynamic fees and congestion support Add congestion detection to the Bridge Hub runtimes and report congestion status to the sending chain. Bridge Hub's `ExportMessage` handling is extended with check if outbound message queue is congested, if so then `CongestedMessage` signal is sent to the sending chain's relevant `pallet-xcm-bridge-hub-router` pallet instance, where dynamic fees factor is processed. When then same Bridge Hub receives message delivery confirmation, there is a another check is outbound queue is still congested, if not then `UncongestedMessage` signal is sent to the sending chain's relevant `pallet-xcm-bridge-hub-router` pallet instance. `pallet-bridge-messages`'s `receive_messages_proof` does another check for congestion or back-preassure with checking status of underlaying XCMP queue (`cumulus_pallet_xcmp_queue::bridging::OutboundXcmpChannelCongestionStatusProvider`). If we cannot deliver a message to the target, then `receive_messages_proof` returns error and Bridge Hub does not allow to receive new bridged messages. More about congestion detection [here](https://github.com/paritytech/parity-bridges-common/pull/2318). Signed-off-by: Branislav Kontur Signed-off-by: Adrian Catangiu Signed-off-by: Svyatoslav Nikolsky Signed-off-by: Serban Iorga Co-authored-by: Adrian Catangiu Co-authored-by: Svyatoslav Nikolsky Co-authored-by: Serban Iorga --- Cargo.lock | 3 + cumulus/pallets/xcmp-queue/Cargo.toml | 2 +- .../bridge-hubs/bridge-hub-kusama/Cargo.toml | 4 +- .../src/bridge_hub_config.rs | 30 +++- .../bridge-hubs/bridge-hub-kusama/src/lib.rs | 20 ++- .../bridge-hub-kusama/src/xcm_config.rs | 11 +- .../bridge-hub-kusama/tests/tests.rs | 25 ++- .../bridge-hub-polkadot/Cargo.toml | 4 +- .../src/bridge_hub_config.rs | 30 +++- .../bridge-hub-polkadot/src/lib.rs | 20 ++- .../bridge-hub-polkadot/src/xcm_config.rs | 18 +-- .../bridge-hub-polkadot/tests/tests.rs | 25 ++- .../bridge-hub-rococo/tests/tests.rs | 8 +- .../bridge-hubs/test-utils/Cargo.toml | 1 + .../bridge-hubs/test-utils/src/test_cases.rs | 151 +++++++++++++++++- 15 files changed, 299 insertions(+), 53 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 611c53cf67a4..54e866c2a7a4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1822,6 +1822,7 @@ dependencies = [ name = "bridge-hub-kusama-runtime" version = "0.1.0" dependencies = [ + "bp-asset-hub-kusama", "bp-bridge-hub-kusama", "bp-bridge-hub-polkadot", "bp-header-chain", @@ -1902,6 +1903,7 @@ dependencies = [ name = "bridge-hub-polkadot-runtime" version = "0.1.0" dependencies = [ + "bp-asset-hub-polkadot", "bp-bridge-hub-kusama", "bp-bridge-hub-polkadot", "bp-header-chain", @@ -2120,6 +2122,7 @@ dependencies = [ "sp-io", "sp-keyring", "sp-runtime", + "sp-tracing", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", diff --git a/cumulus/pallets/xcmp-queue/Cargo.toml b/cumulus/pallets/xcmp-queue/Cargo.toml index 0e6a34ecfe69..2a8b9e48a2aa 100644 --- a/cumulus/pallets/xcmp-queue/Cargo.toml +++ b/cumulus/pallets/xcmp-queue/Cargo.toml @@ -46,7 +46,7 @@ cumulus-pallet-parachain-system = { path = "../parachain-system" } [features] default = [ "std" ] std = [ - "bp-xcm-bridge-hub-router/std", + "bp-xcm-bridge-hub-router?/std", "codec/std", "cumulus-primitives-core/std", "frame-benchmarking?/std", diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/Cargo.toml index 61a5ec19a71f..55621a1d7c56 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/Cargo.toml @@ -64,7 +64,7 @@ cumulus-pallet-dmp-queue = { path = "../../../../pallets/dmp-queue", default-fea cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook",] } cumulus-pallet-session-benchmarking = { path = "../../../../pallets/session-benchmarking", default-features = false} cumulus-pallet-xcm = { path = "../../../../pallets/xcm", default-features = false } -cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false } +cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false, features = ["bridging"] } cumulus-primitives-core = { path = "../../../../primitives/core", default-features = false } cumulus-primitives-utility = { path = "../../../../primitives/utility", default-features = false } pallet-collator-selection = { path = "../../../../pallets/collator-selection", default-features = false } @@ -72,6 +72,7 @@ parachain-info = { path = "../../../pallets/parachain-info", default-features = parachains-common = { path = "../../../common", default-features = false } # Bridges +bp-asset-hub-kusama = { path = "../../../../bridges/primitives/chain-asset-hub-kusama", default-features = false } bp-bridge-hub-kusama = { path = "../../../../bridges/primitives/chain-bridge-hub-kusama", default-features = false } bp-bridge-hub-polkadot = { path = "../../../../bridges/primitives/chain-bridge-hub-polkadot", default-features = false } bp-header-chain = { path = "../../../../bridges/primitives/header-chain", default-features = false } @@ -97,6 +98,7 @@ sp-keyring = { path = "../../../../../substrate/primitives/keyring" } [features] default = [ "std" ] std = [ + "bp-asset-hub-kusama/std", "bp-bridge-hub-kusama/std", "bp-bridge-hub-polkadot/std", "bp-header-chain/std", diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/bridge_hub_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/bridge_hub_config.rs index 51fbd6e3bac9..7d973c2cebad 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/bridge_hub_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/bridge_hub_config.rs @@ -33,6 +33,7 @@ use bridge_runtime_common::{ RefundableParachain, }, }; +use codec::Encode; use frame_support::{parameter_types, traits::PalletInfoAccess}; use sp_runtime::RuntimeDebug; use xcm::{latest::prelude::*, prelude::NetworkId}; @@ -55,6 +56,28 @@ parameter_types! { ParentThen(X1(Parachain(AssetHubKusamaParaId::get().into()))).into(), ASSET_HUB_KUSAMA_TO_ASSET_HUB_POLKADOT_LANE_ID, ); + + pub CongestedMessage: Xcm<()> = sp_std::vec![Transact { + origin_kind: OriginKind::Xcm, + require_weight_at_most: bp_asset_hub_kusama::XcmBridgeHubRouterTransactCallMaxWeight::get(), + call: bp_asset_hub_kusama::Call::ToPolkadotXcmRouter( + bp_asset_hub_kusama::XcmBridgeHubRouterCall::report_bridge_status { + bridge_id: Default::default(), + is_congested: true, + } + ).encode().into(), + }].into(); + + pub UncongestedMessage: Xcm<()> = sp_std::vec![Transact { + origin_kind: OriginKind::Xcm, + require_weight_at_most: bp_asset_hub_kusama::XcmBridgeHubRouterTransactCallMaxWeight::get(), + call: bp_asset_hub_kusama::Call::ToPolkadotXcmRouter( + bp_asset_hub_kusama::XcmBridgeHubRouterCall::report_bridge_status { + bridge_id: Default::default(), + is_congested: false, + } + ).encode().into(), + }].into(); } /// Proof of messages, coming from BridgeHubPolkadot. @@ -81,10 +104,13 @@ impl XcmBlobHauler for ToBridgeHubPolkadotXcmBlobHauler { type SenderAndLane = FromAssetHubKusamaToAssetHubPolkadotRoute; type ToSourceChainSender = crate::XcmRouter; - type CongestedMessage = (); - type UncongestedMessage = (); + type CongestedMessage = CongestedMessage; + type UncongestedMessage = UncongestedMessage; } +/// On messages delivered callback. +pub type OnMessagesDelivered = XcmBlobHaulerAdapter; + /// Messaging Bridge configuration for ThisChain -> BridgeHubPolkadot pub struct WithBridgeHubPolkadotMessageBridge; impl MessageBridge for WithBridgeHubPolkadotMessageBridge { diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/lib.rs index c0c3edb37cf1..b58cb8998fb7 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/lib.rs @@ -493,9 +493,15 @@ impl pallet_bridge_messages::Config for R DeliveryRewardInBalance, >; type SourceHeaderChain = SourceHeaderChainAdapter; - type MessageDispatch = - XcmBlobMessageDispatch, Self::WeightInfo, ()>; - type OnMessagesDelivered = (); + type MessageDispatch = XcmBlobMessageDispatch< + OnThisChainBlobDispatcher, + Self::WeightInfo, + cumulus_pallet_xcmp_queue::bridging::OutboundXcmpChannelCongestionStatusProvider< + bridge_hub_config::AssetHubKusamaParaId, + Runtime, + >, + >; + type OnMessagesDelivered = bridge_hub_config::OnMessagesDelivered; } /// Allows collect and claim rewards for relayers @@ -942,7 +948,11 @@ impl_runtime_apis! { type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::; type XcmGeneric = pallet_xcm_benchmarks::generic::Pallet::; - use bridge_runtime_common::messages_benchmarking::{prepare_message_delivery_proof_from_parachain, prepare_message_proof_from_parachain}; + use bridge_runtime_common::messages_benchmarking::{ + generate_xcm_builder_bridge_message_sample, + prepare_message_delivery_proof_from_parachain, + prepare_message_proof_from_parachain + }; use pallet_bridge_messages::benchmarking::{ Config as BridgeMessagesConfig, Pallet as BridgeMessagesBench, @@ -972,7 +982,7 @@ impl_runtime_apis! { Runtime, BridgeGrandpaPolkadotInstance, bridge_hub_config::WithBridgeHubPolkadotMessageBridge, - >(params, X2(GlobalConsensus(xcm_config::RelayNetwork::get().unwrap()), Parachain(42))) + >(params, generate_xcm_builder_bridge_message_sample(X2(GlobalConsensus(xcm_config::RelayNetwork::get().unwrap()), Parachain(42)))) } fn prepare_message_delivery_proof( params: MessageDeliveryProofParams, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/xcm_config.rs index 028dd5329ca1..7b8e3fa5aada 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/xcm_config.rs @@ -112,12 +112,6 @@ match_types! { MultiLocation { parents: 1, interior: Here } | MultiLocation { parents: 1, interior: X1(_) } }; - // TODO:check-parameter - (https://github.com/paritytech/parity-bridges-common/issues/2084) - // remove this and extend `AllowExplicitUnpaidExecutionFrom` with "or SystemParachains" once merged https://github.com/paritytech/polkadot/pull/7005 - pub type SystemParachains: impl Contains = { - // Statemine - MultiLocation { parents: 1, interior: X1(Parachain(1000)) } - }; } /// A call filter for the XCM Transact instruction. This is a temporary measure until we properly @@ -191,9 +185,8 @@ pub type Barrier = TrailingSetTopicAsId< // If the message is one that immediately attemps to pay for execution, then // allow it. AllowTopLevelPaidExecutionFrom, - // Parent, its pluralities (i.e. governance bodies) and system parachains get - // free execution. - AllowExplicitUnpaidExecutionFrom<(ParentOrParentsPlurality, SystemParachains)>, + // Parent and its pluralities (i.e. governance bodies) get free execution. + AllowExplicitUnpaidExecutionFrom<(ParentOrParentsPlurality,)>, // Subscriptions for version tracking are OK. AllowSubscriptionsFrom, ), diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/tests/tests.rs index e4d92f180bcc..a16a57a8c758 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/tests/tests.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/tests/tests.rs @@ -17,7 +17,7 @@ use bp_polkadot_core::Signature; pub use bridge_hub_kusama_runtime::{ bridge_hub_config, - xcm_config::{RelayNetwork, XcmConfig}, + xcm_config::{KsmRelayLocation, RelayNetwork, XcmConfig}, AllPalletsWithoutSystem, Balances, BridgeGrandpaPolkadotInstance, BridgeRejectObsoleteHeadersAndMessages, ExistentialDeposit, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, SessionKeys, WithBridgeHubPolkadotMessagesInstance, @@ -183,7 +183,10 @@ fn handle_export_message_from_system_parachain_add_to_outbound_queue_works() { } }), || ExportMessage { network: Polkadot, destination: X1(Parachain(1234)), xcm: Xcm(vec![]) }, - bridge_hub_config::ASSET_HUB_KUSAMA_TO_ASSET_HUB_POLKADOT_LANE_ID + bridge_hub_config::ASSET_HUB_KUSAMA_TO_ASSET_HUB_POLKADOT_LANE_ID, + Some((KsmRelayLocation::get(), ExistentialDeposit::get()).into()), + // value should be >= than value generated by `can_calculate_weight_for_paid_export_message_with_reserve_transfer` + Some((KsmRelayLocation::get(), bp_asset_hub_kusama::BridgeHubKusamaBaseFeeInDots::get()).into()), ) } @@ -262,3 +265,21 @@ pub fn complex_relay_extrinsic_works() { construct_and_apply_extrinsic, ); } + +#[test] +pub fn can_calculate_weight_for_paid_export_message_with_reserve_transfer() { + let estimated = bridge_hub_test_utils::test_cases::can_calculate_weight_for_paid_export_message_with_reserve_transfer::< + Runtime, + XcmConfig, + WeightToFee, + >(); + + // check if estimated value is sane + let max_expected = bp_asset_hub_kusama::BridgeHubKusamaBaseFeeInDots::get(); + assert!( + estimated <= max_expected, + "calculated: {:?}, max_expected: {:?}, please adjust `bp_asset_hub_kusama::BridgeHubKusamaBaseFeeInDots` value", + estimated, + max_expected + ); +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/Cargo.toml index 19c678bc57eb..8b32b99f479f 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/Cargo.toml @@ -64,7 +64,7 @@ cumulus-pallet-dmp-queue = { path = "../../../../pallets/dmp-queue", default-fea cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook",] } cumulus-pallet-session-benchmarking = { path = "../../../../pallets/session-benchmarking", default-features = false} cumulus-pallet-xcm = { path = "../../../../pallets/xcm", default-features = false } -cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false } +cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false, features = ["bridging"] } cumulus-primitives-core = { path = "../../../../primitives/core", default-features = false } cumulus-primitives-utility = { path = "../../../../primitives/utility", default-features = false } pallet-collator-selection = { path = "../../../../pallets/collator-selection", default-features = false } @@ -72,6 +72,7 @@ parachain-info = { path = "../../../pallets/parachain-info", default-features = parachains-common = { path = "../../../common", default-features = false } # Bridges +bp-asset-hub-polkadot = { path = "../../../../bridges/primitives/chain-asset-hub-polkadot", default-features = false } bp-bridge-hub-kusama = { path = "../../../../bridges/primitives/chain-bridge-hub-kusama", default-features = false } bp-bridge-hub-polkadot = { path = "../../../../bridges/primitives/chain-bridge-hub-polkadot", default-features = false } bp-header-chain = { path = "../../../../bridges/primitives/header-chain", default-features = false } @@ -97,6 +98,7 @@ sp-keyring = { path = "../../../../../substrate/primitives/keyring" } [features] default = [ "std" ] std = [ + "bp-asset-hub-polkadot/std", "bp-bridge-hub-kusama/std", "bp-bridge-hub-polkadot/std", "bp-header-chain/std", diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/bridge_hub_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/bridge_hub_config.rs index 8414e532f5b7..26a4a2c2175e 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/bridge_hub_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/bridge_hub_config.rs @@ -33,6 +33,7 @@ use bridge_runtime_common::{ RefundableParachain, }, }; +use codec::Encode; use frame_support::{parameter_types, traits::PalletInfoAccess}; use sp_runtime::RuntimeDebug; use xcm::{latest::prelude::*, prelude::NetworkId}; @@ -55,6 +56,28 @@ parameter_types! { ParentThen(X1(Parachain(AssetHubPolkadotParaId::get().into()))).into(), ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA_LANE_ID, ); + + pub CongestedMessage: Xcm<()> = sp_std::vec![Transact { + origin_kind: OriginKind::Xcm, + require_weight_at_most: bp_asset_hub_polkadot::XcmBridgeHubRouterTransactCallMaxWeight::get(), + call: bp_asset_hub_polkadot::Call::ToKusamaXcmRouter( + bp_asset_hub_polkadot::XcmBridgeHubRouterCall::report_bridge_status { + bridge_id: Default::default(), + is_congested: true, + } + ).encode().into(), + }].into(); + + pub UncongestedMessage: Xcm<()> = sp_std::vec![Transact { + origin_kind: OriginKind::Xcm, + require_weight_at_most: bp_asset_hub_polkadot::XcmBridgeHubRouterTransactCallMaxWeight::get(), + call: bp_asset_hub_polkadot::Call::ToKusamaXcmRouter( + bp_asset_hub_polkadot::XcmBridgeHubRouterCall::report_bridge_status { + bridge_id: Default::default(), + is_congested: false, + } + ).encode().into(), + }].into(); } /// Proof of messages, coming from BridgeHubKusama. @@ -81,10 +104,13 @@ impl XcmBlobHauler for ToBridgeHubKusamaXcmBlobHauler { type SenderAndLane = FromAssetHubPolkadotToAssetHubKusamaRoute; type ToSourceChainSender = crate::XcmRouter; - type CongestedMessage = (); - type UncongestedMessage = (); + type CongestedMessage = CongestedMessage; + type UncongestedMessage = UncongestedMessage; } +/// On messages delivered callback. +pub type OnMessagesDelivered = XcmBlobHaulerAdapter; + /// Messaging Bridge configuration for ThisChain -> BridgeHubKusama pub struct WithBridgeHubKusamaMessageBridge; impl MessageBridge for WithBridgeHubKusamaMessageBridge { diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/lib.rs index 83938606ac36..968a89fc2cfe 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/lib.rs @@ -494,9 +494,15 @@ impl pallet_bridge_messages::Config for Run DeliveryRewardInBalance, >; type SourceHeaderChain = SourceHeaderChainAdapter; - type MessageDispatch = - XcmBlobMessageDispatch, Self::WeightInfo, ()>; - type OnMessagesDelivered = (); + type MessageDispatch = XcmBlobMessageDispatch< + OnThisChainBlobDispatcher, + Self::WeightInfo, + cumulus_pallet_xcmp_queue::bridging::OutboundXcmpChannelCongestionStatusProvider< + bridge_hub_config::AssetHubPolkadotParaId, + Runtime, + >, + >; + type OnMessagesDelivered = bridge_hub_config::OnMessagesDelivered; } /// Allows collect and claim rewards for relayers @@ -943,7 +949,11 @@ impl_runtime_apis! { type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::; type XcmGeneric = pallet_xcm_benchmarks::generic::Pallet::; - use bridge_runtime_common::messages_benchmarking::{prepare_message_delivery_proof_from_parachain, prepare_message_proof_from_parachain}; + use bridge_runtime_common::messages_benchmarking::{ + generate_xcm_builder_bridge_message_sample, + prepare_message_delivery_proof_from_parachain, + prepare_message_proof_from_parachain + }; use pallet_bridge_messages::benchmarking::{ Config as BridgeMessagesConfig, Pallet as BridgeMessagesBench, @@ -973,7 +983,7 @@ impl_runtime_apis! { Runtime, BridgeGrandpaKusamaInstance, bridge_hub_config::WithBridgeHubKusamaMessageBridge, - >(params, X2(GlobalConsensus(xcm_config::RelayNetwork::get().unwrap()), Parachain(42))) + >(params, generate_xcm_builder_bridge_message_sample(X2(GlobalConsensus(xcm_config::RelayNetwork::get().unwrap()), Parachain(42)))) } fn prepare_message_delivery_proof( params: MessageDeliveryProofParams, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/xcm_config.rs index 1880c649f57f..ab6643995efa 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/xcm_config.rs @@ -115,14 +115,6 @@ match_types! { pub type FellowsPlurality: impl Contains = { MultiLocation { parents: 1, interior: X2(Parachain(1001), Plurality { id: BodyId::Technical, ..}) } }; - // TODO:check-parameter - (https://github.com/paritytech/parity-bridges-common/issues/2084) - // remove this and extend `AllowExplicitUnpaidExecutionFrom` with "or SystemParachains" once merged https://github.com/paritytech/polkadot/pull/7005 - pub type SystemParachains: impl Contains = { - // Statemint - MultiLocation { parents: 1, interior: X1(Parachain(1000)) } | - // Collectives - MultiLocation { parents: 1, interior: X1(Parachain(1001)) } - }; } /// A call filter for the XCM Transact instruction. This is a temporary measure until we properly @@ -196,13 +188,9 @@ pub type Barrier = TrailingSetTopicAsId< // If the message is one that immediately attemps to pay for execution, then // allow it. AllowTopLevelPaidExecutionFrom, - // Parent, its pluralities (i.e. governance bodies), the Fellows plurality - // and system parachains get free execution. - AllowExplicitUnpaidExecutionFrom<( - ParentOrParentsPlurality, - FellowsPlurality, - SystemParachains, - )>, + // Parent, its pluralities (i.e. governance bodies) and the Fellows plurality + // get free execution. + AllowExplicitUnpaidExecutionFrom<(ParentOrParentsPlurality, FellowsPlurality)>, // Subscriptions for version tracking are OK. AllowSubscriptionsFrom, ), diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/tests/tests.rs index d300e52c4b8f..1cc160c0925f 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/tests/tests.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/tests/tests.rs @@ -18,7 +18,7 @@ use bp_polkadot_core::Signature; pub use bridge_hub_polkadot_runtime::{ bridge_hub_config, constants::fee::WeightToFee, - xcm_config::{RelayNetwork, XcmConfig}, + xcm_config::{DotRelayLocation, RelayNetwork, XcmConfig}, AllPalletsWithoutSystem, Balances, BridgeGrandpaKusamaInstance, BridgeRejectObsoleteHeadersAndMessages, ExistentialDeposit, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, SessionKeys, WithBridgeHubKusamaMessagesInstance, @@ -184,7 +184,10 @@ fn handle_export_message_from_system_parachain_add_to_outbound_queue_works() { } }), || ExportMessage { network: Kusama, destination: X1(Parachain(1234)), xcm: Xcm(vec![]) }, - bridge_hub_config::ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA_LANE_ID + bridge_hub_config::ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA_LANE_ID, + Some((DotRelayLocation::get(), ExistentialDeposit::get()).into()), + // value should be >= than value generated by `can_calculate_weight_for_paid_export_message_with_reserve_transfer` + Some((DotRelayLocation::get(), bp_asset_hub_polkadot::BridgeHubPolkadotBaseFeeInDots::get()).into()), ) } @@ -263,3 +266,21 @@ pub fn complex_relay_extrinsic_works() { construct_and_apply_extrinsic, ); } + +#[test] +pub fn can_calculate_weight_for_paid_export_message_with_reserve_transfer() { + let estimated = bridge_hub_test_utils::test_cases::can_calculate_weight_for_paid_export_message_with_reserve_transfer::< + Runtime, + XcmConfig, + WeightToFee, + >(); + + // check if estimated value is sane + let max_expected = bp_asset_hub_polkadot::BridgeHubPolkadotBaseFeeInDots::get(); + assert!( + estimated <= max_expected, + "calculated: {:?}, max_expected: {:?}, please adjust `bp_asset_hub_polkadot::BridgeHubPolkadotBaseFeeInDots` value", + estimated, + max_expected + ); +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs index 76ee77496649..f128d9fc48db 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs @@ -191,7 +191,9 @@ mod bridge_hub_rococo_tests { } }), || ExportMessage { network: Wococo, destination: X1(Parachain(1234)), xcm: Xcm(vec![]) }, - bridge_hub_rococo_config::DEFAULT_XCM_LANE_TO_BRIDGE_HUB_WOCOCO + bridge_hub_rococo_config::DEFAULT_XCM_LANE_TO_BRIDGE_HUB_WOCOCO, + None, + None, ) } @@ -370,7 +372,9 @@ mod bridge_hub_wococo_tests { } }), || ExportMessage { network: Rococo, destination: X1(Parachain(4321)), xcm: Xcm(vec![]) }, - bridge_hub_wococo_config::DEFAULT_XCM_LANE_TO_BRIDGE_HUB_ROCOCO + bridge_hub_wococo_config::DEFAULT_XCM_LANE_TO_BRIDGE_HUB_ROCOCO, + None, + None, ) } diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml index a6509c58ee21..88cd6e54dd53 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml @@ -19,6 +19,7 @@ sp-core = { path = "../../../../../substrate/primitives/core", default-features sp-io = { path = "../../../../../substrate/primitives/io", default-features = false} sp-keyring = { path = "../../../../../substrate/primitives/keyring" } sp-runtime = { path = "../../../../../substrate/primitives/runtime", default-features = false} +sp-tracing = { path = "../../../../../substrate/primitives/tracing" } pallet-balances = { path = "../../../../../substrate/frame/balances", default-features = false} pallet-utility = { path = "../../../../../substrate/frame/utility", default-features = false} pallet-session = { path = "../../../../../substrate/frame/session", default-features = false} diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases.rs index 3ecccc3988f5..125a4bd460ed 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases.rs @@ -46,10 +46,16 @@ use parachains_runtimes_test_utils::{ }; use sp_core::H256; use sp_keyring::AccountKeyring::*; -use sp_runtime::{traits::Header as HeaderT, AccountId32}; +use sp_runtime::{ + traits::{Header as HeaderT, Zero}, + AccountId32, +}; use xcm::latest::prelude::*; use xcm_builder::DispatchBlobError; -use xcm_executor::XcmExecutor; +use xcm_executor::{ + traits::{TransactAsset, WeightBounds}, + XcmExecutor, +}; // Re-export test_case from assets pub use asset_test_utils::include_teleports_for_native_asset_works; @@ -136,6 +142,8 @@ pub fn handle_export_message_from_system_parachain_to_outbound_queue_works< >, export_message_instruction: fn() -> Instruction, expected_lane_id: LaneId, + existential_deposit: Option, + maybe_paid_export_message: Option, ) where Runtime: frame_system::Config + pallet_balances::Config @@ -169,10 +177,35 @@ pub fn handle_export_message_from_system_parachain_to_outbound_queue_works< ); // prepare `ExportMessage` - let xcm = Xcm(vec![ - UnpaidExecution { weight_limit: Unlimited, check_origin: None }, - export_message_instruction(), - ]); + let xcm = if let Some(fee) = maybe_paid_export_message { + // deposit ED to origin (if needed) + if let Some(ed) = existential_deposit { + XcmConfig::AssetTransactor::deposit_asset( + &ed, + &sibling_parachain_location, + &XcmContext::with_message_id([0; 32]), + ) + .expect("deposited ed"); + } + // deposit fee to origin + XcmConfig::AssetTransactor::deposit_asset( + &fee, + &sibling_parachain_location, + &XcmContext::with_message_id([0; 32]), + ) + .expect("deposited fee"); + + Xcm(vec![ + WithdrawAsset(MultiAssets::from(vec![fee.clone()])), + BuyExecution { fees: fee, weight_limit: Unlimited }, + export_message_instruction(), + ]) + } else { + Xcm(vec![ + UnpaidExecution { weight_limit: Unlimited, check_origin: None }, + export_message_instruction(), + ]) + }; // execute XCM let hash = xcm.using_encoded(sp_io::hashing::blake2_256); @@ -799,6 +832,112 @@ pub fn complex_relay_extrinsic_works() -> u128 +where + Runtime: frame_system::Config + pallet_balances::Config, + XcmConfig: xcm_executor::Config, + WeightToFee: frame_support::weights::WeightToFee>, + ::Balance: From + Into, +{ + // data here are not relevant for weighing + let mut xcm = Xcm(vec![ + WithdrawAsset(MultiAssets::from(vec![MultiAsset { + id: Concrete(MultiLocation { parents: 1, interior: Here }), + fun: Fungible(34333299), + }])), + BuyExecution { + fees: MultiAsset { + id: Concrete(MultiLocation { parents: 1, interior: Here }), + fun: Fungible(34333299), + }, + weight_limit: Unlimited, + }, + ExportMessage { + network: Polkadot, + destination: X1(Parachain(1000)), + xcm: Xcm(vec![ + ReserveAssetDeposited(MultiAssets::from(vec![MultiAsset { + id: Concrete(MultiLocation { + parents: 2, + interior: X1(GlobalConsensus(Kusama)), + }), + fun: Fungible(1000000000000), + }])), + ClearOrigin, + BuyExecution { + fees: MultiAsset { + id: Concrete(MultiLocation { + parents: 2, + interior: X1(GlobalConsensus(Kusama)), + }), + fun: Fungible(1000000000000), + }, + weight_limit: Unlimited, + }, + DepositAsset { + assets: Wild(AllCounted(1)), + beneficiary: MultiLocation { + parents: 0, + interior: X1(xcm::latest::prelude::AccountId32 { + network: None, + id: [ + 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, + 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, + 109, 162, 125, + ], + }), + }, + }, + SetTopic([ + 116, 82, 194, 132, 171, 114, 217, 165, 23, 37, 161, 177, 165, 179, 247, 114, + 137, 101, 147, 70, 28, 157, 168, 32, 154, 63, 74, 228, 152, 180, 5, 63, + ]), + ]), + }, + RefundSurplus, + DepositAsset { + assets: Wild(All), + beneficiary: MultiLocation { parents: 1, interior: X1(Parachain(1000)) }, + }, + SetTopic([ + 36, 224, 250, 165, 82, 195, 67, 110, 160, 170, 140, 87, 217, 62, 201, 164, 42, 98, 219, + 157, 124, 105, 248, 25, 131, 218, 199, 36, 109, 173, 100, 122, + ]), + ]); + + // get weight + let weight = XcmConfig::Weigher::weight(&mut xcm); + assert_ok!(weight); + let weight = weight.unwrap(); + // check if sane + let max_expected = Runtime::BlockWeights::get().max_block / 10; + assert!( + weight.all_lte(max_expected), + "calculated weight: {:?}, max_expected: {:?}", + weight, + max_expected + ); + + // check fee, should not be 0 + let estimated_fee = WeightToFee::weight_to_fee(&weight); + assert!(estimated_fee > BalanceOf::::zero()); + + sp_tracing::try_init_simple(); + log::error!( + target: "bridges::estimate", + "Estimate fee: {:?} for `ExportMessage` for runtime: {:?}", + estimated_fee, + Runtime::Version::get(), + ); + + estimated_fee.into() +} + pub mod test_data { use super::*; use bp_header_chain::justification::GrandpaJustification;