diff --git a/Cargo.lock b/Cargo.lock index 68863d10665f6364f99ccd5843e8f559bb3da648..74b9a1a46264c1a4143e7abc88eb102a28a982d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2177,7 +2177,6 @@ dependencies = [ "pallet-bridge-messages", "pallet-message-queue", "pallet-xcm", - "pallet-xcm-bridge-hub", "parachains-common", "parity-scale-codec", "rococo-system-emulated-network", @@ -2310,8 +2309,6 @@ dependencies = [ "bp-relayers", "bp-runtime", "bp-test-utils", - "bp-xcm-bridge-hub", - "bridge-runtime-common", "cumulus-pallet-parachain-system", "cumulus-pallet-xcmp-queue", "frame-support", @@ -2334,6 +2331,7 @@ dependencies = [ "sp-io 39.0.0", "sp-keyring", "sp-runtime 40.1.0", + "sp-std 14.0.0", "sp-tracing 17.0.1", "staging-xcm", "staging-xcm-builder", @@ -2373,7 +2371,6 @@ dependencies = [ "pallet-bridge-messages", "pallet-message-queue", "pallet-xcm", - "pallet-xcm-bridge-hub", "parachains-common", "parity-scale-codec", "rococo-westend-system-emulated-network", diff --git a/bridges/modules/xcm-bridge-hub/src/lib.rs b/bridges/modules/xcm-bridge-hub/src/lib.rs index 682db811efa77367d1cb54a14641c4ad8cd93e4c..1633e99d7f303abe0e16c12a42d7e98be4fe23ff 100644 --- a/bridges/modules/xcm-bridge-hub/src/lib.rs +++ b/bridges/modules/xcm-bridge-hub/src/lib.rs @@ -145,8 +145,10 @@ use bp_messages::{LaneState, MessageNonce}; use bp_runtime::{AccountIdOf, BalanceOf, RangeInclusiveExt}; -pub use bp_xcm_bridge_hub::{Bridge, BridgeId, BridgeState, LocalXcmChannelManager}; -use bp_xcm_bridge_hub::{BridgeLocations, BridgeLocationsError}; +use bp_xcm_bridge_hub::BridgeLocationsError; +pub use bp_xcm_bridge_hub::{ + Bridge, BridgeId, BridgeLocations, BridgeState, LocalXcmChannelManager, +}; use frame_support::{traits::fungible::MutateHold, DefaultNoBound}; use frame_system::Config as SystemConfig; use pallet_bridge_messages::{Config as BridgeMessagesConfig, LanesManagerError}; diff --git a/cumulus/pallets/xcmp-queue/src/bridging.rs b/cumulus/pallets/xcmp-queue/src/bridging.rs index 8ed11505a27a991cf2f6e2ff2097bf886fca1ddb..355691a41659d4f60d6f4dd98e752ae209077798 100644 --- a/cumulus/pallets/xcmp-queue/src/bridging.rs +++ b/cumulus/pallets/xcmp-queue/src/bridging.rs @@ -45,12 +45,11 @@ impl<Runtime: crate::Config> bp_xcm_bridge_hub_router::XcmChannelStatusProvider } } -/// Adapter implementation for `bp_xcm_bridge_hub_router::XcmChannelStatusProvider` which checks -/// only `OutboundXcmpStatus` for defined `SiblingParaId` if is suspended. +/// Adapter implementation for `bp_xcm_bridge::ChannelStatusProvider` and/or +/// `bp_xcm_bridge_hub_router::XcmChannelStatusProvider` which checks only `OutboundXcmpStatus` +/// for defined `Location` if is suspended. pub struct OutXcmpChannelStatusProvider<Runtime>(core::marker::PhantomData<Runtime>); -impl<Runtime: crate::Config> bp_xcm_bridge_hub_router::XcmChannelStatusProvider - for OutXcmpChannelStatusProvider<Runtime> -{ +impl<Runtime: crate::Config> OutXcmpChannelStatusProvider<Runtime> { fn is_congested(with: &Location) -> bool { // handle congestion only for a sibling parachain locations. let sibling_para_id: ParaId = match with.unpack() { @@ -88,6 +87,14 @@ impl<Runtime: crate::Config> bp_xcm_bridge_hub_router::XcmChannelStatusProvider } } +impl<Runtime: crate::Config> bp_xcm_bridge_hub_router::XcmChannelStatusProvider + for OutXcmpChannelStatusProvider<Runtime> +{ + fn is_congested(with: &Location) -> bool { + Self::is_congested(with) + } +} + #[cfg(feature = "runtime-benchmarks")] pub fn suspend_channel_for_benchmarks<T: crate::Config>(target: ParaId) { pallet::Pallet::<T>::suspend_channel(target) diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml index 6cc68a7300ccceaa65916ec5b4c3c41b782952fa..82d6169e1965c7e6722fccd339edf85d6df235d1 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml @@ -27,7 +27,6 @@ pallet-xcm.workspace = true xcm-executor.workspace = true xcm-runtime-apis.workspace = true pallet-bridge-messages.workspace = true -pallet-xcm-bridge-hub.workspace = true cumulus-pallet-xcmp-queue.workspace = true emulated-integration-tests-common.workspace = true parachains-common.workspace = true diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml index 8fae0a885a2fce008cdac61bbd9afc71f90b0c8a..20503483d5fbec61172b0a1ce409ffc114bedda7 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml @@ -28,7 +28,6 @@ pallet-xcm.workspace = true xcm-executor.workspace = true xcm-runtime-apis.workspace = true pallet-bridge-messages.workspace = true -pallet-xcm-bridge-hub.workspace = true cumulus-pallet-xcmp-queue.workspace = true emulated-integration-tests-common.workspace = true parachains-common.workspace = true diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml index 00f1ad1bcddc4e8a7adda7e4eca3029b989b505e..71bc37ceb70f2e20c53e5d42d917f64e2610b6e0 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml @@ -20,6 +20,7 @@ sp-io.workspace = true sp-keyring.workspace = true sp-keyring.default-features = true sp-runtime.workspace = true +sp-std.workspace = true sp-tracing.workspace = true sp-tracing.default-features = true pallet-balances.workspace = true @@ -42,13 +43,11 @@ bp-polkadot-core.workspace = true bp-relayers.workspace = true bp-runtime.workspace = true bp-test-utils.workspace = true -bp-xcm-bridge-hub.workspace = true pallet-bridge-grandpa.workspace = true pallet-bridge-parachains.workspace = true pallet-bridge-messages = { features = ["test-helpers"], workspace = true } pallet-bridge-relayers.workspace = true pallet-xcm-bridge-hub.workspace = true -bridge-runtime-common.workspace = true [features] default = ["std"] @@ -61,8 +60,6 @@ std = [ "bp-relayers/std", "bp-runtime/std", "bp-test-utils/std", - "bp-xcm-bridge-hub/std", - "bridge-runtime-common/std", "codec/std", "cumulus-pallet-parachain-system/std", "cumulus-pallet-xcmp-queue/std", @@ -83,6 +80,7 @@ std = [ "sp-core/std", "sp-io/std", "sp-runtime/std", + "sp-std/std", "xcm-builder/std", "xcm-executor/std", "xcm/std", diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/lib.rs index bc28df0eb829cc02ba455b363ce6bea51d702950..240aac6c406350b0f1fbb59ddd3e9315af677099 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/lib.rs @@ -24,7 +24,7 @@ extern crate alloc; pub use bp_test_utils::test_header; pub use parachains_runtimes_test_utils::*; use sp_runtime::Perbill; -pub use test_cases::helpers::{ +pub use test_cases::helpers::for_pallet_xcm_bridge_hub::{ ensure_opened_bridge, open_bridge_with_extrinsic, open_bridge_with_storage, }; diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_grandpa_chain.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_grandpa_chain.rs index 320f3030b60a63e362bf88f467ac09afb78ff64b..4a03d624443935836580054f20ab187525c45959 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_grandpa_chain.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_grandpa_chain.rs @@ -20,13 +20,13 @@ use crate::{ test_cases::{bridges_prelude::*, helpers, run_test}, test_data, + test_data::XcmAsPlainPayload, }; use alloc::{boxed::Box, vec}; use bp_header_chain::ChainWithGrandpa; use bp_messages::UnrewardedRelayersState; use bp_relayers::{RewardsAccountOwner, RewardsAccountParams}; -use bp_xcm_bridge_hub::XcmAsPlainPayload; use frame_support::traits::{OnFinalize, OnInitialize}; use frame_system::pallet_prelude::BlockNumberFor; use pallet_bridge_messages::{BridgedChainOf, LaneIdOf, ThisChainOf}; diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_parachain.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_parachain.rs index 1da901e0bcdf9e8da142fba80ad07d053f3fabe2..7e9e10f9306fc34d073c05b09e16b5b4624adda1 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_parachain.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_parachain.rs @@ -20,6 +20,7 @@ use crate::{ test_cases::{bridges_prelude::*, helpers, run_test}, test_data, + test_data::XcmAsPlainPayload, }; use alloc::{boxed::Box, vec}; @@ -28,7 +29,6 @@ use bp_messages::UnrewardedRelayersState; use bp_polkadot_core::parachains::ParaHash; use bp_relayers::{RewardsAccountOwner, RewardsAccountParams}; use bp_runtime::{Chain, Parachain}; -use bp_xcm_bridge_hub::XcmAsPlainPayload; use frame_support::traits::{OnFinalize, OnInitialize}; use frame_system::pallet_prelude::BlockNumberFor; use pallet_bridge_messages::{BridgedChainOf, LaneIdOf, ThisChainOf}; diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/helpers.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/helpers.rs index 03ddc4313b451a82813831d7348d40f60eada2f7..d4931420925a7ce05cfb3993f7144478f18f7199 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/helpers.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/helpers.rs @@ -23,7 +23,6 @@ use bp_messages::MessageNonce; use bp_polkadot_core::parachains::{ParaHash, ParaId}; use bp_relayers::RewardsAccountParams; use bp_runtime::Chain; -use bp_xcm_bridge_hub::BridgeLocations; use codec::Decode; use core::marker::PhantomData; use frame_support::{ @@ -388,203 +387,210 @@ fn execute_and_verify_calls<Runtime: frame_system::Config>( } } -/// Helper function to open the bridge/lane for `source` and `destination` while ensuring all -/// required balances are placed into the SA of the source. -pub fn ensure_opened_bridge< - Runtime, - XcmOverBridgePalletInstance, - LocationToAccountId, - TokenLocation> -(source: Location, destination: InteriorLocation, is_paid_xcm_execution: bool, bridge_opener: impl Fn(BridgeLocations, Option<Asset>)) -> (BridgeLocations, pallet_xcm_bridge_hub::LaneIdOf<Runtime, XcmOverBridgePalletInstance>) -where - Runtime: BasicParachainRuntime + BridgeXcmOverBridgeConfig<XcmOverBridgePalletInstance>, - XcmOverBridgePalletInstance: 'static, - <Runtime as frame_system::Config>::RuntimeCall: GetDispatchInfo + From<BridgeXcmOverBridgeCall<Runtime, XcmOverBridgePalletInstance>>, - <Runtime as pallet_balances::Config>::Balance: From<<<Runtime as pallet_bridge_messages::Config<<Runtime as pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>>::BridgeMessagesPalletInstance>>::ThisChain as bp_runtime::Chain>::Balance>, - <Runtime as pallet_balances::Config>::Balance: From<u128>, - LocationToAccountId: ConvertLocation<AccountIdOf<Runtime>>, -TokenLocation: Get<Location>{ - // construct expected bridge configuration - let locations = - pallet_xcm_bridge_hub::Pallet::<Runtime, XcmOverBridgePalletInstance>::bridge_locations( - source.clone().into(), - destination.clone().into(), +pub(crate) mod for_pallet_xcm_bridge_hub { + use super::{super::for_pallet_xcm_bridge_hub::*, *}; + + /// Helper function to open the bridge/lane for `source` and `destination` while ensuring all + /// required balances are placed into the SA of the source. + pub fn ensure_opened_bridge< + Runtime, + XcmOverBridgePalletInstance, + LocationToAccountId, + TokenLocation> + (source: Location, destination: InteriorLocation, is_paid_xcm_execution: bool, bridge_opener: impl Fn(pallet_xcm_bridge_hub::BridgeLocations, Option<Asset>)) -> (pallet_xcm_bridge_hub::BridgeLocations, pallet_xcm_bridge_hub::LaneIdOf<Runtime, XcmOverBridgePalletInstance>) + where + Runtime: BasicParachainRuntime + BridgeXcmOverBridgeConfig<XcmOverBridgePalletInstance>, + XcmOverBridgePalletInstance: 'static, + <Runtime as frame_system::Config>::RuntimeCall: GetDispatchInfo + From<BridgeXcmOverBridgeCall<Runtime, XcmOverBridgePalletInstance>>, + <Runtime as pallet_balances::Config>::Balance: From<<<Runtime as pallet_bridge_messages::Config<<Runtime as pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>>::BridgeMessagesPalletInstance>>::ThisChain as bp_runtime::Chain>::Balance>, + <Runtime as pallet_balances::Config>::Balance: From<u128>, + LocationToAccountId: ConvertLocation<AccountIdOf<Runtime>>, + TokenLocation: Get<Location> + { + // construct expected bridge configuration + let locations = + pallet_xcm_bridge_hub::Pallet::<Runtime, XcmOverBridgePalletInstance>::bridge_locations( + source.clone().into(), + destination.clone().into(), + ) + .expect("valid bridge locations"); + assert!(pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( + locations.bridge_id() ) - .expect("valid bridge locations"); - assert!(pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( - locations.bridge_id() - ) - .is_none()); + .is_none()); + + // SA of source location needs to have some required balance + if !<Runtime as pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>>::AllowWithoutBridgeDeposit::contains(&source) { + // required balance: ED + fee + BridgeDeposit + let bridge_deposit = + <Runtime as pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>>::BridgeDeposit::get(); + let balance_needed = <Runtime as pallet_balances::Config>::ExistentialDeposit::get() + bridge_deposit.into(); + + let source_account_id = LocationToAccountId::convert_location(&source).expect("valid location"); + let _ = <pallet_balances::Pallet<Runtime>>::mint_into(&source_account_id, balance_needed) + .expect("mint_into passes"); + }; + + let maybe_paid_execution = if is_paid_xcm_execution { + // random high enough value for `BuyExecution` fees + let buy_execution_fee_amount = 5_000_000_000_000_u128; + let buy_execution_fee = (TokenLocation::get(), buy_execution_fee_amount).into(); + + let balance_needed = <Runtime as pallet_balances::Config>::ExistentialDeposit::get() + + buy_execution_fee_amount.into(); + let source_account_id = + LocationToAccountId::convert_location(&source).expect("valid location"); + let _ = + <pallet_balances::Pallet<Runtime>>::mint_into(&source_account_id, balance_needed) + .expect("mint_into passes"); + Some(buy_execution_fee) + } else { + None + }; + + // call the bridge opener + bridge_opener(*locations.clone(), maybe_paid_execution); + + // check opened bridge + let bridge = pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( + locations.bridge_id(), + ) + .expect("opened bridge"); - // SA of source location needs to have some required balance - if !<Runtime as pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>>::AllowWithoutBridgeDeposit::contains(&source) { - // required balance: ED + fee + BridgeDeposit - let bridge_deposit = - <Runtime as pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>>::BridgeDeposit::get( - ); - let balance_needed = <Runtime as pallet_balances::Config>::ExistentialDeposit::get() + bridge_deposit.into(); - - let source_account_id = LocationToAccountId::convert_location(&source).expect("valid location"); - let _ = <pallet_balances::Pallet<Runtime>>::mint_into(&source_account_id, balance_needed) - .expect("mint_into passes"); - }; - - let maybe_paid_execution = if is_paid_xcm_execution { - // random high enough value for `BuyExecution` fees - let buy_execution_fee_amount = 5_000_000_000_000_u128; - let buy_execution_fee = (TokenLocation::get(), buy_execution_fee_amount).into(); - - let balance_needed = <Runtime as pallet_balances::Config>::ExistentialDeposit::get() + - buy_execution_fee_amount.into(); - let source_account_id = - LocationToAccountId::convert_location(&source).expect("valid location"); - let _ = <pallet_balances::Pallet<Runtime>>::mint_into(&source_account_id, balance_needed) - .expect("mint_into passes"); - Some(buy_execution_fee) - } else { - None - }; - - // call the bridge opener - bridge_opener(*locations.clone(), maybe_paid_execution); - - // check opened bridge - let bridge = pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( - locations.bridge_id(), - ) - .expect("opened bridge"); + // check state + assert_ok!( + pallet_xcm_bridge_hub::Pallet::<Runtime, XcmOverBridgePalletInstance>::do_try_state() + ); - // check state - assert_ok!( - pallet_xcm_bridge_hub::Pallet::<Runtime, XcmOverBridgePalletInstance>::do_try_state() - ); + // return locations + (*locations, bridge.lane_id) + } - // return locations - (*locations, bridge.lane_id) -} + /// Utility for opening bridge with dedicated `pallet_xcm_bridge_hub`'s extrinsic. + pub fn open_bridge_with_extrinsic<Runtime, XcmOverBridgePalletInstance>( + (origin, origin_kind): (Location, OriginKind), + bridge_destination_universal_location: InteriorLocation, + maybe_paid_execution: Option<Asset>, + ) where + Runtime: frame_system::Config + + pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance> + + cumulus_pallet_parachain_system::Config + + pallet_xcm::Config, + XcmOverBridgePalletInstance: 'static, + <Runtime as frame_system::Config>::RuntimeCall: + GetDispatchInfo + From<BridgeXcmOverBridgeCall<Runtime, XcmOverBridgePalletInstance>>, + { + // open bridge with `Transact` call + let open_bridge_call = RuntimeCallOf::<Runtime>::from(BridgeXcmOverBridgeCall::< + Runtime, + XcmOverBridgePalletInstance, + >::open_bridge { + bridge_destination_universal_location: Box::new( + bridge_destination_universal_location.clone().into(), + ), + }); + + // execute XCM as source origin would do with `Transact -> Origin::Xcm` + assert_ok!(RuntimeHelper::<Runtime>::execute_as_origin( + (origin, origin_kind), + open_bridge_call, + maybe_paid_execution + ) + .ensure_complete()); + } -/// Utility for opening bridge with dedicated `pallet_xcm_bridge_hub`'s extrinsic. -pub fn open_bridge_with_extrinsic<Runtime, XcmOverBridgePalletInstance>( - (origin, origin_kind): (Location, OriginKind), - bridge_destination_universal_location: InteriorLocation, - maybe_paid_execution: Option<Asset>, -) where - Runtime: frame_system::Config - + pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance> - + cumulus_pallet_parachain_system::Config - + pallet_xcm::Config, - XcmOverBridgePalletInstance: 'static, - <Runtime as frame_system::Config>::RuntimeCall: - GetDispatchInfo + From<BridgeXcmOverBridgeCall<Runtime, XcmOverBridgePalletInstance>>, -{ - // open bridge with `Transact` call - let open_bridge_call = RuntimeCallOf::<Runtime>::from(BridgeXcmOverBridgeCall::< - Runtime, - XcmOverBridgePalletInstance, - >::open_bridge { - bridge_destination_universal_location: Box::new( - bridge_destination_universal_location.clone().into(), - ), - }); - - // execute XCM as source origin would do with `Transact -> Origin::Xcm` - assert_ok!(RuntimeHelper::<Runtime>::execute_as_origin( - (origin, origin_kind), - open_bridge_call, - maybe_paid_execution - ) - .ensure_complete()); -} + /// Utility for opening bridge directly inserting data to the `pallet_xcm_bridge_hub`'s storage + /// (used only for legacy purposes). + pub fn open_bridge_with_storage<Runtime, XcmOverBridgePalletInstance>( + locations: pallet_xcm_bridge_hub::BridgeLocations, + lane_id: pallet_xcm_bridge_hub::LaneIdOf<Runtime, XcmOverBridgePalletInstance>, + ) where + Runtime: pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>, + XcmOverBridgePalletInstance: 'static, + { + // insert bridge data directly to the storage + assert_ok!( + pallet_xcm_bridge_hub::Pallet::<Runtime, XcmOverBridgePalletInstance>::do_open_bridge( + Box::new(locations), + lane_id, + true + ) + ); + } -/// Utility for opening bridge directly inserting data to the storage (used only for legacy -/// purposes). -pub fn open_bridge_with_storage<Runtime, XcmOverBridgePalletInstance>( - locations: BridgeLocations, - lane_id: pallet_xcm_bridge_hub::LaneIdOf<Runtime, XcmOverBridgePalletInstance>, -) where - Runtime: pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>, - XcmOverBridgePalletInstance: 'static, -{ - // insert bridge data directly to the storage - assert_ok!( - pallet_xcm_bridge_hub::Pallet::<Runtime, XcmOverBridgePalletInstance>::do_open_bridge( - Box::new(locations), - lane_id, - true + /// Helper function to close the bridge/lane for `source` and `destination`. + pub fn close_bridge<Runtime, XcmOverBridgePalletInstance, LocationToAccountId, TokenLocation>( + expected_source: Location, + bridge_destination_universal_location: InteriorLocation, + (origin, origin_kind): (Location, OriginKind), + is_paid_xcm_execution: bool + ) where + Runtime: BasicParachainRuntime + BridgeXcmOverBridgeConfig<XcmOverBridgePalletInstance>, + XcmOverBridgePalletInstance: 'static, + <Runtime as frame_system::Config>::RuntimeCall: GetDispatchInfo + From<BridgeXcmOverBridgeCall<Runtime, XcmOverBridgePalletInstance>>, + <Runtime as pallet_balances::Config>::Balance: From<<<Runtime as pallet_bridge_messages::Config<<Runtime as pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>>::BridgeMessagesPalletInstance>>::ThisChain as bp_runtime::Chain>::Balance>, + <Runtime as pallet_balances::Config>::Balance: From<u128>, + LocationToAccountId: ConvertLocation<AccountIdOf<Runtime>>, + TokenLocation: Get<Location> + { + // construct expected bridge configuration + let locations = + pallet_xcm_bridge_hub::Pallet::<Runtime, XcmOverBridgePalletInstance>::bridge_locations( + expected_source.clone().into(), + bridge_destination_universal_location.clone().into(), + ) + .expect("valid bridge locations"); + assert!(pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( + locations.bridge_id() ) - ); -} + .is_some()); -/// Helper function to close the bridge/lane for `source` and `destination`. -pub fn close_bridge<Runtime, XcmOverBridgePalletInstance, LocationToAccountId, TokenLocation>( - expected_source: Location, - bridge_destination_universal_location: InteriorLocation, - (origin, origin_kind): (Location, OriginKind), - is_paid_xcm_execution: bool -) where - Runtime: BasicParachainRuntime + BridgeXcmOverBridgeConfig<XcmOverBridgePalletInstance>, - XcmOverBridgePalletInstance: 'static, - <Runtime as frame_system::Config>::RuntimeCall: GetDispatchInfo + From<BridgeXcmOverBridgeCall<Runtime, XcmOverBridgePalletInstance>>, - <Runtime as pallet_balances::Config>::Balance: From<<<Runtime as pallet_bridge_messages::Config<<Runtime as pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>>::BridgeMessagesPalletInstance>>::ThisChain as bp_runtime::Chain>::Balance>, - <Runtime as pallet_balances::Config>::Balance: From<u128>, - LocationToAccountId: ConvertLocation<AccountIdOf<Runtime>>, -TokenLocation: Get<Location>{ - // construct expected bridge configuration - let locations = - pallet_xcm_bridge_hub::Pallet::<Runtime, XcmOverBridgePalletInstance>::bridge_locations( - expected_source.clone().into(), - bridge_destination_universal_location.clone().into(), + // required balance: ED + fee + BridgeDeposit + let maybe_paid_execution = if is_paid_xcm_execution { + // random high enough value for `BuyExecution` fees + let buy_execution_fee_amount = 2_500_000_000_000_u128; + let buy_execution_fee = (TokenLocation::get(), buy_execution_fee_amount).into(); + + let balance_needed = <Runtime as pallet_balances::Config>::ExistentialDeposit::get() + + buy_execution_fee_amount.into(); + let source_account_id = + LocationToAccountId::convert_location(&expected_source).expect("valid location"); + let _ = + <pallet_balances::Pallet<Runtime>>::mint_into(&source_account_id, balance_needed) + .expect("mint_into passes"); + Some(buy_execution_fee) + } else { + None + }; + + // close bridge with `Transact` call + let close_bridge_call = RuntimeCallOf::<Runtime>::from(BridgeXcmOverBridgeCall::< + Runtime, + XcmOverBridgePalletInstance, + >::close_bridge { + bridge_destination_universal_location: Box::new( + bridge_destination_universal_location.into(), + ), + may_prune_messages: 16, + }); + + // execute XCM as source origin would do with `Transact -> Origin::Xcm` + assert_ok!(RuntimeHelper::<Runtime>::execute_as_origin( + (origin, origin_kind), + close_bridge_call, + maybe_paid_execution ) - .expect("valid bridge locations"); - assert!(pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( - locations.bridge_id() - ) - .is_some()); - - // required balance: ED + fee + BridgeDeposit - let maybe_paid_execution = if is_paid_xcm_execution { - // random high enough value for `BuyExecution` fees - let buy_execution_fee_amount = 2_500_000_000_000_u128; - let buy_execution_fee = (TokenLocation::get(), buy_execution_fee_amount).into(); - - let balance_needed = <Runtime as pallet_balances::Config>::ExistentialDeposit::get() + - buy_execution_fee_amount.into(); - let source_account_id = - LocationToAccountId::convert_location(&expected_source).expect("valid location"); - let _ = <pallet_balances::Pallet<Runtime>>::mint_into(&source_account_id, balance_needed) - .expect("mint_into passes"); - Some(buy_execution_fee) - } else { - None - }; - - // close bridge with `Transact` call - let close_bridge_call = RuntimeCallOf::<Runtime>::from(BridgeXcmOverBridgeCall::< - Runtime, - XcmOverBridgePalletInstance, - >::close_bridge { - bridge_destination_universal_location: Box::new( - bridge_destination_universal_location.into(), - ), - may_prune_messages: 16, - }); - - // execute XCM as source origin would do with `Transact -> Origin::Xcm` - assert_ok!(RuntimeHelper::<Runtime>::execute_as_origin( - (origin, origin_kind), - close_bridge_call, - maybe_paid_execution - ) - .ensure_complete()); + .ensure_complete()); - // bridge is closed - assert!(pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( - locations.bridge_id() - ) - .is_none()); + // bridge is closed + assert!(pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( + locations.bridge_id() + ) + .is_none()); - // check state - assert_ok!( - pallet_xcm_bridge_hub::Pallet::<Runtime, XcmOverBridgePalletInstance>::do_try_state() - ); + // check state + assert_ok!( + pallet_xcm_bridge_hub::Pallet::<Runtime, XcmOverBridgePalletInstance>::do_try_state() + ); + } } diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/mod.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/mod.rs index f96d0bf405b9cdf60cef53f9b2b858d4805b4981..fa0229ce06881a2193ac36d8e05240dc2e149744 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/mod.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/mod.rs @@ -32,7 +32,6 @@ use bp_messages::{ LaneState, MessageKey, MessagesOperatingMode, OutboundLaneData, }; use bp_runtime::BasicOperatingMode; -use bp_xcm_bridge_hub::{Bridge, BridgeState, XcmAsPlainPayload}; use codec::Encode; use frame_support::{ assert_ok, @@ -63,12 +62,11 @@ pub(crate) mod bridges_prelude { pub use pallet_bridge_parachains::{ Call as BridgeParachainsCall, Config as BridgeParachainsConfig, }; - pub use pallet_xcm_bridge_hub::{ - Call as BridgeXcmOverBridgeCall, Config as BridgeXcmOverBridgeConfig, LanesManagerOf, - XcmBlobMessageDispatchResult, - }; } +// Re-export test-case +pub use for_pallet_xcm_bridge_hub::open_and_close_bridge_works; + // Re-export test_case from assets pub use asset_test_utils::include_teleports_for_native_asset_works; use pallet_bridge_messages::LaneIdOf; @@ -77,7 +75,6 @@ pub type RuntimeHelper<Runtime, AllPalletsWithoutSystem = ()> = parachains_runtimes_test_utils::RuntimeHelper<Runtime, AllPalletsWithoutSystem>; // Re-export test_case from `parachains-runtimes-test-utils` -use crate::test_cases::helpers::open_bridge_with_extrinsic; pub use parachains_runtimes_test_utils::test_cases::{ change_storage_constant_by_governance_works, set_storage_keys_by_governance_works, }; @@ -439,7 +436,7 @@ pub fn message_dispatch_routing_works< ) where Runtime: BasicParachainRuntime + cumulus_pallet_xcmp_queue::Config - + BridgeMessagesConfig<MessagesPalletInstance, InboundPayload = XcmAsPlainPayload>, + + BridgeMessagesConfig<MessagesPalletInstance, InboundPayload = test_data::XcmAsPlainPayload>, AllPalletsWithoutSystem: OnInitialize<BlockNumberFor<Runtime>> + OnFinalize<BlockNumberFor<Runtime>>, AccountIdOf<Runtime>: From<AccountId32> @@ -459,9 +456,15 @@ pub fn message_dispatch_routing_works< Location::new(C::get(), [GlobalConsensus(N::get())]) } } - assert_ne!(runtime_para_id, sibling_parachain_id); + #[derive(Debug)] + enum XcmBlobMessageDispatchResult { + Dispatched, + #[allow(dead_code)] + NotDispatched(Option<DispatchBlobError>), + } + run_test::<Runtime, _>(collator_session_key, runtime_para_id, vec![], || { prepare_configuration(); @@ -650,139 +653,150 @@ where estimated_fee.into() } -/// Test-case makes sure that `Runtime` can open/close bridges. -pub fn open_and_close_bridge_works<Runtime, XcmOverBridgePalletInstance, LocationToAccountId, TokenLocation>( - collator_session_key: CollatorSessionKeys<Runtime>, - runtime_para_id: u32, - expected_source: Location, - destination: InteriorLocation, - origin_with_origin_kind: (Location, OriginKind), - is_paid_xcm_execution: bool, -) where - Runtime: BasicParachainRuntime + BridgeXcmOverBridgeConfig<XcmOverBridgePalletInstance>, - XcmOverBridgePalletInstance: 'static, - <Runtime as frame_system::Config>::RuntimeCall: GetDispatchInfo + From<BridgeXcmOverBridgeCall<Runtime, XcmOverBridgePalletInstance>>, - <Runtime as pallet_balances::Config>::Balance: From<<<Runtime as pallet_bridge_messages::Config<<Runtime as pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>>::BridgeMessagesPalletInstance>>::ThisChain as bp_runtime::Chain>::Balance>, - <Runtime as pallet_balances::Config>::Balance: From<u128>, - <<Runtime as pallet_bridge_messages::Config<<Runtime as pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>>::BridgeMessagesPalletInstance>>::ThisChain as bp_runtime::Chain>::AccountId: From<<Runtime as frame_system::Config>::AccountId>, - LocationToAccountId: ConvertLocation<AccountIdOf<Runtime>>, - TokenLocation: Get<Location>, -{ - run_test::<Runtime, _>(collator_session_key, runtime_para_id, vec![], || { - // construct expected bridge configuration - let locations = pallet_xcm_bridge_hub::Pallet::<Runtime, XcmOverBridgePalletInstance>::bridge_locations( - expected_source.clone().into(), - destination.clone().into(), - ).expect("valid bridge locations"); - let expected_lane_id = - locations.calculate_lane_id(xcm::latest::VERSION).expect("valid laneId"); - let lanes_manager = LanesManagerOf::<Runtime, XcmOverBridgePalletInstance>::new(); - - let expected_deposit = if <Runtime as pallet_xcm_bridge_hub::Config< - XcmOverBridgePalletInstance, - >>::AllowWithoutBridgeDeposit::contains( - locations.bridge_origin_relative_location() - ) { - Zero::zero() - } else { - <Runtime as pallet_xcm_bridge_hub::Config< +pub(crate) mod for_pallet_xcm_bridge_hub { + use super::*; + use crate::test_cases::helpers::for_pallet_xcm_bridge_hub::{ + close_bridge, ensure_opened_bridge, open_bridge_with_extrinsic, + }; + pub(crate) use pallet_xcm_bridge_hub::{ + Bridge, BridgeState, Call as BridgeXcmOverBridgeCall, Config as BridgeXcmOverBridgeConfig, + LanesManagerOf, + }; + + /// Test-case makes sure that `Runtime` can open/close bridges. + pub fn open_and_close_bridge_works<Runtime, XcmOverBridgePalletInstance, LocationToAccountId, TokenLocation>( + collator_session_key: CollatorSessionKeys<Runtime>, + runtime_para_id: u32, + expected_source: Location, + destination: InteriorLocation, + origin_with_origin_kind: (Location, OriginKind), + is_paid_xcm_execution: bool, + ) where + Runtime: BasicParachainRuntime + BridgeXcmOverBridgeConfig<XcmOverBridgePalletInstance>, + XcmOverBridgePalletInstance: 'static, + <Runtime as frame_system::Config>::RuntimeCall: GetDispatchInfo + From<BridgeXcmOverBridgeCall<Runtime, XcmOverBridgePalletInstance>>, + <Runtime as pallet_balances::Config>::Balance: From<<<Runtime as pallet_bridge_messages::Config<<Runtime as pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>>::BridgeMessagesPalletInstance>>::ThisChain as bp_runtime::Chain>::Balance>, + <Runtime as pallet_balances::Config>::Balance: From<u128>, + <<Runtime as pallet_bridge_messages::Config<<Runtime as pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>>::BridgeMessagesPalletInstance>>::ThisChain as bp_runtime::Chain>::AccountId: From<<Runtime as frame_system::Config>::AccountId>, + LocationToAccountId: ConvertLocation<AccountIdOf<Runtime>>, + TokenLocation: Get<Location>, + { + run_test::<Runtime, _>(collator_session_key, runtime_para_id, vec![], || { + // construct expected bridge configuration + let locations = pallet_xcm_bridge_hub::Pallet::<Runtime, XcmOverBridgePalletInstance>::bridge_locations( + expected_source.clone().into(), + destination.clone().into(), + ).expect("valid bridge locations"); + let expected_lane_id = + locations.calculate_lane_id(xcm::latest::VERSION).expect("valid laneId"); + let lanes_manager = LanesManagerOf::<Runtime, XcmOverBridgePalletInstance>::new(); + + let expected_deposit = if <Runtime as pallet_xcm_bridge_hub::Config< XcmOverBridgePalletInstance, - >>::BridgeDeposit::get() - }; + >>::AllowWithoutBridgeDeposit::contains( + locations.bridge_origin_relative_location() + ) { + Zero::zero() + } else { + <Runtime as pallet_xcm_bridge_hub::Config< + XcmOverBridgePalletInstance, + >>::BridgeDeposit::get() + }; - // check bridge/lane DOES not exist - assert_eq!( - pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( - locations.bridge_id() - ), - None - ); - assert_eq!( - lanes_manager.active_inbound_lane(expected_lane_id).map(drop), - Err(LanesManagerError::UnknownInboundLane) - ); - assert_eq!( - lanes_manager.active_outbound_lane(expected_lane_id).map(drop), - Err(LanesManagerError::UnknownOutboundLane) - ); + // check bridge/lane DOES not exist + assert_eq!( + pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( + locations.bridge_id() + ), + None + ); + assert_eq!( + lanes_manager.active_inbound_lane(expected_lane_id).map(drop), + Err(LanesManagerError::UnknownInboundLane) + ); + assert_eq!( + lanes_manager.active_outbound_lane(expected_lane_id).map(drop), + Err(LanesManagerError::UnknownOutboundLane) + ); - // open bridge with Transact call - assert_eq!( - helpers::ensure_opened_bridge::< - Runtime, - XcmOverBridgePalletInstance, - LocationToAccountId, - TokenLocation, - >( - expected_source.clone(), - destination.clone(), - is_paid_xcm_execution, - |locations, maybe_paid_execution| open_bridge_with_extrinsic::< + // open bridge with Transact call + assert_eq!( + ensure_opened_bridge::< Runtime, XcmOverBridgePalletInstance, + LocationToAccountId, + TokenLocation, >( - origin_with_origin_kind.clone(), - locations.bridge_destination_universal_location().clone(), - maybe_paid_execution + expected_source.clone(), + destination.clone(), + is_paid_xcm_execution, + |locations, maybe_paid_execution| open_bridge_with_extrinsic::< + Runtime, + XcmOverBridgePalletInstance, + >( + origin_with_origin_kind.clone(), + locations.bridge_destination_universal_location().clone(), + maybe_paid_execution + ) ) - ) - .0 - .bridge_id(), - locations.bridge_id() - ); - - // check bridge/lane DOES exist - assert_eq!( - pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( + .0 + .bridge_id(), locations.bridge_id() - ), - Some(Bridge { - bridge_origin_relative_location: Box::new(expected_source.clone().into()), - bridge_origin_universal_location: Box::new( - locations.bridge_origin_universal_location().clone().into() - ), - bridge_destination_universal_location: Box::new( - locations.bridge_destination_universal_location().clone().into() + ); + + // check bridge/lane DOES exist + assert_eq!( + pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( + locations.bridge_id() ), - state: BridgeState::Opened, - bridge_owner_account: LocationToAccountId::convert_location(&expected_source) - .expect("valid location") - .into(), - deposit: expected_deposit, - lane_id: expected_lane_id - }) - ); - assert_eq!( - lanes_manager.active_inbound_lane(expected_lane_id).map(|lane| lane.state()), - Ok(LaneState::Opened) - ); - assert_eq!( - lanes_manager.active_outbound_lane(expected_lane_id).map(|lane| lane.state()), - Ok(LaneState::Opened) - ); + Some(Bridge { + bridge_origin_relative_location: Box::new(expected_source.clone().into()), + bridge_origin_universal_location: Box::new( + locations.bridge_origin_universal_location().clone().into() + ), + bridge_destination_universal_location: Box::new( + locations.bridge_destination_universal_location().clone().into() + ), + state: BridgeState::Opened, + bridge_owner_account: LocationToAccountId::convert_location(&expected_source) + .expect("valid location") + .into(), + deposit: expected_deposit, + lane_id: expected_lane_id, + }) + ); + assert_eq!( + lanes_manager.active_inbound_lane(expected_lane_id).map(|lane| lane.state()), + Ok(LaneState::Opened) + ); + assert_eq!( + lanes_manager.active_outbound_lane(expected_lane_id).map(|lane| lane.state()), + Ok(LaneState::Opened) + ); - // close bridge with Transact call - helpers::close_bridge::< - Runtime, - XcmOverBridgePalletInstance, - LocationToAccountId, - TokenLocation, - >(expected_source, destination, origin_with_origin_kind, is_paid_xcm_execution); + // close bridge with Transact call + close_bridge::<Runtime, XcmOverBridgePalletInstance, LocationToAccountId, TokenLocation>( + expected_source, + destination, + origin_with_origin_kind, + is_paid_xcm_execution, + ); - // check bridge/lane DOES not exist - assert_eq!( - pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( - locations.bridge_id() - ), - None - ); - assert_eq!( - lanes_manager.active_inbound_lane(expected_lane_id).map(drop), - Err(LanesManagerError::UnknownInboundLane) - ); - assert_eq!( - lanes_manager.active_outbound_lane(expected_lane_id).map(drop), - Err(LanesManagerError::UnknownOutboundLane) - ); - }); + // check bridge/lane DOES not exist + assert_eq!( + pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( + locations.bridge_id() + ), + None + ); + assert_eq!( + lanes_manager.active_inbound_lane(expected_lane_id).map(drop), + Err(LanesManagerError::UnknownInboundLane) + ); + assert_eq!( + lanes_manager.active_outbound_lane(expected_lane_id).map(drop), + Err(LanesManagerError::UnknownOutboundLane) + ); + }); + } } diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_data/from_grandpa_chain.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_data/from_grandpa_chain.rs index 7461085330f27691b4da39e425aebcf64046641d..37605350b8e643a2de91b88dbfcc3a44d9e2d6da 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_data/from_grandpa_chain.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_data/from_grandpa_chain.rs @@ -16,7 +16,7 @@ //! Generating test data for bridges with remote GRANDPA chains. -use crate::test_data::prepare_inbound_xcm; +use crate::test_data::{prepare_inbound_xcm, XcmAsPlainPayload}; use bp_messages::{ source_chain::FromBridgedChainMessagesDeliveryProof, @@ -25,7 +25,6 @@ use bp_messages::{ }; use bp_runtime::{AccountIdOf, BlockNumberOf, Chain, HeaderOf, UnverifiedStorageProofParams}; use bp_test_utils::make_default_justification; -use bp_xcm_bridge_hub::XcmAsPlainPayload; use codec::Encode; use pallet_bridge_grandpa::{BridgedChain, BridgedHeader}; use sp_runtime::traits::Header as HeaderT; diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_data/from_parachain.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_data/from_parachain.rs index a6659b8241dfd50aedbfe14ac2672756fa0a03af..4d91c8215880037cfb39b4c0fff00046b0e29b9b 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_data/from_parachain.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_data/from_parachain.rs @@ -16,7 +16,10 @@ //! Generating test data for bridges with remote parachains. -use super::{from_grandpa_chain::make_complex_bridged_grandpa_header_proof, prepare_inbound_xcm}; +use super::{ + from_grandpa_chain::make_complex_bridged_grandpa_header_proof, prepare_inbound_xcm, + XcmAsPlainPayload, +}; use bp_messages::{ source_chain::FromBridgedChainMessagesDeliveryProof, @@ -28,7 +31,6 @@ use bp_runtime::{ AccountIdOf, BlockNumberOf, Chain, HeaderOf, Parachain, UnverifiedStorageProofParams, }; use bp_test_utils::prepare_parachain_heads_proof; -use bp_xcm_bridge_hub::XcmAsPlainPayload; use codec::Encode; use pallet_bridge_grandpa::BridgedHeader; use sp_runtime::traits::Header as HeaderT; diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_data/mod.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_data/mod.rs index c34188af506896d9fb4e18781b09d804077c3941..cef3c84b8178568e7a0ddb4939f76ca066c52655 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_data/mod.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_data/mod.rs @@ -35,6 +35,8 @@ use xcm::GetVersion; use xcm_builder::{BridgeMessage, HaulBlob, HaulBlobError, HaulBlobExporter}; use xcm_executor::traits::{validate_export, ExportXcm}; +pub(crate) type XcmAsPlainPayload = sp_std::vec::Vec<u8>; + pub fn prepare_inbound_xcm(xcm_message: Xcm<()>, destination: InteriorLocation) -> Vec<u8> { let location = xcm::VersionedInteriorLocation::from(destination); let xcm = xcm::VersionedXcm::<()>::from(xcm_message); diff --git a/prdoc/pr_7383.prdoc b/prdoc/pr_7383.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..bd421d73ab2025f530ebe15ed4d291fa9411533b --- /dev/null +++ b/prdoc/pr_7383.prdoc @@ -0,0 +1,12 @@ +title: Bridges small nits/improvements +doc: +- audience: Runtime Dev + description: 'This PR contains small fixes and backwards compatibility issues identified + during work on the larger PR: https://github.com/paritytech/polkadot-sdk/issues/6906.' +crates: +- name: cumulus-pallet-xcmp-queue + bump: patch +- name: pallet-xcm-bridge-hub + bump: minor +- name: bridge-hub-test-utils + bump: minor