Skip to content
Snippets Groups Projects
Unverified Commit 1908ab47 authored by Branislav Kontur's avatar Branislav Kontur
Browse files

Bridges small nits/improvements (#7383)


This PR contains small fixes and backwards compatibility issues
identified during work on the larger PR:
https://github.com/paritytech/polkadot-sdk/issues/6906.

---------

Co-authored-by: default avatarcmd[bot] <41898282+github-actions[bot]@users.noreply.github.com>
(cherry picked from commit ada12be6)
parent ab5882bb
No related merge requests found
Pipeline #513743 waiting for manual action with stages
in 46 minutes and 18 seconds
Showing
with 382 additions and 345 deletions
......@@ -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",
......
......@@ -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};
......
......@@ -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)
......
......@@ -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
......
......@@ -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
......
......@@ -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",
......
......@@ -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,
};
......
......@@ -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};
......
......@@ -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};
......
......@@ -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()
);
}
}
......@@ -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)
);
});
}
}
......@@ -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;
......
......@@ -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;
......
......@@ -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);
......
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
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment