From 4617ffa2dcc013ce5d7139f675522e3b76a65d11 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Mon, 28 Aug 2023 18:23:08 +0300 Subject: [PATCH 01/17] asset-hubs: transfer assets via bridge using pallet-xcm Add xcm routing configuration for bridging between Polkadot Asset Hub <-> Kusama Asset Hub. We explicitly allow only reserve based transfer for KSM/DOT to cross-consensus AssetHubs and nothing else at first (start defensively). We can later allow whatever (ETH, TrustBackedAssets, ForeignAssets, PoolAssets ...). Add tests for simulation: - `limited_reserve_transfer_assets` with `pallet_xcm` both ways - handling `ReserveAssetDeposisted` on both sides Add local zomienet run for: - reserve based transfer of KSMs from AHK to AHP - reserve based transfer of DOTs from AHP to AHK (check parachains/runtimes/bridge-hubs/README.md in this PR) Signed-off-by: Branislav Kontur Signed-off-by: Adrian Catangiu --- Cargo.lock | 1 + cumulus/parachains/common/src/xcm_config.rs | 140 +++++ .../assets/asset-hub-kusama/src/lib.rs | 5 +- .../asset-hub-kusama/src/weights/xcm/mod.rs | 2 +- .../xcm/pallet_xcm_benchmarks_generic.rs | 10 + .../assets/asset-hub-kusama/src/xcm_config.rs | 183 ++++++- .../assets/asset-hub-kusama/tests/tests.rs | 170 +++++- .../assets/asset-hub-polkadot/src/lib.rs | 7 +- .../asset-hub-polkadot/src/weights/xcm/mod.rs | 2 +- .../xcm/pallet_xcm_benchmarks_generic.rs | 10 + .../asset-hub-polkadot/src/xcm_config.rs | 182 ++++++- .../assets/asset-hub-polkadot/tests/tests.rs | 169 +++++- .../runtimes/assets/common/src/matching.rs | 162 ++++++ .../runtimes/assets/test-utils/Cargo.toml | 2 + .../runtimes/assets/test-utils/src/lib.rs | 1 + .../assets/test-utils/src/test_cases.rs | 7 +- .../test-utils/src/test_cases_over_bridge.rs | 504 ++++++++++++++++++ .../parachains/runtimes/bridge-hubs/README.md | 62 ++- .../bridge-hubs/test-utils/src/test_cases.rs | 11 +- .../parachains/runtimes/test-utils/Cargo.toml | 2 +- .../parachains/runtimes/test-utils/src/lib.rs | 49 +- cumulus/scripts/bridges_kusama_polkadot.sh | 195 +++++++ cumulus/scripts/bridges_rococo_wococo.sh | 54 +- .../bridge_hub_kusama_local_network.toml | 107 ++++ .../bridge_hub_polkadot_local_network.toml | 107 ++++ 25 files changed, 2054 insertions(+), 90 deletions(-) create mode 100644 cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs create mode 100755 cumulus/scripts/bridges_kusama_polkadot.sh create mode 100644 cumulus/zombienet/bridge-hubs/bridge_hub_kusama_local_network.toml create mode 100644 cumulus/zombienet/bridge-hubs/bridge_hub_polkadot_local_network.toml diff --git a/Cargo.lock b/Cargo.lock index c254302517f0..4a81c2221e1a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1007,6 +1007,7 @@ dependencies = [ "sp-runtime", "sp-std", "staging-xcm", + "staging-xcm-builder", "staging-xcm-executor", "substrate-wasm-builder", ] diff --git a/cumulus/parachains/common/src/xcm_config.rs b/cumulus/parachains/common/src/xcm_config.rs index 146671441453..aa1183f5d921 100644 --- a/cumulus/parachains/common/src/xcm_config.rs +++ b/cumulus/parachains/common/src/xcm_config.rs @@ -18,10 +18,12 @@ use core::marker::PhantomData; use frame_support::{ traits::{fungibles::Inspect, tokens::ConversionToAssetBalance, ContainsPair}, weights::Weight, + DefaultNoBound, }; use log; use sp_runtime::traits::Get; use xcm::latest::prelude::*; +use xcm_builder::ExporterFor; /// A `ChargeFeeInFungibles` implementation that converts the output of /// a given WeightToFee implementation an amount charged in @@ -78,3 +80,141 @@ impl> ContainsPair matches!(asset.id, Concrete(ref id) if id == origin && origin == &Location::get()) } } + +/// Trait for matching `Location`. +pub trait MatchesLocation { + fn matches(&self, location: &Location) -> bool; +} + +/// Simple `MultiLocation` filter utility. +#[derive(Debug, DefaultNoBound)] +pub struct LocationFilter { + /// Requested location equals to `Location`. + pub equals_any: sp_std::vec::Vec, + /// Requested location starts with `Location`. + pub starts_with_any: sp_std::vec::Vec, +} + +impl LocationFilter { + pub fn add_equals(mut self, filter: Location) -> Self { + self.equals_any.push(filter); + self + } + pub fn add_starts_with(mut self, filter: Location) -> Self { + self.starts_with_any.push(filter); + self + } +} + +/// `MatchesLocation` implementation which works with `MultiLocation`. +impl MatchesLocation for LocationFilter { + fn matches(&self, location: &MultiLocation) -> bool { + for filter in &self.equals_any { + if location.eq(filter) { + return true + } + } + for filter in &self.starts_with_any { + if location.starts_with(filter) { + return true + } + } + false + } +} + +/// `MatchesLocation` implementation which works with `InteriorMultiLocation`. +impl MatchesLocation for LocationFilter { + fn matches(&self, location: &InteriorMultiLocation) -> bool { + for filter in &self.equals_any { + if location.eq(filter) { + return true + } + } + for filter in &self.starts_with_any { + if location.starts_with(filter) { + return true + } + } + false + } +} + +/// `FilteredNetworkExportTable` is adapter for `ExporterFor` implementation +/// which tries to find (`bridge_location`, `fees`) for requested `network` and `remote_location`. +/// +/// Inspired by `xcm_builder::NetworkExportTable`: +/// the main difference is that `NetworkExportTable` does not check `remote_location`. +pub struct FilteredNetworkExportTable(sp_std::marker::PhantomData); +impl< + T: Get< + sp_std::vec::Vec<( + NetworkId, + LocationFilter, + MultiLocation, + Option, + )>, + >, + > ExporterFor for FilteredNetworkExportTable +{ + fn exporter_for( + network: &NetworkId, + remote_location: &InteriorMultiLocation, + _: &Xcm<()>, + ) -> Option<(MultiLocation, Option)> { + T::get() + .into_iter() + .find(|(ref j, location_filter, ..)| { + j == network && location_filter.matches(remote_location) + }) + .map(|(_, _, bridge_location, p)| (bridge_location, p)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn filtered_network_export_table_works() { + frame_support::parameter_types! { + pub BridgeLocation: MultiLocation = MultiLocation::new(1, X1(Parachain(1234))); + + pub BridgeTable: sp_std::vec::Vec<(NetworkId, LocationFilter, MultiLocation, Option)> = sp_std::vec![ + ( + Kusama, + LocationFilter::default() + .add_equals(X1(Parachain(2000))) + .add_equals(X1(Parachain(3000))) + .add_equals(X1(Parachain(4000))), + BridgeLocation::get(), + None + ) + ]; + } + + let test_data = vec![ + (Polkadot, X1(Parachain(1000)), None), + (Polkadot, X1(Parachain(2000)), None), + (Polkadot, X1(Parachain(3000)), None), + (Polkadot, X1(Parachain(4000)), None), + (Polkadot, X1(Parachain(5000)), None), + (Kusama, X1(Parachain(1000)), None), + (Kusama, X1(Parachain(2000)), Some((BridgeLocation::get(), None))), + (Kusama, X1(Parachain(3000)), Some((BridgeLocation::get(), None))), + (Kusama, X1(Parachain(4000)), Some((BridgeLocation::get(), None))), + (Kusama, X1(Parachain(5000)), None), + ]; + + for (network, remote_location, expected_result) in test_data { + assert_eq!( + FilteredNetworkExportTable::::exporter_for( + &network, + &remote_location, + &Xcm::default() + ), + expected_result, + ) + } + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs index 828d1b4750a3..f8ebdefe6870 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs @@ -1279,7 +1279,10 @@ impl_runtime_apis! { } fn universal_alias() -> Result<(MultiLocation, Junction), BenchmarkError> { - Err(BenchmarkError::Skip) + match xcm_config::bridging::BridgingBenchmarksHelper::prepare_universal_alias() { + Some(alias) => Ok(alias), + None => Err(BenchmarkError::Skip) + } } fn transact_origin_and_runtime_call() -> Result<(MultiLocation, RuntimeCall), BenchmarkError> { diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/xcm/mod.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/xcm/mod.rs index 9aff4902d15b..4bc3209a4e0f 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/xcm/mod.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/xcm/mod.rs @@ -220,7 +220,7 @@ impl XcmWeightInfo for AssetHubKusamaXcmWeight { XcmGeneric::::clear_transact_status() } fn universal_origin(_: &Junction) -> Weight { - Weight::MAX + XcmGeneric::::universal_origin() } fn export_message(_: &NetworkId, _: &Junctions, _: &Xcm<()>) -> Weight { Weight::MAX diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/xcm/pallet_xcm_benchmarks_generic.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/xcm/pallet_xcm_benchmarks_generic.rs index 625549ecfccf..6ab849e50a65 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/xcm/pallet_xcm_benchmarks_generic.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/xcm/pallet_xcm_benchmarks_generic.rs @@ -312,6 +312,16 @@ impl WeightInfo { // Minimum execution time: 2_886_000 picoseconds. Weight::from_parts(3_015_000, 0) } + // Storage: `ParachainInfo::ParachainId` (r:1 w:0) + // Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + pub fn universal_origin() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `1489` + // Minimum execution time: 5_088_000 picoseconds. + Weight::from_parts(5_253_000, 1489) + .saturating_add(T::DbWeight::get().reads(1)) + } pub fn set_fees_mode() -> Weight { // Proof Size summary in bytes: // Measured: `0` diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs index 0c197598f889..99e46a1b4fe6 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs @@ -18,7 +18,7 @@ use super::{ ParachainSystem, PolkadotXcm, PoolAssets, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, TrustBackedAssetsInstance, WeightToFee, XcmpQueue, }; -use crate::ForeignAssets; +use crate::{ForeignAssets, ForeignAssetsInstance}; use assets_common::{ local_and_foreign_assets::MatchesLocalAndForeignAssetsMultiLocation, matching::{ @@ -27,7 +27,7 @@ use assets_common::{ }; use frame_support::{ match_types, parameter_types, - traits::{ConstU32, Contains, Everything, Nothing, PalletInfoAccess}, + traits::{ConstU32, Contains, Everything, EverythingBut, Nothing, PalletInfoAccess}, }; use frame_system::EnsureRoot; use pallet_xcm::XcmPassthrough; @@ -39,11 +39,11 @@ use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, CurrencyAdapter, DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal, DescribeFamily, - EnsureXcmOrigin, FungiblesAdapter, HashedDescription, IsConcrete, LocalMint, NativeAsset, - NoChecking, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, - SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, - WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, + EnsureXcmOrigin, FungiblesAdapter, GlobalConsensusParachainConvertsFor, HashedDescription, + IsConcrete, LocalMint, NativeAsset, NoChecking, ParentAsSuperuser, ParentIsPreset, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, + TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, }; use xcm_executor::{traits::WithOriginFilter, XcmExecutor}; @@ -80,6 +80,9 @@ pub type LocationToAccountId = ( AccountId32Aliases, // Foreign locations alias into accounts according to a hash of their standard description. HashedDescription>, + // Different global consensus parachain sovereign account. + // (Used for over-bridge transfers and reserve processing) + GlobalConsensusParachainConvertsFor, ); /// Means for transacting the native currency on this chain. @@ -463,6 +466,7 @@ pub type Barrier = TrailingSetTopicAsId< >, >; +/// Multiplier used for dedicated `TakeFirstAssetTrader` with `Assets` instance. pub type AssetFeeAsExistentialDepositMultiplierFeeCharger = AssetFeeAsExistentialDepositMultiplier< Runtime, WeightToFee, @@ -470,16 +474,25 @@ pub type AssetFeeAsExistentialDepositMultiplierFeeCharger = AssetFeeAsExistentia TrustBackedAssetsInstance, >; +/// Multiplier used for dedicated `TakeFirstAssetTrader` with `ForeignAssets` instance. +pub type ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger = + AssetFeeAsExistentialDepositMultiplier< + Runtime, + WeightToFee, + pallet_assets::BalanceToAssetBalance, + ForeignAssetsInstance, + >; + pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { type RuntimeCall = RuntimeCall; type XcmSender = XcmRouter; type AssetTransactor = AssetTransactors; type OriginConverter = XcmOriginToTransactDispatchOrigin; - // Asset Hub Kusama does not recognize a reserve location for any asset. This does not prevent - // Asset Hub acting _as_ a reserve location for KSM and assets created under `pallet-assets`. - // For KSM, users must use teleport where allowed (e.g. with the Relay Chain). - type IsReserve = (); + // Asset Hub trusts only particular configured bridge locations as reserve locations. + // Asset Hub may _act_ as a reserve location for KSM and assets created under `pallet-assets`. + // Users must use teleport where allowed (e.g. KSM with the Relay Chain). + type IsReserve = bridging::IsTrustedBridgedReserveLocationForConcreteAsset; // We allow: // - teleportation of KSM // - teleportation of sibling parachain's assets (as ForeignCreators) @@ -496,6 +509,8 @@ impl xcm_executor::Config for XcmConfig { >; type Trader = ( UsingComponents>, + // This trader allows to pay with `is_sufficient=true` "Trust Backed" assets from dedicated + // `pallet_assets` instance - `Assets`. cumulus_primitives_utility::TakeFirstAssetTrader< AccountId, AssetFeeAsExistentialDepositMultiplierFeeCharger, @@ -507,6 +522,19 @@ impl xcm_executor::Config for XcmConfig { XcmAssetFeesReceiver, >, >, + // This trader allows to pay with `is_sufficient=true` "Foreign" assets from dedicated + // `pallet_assets` instance - `ForeignAssets`. + cumulus_primitives_utility::TakeFirstAssetTrader< + AccountId, + ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger, + ForeignAssetsConvertedConcreteId, + ForeignAssets, + cumulus_primitives_utility::XcmFeesTo32ByteAccount< + ForeignFungiblesTransactor, + AccountId, + XcmAssetFeesReceiver, + >, + >, ); type ResponseHandler = PolkadotXcm; type AssetTrap = PolkadotXcm; @@ -518,7 +546,7 @@ impl xcm_executor::Config for XcmConfig { type AssetExchanger = (); type FeeManager = (); type MessageExporter = (); - type UniversalAliases = Nothing; + type UniversalAliases = bridging::UniversalAliases; type CallDispatcher = WithOriginFilter; type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; @@ -528,14 +556,17 @@ impl xcm_executor::Config for XcmConfig { /// Forms the basis for local origins sending/executing XCMs. pub type LocalOriginToLocation = SignedToAccountId32; -/// The means for routing XCM messages which are not for local execution into the right message -/// queues. -pub type XcmRouter = WithUniqueTopic<( +/// For routing XCM messages which do not cross local consensus boundary. +type LocalXcmRouter = ( // Two routers - use UMP to communicate with the relay chain: cumulus_primitives_utility::ParentAsUmp, // ..and XCMP to communicate with the sibling chains. XcmpQueue, -)>; +); + +/// The means for routing XCM messages which are not for local execution into the right message +/// queues. +pub type XcmRouter = WithUniqueTopic<(LocalXcmRouter, bridging::BridgingXcmRouter)>; #[cfg(feature = "runtime-benchmarks")] parameter_types! { @@ -554,7 +585,10 @@ impl pallet_xcm::Config for Runtime { type XcmExecuteFilter = Nothing; type XcmExecutor = XcmExecutor; type XcmTeleportFilter = Everything; - type XcmReserveTransferFilter = Everything; + // Allow reserve based transfer to everywhere except for bridging, here we strictly check what + // assets are allowed. + type XcmReserveTransferFilter = + EverythingBut; type Weigher = WeightInfoBounds< crate::weights::xcm::AssetHubKusamaXcmWeight, RuntimeCall, @@ -624,3 +658,118 @@ where sp_std::boxed::Box::new(Self::asset_id(asset_id)) } } + +/// All configuration related to bridging +pub mod bridging { + use super::*; + use assets_common::{matching, matching::*}; + use parachains_common::xcm_config::LocationFilter; + use sp_std::collections::btree_set::BTreeSet; + use xcm_builder::UnpaidRemoteExporter; + + parameter_types! { + pub BridgeHubKusamaParaId: u32 = 1002; + pub BridgeHubKusama: MultiLocation = MultiLocation::new(1, X1(Parachain(BridgeHubKusamaParaId::get()))); + pub BridgeHubKusamaWithBridgeHubPolkadotInstance: MultiLocation = MultiLocation::new(1, X2(Parachain(BridgeHubKusamaParaId::get()), PalletInstance(53))); + pub const PolkadotNetwork: NetworkId = NetworkId::Polkadot; + pub AssetHubPolkadot: MultiLocation = MultiLocation::new(2, X2(GlobalConsensus(PolkadotNetwork::get()), Parachain(1000))); + pub DotLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(PolkadotNetwork::get()))); + + /// Set up exporters configuration. + pub BridgeTable: sp_std::vec::Vec<(NetworkId, LocationFilter, MultiLocation, Option)> = sp_std::vec![ + ( + PolkadotNetwork::get(), + LocationFilter::default() + // allow to bridge to AssetHubPolkadot + .add_equals(AssetHubPolkadot::get().interior.split_global().expect("invalid configuration for AssetHubPolkadot").1), + // and nothing else + BridgeHubKusama::get(), + None + ) + ]; + + /// Set up trusted bridged reserve locations. + /// Locations from which the runtime accepts reserved assets. + pub TrustedBridgedReserveLocations: sp_std::vec::Vec = sp_std::vec![ + // trust assets from AssetHubPolkadot + ( + AssetHubPolkadot::get(), + AssetFilter::ByMultiLocation( + LocationFilter::default() + // allow receive DOT + .add_equals(DotLocation::get()) + // and nothing else + ) + ) + ]; + + /// Allowed reserve transfer assets per destination. + /// Means that runtime allows to transfer reserve assets to these locations. + pub AllowedReserveTransferAssetsLocations: sp_std::vec::Vec = sp_std::vec![ + // allow to transfer assets to AssetHubPolkadot + ( + AssetHubPolkadot::get(), + AssetFilter::ByMultiLocation( + LocationFilter::default() + // allow send only KSM + .add_equals(KsmLocation::get()) + // and nothing else + ) + ) + ]; + + /// Universal aliases + pub UniversalAliases: BTreeSet<(MultiLocation, Junction)> = BTreeSet::from_iter( + sp_std::vec![ + (BridgeHubKusamaWithBridgeHubPolkadotInstance::get(), GlobalConsensus(PolkadotNetwork::get())) + ] + ); + } + + impl Contains<(MultiLocation, Junction)> for UniversalAliases { + fn contains(alias: &(MultiLocation, Junction)) -> bool { + UniversalAliases::get().contains(alias) + } + } + + pub type FilteredNetworkExportTable = + parachains_common::xcm_config::FilteredNetworkExportTable; + + /// Bridge router, which wraps and sends xcm to BridgeHub to be delivered to the different + /// GlobalConsensus + pub type BridgingXcmRouter = + UnpaidRemoteExporter; + + /// Reserve locations filter for `xcm_executor::Config::IsReserve`. + pub type IsTrustedBridgedReserveLocationForConcreteAsset = + matching::IsTrustedBridgedReserveLocationForConcreteAsset< + UniversalLocation, + TrustedBridgedReserveLocations, + >; + + /// Filter out those assets which are not allowed for bridged reserve based transfer. + /// (asset, location) filter for `pallet_xcm::Config::XcmReserveTransferFilter`. + pub type IsNotAllowedExplicitlyForReserveTransfer = ExcludeOnlyForRemoteDestination< + UniversalLocation, + FilteredNetworkExportTable, + IsNotAllowedConcreteAssetBy, + >; + + /// Benchmarks helper for bridging configuration. + #[cfg(feature = "runtime-benchmarks")] + pub struct BridgingBenchmarksHelper; + + #[cfg(feature = "runtime-benchmarks")] + impl BridgingBenchmarksHelper { + pub fn prepare_universal_alias() -> Option<(MultiLocation, Junction)> { + let alias = UniversalAliases::get().into_iter().find_map(|(location, junction)| { + match BridgeHubKusamaWithBridgeHubPolkadotInstance::get().eq(&location) { + true => Some((location, junction)), + false => None, + } + }); + assert!(alias.is_some(), "we expect here BridgeHubKusama to Polkadot mapping at least"); + Some(alias.unwrap()) + } + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs index 7d49b56e461a..106a09d4e55c 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs @@ -21,17 +21,20 @@ use asset_hub_kusama_runtime::xcm_config::{ AssetFeeAsExistentialDepositMultiplierFeeCharger, KsmLocation, TrustBackedAssetsPalletLocation, }; pub use asset_hub_kusama_runtime::{ - xcm_config::{CheckingAccount, ForeignCreatorsSovereignAccountOf, XcmConfig}, + xcm_config::{ + self, bridging, CheckingAccount, ForeignCreatorsSovereignAccountOf, LocationToAccountId, + XcmConfig, + }, AllPalletsWithoutSystem, AssetDeposit, Assets, Balances, ExistentialDeposit, ForeignAssets, ForeignAssetsInstance, MetadataDepositBase, MetadataDepositPerByte, ParachainSystem, Runtime, - RuntimeCall, RuntimeEvent, SessionKeys, System, TrustBackedAssetsInstance, + RuntimeCall, RuntimeEvent, SessionKeys, System, TrustBackedAssetsInstance, XcmpQueue, }; -use asset_test_utils::{CollatorSessionKeys, ExtBuilder}; +use asset_test_utils::{CollatorSessionKey, CollatorSessionKeys, ExtBuilder}; use codec::{Decode, Encode}; use cumulus_primitives_utility::ChargeWeightInFungibles; use frame_support::{ assert_noop, assert_ok, - traits::fungibles::InspectEnumerable, + traits::{fungibles::InspectEnumerable, Contains}, weights::{Weight, WeightToFee as WeightToFeeT}, }; use parachains_common::{ @@ -49,14 +52,18 @@ type AssetIdForTrustBackedAssetsConvert = type RuntimeHelper = asset_test_utils::RuntimeHelper; -fn collator_session_keys() -> CollatorSessionKeys { - CollatorSessionKeys::new( - AccountId::from(ALICE), - AccountId::from(ALICE), - SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) }, +fn collator_session_key(account: [u8; 32]) -> CollatorSessionKey { + CollatorSessionKey::new( + AccountId::from(account), + AccountId::from(account), + SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(account)) }, ) } +fn collator_session_keys() -> CollatorSessionKeys { + CollatorSessionKeys::default().add(collator_session_key(ALICE)) +} + #[test] fn test_asset_xcm_trader() { ExtBuilder::::default() @@ -632,3 +639,148 @@ asset_test_utils::include_create_and_manage_foreign_assets_for_local_consensus_p assert_eq!(ForeignAssets::asset_ids().collect::>().len(), 1); }) ); + +fn bridging_to_asset_hub_polkadot() -> asset_test_utils::test_cases_over_bridge::TestBridgingConfig +{ + asset_test_utils::test_cases_over_bridge::TestBridgingConfig { + bridged_network: bridging::PolkadotNetwork::get(), + local_bridge_hub_para_id: bridging::BridgeHubKusamaParaId::get(), + local_bridge_hub_location: bridging::BridgeHubKusama::get(), + bridged_target_location: bridging::AssetHubPolkadot::get(), + } +} + +#[test] +fn limited_reserve_transfer_assets_for_native_asset_over_bridge_works() { + asset_test_utils::test_cases_over_bridge::limited_reserve_transfer_assets_for_native_asset_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ParachainSystem, + XcmpQueue, + LocationToAccountId, + >( + collator_session_keys(), + ExistentialDeposit::get(), + AccountId::from(ALICE), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::PolkadotXcm(event)) => Some(event), + _ => None, + } + }), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::XcmpQueue(event)) => Some(event), + _ => None, + } + }), + bridging_to_asset_hub_polkadot, + WeightLimit::Unlimited, + ) +} + +#[test] +fn receive_reserve_asset_deposited_dot_from_asset_hub_polkadot_works() { + const BLOCK_AUTHOR_ACCOUNT: [u8; 32] = [13; 32]; + asset_test_utils::test_cases_over_bridge::receive_reserve_asset_deposited_from_different_consensus_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + LocationToAccountId, + ForeignAssetsInstance, + >( + collator_session_keys().add(collator_session_key(BLOCK_AUTHOR_ACCOUNT)), + ExistentialDeposit::get(), + AccountId::from([73; 32]), + AccountId::from(BLOCK_AUTHOR_ACCOUNT), + // receiving DOTs + (MultiLocation { parents: 2, interior: X1(GlobalConsensus(Polkadot)) }, 1000000000000, 1_000_000_000), + bridging_to_asset_hub_polkadot, + (X1(PalletInstance(53)), GlobalConsensus(Polkadot), X1(Parachain(1000))) + ) +} + +/// Tests expected configuration of isolated `pallet_xcm::Config::XcmReserveTransferFilter`. +#[test] +fn xcm_reserve_transfer_filter_works() { + // prepare assets + let only_native_assets = || vec![MultiAsset::from((KsmLocation::get(), 1000))]; + let only_trust_backed_assets = || { + vec![MultiAsset::from(( + AssetIdForTrustBackedAssetsConvert::convert_back(&12345).unwrap(), + 2000, + ))] + }; + let only_sibling_foreign_assets = + || vec![MultiAsset::from((MultiLocation::new(1, X1(Parachain(12345))), 3000))]; + let only_different_global_consensus_foreign_assets = || { + vec![MultiAsset::from(( + MultiLocation::new(2, X2(GlobalConsensus(Polkadot), Parachain(12345))), + 4000, + ))] + }; + + // prepare destinations + let relaychain = MultiLocation::parent(); + let sibling_parachain = MultiLocation::new(1, X1(Parachain(54321))); + let different_global_consensus_parachain_other_than_asset_hub_polkadot = + MultiLocation::new(2, X2(GlobalConsensus(Polkadot), Parachain(12345))); + let bridged_asset_hub = bridging::AssetHubPolkadot::get(); + + // prepare expected test data sets: (destination, assets, expected_result) + let test_data = vec![ + (relaychain, only_native_assets(), true), + (relaychain, only_trust_backed_assets(), true), + (relaychain, only_sibling_foreign_assets(), true), + (relaychain, only_different_global_consensus_foreign_assets(), true), + (sibling_parachain, only_native_assets(), true), + (sibling_parachain, only_trust_backed_assets(), true), + (sibling_parachain, only_sibling_foreign_assets(), true), + (sibling_parachain, only_different_global_consensus_foreign_assets(), true), + ( + different_global_consensus_parachain_other_than_asset_hub_polkadot, + only_native_assets(), + false, + ), + ( + different_global_consensus_parachain_other_than_asset_hub_polkadot, + only_trust_backed_assets(), + false, + ), + ( + different_global_consensus_parachain_other_than_asset_hub_polkadot, + only_sibling_foreign_assets(), + false, + ), + ( + different_global_consensus_parachain_other_than_asset_hub_polkadot, + only_different_global_consensus_foreign_assets(), + false, + ), + (bridged_asset_hub, only_native_assets(), true), + (bridged_asset_hub, only_trust_backed_assets(), false), + (bridged_asset_hub, only_sibling_foreign_assets(), false), + (bridged_asset_hub, only_different_global_consensus_foreign_assets(), false), + ]; + + // lets test filter with test data + ExtBuilder::::default() + .with_collators(collator_session_keys().collators()) + .with_session_keys(collator_session_keys().session_keys()) + .build() + .execute_with(|| { + type XcmReserveTransferFilter = + ::XcmReserveTransferFilter; + for (dest, assets, expected_result) in test_data { + assert_eq!( + expected_result, + XcmReserveTransferFilter::contains(&(dest, assets.clone())), + "expected_result: {} for dest: {:?} and assets: {:?}", + expected_result, + dest, + assets + ); + } + }) +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs index 0051af21f9a3..2e63d630dd60 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs @@ -569,7 +569,6 @@ parameter_types! { } impl cumulus_pallet_xcmp_queue::Config for Runtime { - type WeightInfo = weights::cumulus_pallet_xcmp_queue::WeightInfo; type RuntimeEvent = RuntimeEvent; type XcmExecutor = XcmExecutor; type ChannelInfo = ParachainSystem; @@ -581,6 +580,7 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { >; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type PriceForSiblingDelivery = (); + type WeightInfo = weights::cumulus_pallet_xcmp_queue::WeightInfo; } impl cumulus_pallet_dmp_queue::Config for Runtime { @@ -1158,7 +1158,10 @@ impl_runtime_apis! { } fn universal_alias() -> Result<(MultiLocation, Junction), BenchmarkError> { - Err(BenchmarkError::Skip) + match xcm_config::bridging::BridgingBenchmarksHelper::prepare_universal_alias() { + Some(alias) => Ok(alias), + None => Err(BenchmarkError::Skip) + } } fn transact_origin_and_runtime_call() -> Result<(MultiLocation, RuntimeCall), BenchmarkError> { diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/xcm/mod.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/xcm/mod.rs index 55fed809e2b7..6a525df07cf1 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/xcm/mod.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/xcm/mod.rs @@ -220,7 +220,7 @@ impl XcmWeightInfo for AssetHubPolkadotXcmWeight { XcmGeneric::::clear_transact_status() } fn universal_origin(_: &Junction) -> Weight { - Weight::MAX + XcmGeneric::::universal_origin() } fn export_message(_: &NetworkId, _: &Junctions, _: &Xcm<()>) -> Weight { Weight::MAX diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/xcm/pallet_xcm_benchmarks_generic.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/xcm/pallet_xcm_benchmarks_generic.rs index 061992691a60..961857553da3 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/xcm/pallet_xcm_benchmarks_generic.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/xcm/pallet_xcm_benchmarks_generic.rs @@ -312,6 +312,16 @@ impl WeightInfo { // Minimum execution time: 2_845_000 picoseconds. Weight::from_parts(2_970_000, 0) } + // Storage: `ParachainInfo::ParachainId` (r:1 w:0) + // Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + pub fn universal_origin() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `1489` + // Minimum execution time: 4_942_000 picoseconds. + Weight::from_parts(5_195_000, 1489) + .saturating_add(T::DbWeight::get().reads(1)) + } pub fn set_fees_mode() -> Weight { // Proof Size summary in bytes: // Measured: `0` diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs index d59507e4bd07..4b11eb6682c5 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs @@ -18,12 +18,13 @@ use super::{ ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, TrustBackedAssetsInstance, WeightToFee, XcmpQueue, }; +use crate::ForeignAssetsInstance; use assets_common::matching::{ FromSiblingParachain, IsForeignConcreteAsset, StartsWith, StartsWithExplicitGlobalConsensus, }; use frame_support::{ match_types, parameter_types, - traits::{ConstU32, Contains, Everything, Nothing, PalletInfoAccess}, + traits::{ConstU32, Contains, Everything, EverythingBut, Nothing, PalletInfoAccess}, }; use frame_system::EnsureRoot; use pallet_xcm::XcmPassthrough; @@ -35,11 +36,11 @@ use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, CurrencyAdapter, DenyReserveTransferToRelayChain, DenyThenTry, DescribeFamily, DescribePalletTerminal, - EnsureXcmOrigin, FungiblesAdapter, HashedDescription, IsConcrete, LocalMint, NativeAsset, - NoChecking, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, - SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, - WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, + EnsureXcmOrigin, FungiblesAdapter, GlobalConsensusParachainConvertsFor, HashedDescription, + IsConcrete, LocalMint, NativeAsset, NoChecking, ParentAsSuperuser, ParentIsPreset, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, + TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, }; use xcm_executor::{traits::WithOriginFilter, XcmExecutor}; @@ -70,6 +71,9 @@ pub type LocationToAccountId = ( // Foreign chain account alias into local accounts according to a hash of their standard // description. HashedDescription>, + // Different global consensus parachain sovereign account. + // (Used for over-bridge transfers and reserve processing) + GlobalConsensusParachainConvertsFor, ); /// Means for transacting the native currency on this chain. @@ -383,6 +387,7 @@ pub type Barrier = TrailingSetTopicAsId< >, >; +/// Multiplier used for dedicated `TakeFirstAssetTrader` with `Assets` instance. pub type AssetFeeAsExistentialDepositMultiplierFeeCharger = AssetFeeAsExistentialDepositMultiplier< Runtime, WeightToFee, @@ -390,16 +395,25 @@ pub type AssetFeeAsExistentialDepositMultiplierFeeCharger = AssetFeeAsExistentia TrustBackedAssetsInstance, >; +/// Multiplier used for dedicated `TakeFirstAssetTrader` with `ForeignAssets` instance. +pub type ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger = + AssetFeeAsExistentialDepositMultiplier< + Runtime, + WeightToFee, + pallet_assets::BalanceToAssetBalance, + ForeignAssetsInstance, + >; + pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { type RuntimeCall = RuntimeCall; type XcmSender = XcmRouter; type AssetTransactor = AssetTransactors; type OriginConverter = XcmOriginToTransactDispatchOrigin; - // Asset Hub Polkadot does not recognize a reserve location for any asset. This does not prevent - // Asset Hub acting _as_ a reserve location for DOT and assets created under `pallet-assets`. - // For DOT, users must use teleport where allowed (e.g. with the Relay Chain). - type IsReserve = (); + // Asset Hub trusts only particular configured bridge locations as reserve locations. + // Asset Hub may _act_ as a reserve location for DOT and assets created under `pallet-assets`. + // Users must use teleport where allowed (e.g. DOT with the Relay Chain). + type IsReserve = bridging::IsTrustedBridgedReserveLocationForConcreteAsset; // We allow: // - teleportation of DOT // - teleportation of sibling parachain's assets (as ForeignCreators) @@ -416,6 +430,8 @@ impl xcm_executor::Config for XcmConfig { >; type Trader = ( UsingComponents>, + // This trader allows to pay with `is_sufficient=true` "Trust Backed" assets from dedicated + // `pallet_assets` instance - `Assets`. cumulus_primitives_utility::TakeFirstAssetTrader< AccountId, AssetFeeAsExistentialDepositMultiplierFeeCharger, @@ -427,6 +443,19 @@ impl xcm_executor::Config for XcmConfig { XcmAssetFeesReceiver, >, >, + // This trader allows to pay with `is_sufficient=true` "Foreign" assets from dedicated + // `pallet_assets` instance - `ForeignAssets`. + cumulus_primitives_utility::TakeFirstAssetTrader< + AccountId, + ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger, + ForeignAssetsConvertedConcreteId, + ForeignAssets, + cumulus_primitives_utility::XcmFeesTo32ByteAccount< + ForeignFungiblesTransactor, + AccountId, + XcmAssetFeesReceiver, + >, + >, ); type ResponseHandler = PolkadotXcm; type AssetTrap = PolkadotXcm; @@ -438,7 +467,7 @@ impl xcm_executor::Config for XcmConfig { type AssetExchanger = (); type FeeManager = (); type MessageExporter = (); - type UniversalAliases = Nothing; + type UniversalAliases = bridging::UniversalAliases; type CallDispatcher = WithOriginFilter; type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; @@ -448,14 +477,17 @@ impl xcm_executor::Config for XcmConfig { /// Forms the basis for local origins sending/executing XCMs. pub type LocalOriginToLocation = SignedToAccountId32; -/// The means for routing XCM messages which are not for local execution into the right message -/// queues. -pub type XcmRouter = WithUniqueTopic<( +/// For routing XCM messages which do not cross local consensus boundary. +type LocalXcmRouter = ( // Two routers - use UMP to communicate with the relay chain: cumulus_primitives_utility::ParentAsUmp, // ..and XCMP to communicate with the sibling chains. XcmpQueue, -)>; +); + +/// The means for routing XCM messages which are not for local execution into the right message +/// queues. +pub type XcmRouter = WithUniqueTopic<(LocalXcmRouter, bridging::BridgingXcmRouter)>; #[cfg(feature = "runtime-benchmarks")] parameter_types! { @@ -474,7 +506,10 @@ impl pallet_xcm::Config for Runtime { type XcmExecuteFilter = Nothing; type XcmExecutor = XcmExecutor; type XcmTeleportFilter = Everything; - type XcmReserveTransferFilter = Everything; + // Allow reserve based transfer to everywhere except for bridging, here we strictly check what + // assets are allowed. + type XcmReserveTransferFilter = + EverythingBut; type Weigher = WeightInfoBounds< crate::weights::xcm::AssetHubPolkadotXcmWeight, RuntimeCall, @@ -532,3 +567,118 @@ fn foreign_pallet_has_correct_local_account() { let address = Ss58Codec::to_ss58check_with_version(&account, polkadot); assert_eq!(address, "13w7NdvSR1Af8xsQTArDtZmVvjE8XhWNdL4yed3iFHrUNCnS"); } + +/// All configuration related to bridging +pub mod bridging { + use super::*; + use assets_common::{matching, matching::*}; + use parachains_common::xcm_config::LocationFilter; + use sp_std::collections::btree_set::BTreeSet; + use xcm_builder::UnpaidRemoteExporter; + + parameter_types! { + pub BridgeHubPolkadotParaId: u32 = 1002; + pub BridgeHubPolkadot: MultiLocation = MultiLocation::new(1, X1(Parachain(BridgeHubPolkadotParaId::get()))); + pub BridgeHubPolkadotWithBridgeHubKusamaInstance: MultiLocation = MultiLocation::new(1, X2(Parachain(BridgeHubPolkadotParaId::get()), PalletInstance(53))); + pub const KusamaNetwork: NetworkId = NetworkId::Kusama; + pub AssetHubKusama: MultiLocation = MultiLocation::new(2, X2(GlobalConsensus(KusamaNetwork::get()), Parachain(1000))); + pub KsmLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(KusamaNetwork::get()))); + + /// Set up exporters configuration. + pub BridgeTable: sp_std::vec::Vec<(NetworkId, LocationFilter, MultiLocation, Option)> = sp_std::vec![ + ( + KusamaNetwork::get(), + LocationFilter::default() + // allow to bridge to AssetHubKusama + .add_equals(AssetHubKusama::get().interior.split_global().expect("invalid configuration for AssetHubKusama").1), + // and nothing else + BridgeHubPolkadot::get(), + None + ) + ]; + + /// Set up trusted bridged reserve locations. + /// Locations from which the runtime accepts reserved assets. + pub TrustedBridgedReserveLocations: sp_std::vec::Vec = sp_std::vec![ + // trust assets from AssetHubKusama + ( + AssetHubKusama::get(), + AssetFilter::ByMultiLocation( + LocationFilter::default() + // allow receive KSM + .add_equals(KsmLocation::get()) + // and nothing else + ) + ) + ]; + + /// Allowed reserve transfer assets per destination. + /// Means that runtime allows to transfer reserve assets to these locations. + pub AllowedReserveTransferAssetsLocations: sp_std::vec::Vec = sp_std::vec![ + // allow to transfer assets to AssetHubKusama + ( + AssetHubKusama::get(), + AssetFilter::ByMultiLocation( + LocationFilter::default() + // allow send only DOT + .add_equals(DotLocation::get()) + // and nothing else + ) + ) + ]; + + /// Universal aliases + pub UniversalAliases: BTreeSet<(MultiLocation, Junction)> = BTreeSet::from_iter( + sp_std::vec![ + (BridgeHubPolkadotWithBridgeHubKusamaInstance::get(), GlobalConsensus(KusamaNetwork::get())) + ] + ); + } + + impl Contains<(MultiLocation, Junction)> for UniversalAliases { + fn contains(alias: &(MultiLocation, Junction)) -> bool { + UniversalAliases::get().contains(alias) + } + } + + pub type FilteredNetworkExportTable = + parachains_common::xcm_config::FilteredNetworkExportTable; + + /// Bridge router, which wraps and sends xcm to BridgeHub to be delivered to the different + /// GlobalConsensus + pub type BridgingXcmRouter = + UnpaidRemoteExporter; + + /// Reserve locations filter for `xcm_executor::Config::IsReserve`. + pub type IsTrustedBridgedReserveLocationForConcreteAsset = + matching::IsTrustedBridgedReserveLocationForConcreteAsset< + UniversalLocation, + TrustedBridgedReserveLocations, + >; + + /// Filter out those assets which are not allowed for bridged reserve based transfer. + /// (asset, location) filter for `pallet_xcm::Config::XcmReserveTransferFilter`. + pub type IsNotAllowedExplicitlyForReserveTransfer = ExcludeOnlyForRemoteDestination< + UniversalLocation, + FilteredNetworkExportTable, + IsNotAllowedConcreteAssetBy, + >; + + /// Benchmarks helper for bridging configuration. + #[cfg(feature = "runtime-benchmarks")] + pub struct BridgingBenchmarksHelper; + + #[cfg(feature = "runtime-benchmarks")] + impl BridgingBenchmarksHelper { + pub fn prepare_universal_alias() -> Option<(MultiLocation, Junction)> { + let alias = UniversalAliases::get().into_iter().find_map(|(location, junction)| { + match BridgeHubPolkadotWithBridgeHubKusamaInstance::get().eq(&location) { + true => Some((location, junction)), + false => None, + } + }); + assert!(alias.is_some(), "we expect here BridgeHubPolkadot to Kusama mapping at least"); + Some(alias.unwrap()) + } + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs index 7200ebc16a28..f76f11bac176 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs @@ -18,20 +18,21 @@ //! Tests for the Statemint (Polkadot Assets Hub) chain. use asset_hub_polkadot_runtime::xcm_config::{ - AssetFeeAsExistentialDepositMultiplierFeeCharger, CheckingAccount, DotLocation, - ForeignCreatorsSovereignAccountOf, TrustBackedAssetsPalletLocation, XcmConfig, + bridging, AssetFeeAsExistentialDepositMultiplierFeeCharger, CheckingAccount, DotLocation, + ForeignCreatorsSovereignAccountOf, LocationToAccountId, TrustBackedAssetsPalletLocation, + XcmConfig, }; pub use asset_hub_polkadot_runtime::{ AllPalletsWithoutSystem, AssetDeposit, Assets, Balances, ExistentialDeposit, ForeignAssets, ForeignAssetsInstance, MetadataDepositBase, MetadataDepositPerByte, ParachainSystem, Runtime, - RuntimeCall, RuntimeEvent, SessionKeys, System, TrustBackedAssetsInstance, + RuntimeCall, RuntimeEvent, SessionKeys, System, TrustBackedAssetsInstance, XcmpQueue, }; -use asset_test_utils::{CollatorSessionKeys, ExtBuilder}; +use asset_test_utils::{CollatorSessionKey, CollatorSessionKeys, ExtBuilder}; use codec::{Decode, Encode}; use cumulus_primitives_utility::ChargeWeightInFungibles; use frame_support::{ assert_noop, assert_ok, - traits::fungibles::InspectEnumerable, + traits::{fungibles::InspectEnumerable, Contains}, weights::{Weight, WeightToFee as WeightToFeeT}, }; use parachains_common::{ @@ -50,14 +51,18 @@ type AssetIdForTrustBackedAssetsConvert = type RuntimeHelper = asset_test_utils::RuntimeHelper; -fn collator_session_keys() -> CollatorSessionKeys { - CollatorSessionKeys::new( - AccountId::from(ALICE), - AccountId::from(ALICE), - SessionKeys { aura: AuraId::from(sp_core::ed25519::Public::from_raw(ALICE)) }, +fn collator_session_key(account: [u8; 32]) -> CollatorSessionKey { + CollatorSessionKey::new( + AccountId::from(account), + AccountId::from(account), + SessionKeys { aura: AuraId::from(sp_core::ed25519::Public::from_raw(account)) }, ) } +fn collator_session_keys() -> CollatorSessionKeys { + CollatorSessionKeys::default().add(collator_session_key(ALICE)) +} + #[test] fn test_asset_xcm_trader() { ExtBuilder::::default() @@ -657,3 +662,147 @@ asset_test_utils::include_create_and_manage_foreign_assets_for_local_consensus_p assert_eq!(ForeignAssets::asset_ids().collect::>().len(), 1); }) ); + +fn bridging_to_asset_hub_kusama() -> asset_test_utils::test_cases_over_bridge::TestBridgingConfig { + asset_test_utils::test_cases_over_bridge::TestBridgingConfig { + bridged_network: bridging::KusamaNetwork::get(), + local_bridge_hub_para_id: bridging::BridgeHubPolkadotParaId::get(), + local_bridge_hub_location: bridging::BridgeHubPolkadot::get(), + bridged_target_location: bridging::AssetHubKusama::get(), + } +} + +#[test] +fn limited_reserve_transfer_assets_for_native_asset_over_bridge_works() { + asset_test_utils::test_cases_over_bridge::limited_reserve_transfer_assets_for_native_asset_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ParachainSystem, + XcmpQueue, + LocationToAccountId, + >( + collator_session_keys(), + ExistentialDeposit::get(), + AccountId::from(ALICE), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::PolkadotXcm(event)) => Some(event), + _ => None, + } + }), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::XcmpQueue(event)) => Some(event), + _ => None, + } + }), + bridging_to_asset_hub_kusama, + WeightLimit::Unlimited, + ) +} + +#[test] +fn receive_reserve_asset_deposited_ksm_from_asset_hub_kusama_works() { + const BLOCK_AUTHOR_ACCOUNT: [u8; 32] = [13; 32]; + asset_test_utils::test_cases_over_bridge::receive_reserve_asset_deposited_from_different_consensus_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + LocationToAccountId, + ForeignAssetsInstance, + >( + collator_session_keys().add(collator_session_key(BLOCK_AUTHOR_ACCOUNT)), + ExistentialDeposit::get(), + AccountId::from([73; 32]), + AccountId::from(BLOCK_AUTHOR_ACCOUNT), + // receiving DOTs + (MultiLocation { parents: 2, interior: X1(GlobalConsensus(Kusama)) }, 1000000000000, 10_000_000_000), + bridging_to_asset_hub_kusama, + (X1(PalletInstance(53)), GlobalConsensus(Kusama), X1(Parachain(1000))) + ) +} + +/// Tests expected configuration of isolated `pallet_xcm::Config::XcmReserveTransferFilter`. +#[test] +fn xcm_reserve_transfer_filter_works() { + // prepare assets + let only_native_assets = || vec![MultiAsset::from((DotLocation::get(), 1000))]; + let only_trust_backed_assets = || { + vec![MultiAsset::from(( + AssetIdForTrustBackedAssetsConvert::convert_back(&12345).unwrap(), + 2000, + ))] + }; + let only_sibling_foreign_assets = + || vec![MultiAsset::from((MultiLocation::new(1, X1(Parachain(12345))), 3000))]; + let only_different_global_consensus_foreign_assets = || { + vec![MultiAsset::from(( + MultiLocation::new(2, X2(GlobalConsensus(Kusama), Parachain(12345))), + 4000, + ))] + }; + + // prepare destinations + let relaychain = MultiLocation::parent(); + let sibling_parachain = MultiLocation::new(1, X1(Parachain(54321))); + let different_global_consensus_parachain_other_than_asset_hub_kusama = + MultiLocation::new(2, X2(GlobalConsensus(Kusama), Parachain(12345))); + let bridged_asset_hub = bridging::AssetHubKusama::get(); + + // prepare expected test data sets: (destination, assets, expected_result) + let test_data = vec![ + (relaychain, only_native_assets(), true), + (relaychain, only_trust_backed_assets(), true), + (relaychain, only_sibling_foreign_assets(), true), + (relaychain, only_different_global_consensus_foreign_assets(), true), + (sibling_parachain, only_native_assets(), true), + (sibling_parachain, only_trust_backed_assets(), true), + (sibling_parachain, only_sibling_foreign_assets(), true), + (sibling_parachain, only_different_global_consensus_foreign_assets(), true), + ( + different_global_consensus_parachain_other_than_asset_hub_kusama, + only_native_assets(), + false, + ), + ( + different_global_consensus_parachain_other_than_asset_hub_kusama, + only_trust_backed_assets(), + false, + ), + ( + different_global_consensus_parachain_other_than_asset_hub_kusama, + only_sibling_foreign_assets(), + false, + ), + ( + different_global_consensus_parachain_other_than_asset_hub_kusama, + only_different_global_consensus_foreign_assets(), + false, + ), + (bridged_asset_hub, only_native_assets(), true), + (bridged_asset_hub, only_trust_backed_assets(), false), + (bridged_asset_hub, only_sibling_foreign_assets(), false), + (bridged_asset_hub, only_different_global_consensus_foreign_assets(), false), + ]; + + // lets test filter with test data + ExtBuilder::::default() + .with_collators(collator_session_keys().collators()) + .with_session_keys(collator_session_keys().session_keys()) + .build() + .execute_with(|| { + type XcmReserveTransferFilter = + ::XcmReserveTransferFilter; + for (dest, assets, expected_result) in test_data { + assert_eq!( + expected_result, + XcmReserveTransferFilter::contains(&(dest, assets.clone())), + "expected_result: {} for dest: {:?} and assets: {:?}", + expected_result, + dest, + assets + ); + } + }) +} diff --git a/cumulus/parachains/runtimes/assets/common/src/matching.rs b/cumulus/parachains/runtimes/assets/common/src/matching.rs index 08d391170014..0402e7a560ed 100644 --- a/cumulus/parachains/runtimes/assets/common/src/matching.rs +++ b/cumulus/parachains/runtimes/assets/common/src/matching.rs @@ -18,10 +18,12 @@ use frame_support::{ pallet_prelude::Get, traits::{Contains, ContainsPair}, }; +use parachains_common::xcm_config::{LocationFilter, MatchesLocation}; use xcm::{ latest::prelude::{MultiAsset, MultiLocation}, prelude::*, }; +use xcm_builder::{ensure_is_remote, ExporterFor}; pub struct StartsWith(sp_std::marker::PhantomData); impl> Contains for StartsWith { @@ -82,3 +84,163 @@ impl> ContainsPair } } } + +/// Adapter verifies if it is allowed to receive `MultiAsset` from `MultiLocation`. +/// +/// Note: `MultiLocation` has to be from different global consensus. +pub struct IsTrustedBridgedReserveLocationForConcreteAsset( + sp_std::marker::PhantomData<(UniversalLocation, Reserves)>, +); +impl< + UniversalLocation: Get, + Reserves: Get>, + > ContainsPair + for IsTrustedBridgedReserveLocationForConcreteAsset +{ + fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool { + let universal_source = UniversalLocation::get(); + log::trace!( + target: "xcm::contains", + "IsTrustedBridgedReserveLocationForConcreteAsset asset: {:?}, origin: {:?}, universal_source: {:?}", + asset, origin, universal_source + ); + + // check remote origin + let _ = match ensure_is_remote(universal_source, *origin) { + Ok(devolved) => devolved, + Err(_) => { + log::trace!( + target: "xcm::contains", + "IsTrustedBridgedReserveLocationForConcreteAsset origin: {:?} is not remote to the universal_source: {:?}", + origin, universal_source + ); + return false + }, + }; + + // check asset location + let asset_location = match &asset.id { + Concrete(location) => location, + _ => return false, + }; + + // check asset according to the configured reserve locations + for (reserve_location, asset_filter) in Reserves::get() { + if origin.eq(&reserve_location) { + if asset_filter.matches(asset_location) { + return true + } + } + } + + false + } +} + +/// Filter assets that are explicitly not allowed for destination. +/// +/// Returns true if asset is not `Concrete` or is explicitly not allowed by `LocationAssetFilters`. +/// Returns false if `dest` does not match any location in `LocationAssetFilters`. +pub struct IsNotAllowedConcreteAssetBy( + sp_std::marker::PhantomData, +); +impl>> + Contains<(MultiLocation, sp_std::vec::Vec)> + for IsNotAllowedConcreteAssetBy +{ + fn contains((dest, assets): &(MultiLocation, sp_std::vec::Vec)) -> bool { + for (allowed_dest, asset_filter) in LocationAssetFilters::get().iter() { + // we care only about explicitly configured destinations + if !allowed_dest.eq(dest) { + continue + } + + // check all assets + for asset in assets { + let asset_location = match &asset.id { + Concrete(location) => location, + _ => return true, + }; + + // filter have to match for all assets + if !asset_filter.matches(asset_location) { + // if asset does not match filter, we found explicitly not allowed asset + return true + } + } + } + + // by default, everything is allowed + false + } +} + +/// Adapter for `Contains<(MultiLocation, sp_std::vec::Vec)>` which checks +/// if `Exporters` contains exporter for **remote** `MultiLocation` and iff so, then checks +/// `Filter`, anyway return false. +/// +/// Note: Assumes that `Exporters` do not depend on `XCM program` and works for `Xcm::default()`. +pub struct ExcludeOnlyForRemoteDestination( + sp_std::marker::PhantomData<(UniversalLocation, Exporters, Exclude)>, +); +impl Contains<(MultiLocation, sp_std::vec::Vec)> + for ExcludeOnlyForRemoteDestination +where + UniversalLocation: Get, + Exporters: ExporterFor, + Exclude: Contains<(MultiLocation, sp_std::vec::Vec)>, +{ + fn contains(dest_and_assets: &(MultiLocation, sp_std::vec::Vec)) -> bool { + let universal_source = UniversalLocation::get(); + log::trace!( + target: "xcm::contains", + "CheckOnlyForRemoteDestination dest: {:?}, assets: {:?}, universal_source: {:?}", + dest_and_assets.0, dest_and_assets.1, universal_source + ); + + // check if it is remote destination + match ensure_is_remote(universal_source, dest_and_assets.0) { + Ok((remote_network, remote_destination)) => { + if Exporters::exporter_for(&remote_network, &remote_destination, &Xcm::default()) + .is_some() + { + Exclude::contains(dest_and_assets) + } else { + log::trace!( + target: "xcm::contains", + "CheckOnlyForRemoteDestination no exporter for dest: {:?}", + dest_and_assets.0 + ); + // no exporter means that we exclude by default + true + } + }, + Err(_) => { + log::trace!( + target: "xcm::contains", + "CheckOnlyForRemoteDestination dest: {:?} is not remote to the universal_source: {:?}", + dest_and_assets.0, universal_source + ); + // + false + }, + } + } +} + +/// Location as `MultiLocation` with `AssetFilter`. +pub type FilteredLocation = (MultiLocation, AssetFilter); + +/// Simple asset location filter. +#[derive(Debug)] +pub enum AssetFilter { + ByMultiLocation(LocationFilter), +} + +impl MatchesLocation for AssetFilter { + fn matches(&self, asset_location: &MultiLocation) -> bool { + match self { + AssetFilter::ByMultiLocation(by_location) => by_location.matches(asset_location), + } + } +} diff --git a/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml b/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml index 7fee710f000c..691314419102 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml @@ -36,6 +36,7 @@ parachains-runtimes-test-utils = { path = "../../test-utils", default-features = # Polkadot xcm = { package = "staging-xcm", path = "../../../../../polkadot/xcm", default-features = false} +xcm-builder = { package = "staging-xcm-builder", path = "../../../../../polkadot/xcm/xcm-builder", default-features = false} xcm-executor = { package = "staging-xcm-executor", path = "../../../../../polkadot/xcm/xcm-executor", default-features = false} pallet-xcm = { path = "../../../../../polkadot/xcm/pallet-xcm", default-features = false} polkadot-parachain-primitives = { path = "../../../../../polkadot/parachain", default-features = false} @@ -72,6 +73,7 @@ std = [ "sp-io/std", "sp-runtime/std", "sp-std/std", + "xcm-builder/std", "xcm-executor/std", "xcm/std", ] diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/lib.rs b/cumulus/parachains/runtimes/assets/test-utils/src/lib.rs index 7177726e0704..3c62faf3d5ec 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/lib.rs @@ -17,4 +17,5 @@ //! Module contains predefined test-case scenarios for `Runtime` with various assets. pub mod test_cases; +pub mod test_cases_over_bridge; pub use parachains_runtimes_test_utils::*; diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs index 7a8d571403c6..6503d7e6a736 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs @@ -78,6 +78,7 @@ pub fn teleports_for_native_asset_works< Into<<::RuntimeOrigin as OriginTrait>::AccountId>, <::Lookup as StaticLookup>::Source: From<::AccountId>, + ::AccountId: From, XcmConfig: xcm_executor::Config, CheckingAccount: Get>, HrmpChannelOpener: frame_support::inherent::ProvideInherent< @@ -96,7 +97,7 @@ pub fn teleports_for_native_asset_works< let included_head = RuntimeHelper::::run_to_block( 2, - AccountId::from(alice), + AccountId::from(alice).into(), ); // check Balances before assert_eq!(>::free_balance(&target_account), 0.into()); @@ -346,6 +347,7 @@ pub fn teleports_for_foreign_assets_works< Into<<::RuntimeOrigin as OriginTrait>::AccountId>, <::Lookup as StaticLookup>::Source: From<::AccountId>, + ::AccountId: From, ForeignAssetsPalletInstance: 'static, { // foreign parachain with the same consenus currency as asset @@ -391,7 +393,7 @@ pub fn teleports_for_foreign_assets_works< let included_head = RuntimeHelper::::run_to_block( 2, - AccountId::from(alice), + AccountId::from(alice).into(), ); // checks target_account before assert_eq!( @@ -1005,6 +1007,7 @@ macro_rules! include_asset_transactor_transfer_with_pallet_assets_instance_works } ); +/// Test-case makes sure that `Runtime` can create and manage `ForeignAssets` pub fn create_and_manage_foreign_assets_for_local_consensus_parachain_assets_works< Runtime, XcmConfig, diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs new file mode 100644 index 000000000000..a815367587ab --- /dev/null +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs @@ -0,0 +1,504 @@ +// Copyright (C) 2023 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Module contains predefined test-case scenarios for `Runtime` with various assets transferred +//! over a bridge. + +use codec::Encode; +use cumulus_primitives_core::XcmpMessageSource; +use frame_support::{ + assert_ok, + traits::{Currency, OnFinalize, OnInitialize, OriginTrait, ProcessMessageError}, +}; +use frame_system::pallet_prelude::BlockNumberFor; +use parachains_common::{AccountId, Balance}; +use parachains_runtimes_test_utils::{ + mock_open_hrmp_channel, AccountIdOf, BalanceOf, CollatorSessionKeys, ExtBuilder, RuntimeHelper, + ValidatorIdOf, XcmReceivedFrom, +}; +use sp_runtime::traits::StaticLookup; +use xcm::{latest::prelude::*, VersionedMultiAssets}; +use xcm_builder::{CreateMatcher, MatchXcm}; +use xcm_executor::{traits::ConvertLocation, XcmExecutor}; + +pub struct TestBridgingConfig { + pub bridged_network: NetworkId, + pub local_bridge_hub_para_id: u32, + pub local_bridge_hub_location: MultiLocation, + pub bridged_target_location: MultiLocation, +} + +/// Test-case makes sure that `Runtime` can initiate **reserve transfer assets** over bridge. +pub fn limited_reserve_transfer_assets_for_native_asset_works< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + HrmpChannelOpener, + HrmpChannelSource, + LocationToAccountId, +>( + collator_session_keys: CollatorSessionKeys, + existential_deposit: BalanceOf, + alice_account: AccountIdOf, + unwrap_pallet_xcm_event: Box) -> Option>>, + unwrap_xcmp_queue_event: Box< + dyn Fn(Vec) -> Option>, + >, + ensure_configuration: fn() -> TestBridgingConfig, + weight_limit: WeightLimit, +) where + Runtime: frame_system::Config + + pallet_balances::Config + + pallet_session::Config + + pallet_xcm::Config + + parachain_info::Config + + pallet_collator_selection::Config + + cumulus_pallet_parachain_system::Config + + cumulus_pallet_xcmp_queue::Config, + AllPalletsWithoutSystem: + OnInitialize> + OnFinalize>, + AccountIdOf: Into<[u8; 32]>, + ValidatorIdOf: From>, + BalanceOf: From, + ::Balance: From + Into, + XcmConfig: xcm_executor::Config, + LocationToAccountId: ConvertLocation>, + ::AccountId: + Into<<::RuntimeOrigin as OriginTrait>::AccountId>, + <::Lookup as StaticLookup>::Source: + From<::AccountId>, + ::AccountId: From, + HrmpChannelOpener: frame_support::inherent::ProvideInherent< + Call = cumulus_pallet_parachain_system::Call, + >, + HrmpChannelSource: XcmpMessageSource, +{ + let runtime_para_id = 1000; + ExtBuilder::::default() + .with_collators(collator_session_keys.collators()) + .with_session_keys(collator_session_keys.session_keys()) + .with_tracing() + .with_safe_xcm_version(3) + .with_para_id(runtime_para_id.into()) + .build() + .execute_with(|| { + let mut alice = [0u8; 32]; + alice[0] = 1; + let included_head = RuntimeHelper::::run_to_block( + 2, + AccountId::from(alice).into(), + ); + + // prepare bridge config + let TestBridgingConfig { + bridged_network, + local_bridge_hub_para_id, + bridged_target_location: target_location_from_different_consensus, + .. + } = ensure_configuration(); + + let reserve_account = + LocationToAccountId::convert_location(&target_location_from_different_consensus) + .expect("Sovereign account for reserves"); + let balance_to_transfer = 1_000_000_000_000_u128; + let native_asset = MultiLocation::parent(); + + // open HRMP to bridge hub + mock_open_hrmp_channel::( + runtime_para_id.into(), + local_bridge_hub_para_id.into(), + included_head, + &alice, + ); + + // drip ED to account + let alice_account_init_balance = existential_deposit + balance_to_transfer.into(); + let _ = >::deposit_creating( + &alice_account, + alice_account_init_balance, + ); + // SA of target location needs to have at least ED, otherwise making reserve fails + let _ = >::deposit_creating( + &reserve_account, + existential_deposit, + ); + + // we just check here, that user retains enough balance after withdrawal + // and also we check if `balance_to_transfer` is more than `existential_deposit`, + assert!( + (>::free_balance(&alice_account) - + balance_to_transfer.into()) >= + existential_deposit + ); + // SA has just ED + assert_eq!( + >::free_balance(&reserve_account), + existential_deposit + ); + + // local native asset (pallet_balances) + let asset_to_transfer = MultiAsset { + fun: Fungible(balance_to_transfer.into()), + id: Concrete(native_asset), + }; + + // destination is (some) account relative to the destination different consensus + let target_destination_account = MultiLocation { + parents: 0, + interior: X1(AccountId32 { + network: Some(bridged_network), + id: sp_runtime::AccountId32::new([3; 32]).into(), + }), + }; + + // do pallet_xcm call reserve transfer + assert_ok!(>::limited_reserve_transfer_assets( + RuntimeHelper::::origin_of(alice_account.clone()), + Box::new(target_location_from_different_consensus.into_versioned()), + Box::new(target_destination_account.into_versioned()), + Box::new(VersionedMultiAssets::from(MultiAssets::from(asset_to_transfer))), + 0, + weight_limit, + )); + + // check alice account decreased by balance_to_transfer + assert_eq!( + >::free_balance(&alice_account), + alice_account_init_balance - balance_to_transfer.into() + ); + + // check reserve account + // check reserve account increased by balance_to_transfer + assert_eq!( + >::free_balance(&reserve_account), + existential_deposit + balance_to_transfer.into() + ); + + // check events + // check pallet_xcm attempted + RuntimeHelper::::assert_pallet_xcm_event_outcome( + &unwrap_pallet_xcm_event, + |outcome| { + assert_ok!(outcome.ensure_complete()); + }, + ); + + // check that xcm was sent + let xcm_sent_message_hash = >::events() + .into_iter() + .filter_map(|e| unwrap_xcmp_queue_event(e.event.encode())) + .find_map(|e| match e { + cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { message_hash } => + Some(message_hash), + _ => None, + }); + + // read xcm + let xcm_sent = RuntimeHelper::::take_xcm( + local_bridge_hub_para_id.into(), + ) + .unwrap(); + + assert_eq!( + xcm_sent_message_hash, + Some(xcm_sent.using_encoded(sp_io::hashing::blake2_256)) + ); + let mut xcm_sent: Xcm<()> = xcm_sent.try_into().expect("versioned xcm"); + + // check sent XCM ExportMessage to bridge-hub + xcm_sent + .0 + .matcher() + .match_next_inst(|instr| match instr { + // first instruction is UNpai (because we have explicit unpaid execution on + // bridge-hub now) + UnpaidExecution { weight_limit, check_origin } + if weight_limit == &Unlimited && check_origin.is_none() => + Ok(()), + _ => Err(ProcessMessageError::BadFormat), + }) + .expect("contains UnpaidExecution") + .match_next_inst(|instr| match instr { + // second instruction is ExportMessage + ExportMessage { network, destination, xcm: inner_xcm } => { + assert_eq!(network, &bridged_network); + let (_, target_location_junctions_without_global_consensus) = + target_location_from_different_consensus + .interior + .split_global() + .expect("split works"); + assert_eq!( + destination, + &target_location_junctions_without_global_consensus + ); + assert_matches_pallet_xcm_reserve_transfer_assets_instructions(inner_xcm); + Ok(()) + }, + _ => Err(ProcessMessageError::BadFormat), + }) + .expect("contains ExportMessage"); + }) +} + +pub fn receive_reserve_asset_deposited_from_different_consensus_works< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + LocationToAccountId, + ForeignAssetsPalletInstance, +>( + collator_session_keys: CollatorSessionKeys, + existential_deposit: BalanceOf, + target_account: AccountIdOf, + block_author_account: AccountIdOf, + ( + foreign_asset_id_multilocation, + transfered_foreign_asset_id_amount, + foreign_asset_id_minimum_balance, + ): (MultiLocation, u128, u128), + ensure_configuration: fn() -> TestBridgingConfig, + (bridge_instance, universal_origin, descend_origin): (Junctions, Junction, Junctions), /* bridge adds origin manipulation on the way */ +) where + Runtime: frame_system::Config + + pallet_balances::Config + + pallet_session::Config + + pallet_xcm::Config + + parachain_info::Config + + pallet_collator_selection::Config + + cumulus_pallet_parachain_system::Config + + cumulus_pallet_xcmp_queue::Config + + pallet_assets::Config, + AllPalletsWithoutSystem: + OnInitialize> + OnFinalize>, + AccountIdOf: Into<[u8; 32]>, + ValidatorIdOf: From>, + BalanceOf: From, + XcmConfig: xcm_executor::Config, + LocationToAccountId: ConvertLocation>, + >::AssetId: + From + Into, + >::AssetIdParameter: + From + Into, + >::Balance: + From + Into + From, + ::AccountId: + Into<<::RuntimeOrigin as OriginTrait>::AccountId>, + <::Lookup as StaticLookup>::Source: + From<::AccountId>, + ForeignAssetsPalletInstance: 'static, +{ + ExtBuilder::::default() + .with_collators(collator_session_keys.collators()) + .with_session_keys(collator_session_keys.session_keys()) + .with_tracing() + .build() + .execute_with(|| { + // Set account as block author, who will receive fees + RuntimeHelper::::run_to_block( + 2, + block_author_account.clone(), + ); + + // prepare bridge config + let TestBridgingConfig { local_bridge_hub_location, .. } = ensure_configuration(); + + // drip 'ED' user target account + let _ = >::deposit_creating( + &target_account, + existential_deposit, + ); + + // sovereign account as foreign asset owner (can be whoever for this scenario, doesnt + // matter) + let sovereign_account_as_owner_of_foreign_asset = + LocationToAccountId::convert_location(&MultiLocation::parent()).unwrap(); + + // staking pot account for collecting local native fees from `BuyExecution` + let staking_pot = >::account_id(); + let _ = >::deposit_creating( + &staking_pot, + existential_deposit, + ); + + // create foreign asset for wrapped/derivated representation + assert_ok!( + >::force_create( + RuntimeHelper::::root_origin(), + foreign_asset_id_multilocation.into(), + sovereign_account_as_owner_of_foreign_asset.clone().into(), + true, // is_sufficient=true + foreign_asset_id_minimum_balance.into() + ) + ); + + // Balances before + assert_eq!( + >::free_balance(&target_account), + existential_deposit.clone() + ); + assert_eq!( + >::free_balance(&block_author_account), + 0.into() + ); + assert_eq!( + >::free_balance(&staking_pot), + existential_deposit.clone() + ); + + // ForeignAssets balances before + assert_eq!( + >::balance( + foreign_asset_id_multilocation.into(), + &target_account + ), + 0.into() + ); + assert_eq!( + >::balance( + foreign_asset_id_multilocation.into(), + &block_author_account + ), + 0.into() + ); + assert_eq!( + >::balance( + foreign_asset_id_multilocation.into(), + &staking_pot + ), + 0.into() + ); + + // Call received XCM execution + let xcm = Xcm(vec![ + DescendOrigin(bridge_instance), + UniversalOrigin(universal_origin), + DescendOrigin(descend_origin), + ReserveAssetDeposited(MultiAssets::from(vec![MultiAsset { + id: Concrete(foreign_asset_id_multilocation), + fun: Fungible(transfered_foreign_asset_id_amount), + }])), + ClearOrigin, + BuyExecution { + fees: MultiAsset { + id: Concrete(foreign_asset_id_multilocation), + fun: Fungible(transfered_foreign_asset_id_amount), + }, + weight_limit: Unlimited, + }, + DepositAsset { + assets: Wild(AllCounted(1)), + beneficiary: MultiLocation { + parents: 0, + interior: X1(AccountId32 { + network: None, + id: target_account.clone().into(), + }), + }, + }, + SetTopic([ + 220, 188, 144, 32, 213, 83, 111, 175, 44, 210, 111, 19, 90, 165, 191, 112, 140, + 247, 192, 124, 42, 17, 153, 141, 114, 34, 189, 20, 83, 69, 237, 173, + ]), + ]); + assert_matches_pallet_xcm_reserve_transfer_assets_instructions(&mut xcm.clone()); + + let hash = xcm.using_encoded(sp_io::hashing::blake2_256); + + // execute xcm as XcmpQueue would do + let outcome = XcmExecutor::::execute_xcm( + local_bridge_hub_location, + xcm, + hash, + RuntimeHelper::::xcm_max_weight( + XcmReceivedFrom::Sibling, + ), + ); + assert_eq!(outcome.ensure_complete(), Ok(())); + + // author actual balance after (received fees from Trader for ForeignAssets) + let author_received_fees = + >::balance( + foreign_asset_id_multilocation.into(), + &block_author_account, + ); + + // Balances after (untouched) + assert_eq!( + >::free_balance(&target_account), + existential_deposit.clone() + ); + assert_eq!( + >::free_balance(&block_author_account), + 0.into() + ); + assert_eq!( + >::free_balance(&staking_pot), + existential_deposit.clone() + ); + + // ForeignAssets balances after + assert_eq!( + >::balance( + foreign_asset_id_multilocation.into(), + &target_account + ), + (transfered_foreign_asset_id_amount - author_received_fees.into()).into() + ); + assert_eq!( + >::balance( + foreign_asset_id_multilocation.into(), + &block_author_account + ), + author_received_fees + ); + assert_eq!( + >::balance( + foreign_asset_id_multilocation.into(), + &staking_pot + ), + 0.into() + ); + }) +} + +fn assert_matches_pallet_xcm_reserve_transfer_assets_instructions( + xcm: &mut Xcm, +) { + let _ = xcm + .0 + .matcher() + .skip_inst_while(|inst| !matches!(inst, ReserveAssetDeposited(..))) + .expect("no instruction ReserveAssetDeposited?") + .match_next_inst(|instr| match instr { + ReserveAssetDeposited(..) => Ok(()), + _ => Err(ProcessMessageError::BadFormat), + }) + .expect("expected instruction ReserveAssetDeposited") + .match_next_inst(|instr| match instr { + ClearOrigin => Ok(()), + _ => Err(ProcessMessageError::BadFormat), + }) + .expect("expected instruction ClearOrigin") + .match_next_inst(|instr| match instr { + BuyExecution { .. } => Ok(()), + _ => Err(ProcessMessageError::BadFormat), + }) + .expect("expected instruction BuyExecution") + .match_next_inst(|instr| match instr { + DepositAsset { .. } => Ok(()), + _ => Err(ProcessMessageError::BadFormat), + }) + .expect("expected instruction DepositAsset"); +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/README.md b/cumulus/parachains/runtimes/bridge-hubs/README.md index 487c601ef840..56b6ad3ed620 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/README.md +++ b/cumulus/parachains/runtimes/bridge-hubs/README.md @@ -2,13 +2,16 @@ - [Requirements for local run/testing](#requirements-for-local-runtesting) - [How to test local Rococo <-> Wococo bridge](#how-to-test-local-rococo---wococo-bridge) - [Run chains (Rococo + BridgeHub, Wococo + BridgeHub) with - zombienet](#run-chains-rococo--bridgehub-wococo--bridgehub-with-zombienet) + zombienet](#run-chains-rococo--bridgehub--assethub-wococo--bridgehub--assethub-with-zombienet) - [Run relayer (BridgeHubRococo, BridgeHubWococo)](#run-relayer-bridgehubrococo-bridgehubwococo) - [Run with script (alternative 1)](#run-with-script-alternative-1) - [Run with binary (alternative 2)](#run-with-binary-alternative-2) - [Send messages - transfer asset over bridge](#send-messages---transfer-asset-over-bridge) - [How to test live BridgeHubRococo/BridgeHubWococo](#how-to-test-live-bridgehubrococobridgehubwococo) - [How to test local BridgeHubKusama/BridgeHubPolkadot](#how-to-test-local-bridgehubkusamabridgehubpolkadot) + - [1. Run chains (Kusama + BridgeHub + AssetHub, Polkadot + BridgeHub + AssetHub) with zombienet](#1-run-chains-kusama--bridgehub--assethub-polkadot--bridgehub--assethub-with-zombienet) + - [2. Init bridge and run relayer (BridgeHubKusama, BridgeHubPolkadot)](#2-init-bridge-and-run-relayer-bridgehubkusama-bridgehubpolkadot) + - [Send messages - transfer asset over bridge (DOTs/KSMs)](#4-send-messages---transfer-asset-over-bridge-dotsksms) # Bridge-hub Parachains @@ -227,7 +230,60 @@ is going to be replaced by `pallet_xcm` usage) https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fwococo-wockmint-rpc.polkadot.io#/explorer - BridgeHubRococo (see `bridgeWococoMessages.MessagesDelivered`) - ## How to test local BridgeHubKusama/BridgeHubPolkadot -TODO: see `# !!! READ HERE` above +Check [requirements](#requirements-for-local-runtesting) for "sudo pallet + fast-runtime". + +### 1. Run chains (Kusama + BridgeHub + AssetHub, Polkadot + BridgeHub + AssetHub) with zombienet + +``` +# Kusama + BridgeHubKusama + AssetHubKusama +POLKADOT_BINARY_PATH=~/local_bridge_testing/bin/polkadot \ +POLKADOT_PARACHAIN_BINARY_PATH=~/local_bridge_testing/bin/polkadot-parachain \ +POLKADOT_PARACHAIN_BINARY_PATH_FOR_ASSET_HUB_KUSAMA=~/local_bridge_testing/bin/polkadot-parachain-asset-hub \ + ~/local_bridge_testing/bin/zombienet-linux --provider native spawn ./zombienet/bridge-hubs/bridge_hub_kusama_local_network.toml +``` + +``` +# Polkadot + BridgeHubPolkadot + AssetHubPolkadot +POLKADOT_BINARY_PATH=~/local_bridge_testing/bin/polkadot \ +POLKADOT_PARACHAIN_BINARY_PATH=~/local_bridge_testing/bin/polkadot-parachain \ +POLKADOT_PARACHAIN_BINARY_PATH_FOR_ASSET_HUB_POLKADOT=~/local_bridge_testing/bin/polkadot-parachain-asset-hub \ + ~/local_bridge_testing/bin/zombienet-linux --provider native spawn ./zombienet/bridge-hubs/bridge_hub_polkadot_local_network.toml +``` + +### 2. Init bridge and run relayer (BridgeHubKusama, BridgeHubPolkadot) + +``` +cd +./scripts/bridges_kusama_polkadot.sh run-relay +``` + +### 3. Initialize transfer asset over bridge (DOTs/KSMs) + +This initialization does several things: +- creates `ForeignAssets` for wrappedDOTs/wrappedKSMs +- drips SA for AssetHubKusama on AssetHubPolkadot (and vice versa) which holds reserved assets on source chains +``` +./scripts/bridges_kusama_polkadot.sh init-asset-hub-kusama-local +./scripts/bridges_kusama_polkadot.sh init-asset-hub-polkadot-local +``` + +### 4. Send messages - transfer asset over bridge (DOTs/KSMs) + +Do (asset) transfers: +``` +# KSMs from Kusama's Asset Hub to Polkadot's. +./scripts/bridges_kusama_polkadot.sh reserve-transfer-assets-from-asset-hub-kusama-local +``` +``` +# DOTs from Polkadot's Asset Hub to Kusama's. +./scripts/bridges_kusama_polkadot.sh reserve-transfer-assets-from-asset-hub-polkadot-local +``` + +- open explorers: (see zombienets) + - AssetHubKusama (see events `xcmpQueue.XcmpMessageSent`, `polkadotXcm.Attempted`) https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:9910#/explorer + - BridgeHubKusama (see `bridgePolkadotMessages.MessageAccepted`) https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:8943#/explorer + - BridgeHubPolkadot (see `bridgeKusamaMessages.MessagesReceived`, `xcmpQueue.XcmpMessageSent`) https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:8945#/explorer + - AssetHubPolkadot (see `foreignAssets.Issued`, `xcmpQueue.Success`) https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:9010#/explorer + - BridgeHubKusama (see `bridgePolkadotMessages.MessagesDelivered`) https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:8943#/explorer 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 aa7fa16a9791..a3e36a39fd1e 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 @@ -249,6 +249,7 @@ pub fn message_dispatch_routing_works< XcmConfig: xcm_executor::Config, MessagesPalletInstance: 'static, ValidatorIdOf: From>, + ::AccountId: From, HrmpChannelOpener: frame_support::inherent::ProvideInherent< Call = cumulus_pallet_parachain_system::Call, >, @@ -272,7 +273,7 @@ pub fn message_dispatch_routing_works< let included_head = RuntimeHelper::::run_to_block( 2, - AccountId::from(alice), + AccountId::from(alice).into(), ); // 1. this message is sent from other global consensus with destination of this Runtime relay chain (UMP) let bridging_message = @@ -374,6 +375,7 @@ pub fn relayed_incoming_message_works>::BridgedChain as bp_runtime::Chain>::Hash>, ::AccountId: Into<<::RuntimeOrigin as OriginTrait>::AccountId>, + ::AccountId: From, AccountIdOf: From, >::InboundRelayer: From, { @@ -393,7 +395,7 @@ pub fn relayed_incoming_message_works::run_to_block( 2, - AccountId::from(alice), + AccountId::from(alice).into(), ); mock_open_hrmp_channel::( runtime_para_id.into(), @@ -591,6 +593,7 @@ pub fn complex_relay_extrinsic_works::AccountId: Into<<::RuntimeOrigin as OriginTrait>::AccountId>, AccountIdOf: From, + ::AccountId: From, >::InboundRelayer: From, ::RuntimeCall: From> @@ -622,7 +625,7 @@ pub fn complex_relay_extrinsic_works::run_to_block( 2, - AccountId::from(alice), + AccountId::from(alice).into(), ); let zero: BlockNumberFor = 0u32.into(); let genesis_hash = frame_system::Pallet::::block_hash(zero); @@ -928,7 +931,7 @@ pub mod test_data { ); /// Simulates `HaulBlobExporter` and all its wrapping and captures generated plain bytes, - /// which are transfered over bridge. + /// which are transferred over bridge. pub(crate) fn simulate_message_exporter_on_bridged_chain< SourceNetwork: Get, DestinationNetwork: Get, diff --git a/cumulus/parachains/runtimes/test-utils/Cargo.toml b/cumulus/parachains/runtimes/test-utils/Cargo.toml index 681e5e64d412..6aec711f4a56 100644 --- a/cumulus/parachains/runtimes/test-utils/Cargo.toml +++ b/cumulus/parachains/runtimes/test-utils/Cargo.toml @@ -28,11 +28,11 @@ cumulus-pallet-xcmp-queue = { path = "../../../pallets/xcmp-queue", default-feat cumulus-pallet-dmp-queue = { path = "../../../pallets/dmp-queue", default-features = false } pallet-collator-selection = { path = "../../../pallets/collator-selection", default-features = false } parachains-common = { path = "../../common", default-features = false } +parachain-info = { path = "../../pallets/parachain-info", default-features = false } assets-common = { path = "../assets/common", default-features = false } cumulus-primitives-core = { path = "../../../primitives/core", default-features = false } cumulus-primitives-parachain-inherent = { path = "../../../primitives/parachain-inherent", default-features = false } cumulus-test-relay-sproof-builder = { path = "../../../test/relay-sproof-builder", default-features = false } -parachain-info = { path = "../../pallets/parachain-info", default-features = false } # Polkadot xcm = { package = "staging-xcm", path = "../../../../polkadot/xcm", default-features = false} diff --git a/cumulus/parachains/runtimes/test-utils/src/lib.rs b/cumulus/parachains/runtimes/test-utils/src/lib.rs index 8289a80baa11..3f13b78fb59b 100644 --- a/cumulus/parachains/runtimes/test-utils/src/lib.rs +++ b/cumulus/parachains/runtimes/test-utils/src/lib.rs @@ -24,11 +24,12 @@ use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder; use frame_support::{ dispatch::{DispatchResult, RawOrigin}, inherent::{InherentData, ProvideInherent}, + pallet_prelude::Get, traits::{OnFinalize, OnInitialize, OriginTrait, UnfilteredDispatchable}, weights::Weight, }; use frame_system::pallet_prelude::{BlockNumberFor, HeaderFor}; -use parachains_common::{AccountId, SLOT_DURATION}; +use parachains_common::SLOT_DURATION; use polkadot_parachain_primitives::primitives::{ HeadData, HrmpChannelId, RelayChainBlockNumber, XcmpMessageFormat, }; @@ -49,7 +50,7 @@ pub type AccountIdOf = ::AccountId; pub type ValidatorIdOf = ::ValidatorId; pub type SessionKeysOf = ::Keys; -pub struct CollatorSessionKeys< +pub struct CollatorSessionKey< Runtime: frame_system::Config + pallet_balances::Config + pallet_session::Config, > { collator: AccountIdOf, @@ -57,8 +58,14 @@ pub struct CollatorSessionKeys< key: SessionKeysOf, } +pub struct CollatorSessionKeys< + Runtime: frame_system::Config + pallet_balances::Config + pallet_session::Config, +> { + items: Vec>, +} + impl - CollatorSessionKeys + CollatorSessionKey { pub fn new( collator: AccountIdOf, @@ -67,14 +74,43 @@ impl Self { Self { collator, validator, key } } +} + +impl Default + for CollatorSessionKeys +{ + fn default() -> Self { + Self { items: vec![] } + } +} + +impl + CollatorSessionKeys +{ + pub fn new( + collator: AccountIdOf, + validator: ValidatorIdOf, + key: SessionKeysOf, + ) -> Self { + Self { items: vec![CollatorSessionKey::new(collator, validator, key)] } + } + + pub fn add(mut self, item: CollatorSessionKey) -> Self { + self.items.push(item); + self + } + pub fn collators(&self) -> Vec> { - vec![self.collator.clone()] + self.items.iter().map(|item| item.collator.clone()).collect::>() } pub fn session_keys( &self, ) -> Vec<(AccountIdOf, ValidatorIdOf, SessionKeysOf)> { - vec![(self.collator.clone(), self.validator.clone(), self.key.clone())] + self.items + .iter() + .map(|item| (item.collator.clone(), item.validator.clone(), item.key.clone())) + .collect::>() } } @@ -225,7 +261,7 @@ where AllPalletsWithoutSystem: OnInitialize> + OnFinalize>, { - pub fn run_to_block(n: u32, author: AccountId) -> HeaderFor { + pub fn run_to_block(n: u32, author: AccountIdOf) -> HeaderFor { let mut last_header = None; loop { let block_number = frame_system::Pallet::::block_number(); @@ -360,7 +396,6 @@ impl { pub fn xcm_max_weight(from: XcmReceivedFrom) -> Weight { - use frame_support::traits::Get; match from { XcmReceivedFrom::Parent => ParachainSystem::ReservedDmpWeight::get(), XcmReceivedFrom::Sibling => ParachainSystem::ReservedXcmpWeight::get(), diff --git a/cumulus/scripts/bridges_kusama_polkadot.sh b/cumulus/scripts/bridges_kusama_polkadot.sh new file mode 100755 index 000000000000..43ca5356d2c0 --- /dev/null +++ b/cumulus/scripts/bridges_kusama_polkadot.sh @@ -0,0 +1,195 @@ +#!/bin/bash + +# import common functions +source "$(dirname "$0")"/bridges_rococo_wococo.sh "import" + +# Address: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY +# AccountId: [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] +ASSET_HUB_KUSAMA_ACCOUNT_SEED_FOR_LOCAL="//Alice" +# Address: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY +# AccountId: [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] +ASSET_HUB_POLKADOT_ACCOUNT_ADDRESS_FOR_LOCAL="5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" + +# Expected sovereign accounts. +# +# Generated by: +# +# #[test] +# fn generate_sovereign_accounts() { +# use sp_core::crypto::Ss58Codec; +# +# parameter_types! { +# pub UniversalLocationAHK: InteriorMultiLocation = X2(GlobalConsensus(Kusama), Parachain(1000)); +# pub UniversalLocationAHP: InteriorMultiLocation = X2(GlobalConsensus(Polkadot), Parachain(1000)); +# } +# +# // SS58=0 +# println!("GLOBAL_CONSENSUS_KUSAMA_SOVEREIGN_ACCOUNT=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# GlobalConsensusConvertsFor::::convert_location( +# &MultiLocation { parents: 2, interior: X1(GlobalConsensus(Kusama)) }).unwrap() +# ).to_ss58check_with_version(0_u16.into()) +# ); +# println!("GLOBAL_CONSENSUS_KUSAMA_ASSET_HUB_KUSAMA_1000_SOVEREIGN_ACCOUNT=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# GlobalConsensusParachainConvertsFor::::convert_location( +# &MultiLocation { parents: 2, interior: X2(GlobalConsensus(Kusama), Parachain(1000)) }).unwrap() +# ).to_ss58check_with_version(0_u16.into()) +# ); +# +# // SS58=2 +# println!("GLOBAL_CONSENSUS_POLKADOT_SOVEREIGN_ACCOUNT=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# GlobalConsensusConvertsFor::::convert_location( +# &MultiLocation { parents: 2, interior: X1(GlobalConsensus(Polkadot)) }).unwrap() +# ).to_ss58check_with_version(2_u16.into()) +# ); +# println!("GLOBAL_CONSENSUS_POLKADOT_ASSET_HUB_POLKADOT_1000_SOVEREIGN_ACCOUNT=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# GlobalConsensusParachainConvertsFor::::convert_location( +# &MultiLocation { parents: 2, interior: X2(GlobalConsensus(Polkadot), Parachain(1000)) }).unwrap() +# ).to_ss58check_with_version(2_u16.into()) +# ); +# } +GLOBAL_CONSENSUS_KUSAMA_SOVEREIGN_ACCOUNT="14zcUAhP5XypiFQWA3b1AnGKrhZqR4XWUo4deWkwuN5y983G" +GLOBAL_CONSENSUS_KUSAMA_ASSET_HUB_KUSAMA_1000_SOVEREIGN_ACCOUNT="12GvRkNCmXFuaaziTJ2ZKAfa7MArKfLT2HYvLjQuepP3JuHf" +GLOBAL_CONSENSUS_POLKADOT_SOVEREIGN_ACCOUNT="FxqimVubBRPqJ8kTwb3wL7G4q645hEkBEnXPyttLsTrFc5Q" +GLOBAL_CONSENSUS_POLKADOT_ASSET_HUB_POLKADOT_1000_SOVEREIGN_ACCOUNT="FwGjEp7GXJXT9NjH8r4sqdyd8XZVogbxSs3iFakx4wFwJ5Y" + +function init_ksm_dot() { + ensure_relayer + + RUST_LOG=runtime=trace,rpc=trace,bridge=trace \ + ~/local_bridge_testing/bin/substrate-relay init-bridge kusama-to-bridge-hub-polkadot \ + --source-host localhost \ + --source-port 9942 \ + --source-version-mode Auto \ + --target-host localhost \ + --target-port 8945 \ + --target-version-mode Auto \ + --target-signer //Bob +} + +function init_dot_ksm() { + ensure_relayer + + RUST_LOG=runtime=trace,rpc=trace,bridge=trace \ + ~/local_bridge_testing/bin/substrate-relay init-bridge polkadot-to-bridge-hub-kusama \ + --source-host localhost \ + --source-port 9945 \ + --source-version-mode Auto \ + --target-host localhost \ + --target-port 8943 \ + --target-version-mode Auto \ + --target-signer //Bob +} + +function run_relay() { + ensure_relayer + +RUST_LOG=runtime=trace,rpc=trace,bridge=trace \ + ~/local_bridge_testing/bin/substrate-relay relay-headers-and-messages bridge-hub-kusama-bridge-hub-polkadot \ + --kusama-host localhost \ + --kusama-port 9942 \ + --kusama-version-mode Auto \ + --bridge-hub-kusama-host localhost \ + --bridge-hub-kusama-port 8943 \ + --bridge-hub-kusama-version-mode Auto \ + --bridge-hub-kusama-signer //Charlie \ + --polkadot-headers-to-bridge-hub-kusama-signer //Bob \ + --polkadot-parachains-to-bridge-hub-kusama-signer //Bob \ + --bridge-hub-kusama-transactions-mortality 4 \ + --polkadot-host localhost \ + --polkadot-port 9945 \ + --polkadot-version-mode Auto \ + --bridge-hub-polkadot-host localhost \ + --bridge-hub-polkadot-port 8945 \ + --bridge-hub-polkadot-version-mode Auto \ + --bridge-hub-polkadot-signer //Charlie \ + --kusama-headers-to-bridge-hub-polkadot-signer //Bob \ + --kusama-parachains-to-bridge-hub-polkadot-signer //Bob \ + --bridge-hub-polkadot-transactions-mortality 4 \ + --lane 00000000 +} + +case "$1" in + run-relay) + init_ksm_dot + init_dot_ksm + run_relay + ;; + init-asset-hub-kusama-local) + # create foreign assets for native Polkadot token (governance call on Kusama) + force_create_foreign_asset \ + "ws://127.0.0.1:9942" \ + "//Alice" \ + 1000 \ + "ws://127.0.0.1:9910" \ + "$(jq --null-input '{ "parents": 2, "interior": { "X1": { "GlobalConsensus": "Polkadot" } } }')" \ + "$GLOBAL_CONSENSUS_POLKADOT_SOVEREIGN_ACCOUNT" \ + 1000000000 \ + true + # drip SA which holds reserves + transfer_balance \ + "ws://127.0.0.1:9910" \ + "//Alice" \ + "$GLOBAL_CONSENSUS_POLKADOT_ASSET_HUB_POLKADOT_1000_SOVEREIGN_ACCOUNT" \ + $((1000000000 + 50000000000 * 20)) + ;; + init-asset-hub-polkadot-local) + # create foreign assets for native Polkadot token (governance call on Kusama) + force_create_foreign_asset \ + "ws://127.0.0.1:9945" \ + "//Alice" \ + 1000 \ + "ws://127.0.0.1:9010" \ + "$(jq --null-input '{ "parents": 2, "interior": { "X1": { "GlobalConsensus": "Kusama" } } }')" \ + "$GLOBAL_CONSENSUS_KUSAMA_SOVEREIGN_ACCOUNT" \ + 1000000000 \ + true + # drip SA which holds reserves + transfer_balance \ + "ws://127.0.0.1:9010" \ + "//Alice" \ + "$GLOBAL_CONSENSUS_KUSAMA_ASSET_HUB_KUSAMA_1000_SOVEREIGN_ACCOUNT" \ + $((1000000000 + 50000000000 * 20)) + ;; + reserve-transfer-assets-from-asset-hub-kusama-local) + ensure_polkadot_js_api + # send KSMs to Alice account on AHP + limited_reserve_transfer_assets \ + "ws://127.0.0.1:9910" \ + "//Alice" \ + "$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Polkadot" }, { "Parachain": 1000 } ] } } }')" \ + "$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "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] } } } } }')" \ + "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 1, "interior": "Here" } }, "fun": { "Fungible": 1000000000000 } } ] }')" \ + 0 \ + "Unlimited" + ;; + reserve-transfer-assets-from-asset-hub-polkadot-local) + ensure_polkadot_js_api + # send DOTs to Alice account on AHH + limited_reserve_transfer_assets \ + "ws://127.0.0.1:9010" \ + "//Alice" \ + "$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Kusama" }, { "Parachain": 1000 } ] } } }')" \ + "$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "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] } } } } }')" \ + "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 1, "interior": "Here" } }, "fun": { "Fungible": 2000000000000 } } ] }')" \ + 0 \ + "Unlimited" + ;; + stop) + pkill -f polkadot + pkill -f parachain + ;; + *) + echo "A command is require. Supported commands for: + Local (zombienet) run: + - run-relay + - init-asset-hub-kusama-local + - init-asset-hub-polkadot-local + - reserve-transfer-assets-from-asset-hub-kusama-local + - reserve-transfer-assets-from-asset-hub-polkadot-local"; + exit 1 + ;; +esac diff --git a/cumulus/scripts/bridges_rococo_wococo.sh b/cumulus/scripts/bridges_rococo_wococo.sh index 1117ed681092..2ed43a4be64e 100755 --- a/cumulus/scripts/bridges_rococo_wococo.sh +++ b/cumulus/scripts/bridges_rococo_wococo.sh @@ -270,38 +270,60 @@ function force_create_foreign_asset() { local relay_chain_seed=$2 local runtime_para_id=$3 local runtime_para_endpoint=$4 - local global_consensus=$5 + local asset_multilocation=$5 local asset_owner_account_id=$6 + local min_balance=$7 + local is_sufficient=$8 echo " calling force_create_foreign_asset:" echo " relay_url: ${relay_url}" echo " relay_chain_seed: ${relay_chain_seed}" echo " runtime_para_id: ${runtime_para_id}" echo " runtime_para_endpoint: ${runtime_para_endpoint}" - echo " global_consensus: ${global_consensus}" + echo " asset_multilocation: ${asset_multilocation}" echo " asset_owner_account_id: ${asset_owner_account_id}" + echo " min_balance: ${min_balance}" + echo " is_sufficient: ${is_sufficient}" echo " params:" # 1. generate data for Transact (ForeignAssets::force_create) - local asset_id=$(jq --null-input \ - --arg global_consensus "$global_consensus" \ - ' - { - "parents": 2, - "interior": { - "X1": { - "GlobalConsensus": $global_consensus, - } - } - } - ' - ) local tmp_output_file=$(mktemp) - generate_hex_encoded_call_data "force-create-asset" "${runtime_para_endpoint}" "${tmp_output_file}" "$asset_id" "$asset_owner_account_id" false "1000" + generate_hex_encoded_call_data "force-create-asset" "${runtime_para_endpoint}" "${tmp_output_file}" "$asset_multilocation" "$asset_owner_account_id" $is_sufficient $min_balance local hex_encoded_data=$(cat $tmp_output_file) + # 2. trigger governance call send_governance_transact "${relay_url}" "${relay_chain_seed}" "${runtime_para_id}" "${hex_encoded_data}" 200000000 12000 } +function limited_reserve_transfer_assets() { + local url=$1 + local seed=$2 + local destination=$3 + local beneficiary=$4 + local assets=$5 + local fee_asset_item=$6 + local weight_limit=$7 + echo " calling limited_reserve_transfer_assets:" + echo " url: ${url}" + echo " seed: ${seed}" + echo " destination: ${destination}" + echo " beneficiary: ${beneficiary}" + echo " assets: ${assets}" + echo " fee_asset_item: ${fee_asset_item}" + echo " weight_limit: ${weight_limit}" + echo "" + echo "--------------------------------------------------" + + polkadot-js-api \ + --ws "${url?}" \ + --seed "${seed?}" \ + tx.polkadotXcm.limitedReserveTransferAssets \ + "${destination}" \ + "${beneficiary}" \ + "${assets}" \ + "${fee_asset_item}" \ + "${weight_limit}" +} + function allow_assets_transfer_receive() { local relay_url=$1 local relay_chain_seed=$2 diff --git a/cumulus/zombienet/bridge-hubs/bridge_hub_kusama_local_network.toml b/cumulus/zombienet/bridge-hubs/bridge_hub_kusama_local_network.toml new file mode 100644 index 000000000000..7f753d6dd504 --- /dev/null +++ b/cumulus/zombienet/bridge-hubs/bridge_hub_kusama_local_network.toml @@ -0,0 +1,107 @@ +[settings] +node_spawn_timeout = 240 + +[relaychain] +default_command = "{{POLKADOT_BINARY_PATH}}" +default_args = [ "-lparachain=debug,xcm=trace" ] +chain = "kusama-local" + + [[relaychain.nodes]] + name = "alice-validator" + validator = true + rpc_port = 9932 + ws_port = 9942 + extra_args = ["--no-mdns --bootnodes {{'bob-validator'|zombie('multiAddress')}}"] + balance = 2000000000000 + + [[relaychain.nodes]] + name = "bob-validator" + validator = true + rpc_port = 9933 + ws_port = 9943 + extra_args = ["--no-mdns --bootnodes {{'alice-validator'|zombie('multiAddress')}}"] + balance = 2000000000000 + + [[relaychain.nodes]] + name = "charlie-validator" + validator = true + rpc_port = 9934 + ws_port = 9944 + extra_args = ["--no-mdns --bootnodes {{'alice-validator'|zombie('multiAddress')}}"] + balance = 2000000000000 + +[[parachains]] +id = 1002 +chain = "bridge-hub-kusama-local" +cumulus_based = true + + # run alice as parachain collator + [[parachains.collators]] + name = "alice-collator" + validator = true + command = "{{POLKADOT_PARACHAIN_BINARY_PATH}}" + rpc_port = 8933 + ws_port = 8943 + args = [ + "-lparachain=debug,runtime::bridge-hub=trace,runtime::bridge=trace,runtime::bridge-dispatch=trace,bridge=trace,runtime::bridge-messages=trace,xcm=trace", + ] + extra_args = [ + "--force-authoring", "--no-mdns", "--bootnodes {{'bob-collator'|zombie('multiAddress')}}", + "-- --port 41333 --rpc-port 48933 --ws-port 48943 --no-mdns", "--bootnodes {{'alice-validator'|zombie('multiAddress')}}" + ] + + # run bob as parachain collator + [[parachains.collators]] + name = "bob-collator" + validator = true + command = "{{POLKADOT_PARACHAIN_BINARY_PATH}}" + rpc_port = 8934 + ws_port = 8944 + args = [ + "-lparachain=trace,runtime::bridge-hub=trace,runtime::bridge=trace,runtime::bridge-dispatch=trace,bridge=trace,runtime::bridge-messages=trace,xcm=trace", + ] + extra_args = [ + "--force-authoring", "--no-mdns", "--bootnodes {{'alice-collator'|zombie('multiAddress')}}", + "-- --port 41334 --rpc-port 48934 --ws-port 48944 --no-mdns", "--bootnodes {{'bob-validator'|zombie('multiAddress')}}" + ] + +[[parachains]] +id = 1000 +chain = "asset-hub-kusama-local" +cumulus_based = true + + [[parachains.collators]] + name = "asset-hub-kusama-collator1" + rpc_port = 9911 + ws_port = 9910 + command = "{{POLKADOT_PARACHAIN_BINARY_PATH_FOR_ASSET_HUB_KUSAMA}}" + args = [ + "-lparachain=debug,xcm=trace,runtime::bridge-transfer=trace", + ] + extra_args = [ + "--no-mdns", "--bootnodes {{'asset-hub-kusama-collator2'|zombie('multiAddress')}}", + "-- --port 51333 --rpc-port 58933 --ws-port 58943 --no-mdns", "--bootnodes {{'alice-validator'|zombie('multiAddress')}}" + ] + + [[parachains.collators]] + name = "asset-hub-kusama-collator2" + command = "{{POLKADOT_PARACHAIN_BINARY_PATH_FOR_ASSET_HUB_KUSAMA}}" + args = [ + "-lparachain=debug,xcm=trace,runtime::bridge-transfer=trace", + ] + extra_args = [ + "--no-mdns", "--bootnodes {{'asset-hub-kusama-collator1'|zombie('multiAddress')}}", + "-- --port 51433 --rpc-port 58833 --ws-port 58843 --no-mdns", "--bootnodes {{'alice-validator'|zombie('multiAddress')}}" + ] + +[[hrmp_channels]] +sender = 1000 +recipient = 1002 +max_capacity = 4 +max_message_size = 524288 + +[[hrmp_channels]] +sender = 1002 +recipient = 1000 +max_capacity = 4 +max_message_size = 524288 diff --git a/cumulus/zombienet/bridge-hubs/bridge_hub_polkadot_local_network.toml b/cumulus/zombienet/bridge-hubs/bridge_hub_polkadot_local_network.toml new file mode 100644 index 000000000000..320456a25652 --- /dev/null +++ b/cumulus/zombienet/bridge-hubs/bridge_hub_polkadot_local_network.toml @@ -0,0 +1,107 @@ +[settings] +node_spawn_timeout = 240 + +[relaychain] +default_command = "{{POLKADOT_BINARY_PATH}}" +default_args = [ "-lparachain=debug,xcm=trace" ] +chain = "polkadot-local" + + [[relaychain.nodes]] + name = "alice-validator-dot" + validator = true + rpc_port = 9935 + ws_port = 9945 + extra_args = ["--no-mdns --bootnodes {{'bob-validator-dot'|zombie('multiAddress')}}"] + balance = 2000000000000 + + [[relaychain.nodes]] + name = "bob-validator-dot" + validator = true + rpc_port = 9936 + ws_port = 9946 + extra_args = ["--no-mdns --bootnodes {{'alice-validator-dot'|zombie('multiAddress')}}"] + balance = 2000000000000 + + [[relaychain.nodes]] + name = "charlie-validator-dot" + validator = true + rpc_port = 9937 + ws_port = 9947 + extra_args = ["--no-mdns --bootnodes {{'alice-validator-dot'|zombie('multiAddress')}}"] + balance = 2000000000000 + +[[parachains]] +id = 1002 +chain = "bridge-hub-polkadot-local" +cumulus_based = true + + # run alice as parachain collator + [[parachains.collators]] + name = "alice-collator-dot" + validator = true + command = "{{POLKADOT_PARACHAIN_BINARY_PATH}}" + rpc_port = 8935 + ws_port = 8945 + args = [ + "-lparachain=debug,runtime::mmr=info,substrate=info,runtime=info,runtime::bridge-hub=trace,runtime::bridge=trace,runtime::bridge-dispatch=trace,bridge=trace,runtime::bridge-messages=trace,xcm=trace", + ] + extra_args = [ + "--force-authoring", "--no-mdns", "--bootnodes {{'bob-collator-dot'|zombie('multiAddress')}}", + "-- --port 41335 --rpc-port 48935 --ws-port 48945 --no-mdns", "--bootnodes {{'alice-validator-dot'|zombie('multiAddress')}}" + ] + + # run bob as parachain collator + [[parachains.collators]] + name = "bob-collator-dot" + validator = true + command = "{{POLKADOT_PARACHAIN_BINARY_PATH}}" + rpc_port = 8936 + ws_port = 8946 + args = [ + "-lparachain=trace,runtime::mmr=info,substrate=info,runtime=info,runtime::bridge-hub=trace,runtime::bridge=trace,runtime::bridge-dispatch=trace,bridge=trace,runtime::bridge-messages=trace,xcm=trace", + ] + extra_args = [ + "--force-authoring", "--no-mdns", "--bootnodes {{'alice-collator-dot'|zombie('multiAddress')}}", + "-- --port 41336 --rpc-port 48936 --ws-port 48946 --no-mdns", "--bootnodes {{'bob-validator-dot'|zombie('multiAddress')}}" + ] + +[[parachains]] +id = 1000 +chain = "asset-hub-polkadot-local" +cumulus_based = true + + [[parachains.collators]] + name = "asset-hub-polkadot-collator1" + rpc_port = 9011 + ws_port = 9010 + command = "{{POLKADOT_PARACHAIN_BINARY_PATH_FOR_ASSET_HUB_POLKADOT}}" + args = [ + "-lparachain=debug,xcm=trace,runtime::bridge-transfer=trace", + ] + extra_args = [ + "--no-mdns", "--bootnodes {{'asset-hub-polkadot-collator2'|zombie('multiAddress')}}", + "-- --port 31333 --rpc-port 38933 --ws-port 38943 --no-mdns", "--bootnodes {{'alice-validator-dot'|zombie('multiAddress')}}" + ] + + [[parachains.collators]] + name = "asset-hub-polkadot-collator2" + command = "{{POLKADOT_PARACHAIN_BINARY_PATH_FOR_ASSET_HUB_POLKADOT}}" + args = [ + "-lparachain=debug,xcm=trace,runtime::bridge-transfer=trace", + ] + extra_args = [ + "--no-mdns", "--bootnodes {{'asset-hub-polkadot-collator1'|zombie('multiAddress')}}", + "-- --port 31433 --rpc-port 38833 --ws-port 38843 --no-mdns", "--bootnodes {{'alice-validator-dot'|zombie('multiAddress')}}" + ] + +[[hrmp_channels]] +sender = 1000 +recipient = 1002 +max_capacity = 4 +max_message_size = 524288 + +[[hrmp_channels]] +sender = 1002 +recipient = 1000 +max_capacity = 4 +max_message_size = 524288 From a51742095c42daa31628eb06910f90a32373136d Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Sun, 3 Sep 2023 21:25:24 +0200 Subject: [PATCH 02/17] Transfer reserve asset with dynamic fees and back-pressure. Change XCM routing configuration for bridging from unpaid to paid version. Paid version means that origin (besides extrinsic fees) pays delivery fees at source Asset Hub and also Asset Hub sovereign account pays for execution of `ExportMessage` instruction at local Bridge Hub. Change XCM bridging router from `UnpaidRemoteExporter` to `ToPolkadotXcmRouter` and `ToKusamaXcmRouter` which are pallet instances of new module `pallet-xcm-bridge-hub-router`. The main thing that the pallet `pallet-xcm-bridge-hub-router` offers is the dynamic message fee, that is computed based on the bridge queues state. It starts exponentially increasing if the queue between this chain and the sibling/child bridge hub is congested. More about dynamic fees and back-preasure for v1 can be found [here](https://github.com/paritytech/parity-bridges-common/pull/2294). Signed-off-by: Branislav Kontur Signed-off-by: Adrian Catangiu Signed-off-by: Svyatoslav Nikolsky Co-authored-by: Adrian Catangiu Co-authored-by: Svyatoslav Nikolsky --- Cargo.lock | 6 + cumulus/pallets/xcmp-queue/Cargo.toml | 5 + cumulus/pallets/xcmp-queue/src/bridging.rs | 116 +++++++++++ cumulus/pallets/xcmp-queue/src/lib.rs | 19 ++ cumulus/parachains/common/src/xcm_config.rs | 65 ++++++- .../assets/asset-hub-kusama/Cargo.toml | 10 +- .../assets/asset-hub-kusama/src/lib.rs | 56 ++++++ .../asset-hub-kusama/src/weights/mod.rs | 1 + .../weights/pallet_xcm_bridge_hub_router.rs | 118 ++++++++++++ .../assets/asset-hub-kusama/src/xcm_config.rs | 67 +++++-- .../assets/asset-hub-kusama/tests/tests.rs | 130 ++++++++++++- .../assets/asset-hub-polkadot/Cargo.toml | 10 +- .../assets/asset-hub-polkadot/src/lib.rs | 56 ++++++ .../asset-hub-polkadot/src/weights/mod.rs | 1 + .../weights/pallet_xcm_bridge_hub_router.rs | 118 ++++++++++++ .../asset-hub-polkadot/src/xcm_config.rs | 63 ++++-- .../assets/asset-hub-polkadot/tests/tests.rs | 132 ++++++++++++- .../runtimes/assets/test-utils/Cargo.toml | 4 + .../test-utils/src/test_cases_over_bridge.rs | 181 ++++++++++++++---- .../parachains/runtimes/bridge-hubs/README.md | 2 + .../parachains/runtimes/test-utils/src/lib.rs | 12 +- cumulus/scripts/bridges_kusama_polkadot.sh | 32 ++++ 22 files changed, 1134 insertions(+), 70 deletions(-) create mode 100644 cumulus/pallets/xcmp-queue/src/bridging.rs create mode 100644 cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/pallet_xcm_bridge_hub_router.rs create mode 100644 cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/pallet_xcm_bridge_hub_router.rs diff --git a/Cargo.lock b/Cargo.lock index 4a81c2221e1a..1f9a68787bf2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -722,6 +722,7 @@ version = "0.9.420" dependencies = [ "asset-test-utils", "assets-common", + "bp-asset-hub-kusama", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", @@ -761,6 +762,7 @@ dependencies = [ "pallet-utility", "pallet-xcm", "pallet-xcm-benchmarks", + "pallet-xcm-bridge-hub-router", "parachain-info", "parachains-common", "parity-scale-codec", @@ -818,6 +820,7 @@ version = "0.9.420" dependencies = [ "asset-test-utils", "assets-common", + "bp-asset-hub-polkadot", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", @@ -853,6 +856,7 @@ dependencies = [ "pallet-utility", "pallet-xcm", "pallet-xcm-benchmarks", + "pallet-xcm-bridge-hub-router", "parachain-info", "parachains-common", "parity-scale-codec", @@ -996,6 +1000,7 @@ dependencies = [ "pallet-collator-selection", "pallet-session", "pallet-xcm", + "pallet-xcm-bridge-hub-router", "parachain-info", "parachains-common", "parachains-runtimes-test-utils", @@ -3626,6 +3631,7 @@ dependencies = [ name = "cumulus-pallet-xcmp-queue" version = "0.1.0" dependencies = [ + "bp-xcm-bridge-hub-router", "cumulus-pallet-parachain-system", "cumulus-primitives-core", "frame-benchmarking", diff --git a/cumulus/pallets/xcmp-queue/Cargo.toml b/cumulus/pallets/xcmp-queue/Cargo.toml index de4ad61de9e0..0e6a34ecfe69 100644 --- a/cumulus/pallets/xcmp-queue/Cargo.toml +++ b/cumulus/pallets/xcmp-queue/Cargo.toml @@ -28,6 +28,9 @@ cumulus-primitives-core = { path = "../../primitives/core", default-features = f # Optional import for benchmarking frame-benchmarking = { path = "../../../substrate/frame/benchmarking", default-features = false, optional = true} +# Bridges +bp-xcm-bridge-hub-router = { path = "../../bridges/primitives/xcm-bridge-hub-router", default-features = false, optional = true } + [dev-dependencies] # Substrate @@ -43,6 +46,7 @@ cumulus-pallet-parachain-system = { path = "../parachain-system" } [features] default = [ "std" ] std = [ + "bp-xcm-bridge-hub-router/std", "codec/std", "cumulus-primitives-core/std", "frame-benchmarking?/std", @@ -77,3 +81,4 @@ try-runtime = [ "polkadot-runtime-common/try-runtime", "sp-runtime/try-runtime", ] +bridging = [ "bp-xcm-bridge-hub-router" ] diff --git a/cumulus/pallets/xcmp-queue/src/bridging.rs b/cumulus/pallets/xcmp-queue/src/bridging.rs new file mode 100644 index 000000000000..bd36ded8d628 --- /dev/null +++ b/cumulus/pallets/xcmp-queue/src/bridging.rs @@ -0,0 +1,116 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::pallet; +use cumulus_primitives_core::ParaId; +use frame_support::pallet_prelude::Get; + +/// Adapter implementation for `bp_xcm_bridge_hub_router::XcmChannelStatusProvider` which checks +/// both `OutboundXcmpStatus` and `InboundXcmpStatus` for defined `ParaId` if any of those is +/// suspended. +pub struct InboundAndOutboundXcmpChannelCongestionStatusProvider( + sp_std::marker::PhantomData<(SiblingBridgeHubParaId, Runtime)>, +); +impl, Runtime: crate::Config> + bp_xcm_bridge_hub_router::XcmChannelStatusProvider + for InboundAndOutboundXcmpChannelCongestionStatusProvider +{ + fn is_congested() -> bool { + // if the outbound channel with recipient is suspended, it means that one of further + // bridge queues (e.g. bridge queue between two bridge hubs) is overloaded, so we shall + // take larger fee for our outbound messages + let sibling_bridge_hub_id: ParaId = SiblingBridgeHubParaId::get(); + let outbound_channels = pallet::OutboundXcmpStatus::::get(); + let outbound_channel = + outbound_channels.iter().find(|c| c.recipient == sibling_bridge_hub_id); + let is_outbound_channel_suspended = + outbound_channel.map(|c| c.is_suspended()).unwrap_or(false); + if is_outbound_channel_suspended { + return true + } + + // if the inbound channel with recipient is suspended, it means that we are unable to + // receive congestion reports from the bridge hub. So we assume the bridge pipeline is + // congested too + let inbound_channels = pallet::InboundXcmpStatus::::get(); + let inbound_channel = inbound_channels.iter().find(|c| c.sender == sibling_bridge_hub_id); + let is_inbound_channel_suspended = + inbound_channel.map(|c| c.is_suspended()).unwrap_or(false); + if is_inbound_channel_suspended { + return true + } + + // TODO: https://github.com/paritytech/cumulus/pull/2342 - once this PR is merged, we may + // remove the following code + // + // if the outbound channel has at least `N` pages enqueued, let's assume it is congested. + // Normally, the chain with a few opened HRMP channels, will "send" pages at every block. + // Having `N` pages means that for last `N` blocks we either have not sent any messages, + // or have sent signals. + const MAX_OUTBOUND_PAGES_BEFORE_CONGESTION: u16 = 4; + let is_outbound_channel_congested = outbound_channel.map(|c| c.queued_pages()).unwrap_or(0); + is_outbound_channel_congested > MAX_OUTBOUND_PAGES_BEFORE_CONGESTION + } +} + +/// Adapter implementation for `bp_xcm_bridge_hub_router::XcmChannelStatusProvider` which checks +/// only `OutboundXcmpStatus` for defined `SiblingParaId` if is suspended. +pub struct OutboundXcmpChannelCongestionStatusProvider( + sp_std::marker::PhantomData<(SiblingBridgeHubParaId, Runtime)>, +); +impl, Runtime: crate::Config> + bp_xcm_bridge_hub_router::XcmChannelStatusProvider + for OutboundXcmpChannelCongestionStatusProvider +{ + fn is_congested() -> bool { + // let's find the channel with the sibling parachain + let sibling_para_id: cumulus_primitives_core::ParaId = SiblingParaId::get(); + let outbound_channels = pallet::OutboundXcmpStatus::::get(); + let channel_with_sibling_parachain = + outbound_channels.iter().find(|c| c.recipient == sibling_para_id); + + // no channel => it is empty, so not congested + let channel_with_sibling_parachain = match channel_with_sibling_parachain { + Some(channel_with_sibling_parachain) => channel_with_sibling_parachain, + None => return false, + }; + + // suspended channel => it is congested + if channel_with_sibling_parachain.is_suspended() { + return true + } + + // TODO: the following restriction is arguable, we may live without that, assuming that + // there can't be more than some `N` messages queued at the bridge queue (at the source BH) + // AND before accepting next (or next-after-next) delivery transaction, we'll receive the + // suspension signal from the target parachain and stop accepting delivery transactions + + // it takes some time for target parachain to suspend inbound channel with the target BH and + // during that we will keep accepting new message delivery transactions. Let's also reject + // new deliveries if there are too many "pages" (concatenated XCM messages) in the target BH + // -> target parachain queue. + const MAX_QUEUED_PAGES_BEFORE_DEACTIVATION: u16 = 4; + if channel_with_sibling_parachain.queued_pages() > MAX_QUEUED_PAGES_BEFORE_DEACTIVATION { + return true + } + + true + } +} + +#[cfg(feature = "runtime-benchmarks")] +pub fn suspend_channel_for_benchmarks(target: ParaId) { + pallet::Pallet::::suspend_channel(target) +} diff --git a/cumulus/pallets/xcmp-queue/src/lib.rs b/cumulus/pallets/xcmp-queue/src/lib.rs index 1cb92f595186..db9c433b52d3 100644 --- a/cumulus/pallets/xcmp-queue/src/lib.rs +++ b/cumulus/pallets/xcmp-queue/src/lib.rs @@ -35,6 +35,8 @@ mod tests; #[cfg(feature = "runtime-benchmarks")] mod benchmarking; +#[cfg(feature = "bridging")] +pub mod bridging; pub mod weights; pub use weights::WeightInfo; @@ -400,6 +402,13 @@ pub struct InboundChannelDetails { message_metadata: Vec<(RelayBlockNumber, XcmpMessageFormat)>, } +impl InboundChannelDetails { + #[cfg(feature = "bridging")] + pub(crate) fn is_suspended(&self) -> bool { + self.state == InboundState::Suspended + } +} + /// Struct containing detailed information about the outbound channel. #[derive(Clone, Eq, PartialEq, Encode, Decode, TypeInfo)] pub struct OutboundChannelDetails { @@ -435,6 +444,16 @@ impl OutboundChannelDetails { self.state = OutboundState::Suspended; self } + + #[cfg(feature = "bridging")] + pub(crate) fn is_suspended(&self) -> bool { + self.state == OutboundState::Suspended + } + + #[cfg(feature = "bridging")] + pub(crate) fn queued_pages(&self) -> u16 { + self.last_index.saturating_sub(self.first_index) + } } #[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] diff --git a/cumulus/parachains/common/src/xcm_config.rs b/cumulus/parachains/common/src/xcm_config.rs index aa1183f5d921..984cce297adf 100644 --- a/cumulus/parachains/common/src/xcm_config.rs +++ b/cumulus/parachains/common/src/xcm_config.rs @@ -14,16 +14,22 @@ // limitations under the License. use crate::impls::AccountIdOf; +use codec::Decode; use core::marker::PhantomData; use frame_support::{ - traits::{fungibles::Inspect, tokens::ConversionToAssetBalance, ContainsPair}, + ensure, + traits::{ + fungibles::Inspect, tokens::ConversionToAssetBalance, Contains, ContainsPair, + ProcessMessageError, + }, weights::Weight, DefaultNoBound, }; use log; use sp_runtime::traits::Get; -use xcm::latest::prelude::*; -use xcm_builder::ExporterFor; +use xcm::{latest::prelude::*, DoubleEncoded}; +use xcm_builder::{CreateMatcher, ExporterFor, MatchXcm}; +use xcm_executor::traits::ShouldExecute; /// A `ChargeFeeInFungibles` implementation that converts the output of /// a given WeightToFee implementation an amount charged in @@ -171,6 +177,59 @@ impl< } } +/// Allows execution from `origin` if it is contained in `AllowedOrigin` +/// and if it is just a straight `Transact` which contains `AllowedCall`. +pub struct AllowUnpaidTransactsFrom( + sp_std::marker::PhantomData<(RuntimeCall, AllowedCall, AllowedOrigin)>, +); +impl< + RuntimeCall: Decode, + AllowedCall: Contains, + AllowedOrigin: Contains, + > ShouldExecute for AllowUnpaidTransactsFrom +{ + fn should_execute( + origin: &MultiLocation, + instructions: &mut [Instruction], + max_weight: Weight, + _properties: &mut xcm_executor::traits::Properties, + ) -> Result<(), ProcessMessageError> { + log::trace!( + target: "xcm::barriers", + "AllowUnpaidTransactFrom origin: {:?}, instructions: {:?}, max_weight: {:?}, properties: {:?}", + origin, instructions, max_weight, _properties, + ); + + // we only allow from configured origins + ensure!(AllowedOrigin::contains(origin), ProcessMessageError::Unsupported); + + // we expect an XCM program with single `Transact` call + instructions + .matcher() + .assert_remaining_insts(1)? + .match_next_inst(|inst| match inst { + Transact { origin_kind: OriginKind::Xcm, call: encoded_call, .. } => { + // this is a hack - don't know if there's a way to do that properly + // or else we can simply allow all calls + let mut decoded_call = DoubleEncoded::::from(encoded_call.clone()); + ensure!( + AllowedCall::contains( + decoded_call + .ensure_decoded() + .map_err(|_| ProcessMessageError::BadFormat)? + ), + ProcessMessageError::BadFormat, + ); + + Ok(()) + }, + _ => Err(ProcessMessageError::BadFormat), + })?; + + Ok(()) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-kusama/Cargo.toml index 53555499842f..6a9f7c7f8a81 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/Cargo.toml @@ -71,7 +71,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 } @@ -79,6 +79,10 @@ parachain-info = { path = "../../../pallets/parachain-info", default-features = parachains-common = { path = "../../../common", default-features = false } assets-common = { path = "../common", default-features = false } +# Bridges +pallet-xcm-bridge-hub-router = { path = "../../../../bridges/modules/xcm-bridge-hub-router", default-features = false } +bp-asset-hub-kusama = { path = "../../../../bridges/primitives/chain-asset-hub-kusama", default-features = false } + [dev-dependencies] asset-test-utils = { path = "../test-utils" } @@ -117,6 +121,7 @@ runtime-benchmarks = [ "pallet-uniques/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-xcm-benchmarks/runtime-benchmarks", + "pallet-xcm-bridge-hub-router/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", "polkadot-runtime-common/runtime-benchmarks", @@ -151,6 +156,7 @@ try-runtime = [ "pallet-transaction-payment/try-runtime", "pallet-uniques/try-runtime", "pallet-utility/try-runtime", + "pallet-xcm-bridge-hub-router/try-runtime", "pallet-xcm/try-runtime", "parachain-info/try-runtime", "polkadot-runtime-common/try-runtime", @@ -158,6 +164,7 @@ try-runtime = [ ] std = [ "assets-common/std", + "bp-asset-hub-kusama/std", "codec/std", "cumulus-pallet-aura-ext/std", "cumulus-pallet-dmp-queue/std", @@ -196,6 +203,7 @@ std = [ "pallet-uniques/std", "pallet-utility/std", "pallet-xcm-benchmarks?/std", + "pallet-xcm-bridge-hub-router/std", "pallet-xcm/std", "parachain-info/std", "parachains-common/std", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs index f8ebdefe6870..44d6d81edd76 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs @@ -815,6 +815,38 @@ impl pallet_nfts::Config for Runtime { type Helper = (); } +/// XCM router instance to BridgeHub with bridging capabilities for `Polkadot` global consensus with +/// dynamic fees and back-pressure. +pub type ToPolkadotXcmRouterInstance = pallet_assets::Instance1; +impl pallet_xcm_bridge_hub_router::Config for Runtime { + type WeightInfo = weights::pallet_xcm_bridge_hub_router::WeightInfo; + + type UniversalLocation = xcm_config::UniversalLocation; + type BridgedNetworkId = xcm_config::bridging::PolkadotNetwork; + type Bridges = xcm_config::bridging::FilteredNetworkExportTable; + + #[cfg(not(feature = "runtime-benchmarks"))] + type BridgeHubOrigin = + EnsureXcm>; + #[cfg(feature = "runtime-benchmarks")] + type BridgeHubOrigin = EitherOfDiverse< + // for running benchmarks + EnsureRoot, + // for running tests with `--feature runtime-benchmarks` + EnsureXcm>, + >; + + type ToBridgeHubSender = XcmpQueue; + type WithBridgeHubChannel = + cumulus_pallet_xcmp_queue::bridging::InboundAndOutboundXcmpChannelCongestionStatusProvider< + xcm_config::bridging::BridgeHubKusamaParaId, + Runtime, + >; + + type ByteFee = xcm_config::bridging::XcmBridgeHubRouterByteFee; + type FeeAsset = xcm_config::bridging::XcmBridgeHubRouterFeeAssetId; +} + // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub enum Runtime @@ -851,6 +883,9 @@ construct_runtime!( Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 41, Proxy: pallet_proxy::{Pallet, Call, Storage, Event} = 42, + // Bridge utilities. + ToPolkadotXcmRouter: pallet_xcm_bridge_hub_router::::{Pallet, Storage, Call} = 43, + // The main stage. Assets: pallet_assets::::{Pallet, Call, Storage, Event} = 50, Uniques: pallet_uniques::{Pallet, Call, Storage, Event} = 51, @@ -924,6 +959,7 @@ mod benches { [pallet_timestamp, Timestamp] [pallet_collator_selection, CollatorSelection] [cumulus_pallet_xcmp_queue, XcmpQueue] + [pallet_xcm_bridge_hub_router, XcmBridgeHubRouterBench] // XCM [pallet_xcm, PolkadotXcm] // NOTE: Make sure you point to the individual modules below. @@ -1163,6 +1199,7 @@ impl_runtime_apis! { use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; + use pallet_xcm_bridge_hub_router::benchmarking::Pallet as XcmBridgeHubRouterBench; // This is defined once again in dispatch_benchmark, because list_benchmarks! // and add_benchmarks! are macros exported by define_benchmarks! macros and those types @@ -1206,6 +1243,25 @@ impl_runtime_apis! { use cumulus_pallet_session_benchmarking::Pallet as SessionBench; impl cumulus_pallet_session_benchmarking::Config for Runtime {} + use pallet_xcm_bridge_hub_router::benchmarking::{ + Pallet as XcmBridgeHubRouterBench, + Config as XcmBridgeHubRouterConfig, + }; + + impl XcmBridgeHubRouterConfig for Runtime { + fn make_congested() { + cumulus_pallet_xcmp_queue::bridging::suspend_channel_for_benchmarks::( + xcm_config::bridging::BridgeHubKusamaParaId::get().into() + ); + } + fn ensure_bridged_target_destination() -> MultiLocation { + ParachainSystem::open_outbound_hrmp_channel_for_benchmarks( + xcm_config::bridging::BridgeHubKusamaParaId::get().into() + ); + xcm_config::bridging::AssetHubPolkadot::get() + } + } + use xcm::latest::prelude::*; use xcm_config::{KsmLocation, MaxAssetsIntoHolding}; use pallet_xcm_benchmarks::asset_instance_from; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/mod.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/mod.rs index 281c013b3372..a857dc620622 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/mod.rs @@ -33,6 +33,7 @@ pub mod pallet_timestamp; pub mod pallet_uniques; pub mod pallet_utility; pub mod pallet_xcm; +pub mod pallet_xcm_bridge_hub_router; pub mod paritydb_weights; pub mod rocksdb_weights; pub mod xcm; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/pallet_xcm_bridge_hub_router.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/pallet_xcm_bridge_hub_router.rs new file mode 100644 index 000000000000..8fc21a35bd61 --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/pallet_xcm_bridge_hub_router.rs @@ -0,0 +1,118 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see . + +//! Autogenerated weights for `pallet_xcm_bridge_hub_router` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-08-17, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-aahe6cbd-project-238-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-kusama-dev")`, DB CACHE: 1024 + +// Executed Command: +// target/production/polkadot-parachain +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/cumulus/.git/.artifacts/bench.json +// --pallet=pallet_xcm_bridge_hub_router +// --chain=asset-hub-kusama-dev +// --header=./file_header.txt +// --output=./parachains/runtimes/assets/asset-hub-kusama/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_xcm_bridge_hub_router`. +pub struct WeightInfo(PhantomData); +impl pallet_xcm_bridge_hub_router::WeightInfo for WeightInfo { + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:0) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmpQueue::InboundXcmpStatus` (r:1 w:0) + /// Proof: `XcmpQueue::InboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ToPolkadotXcmRouter::Bridge` (r:1 w:1) + /// Proof: `ToPolkadotXcmRouter::Bridge` (`max_values`: Some(1), `max_size`: Some(17), added: 512, mode: `MaxEncodedLen`) + fn on_initialize_when_non_congested() -> Weight { + // Proof Size summary in bytes: + // Measured: `159` + // Estimated: `1644` + // Minimum execution time: 9_957_000 picoseconds. + Weight::from_parts(10_409_000, 0) + .saturating_add(Weight::from_parts(0, 1644)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:0) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + fn on_initialize_when_congested() -> Weight { + // Proof Size summary in bytes: + // Measured: `111` + // Estimated: `1596` + // Minimum execution time: 3_274_000 picoseconds. + Weight::from_parts(3_445_000, 0) + .saturating_add(Weight::from_parts(0, 1596)) + .saturating_add(T::DbWeight::get().reads(1)) + } + /// Storage: `ToPolkadotXcmRouter::Bridge` (r:1 w:1) + /// Proof: `ToPolkadotXcmRouter::Bridge` (`max_values`: Some(1), `max_size`: Some(17), added: 512, mode: `MaxEncodedLen`) + fn report_bridge_status() -> Weight { + // Proof Size summary in bytes: + // Measured: `83` + // Estimated: `1502` + // Minimum execution time: 11_282_000 picoseconds. + Weight::from_parts(11_712_000, 0) + .saturating_add(Weight::from_parts(0, 1502)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) + /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x0973fe64c85043ba1c965cbc38eb63c7` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x0973fe64c85043ba1c965cbc38eb63c7` (r:1 w:0) + /// Storage: `ToPolkadotXcmRouter::Bridge` (r:1 w:1) + /// Proof: `ToPolkadotXcmRouter::Bridge` (`max_values`: Some(1), `max_size`: Some(17), added: 512, mode: `MaxEncodedLen`) + /// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) + /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) + /// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) + /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParachainSystem::RelevantMessagingState` (r:1 w:0) + /// Proof: `ParachainSystem::RelevantMessagingState` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:1) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmpQueue::OutboundXcmpMessages` (r:0 w:1) + /// Proof: `XcmpQueue::OutboundXcmpMessages` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn send_message() -> Weight { + // Proof Size summary in bytes: + // Measured: `355` + // Estimated: `3820` + // Minimum execution time: 49_615_000 picoseconds. + Weight::from_parts(50_859_000, 0) + .saturating_add(Weight::from_parts(0, 3820)) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(4)) + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs index 99e46a1b4fe6..183940956f52 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs @@ -14,11 +14,11 @@ // limitations under the License. use super::{ - AccountId, AllPalletsWithSystem, Assets, Authorship, Balance, Balances, ParachainInfo, - ParachainSystem, PolkadotXcm, PoolAssets, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, + AccountId, AllPalletsWithSystem, Assets, Authorship, Balance, Balances, ForeignAssets, + ForeignAssetsInstance, ParachainInfo, ParachainSystem, PolkadotXcm, PoolAssets, Runtime, + RuntimeCall, RuntimeEvent, RuntimeOrigin, ToPolkadotXcmRouter, TransactionByteFee, TrustBackedAssetsInstance, WeightToFee, XcmpQueue, }; -use crate::{ForeignAssets, ForeignAssetsInstance}; use assets_common::{ local_and_foreign_assets::MatchesLocalAndForeignAssetsMultiLocation, matching::{ @@ -31,7 +31,10 @@ use frame_support::{ }; use frame_system::EnsureRoot; use pallet_xcm::XcmPassthrough; -use parachains_common::{impls::ToStakingPot, xcm_config::AssetFeeAsExistentialDepositMultiplier}; +use parachains_common::{ + impls::ToStakingPot, + xcm_config::{AllowUnpaidTransactsFrom, AssetFeeAsExistentialDepositMultiplier}, +}; use polkadot_parachain_primitives::primitives::Sibling; use sp_runtime::traits::ConvertInto; use xcm::latest::prelude::*; @@ -252,6 +255,14 @@ impl Contains for SafeCallFilter { } } + // Allow to change dedicated storage items (called by governance-like) + match call { + RuntimeCall::System(frame_system::Call::set_storage { items }) + if items.iter().all(|(k, _)| k.eq(&bridging::XcmBridgeHubRouterByteFee::key())) => + return true, + _ => (), + }; + matches!( call, RuntimeCall::PolkadotXcm(pallet_xcm::Call::force_xcm_version { .. }) | @@ -436,6 +447,8 @@ impl Contains for SafeCallFilter { pallet_uniques::Call::set_collection_max_supply { .. } | pallet_uniques::Call::set_price { .. } | pallet_uniques::Call::buy_item { .. } + ) | RuntimeCall::ToPolkadotXcmRouter( + pallet_xcm_bridge_hub_router::Call::report_bridge_status { .. } ) ) } @@ -458,6 +471,8 @@ pub type Barrier = TrailingSetTopicAsId< AllowExplicitUnpaidExecutionFrom, // Subscriptions for version tracking are OK. AllowSubscriptionsFrom, + // Allows Transacts with `report_bridge_status` from sibling BridgeHub. + bridging::AllowUnpaidStatusReportsFromSiblingBridgeHub, ), UniversalLocation, ConstU32<8>, @@ -544,6 +559,7 @@ impl xcm_executor::Config for XcmConfig { type MaxAssetsIntoHolding = MaxAssetsIntoHolding; type AssetLocker = (); type AssetExchanger = (); + // TODO:check-parameter: change and assert in tests when (https://github.com/paritytech/polkadot/pull/7005) merged type FeeManager = (); type MessageExporter = (); type UniversalAliases = bridging::UniversalAliases; @@ -566,7 +582,12 @@ type LocalXcmRouter = ( /// The means for routing XCM messages which are not for local execution into the right message /// queues. -pub type XcmRouter = WithUniqueTopic<(LocalXcmRouter, bridging::BridgingXcmRouter)>; +pub type XcmRouter = WithUniqueTopic<( + LocalXcmRouter, + // Router which wraps and sends xcm to BridgeHub to be delivered to the Polkadot + // GlobalConsensus + ToPolkadotXcmRouter, +)>; #[cfg(feature = "runtime-benchmarks")] parameter_types! { @@ -665,7 +686,6 @@ pub mod bridging { use assets_common::{matching, matching::*}; use parachains_common::xcm_config::LocationFilter; use sp_std::collections::btree_set::BTreeSet; - use xcm_builder::UnpaidRemoteExporter; parameter_types! { pub BridgeHubKusamaParaId: u32 = 1002; @@ -675,7 +695,14 @@ pub mod bridging { pub AssetHubPolkadot: MultiLocation = MultiLocation::new(2, X2(GlobalConsensus(PolkadotNetwork::get()), Parachain(1000))); pub DotLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(PolkadotNetwork::get()))); + /// Router expects payment with this `AssetId`. + /// (`AssetId` has to be aligned with `BridgeTable`) + pub XcmBridgeHubRouterFeeAssetId: AssetId = KsmLocation::get().into(); + /// Price per byte - can be adjusted via governance `set_storage` call. + pub storage XcmBridgeHubRouterByteFee: Balance = TransactionByteFee::get(); + /// Set up exporters configuration. + /// `Option` represents static "base fee" which is used for total delivery fee calculation. pub BridgeTable: sp_std::vec::Vec<(NetworkId, LocationFilter, MultiLocation, Option)> = sp_std::vec![ ( PolkadotNetwork::get(), @@ -684,7 +711,11 @@ pub mod bridging { .add_equals(AssetHubPolkadot::get().interior.split_global().expect("invalid configuration for AssetHubPolkadot").1), // and nothing else BridgeHubKusama::get(), - None + // base delivery fee to local `BridgeHub` + Some(( + XcmBridgeHubRouterFeeAssetId::get(), + bp_asset_hub_kusama::BridgeHubKusamaBaseFeeInDots::get(), + ).into()) ) ]; @@ -724,6 +755,7 @@ pub mod bridging { (BridgeHubKusamaWithBridgeHubPolkadotInstance::get(), GlobalConsensus(PolkadotNetwork::get())) ] ); + } impl Contains<(MultiLocation, Junction)> for UniversalAliases { @@ -735,11 +767,6 @@ pub mod bridging { pub type FilteredNetworkExportTable = parachains_common::xcm_config::FilteredNetworkExportTable; - /// Bridge router, which wraps and sends xcm to BridgeHub to be delivered to the different - /// GlobalConsensus - pub type BridgingXcmRouter = - UnpaidRemoteExporter; - /// Reserve locations filter for `xcm_executor::Config::IsReserve`. pub type IsTrustedBridgedReserveLocationForConcreteAsset = matching::IsTrustedBridgedReserveLocationForConcreteAsset< @@ -755,6 +782,22 @@ pub mod bridging { IsNotAllowedConcreteAssetBy, >; + impl Contains for ToPolkadotXcmRouter { + fn contains(call: &RuntimeCall) -> bool { + matches!( + call, + RuntimeCall::ToPolkadotXcmRouter( + pallet_xcm_bridge_hub_router::Call::report_bridge_status { .. } + ) + ) + } + } + + /// Barrier for `pallet_xcm_bridge_hub_router::Pallet` to receive congestion statuses from + /// sibling BridgeHub. + pub type AllowUnpaidStatusReportsFromSiblingBridgeHub = + AllowUnpaidTransactsFrom>; + /// Benchmarks helper for bridging configuration. #[cfg(feature = "runtime-benchmarks")] pub struct BridgingBenchmarksHelper; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs index 106a09d4e55c..d62d7479f9df 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs @@ -27,7 +27,8 @@ pub use asset_hub_kusama_runtime::{ }, AllPalletsWithoutSystem, AssetDeposit, Assets, Balances, ExistentialDeposit, ForeignAssets, ForeignAssetsInstance, MetadataDepositBase, MetadataDepositPerByte, ParachainSystem, Runtime, - RuntimeCall, RuntimeEvent, SessionKeys, System, TrustBackedAssetsInstance, XcmpQueue, + RuntimeCall, RuntimeEvent, SessionKeys, System, ToPolkadotXcmRouterInstance, + TrustBackedAssetsInstance, XcmpQueue, }; use asset_test_utils::{CollatorSessionKey, CollatorSessionKeys, ExtBuilder}; use codec::{Decode, Encode}; @@ -677,6 +678,7 @@ fn limited_reserve_transfer_assets_for_native_asset_over_bridge_works() { }), bridging_to_asset_hub_polkadot, WeightLimit::Unlimited, + Some(xcm_config::bridging::XcmBridgeHubRouterFeeAssetId::get()), ) } @@ -694,7 +696,7 @@ fn receive_reserve_asset_deposited_dot_from_asset_hub_polkadot_works() { ExistentialDeposit::get(), AccountId::from([73; 32]), AccountId::from(BLOCK_AUTHOR_ACCOUNT), - // receiving DOTs + // receiving DOTs (MultiLocation { parents: 2, interior: X1(GlobalConsensus(Polkadot)) }, 1000000000000, 1_000_000_000), bridging_to_asset_hub_polkadot, (X1(PalletInstance(53)), GlobalConsensus(Polkadot), X1(Parachain(1000))) @@ -784,3 +786,127 @@ fn xcm_reserve_transfer_filter_works() { } }) } + +#[test] +fn change_xcm_bridge_hub_router_byte_fee_by_governance_works() { + asset_test_utils::test_cases::change_storage_constant_by_governance_works::< + Runtime, + bridging::XcmBridgeHubRouterByteFee, + Balance, + >( + collator_session_keys(), + 1000, + Box::new(|call| RuntimeCall::System(call).encode()), + || { + ( + bridging::XcmBridgeHubRouterByteFee::key().to_vec(), + bridging::XcmBridgeHubRouterByteFee::get(), + ) + }, + |old_value| { + if let Some(new_value) = old_value.checked_add(1) { + new_value + } else { + old_value.checked_sub(1).unwrap() + } + }, + ) +} + +#[test] +fn test_report_bridge_status_call_compatibility() { + // if this test fails, make sure `bp_asset_hub_kusama` has valid encoding + assert_eq!( + RuntimeCall::ToPolkadotXcmRouter( + pallet_xcm_bridge_hub_router::Call::report_bridge_status { + bridge_id: Default::default(), + is_congested: true, + } + ) + .encode(), + bp_asset_hub_kusama::Call::ToPolkadotXcmRouter( + bp_asset_hub_kusama::XcmBridgeHubRouterCall::report_bridge_status { + bridge_id: Default::default(), + is_congested: true, + } + ) + .encode() + ) +} + +#[test] +fn report_bridge_status_from_xcm_bridge_router_works() { + asset_test_utils::test_cases_over_bridge::report_bridge_status_from_xcm_bridge_router_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ParachainSystem, + XcmpQueue, + LocationToAccountId, + ToPolkadotXcmRouterInstance, + >( + collator_session_keys(), + ExistentialDeposit::get(), + AccountId::from(ALICE), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::PolkadotXcm(event)) => Some(event), + _ => None, + } + }), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::XcmpQueue(event)) => Some(event), + _ => None, + } + }), + bridging_to_asset_hub_polkadot, + WeightLimit::Unlimited, + Some(xcm_config::bridging::XcmBridgeHubRouterFeeAssetId::get()), + || { + 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() + }, + || { + 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() + }, + ) +} + +#[test] +fn check_sane_weight_report_bridge_status() { + use pallet_xcm_bridge_hub_router::WeightInfo; + let actual = >::WeightInfo::report_bridge_status(); + let max_weight = bp_asset_hub_kusama::XcmBridgeHubRouterTransactCallMaxWeight::get(); + assert!( + actual.all_lte(max_weight), + "max_weight: {:?} should be adjusted to actual {:?}", + max_weight, + actual + ); +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/Cargo.toml index dfc3d5416cc3..59d937f67322 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/Cargo.toml @@ -66,7 +66,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 } @@ -74,6 +74,10 @@ parachain-info = { path = "../../../pallets/parachain-info", default-features = parachains-common = { path = "../../../common", default-features = false } assets-common = { path = "../common", default-features = false } +# Bridges +pallet-xcm-bridge-hub-router = { path = "../../../../bridges/modules/xcm-bridge-hub-router", default-features = false } +bp-asset-hub-polkadot = { path = "../../../../bridges/primitives/chain-asset-hub-polkadot", default-features = false } + [dev-dependencies] hex-literal = "0.4.1" asset-test-utils = { path = "../test-utils" } @@ -104,6 +108,7 @@ runtime-benchmarks = [ "pallet-uniques/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-xcm-benchmarks/runtime-benchmarks", + "pallet-xcm-bridge-hub-router/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", "polkadot-runtime-common/runtime-benchmarks", @@ -135,6 +140,7 @@ try-runtime = [ "pallet-transaction-payment/try-runtime", "pallet-uniques/try-runtime", "pallet-utility/try-runtime", + "pallet-xcm-bridge-hub-router/try-runtime", "pallet-xcm/try-runtime", "parachain-info/try-runtime", "polkadot-runtime-common/try-runtime", @@ -142,6 +148,7 @@ try-runtime = [ ] std = [ "assets-common/std", + "bp-asset-hub-polkadot/std", "codec/std", "cumulus-pallet-aura-ext/std", "cumulus-pallet-dmp-queue/std", @@ -176,6 +183,7 @@ std = [ "pallet-uniques/std", "pallet-utility/std", "pallet-xcm-benchmarks?/std", + "pallet-xcm-bridge-hub-router/std", "pallet-xcm/std", "parachain-info/std", "parachains-common/std", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs index 2e63d630dd60..cadd44c46c40 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs @@ -729,6 +729,38 @@ impl pallet_nfts::Config for Runtime { type Helper = (); } +/// XCM router instance to BridgeHub with bridging capabilities for `Kusama` global consensus with +/// dynamic fees and back-pressure. +pub type ToKusamaXcmRouterInstance = pallet_assets::Instance1; +impl pallet_xcm_bridge_hub_router::Config for Runtime { + type WeightInfo = weights::pallet_xcm_bridge_hub_router::WeightInfo; + + type UniversalLocation = xcm_config::UniversalLocation; + type BridgedNetworkId = xcm_config::bridging::KusamaNetwork; + type Bridges = xcm_config::bridging::FilteredNetworkExportTable; + + #[cfg(not(feature = "runtime-benchmarks"))] + type BridgeHubOrigin = + EnsureXcm>; + #[cfg(feature = "runtime-benchmarks")] + type BridgeHubOrigin = EitherOfDiverse< + // for running benchmarks + EnsureRoot, + // for running tests with `--feature runtime-benchmarks` + EnsureXcm>, + >; + + type ToBridgeHubSender = XcmpQueue; + type WithBridgeHubChannel = + cumulus_pallet_xcmp_queue::bridging::InboundAndOutboundXcmpChannelCongestionStatusProvider< + xcm_config::bridging::BridgeHubPolkadotParaId, + Runtime, + >; + + type ByteFee = xcm_config::bridging::XcmBridgeHubRouterByteFee; + type FeeAsset = xcm_config::bridging::XcmBridgeHubRouterFeeAssetId; +} + // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub enum Runtime @@ -765,6 +797,9 @@ construct_runtime!( Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 41, Proxy: pallet_proxy::{Pallet, Call, Storage, Event} = 42, + // Bridge utilities. + ToKusamaXcmRouter: pallet_xcm_bridge_hub_router::::{Pallet, Storage, Call} = 43, + // The main stage. Assets: pallet_assets::::{Pallet, Call, Storage, Event} = 50, Uniques: pallet_uniques::{Pallet, Call, Storage, Event} = 51, @@ -828,6 +863,7 @@ mod benches { [pallet_timestamp, Timestamp] [pallet_collator_selection, CollatorSelection] [cumulus_pallet_xcmp_queue, XcmpQueue] + [pallet_xcm_bridge_hub_router, XcmBridgeHubRouterBench] // XCM [pallet_xcm, PolkadotXcm] // NOTE: Make sure you point to the individual modules below. @@ -1043,6 +1079,7 @@ impl_runtime_apis! { use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; + use pallet_xcm_bridge_hub_router::benchmarking::Pallet as XcmBridgeHubRouterBench; // This is defined once again in dispatch_benchmark, because list_benchmarks! // and add_benchmarks! are macros exported by define_benchmarks! macros and those types @@ -1085,6 +1122,25 @@ impl_runtime_apis! { use cumulus_pallet_session_benchmarking::Pallet as SessionBench; impl cumulus_pallet_session_benchmarking::Config for Runtime {} + use pallet_xcm_bridge_hub_router::benchmarking::{ + Pallet as XcmBridgeHubRouterBench, + Config as XcmBridgeHubRouterConfig, + }; + + impl XcmBridgeHubRouterConfig for Runtime { + fn make_congested() { + cumulus_pallet_xcmp_queue::bridging::suspend_channel_for_benchmarks::( + xcm_config::bridging::BridgeHubPolkadotParaId::get().into() + ); + } + fn ensure_bridged_target_destination() -> MultiLocation { + ParachainSystem::open_outbound_hrmp_channel_for_benchmarks( + xcm_config::bridging::BridgeHubPolkadotParaId::get().into() + ); + xcm_config::bridging::AssetHubKusama::get() + } + } + use xcm::latest::prelude::*; use xcm_config::{DotLocation, MaxAssetsIntoHolding}; use pallet_xcm_benchmarks::asset_instance_from; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/mod.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/mod.rs index 3eb3b925e651..18255317e233 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/mod.rs @@ -30,6 +30,7 @@ pub mod pallet_timestamp; pub mod pallet_uniques; pub mod pallet_utility; pub mod pallet_xcm; +pub mod pallet_xcm_bridge_hub_router; pub mod paritydb_weights; pub mod rocksdb_weights; pub mod xcm; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/pallet_xcm_bridge_hub_router.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/pallet_xcm_bridge_hub_router.rs new file mode 100644 index 000000000000..2fdc9747f81f --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/pallet_xcm_bridge_hub_router.rs @@ -0,0 +1,118 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see . + +//! Autogenerated weights for `pallet_xcm_bridge_hub_router` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-08-17, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-aahe6cbd-project-238-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-polkadot-dev")`, DB CACHE: 1024 + +// Executed Command: +// target/production/polkadot-parachain +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/cumulus/.git/.artifacts/bench.json +// --pallet=pallet_xcm_bridge_hub_router +// --chain=asset-hub-polkadot-dev +// --header=./file_header.txt +// --output=./parachains/runtimes/assets/asset-hub-polkadot/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_xcm_bridge_hub_router`. +pub struct WeightInfo(PhantomData); +impl pallet_xcm_bridge_hub_router::WeightInfo for WeightInfo { + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:0) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmpQueue::InboundXcmpStatus` (r:1 w:0) + /// Proof: `XcmpQueue::InboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ToKusamaXcmRouter::Bridge` (r:1 w:1) + /// Proof: `ToKusamaXcmRouter::Bridge` (`max_values`: Some(1), `max_size`: Some(17), added: 512, mode: `MaxEncodedLen`) + fn on_initialize_when_non_congested() -> Weight { + // Proof Size summary in bytes: + // Measured: `193` + // Estimated: `1678` + // Minimum execution time: 9_963_000 picoseconds. + Weight::from_parts(10_410_000, 0) + .saturating_add(Weight::from_parts(0, 1678)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:0) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + fn on_initialize_when_congested() -> Weight { + // Proof Size summary in bytes: + // Measured: `111` + // Estimated: `1596` + // Minimum execution time: 3_322_000 picoseconds. + Weight::from_parts(3_513_000, 0) + .saturating_add(Weight::from_parts(0, 1596)) + .saturating_add(T::DbWeight::get().reads(1)) + } + /// Storage: `ToKusamaXcmRouter::Bridge` (r:1 w:1) + /// Proof: `ToKusamaXcmRouter::Bridge` (`max_values`: Some(1), `max_size`: Some(17), added: 512, mode: `MaxEncodedLen`) + fn report_bridge_status() -> Weight { + // Proof Size summary in bytes: + // Measured: `117` + // Estimated: `1502` + // Minimum execution time: 11_296_000 picoseconds. + Weight::from_parts(11_778_000, 0) + .saturating_add(Weight::from_parts(0, 1502)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) + /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x0973fe64c85043ba1c965cbc38eb63c7` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x0973fe64c85043ba1c965cbc38eb63c7` (r:1 w:0) + /// Storage: `ToKusamaXcmRouter::Bridge` (r:1 w:1) + /// Proof: `ToKusamaXcmRouter::Bridge` (`max_values`: Some(1), `max_size`: Some(17), added: 512, mode: `MaxEncodedLen`) + /// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) + /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) + /// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) + /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParachainSystem::RelevantMessagingState` (r:1 w:0) + /// Proof: `ParachainSystem::RelevantMessagingState` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:1) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmpQueue::OutboundXcmpMessages` (r:0 w:1) + /// Proof: `XcmpQueue::OutboundXcmpMessages` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn send_message() -> Weight { + // Proof Size summary in bytes: + // Measured: `355` + // Estimated: `3820` + // Minimum execution time: 50_336_000 picoseconds. + Weight::from_parts(51_994_000, 0) + .saturating_add(Weight::from_parts(0, 3820)) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(4)) + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs index 4b11eb6682c5..5479eb82d70e 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs @@ -16,7 +16,7 @@ use super::{ AccountId, AllPalletsWithSystem, Assets, Authorship, Balance, Balances, ForeignAssets, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, - TrustBackedAssetsInstance, WeightToFee, XcmpQueue, + ToKusamaXcmRouter, TransactionByteFee, TrustBackedAssetsInstance, WeightToFee, XcmpQueue, }; use crate::ForeignAssetsInstance; use assets_common::matching::{ @@ -28,7 +28,10 @@ use frame_support::{ }; use frame_system::EnsureRoot; use pallet_xcm::XcmPassthrough; -use parachains_common::{impls::ToStakingPot, xcm_config::AssetFeeAsExistentialDepositMultiplier}; +use parachains_common::{ + impls::ToStakingPot, + xcm_config::{AllowUnpaidTransactsFrom, AssetFeeAsExistentialDepositMultiplier}, +}; use polkadot_parachain_primitives::primitives::Sibling; use sp_runtime::traits::ConvertInto; use xcm::latest::prelude::*; @@ -209,6 +212,14 @@ impl Contains for SafeCallFilter { } } + // Allow to change dedicated storage items (called by governance-like) + match call { + RuntimeCall::System(frame_system::Call::set_storage { items }) + if items.iter().all(|(k, _)| k.eq(&bridging::XcmBridgeHubRouterByteFee::key())) => + return true, + _ => (), + }; + matches!( call, RuntimeCall::PolkadotXcm(pallet_xcm::Call::force_xcm_version { .. }) | @@ -351,7 +362,9 @@ impl Contains for SafeCallFilter { pallet_uniques::Call::set_accept_ownership { .. } | pallet_uniques::Call::set_collection_max_supply { .. } | pallet_uniques::Call::set_price { .. } | - pallet_uniques::Call::buy_item { .. } + pallet_uniques::Call::buy_item { .. }, + ) | RuntimeCall::ToKusamaXcmRouter( + pallet_xcm_bridge_hub_router::Call::report_bridge_status { .. } ) ) } @@ -379,6 +392,8 @@ pub type Barrier = TrailingSetTopicAsId< )>, // Subscriptions for version tracking are OK. AllowSubscriptionsFrom, + // Allows Transacts with `report_bridge_status` from sibling BridgeHub. + bridging::AllowUnpaidStatusReportsFromSiblingBridgeHub, ), UniversalLocation, ConstU32<8>, @@ -465,6 +480,7 @@ impl xcm_executor::Config for XcmConfig { type MaxAssetsIntoHolding = MaxAssetsIntoHolding; type AssetLocker = (); type AssetExchanger = (); + // TODO:check-parameter: change and assert in tests when (https://github.com/paritytech/polkadot/pull/7005) merged type FeeManager = (); type MessageExporter = (); type UniversalAliases = bridging::UniversalAliases; @@ -487,7 +503,11 @@ type LocalXcmRouter = ( /// The means for routing XCM messages which are not for local execution into the right message /// queues. -pub type XcmRouter = WithUniqueTopic<(LocalXcmRouter, bridging::BridgingXcmRouter)>; +pub type XcmRouter = WithUniqueTopic<( + LocalXcmRouter, + // Router which wraps and sends XCM to BridgeHub to be delivered to the Kusama GlobalConsensus + ToKusamaXcmRouter, +)>; #[cfg(feature = "runtime-benchmarks")] parameter_types! { @@ -574,7 +594,6 @@ pub mod bridging { use assets_common::{matching, matching::*}; use parachains_common::xcm_config::LocationFilter; use sp_std::collections::btree_set::BTreeSet; - use xcm_builder::UnpaidRemoteExporter; parameter_types! { pub BridgeHubPolkadotParaId: u32 = 1002; @@ -584,7 +603,14 @@ pub mod bridging { pub AssetHubKusama: MultiLocation = MultiLocation::new(2, X2(GlobalConsensus(KusamaNetwork::get()), Parachain(1000))); pub KsmLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(KusamaNetwork::get()))); + /// Router expects payment with this `AssetId`. + /// (`AssetId` has to be aligned with `BridgeTable`) + pub XcmBridgeHubRouterFeeAssetId: AssetId = DotLocation::get().into(); + /// Price per byte - can be adjusted via governance `set_storage` call. + pub storage XcmBridgeHubRouterByteFee: Balance = TransactionByteFee::get(); + /// Set up exporters configuration. + /// `Option` represents static "base fee" which is used for total delivery fee calculation. pub BridgeTable: sp_std::vec::Vec<(NetworkId, LocationFilter, MultiLocation, Option)> = sp_std::vec![ ( KusamaNetwork::get(), @@ -593,7 +619,11 @@ pub mod bridging { .add_equals(AssetHubKusama::get().interior.split_global().expect("invalid configuration for AssetHubKusama").1), // and nothing else BridgeHubPolkadot::get(), - None + // base delivery fee to local `BridgeHub` + Some(( + XcmBridgeHubRouterFeeAssetId::get(), + bp_asset_hub_polkadot::BridgeHubPolkadotBaseFeeInDots::get() + ).into()) ) ]; @@ -644,11 +674,6 @@ pub mod bridging { pub type FilteredNetworkExportTable = parachains_common::xcm_config::FilteredNetworkExportTable; - /// Bridge router, which wraps and sends xcm to BridgeHub to be delivered to the different - /// GlobalConsensus - pub type BridgingXcmRouter = - UnpaidRemoteExporter; - /// Reserve locations filter for `xcm_executor::Config::IsReserve`. pub type IsTrustedBridgedReserveLocationForConcreteAsset = matching::IsTrustedBridgedReserveLocationForConcreteAsset< @@ -664,6 +689,22 @@ pub mod bridging { IsNotAllowedConcreteAssetBy, >; + impl Contains for ToKusamaXcmRouter { + fn contains(call: &RuntimeCall) -> bool { + matches!( + call, + RuntimeCall::ToKusamaXcmRouter( + pallet_xcm_bridge_hub_router::Call::report_bridge_status { .. } + ) + ) + } + } + + /// Barrier for `pallet_xcm_bridge_hub_router::Pallet` to receive congestion statuses from + /// sibling BridgeHub. + pub type AllowUnpaidStatusReportsFromSiblingBridgeHub = + AllowUnpaidTransactsFrom>; + /// Benchmarks helper for bridging configuration. #[cfg(feature = "runtime-benchmarks")] pub struct BridgingBenchmarksHelper; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs index f76f11bac176..7c9b00903ea9 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs @@ -23,9 +23,10 @@ use asset_hub_polkadot_runtime::xcm_config::{ XcmConfig, }; pub use asset_hub_polkadot_runtime::{ - AllPalletsWithoutSystem, AssetDeposit, Assets, Balances, ExistentialDeposit, ForeignAssets, - ForeignAssetsInstance, MetadataDepositBase, MetadataDepositPerByte, ParachainSystem, Runtime, - RuntimeCall, RuntimeEvent, SessionKeys, System, TrustBackedAssetsInstance, XcmpQueue, + xcm_config, AllPalletsWithoutSystem, AssetDeposit, Assets, Balances, ExistentialDeposit, + ForeignAssets, ForeignAssetsInstance, MetadataDepositBase, MetadataDepositPerByte, + ParachainSystem, Runtime, RuntimeCall, RuntimeEvent, SessionKeys, System, + ToKusamaXcmRouterInstance, TrustBackedAssetsInstance, XcmpQueue, }; use asset_test_utils::{CollatorSessionKey, CollatorSessionKeys, ExtBuilder}; use codec::{Decode, Encode}; @@ -699,6 +700,7 @@ fn limited_reserve_transfer_assets_for_native_asset_over_bridge_works() { }), bridging_to_asset_hub_kusama, WeightLimit::Unlimited, + Some(xcm_config::bridging::XcmBridgeHubRouterFeeAssetId::get()), ) } @@ -716,7 +718,7 @@ fn receive_reserve_asset_deposited_ksm_from_asset_hub_kusama_works() { ExistentialDeposit::get(), AccountId::from([73; 32]), AccountId::from(BLOCK_AUTHOR_ACCOUNT), - // receiving DOTs + // receiving KSMs (MultiLocation { parents: 2, interior: X1(GlobalConsensus(Kusama)) }, 1000000000000, 10_000_000_000), bridging_to_asset_hub_kusama, (X1(PalletInstance(53)), GlobalConsensus(Kusama), X1(Parachain(1000))) @@ -806,3 +808,125 @@ fn xcm_reserve_transfer_filter_works() { } }) } + +#[test] +fn change_xcm_bridge_hub_router_byte_fee_by_governance_works() { + asset_test_utils::test_cases::change_storage_constant_by_governance_works::< + Runtime, + bridging::XcmBridgeHubRouterByteFee, + Balance, + >( + collator_session_keys(), + 1000, + Box::new(|call| RuntimeCall::System(call).encode()), + || { + ( + bridging::XcmBridgeHubRouterByteFee::key().to_vec(), + bridging::XcmBridgeHubRouterByteFee::get(), + ) + }, + |old_value| { + if let Some(new_value) = old_value.checked_add(1) { + new_value + } else { + old_value.checked_sub(1).unwrap() + } + }, + ) +} + +#[test] +fn test_report_bridge_status_call_compatibility() { + // if this test fails, make sure `bp_asset_hub_polkadot` has valid encoding + assert_eq!( + RuntimeCall::ToKusamaXcmRouter(pallet_xcm_bridge_hub_router::Call::report_bridge_status { + bridge_id: Default::default(), + is_congested: true, + }) + .encode(), + bp_asset_hub_polkadot::Call::ToKusamaXcmRouter( + bp_asset_hub_polkadot::XcmBridgeHubRouterCall::report_bridge_status { + bridge_id: Default::default(), + is_congested: true, + } + ) + .encode() + ) +} + +#[test] +fn report_bridge_status_from_xcm_bridge_router_works() { + asset_test_utils::test_cases_over_bridge::report_bridge_status_from_xcm_bridge_router_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ParachainSystem, + XcmpQueue, + LocationToAccountId, + ToKusamaXcmRouterInstance, + >( + collator_session_keys(), + ExistentialDeposit::get(), + AccountId::from(ALICE), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::PolkadotXcm(event)) => Some(event), + _ => None, + } + }), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::XcmpQueue(event)) => Some(event), + _ => None, + } + }), + bridging_to_asset_hub_kusama, + WeightLimit::Unlimited, + Some(xcm_config::bridging::XcmBridgeHubRouterFeeAssetId::get()), + || { + 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() + }, + || { + 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() + }, + ) +} + +#[test] +fn check_sane_weight_report_bridge_status() { + use pallet_xcm_bridge_hub_router::WeightInfo; + let actual = >::WeightInfo::report_bridge_status(); + let max_weight = bp_asset_hub_polkadot::XcmBridgeHubRouterTransactCallMaxWeight::get(); + assert!( + actual.all_lte(max_weight), + "max_weight: {:?} should be adjusted to actual {:?}", + max_weight, + actual + ); +} diff --git a/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml b/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml index 691314419102..1e0169782287 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml @@ -41,6 +41,9 @@ xcm-executor = { package = "staging-xcm-executor", path = "../../../../../polkad pallet-xcm = { path = "../../../../../polkadot/xcm/pallet-xcm", default-features = false} polkadot-parachain-primitives = { path = "../../../../../polkadot/parachain", default-features = false} +# Bridges +pallet-xcm-bridge-hub-router = { path = "../../../../bridges/modules/xcm-bridge-hub-router", default-features = false } + [dev-dependencies] hex-literal = "0.4.1" @@ -63,6 +66,7 @@ std = [ "pallet-balances/std", "pallet-collator-selection/std", "pallet-session/std", + "pallet-xcm-bridge-hub-router/std", "pallet-xcm/std", "parachain-info/std", "parachains-common/std", diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs index a815367587ab..a0ec6bb4f7d1 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs @@ -58,6 +58,7 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works< >, ensure_configuration: fn() -> TestBridgingConfig, weight_limit: WeightLimit, + maybe_paid_export_message: Option, ) where Runtime: frame_system::Config + pallet_balances::Config @@ -174,6 +175,7 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works< )); // check alice account decreased by balance_to_transfer + // TODO:check-parameter: change and assert in tests when (https://github.com/paritytech/polkadot/pull/7005) merged assert_eq!( >::free_balance(&alice_account), alice_account_init_balance - balance_to_transfer.into() @@ -217,38 +219,54 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works< ); let mut xcm_sent: Xcm<()> = xcm_sent.try_into().expect("versioned xcm"); - // check sent XCM ExportMessage to bridge-hub - xcm_sent - .0 - .matcher() - .match_next_inst(|instr| match instr { - // first instruction is UNpai (because we have explicit unpaid execution on - // bridge-hub now) - UnpaidExecution { weight_limit, check_origin } - if weight_limit == &Unlimited && check_origin.is_none() => - Ok(()), - _ => Err(ProcessMessageError::BadFormat), - }) - .expect("contains UnpaidExecution") - .match_next_inst(|instr| match instr { - // second instruction is ExportMessage - ExportMessage { network, destination, xcm: inner_xcm } => { - assert_eq!(network, &bridged_network); - let (_, target_location_junctions_without_global_consensus) = - target_location_from_different_consensus - .interior - .split_global() - .expect("split works"); - assert_eq!( - destination, - &target_location_junctions_without_global_consensus - ); - assert_matches_pallet_xcm_reserve_transfer_assets_instructions(inner_xcm); - Ok(()) - }, - _ => Err(ProcessMessageError::BadFormat), - }) - .expect("contains ExportMessage"); + // check sent XCM ExportMessage to BridgeHub + + // 1. check paid or unpaid + if let Some(expected_fee_asset_id) = maybe_paid_export_message { + xcm_sent + .0 + .matcher() + .match_next_inst(|instr| match instr { + WithdrawAsset(_) => Ok(()), + _ => Err(ProcessMessageError::BadFormat), + }) + .expect("contains WithdrawAsset") + .match_next_inst(|instr| match instr { + BuyExecution { fees, .. } if fees.id.eq(&expected_fee_asset_id) => Ok(()), + _ => Err(ProcessMessageError::BadFormat), + }) + .expect("contains BuyExecution") + } else { + xcm_sent + .0 + .matcher() + .match_next_inst(|instr| match instr { + // first instruction could be UnpaidExecution (because we could have + // explicit unpaid execution on BridgeHub) + UnpaidExecution { weight_limit, check_origin } + if weight_limit == &Unlimited && check_origin.is_none() => + Ok(()), + _ => Err(ProcessMessageError::BadFormat), + }) + .expect("contains UnpaidExecution") + } + // 2. check ExportMessage + .match_next_inst(|instr| match instr { + // second instruction is ExportMessage + ExportMessage { network, destination, xcm: inner_xcm } => { + assert_eq!(network, &bridged_network); + let (_, target_location_junctions_without_global_consensus) = + target_location_from_different_consensus + .interior + .split_global() + .expect("split works"); + assert_eq!(destination, &target_location_junctions_without_global_consensus); + assert_matches_pallet_xcm_reserve_transfer_assets_instructions(inner_xcm); + Ok(()) + }, + _ => Err(ProcessMessageError::BadFormat), + }) + .expect("contains ExportMessage"); }) } @@ -502,3 +520,102 @@ fn assert_matches_pallet_xcm_reserve_transfer_assets_instructions( }) .expect("expected instruction DepositAsset"); } + +pub fn report_bridge_status_from_xcm_bridge_router_works< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + HrmpChannelOpener, + HrmpChannelSource, + LocationToAccountId, + XcmBridgeHubRouterInstance, +>( + collator_session_keys: CollatorSessionKeys, + existential_deposit: BalanceOf, + alice_account: AccountIdOf, + unwrap_pallet_xcm_event: Box) -> Option>>, + unwrap_xcmp_queue_event: Box< + dyn Fn(Vec) -> Option>, + >, + ensure_configuration: fn() -> TestBridgingConfig, + weight_limit: WeightLimit, + maybe_paid_export_message: Option, + congested_message: fn() -> Xcm, + uncongested_message: fn() -> Xcm, +) where + Runtime: frame_system::Config + + pallet_balances::Config + + pallet_session::Config + + pallet_xcm::Config + + parachain_info::Config + + pallet_collator_selection::Config + + cumulus_pallet_parachain_system::Config + + cumulus_pallet_xcmp_queue::Config + + pallet_xcm_bridge_hub_router::Config, + AllPalletsWithoutSystem: + OnInitialize> + OnFinalize>, + AccountIdOf: Into<[u8; 32]>, + ValidatorIdOf: From>, + BalanceOf: From, + ::Balance: From + Into, + XcmConfig: xcm_executor::Config, + LocationToAccountId: ConvertLocation>, + ::AccountId: + Into<<::RuntimeOrigin as OriginTrait>::AccountId>, + <::Lookup as StaticLookup>::Source: + From<::AccountId>, + ::AccountId: From, + HrmpChannelOpener: frame_support::inherent::ProvideInherent< + Call = cumulus_pallet_parachain_system::Call, + >, + HrmpChannelSource: XcmpMessageSource, + XcmBridgeHubRouterInstance: 'static, +{ + ExtBuilder::::default() + .with_collators(collator_session_keys.collators()) + .with_session_keys(collator_session_keys.session_keys()) + .with_tracing() + .build() + .execute_with(|| { + // check transfer works + limited_reserve_transfer_assets_for_native_asset_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + HrmpChannelOpener, + HrmpChannelSource, + LocationToAccountId, + >( + collator_session_keys, + existential_deposit, + alice_account, + unwrap_pallet_xcm_event, + unwrap_xcmp_queue_event, + ensure_configuration, + weight_limit, + maybe_paid_export_message, + ); + + let report_brigde_status = |is_congested: bool| { + // prepare bridge config + let TestBridgingConfig { local_bridge_hub_location, .. } = ensure_configuration(); + + // Call received XCM execution + let xcm = if is_congested { congested_message() } else { uncongested_message() }; + let hash = xcm.using_encoded(sp_io::hashing::blake2_256); + + // execute xcm as XcmpQueue would do + let outcome = XcmExecutor::::execute_xcm( + local_bridge_hub_location, + xcm, + hash, + RuntimeHelper::::xcm_max_weight(XcmReceivedFrom::Sibling), + ); + assert_eq!(outcome.ensure_complete(), Ok(())); + assert_eq!(is_congested, pallet_xcm_bridge_hub_router::Pallet::::bridge().is_congested); + }; + + report_brigde_status(true); + report_brigde_status(false); + }) +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/README.md b/cumulus/parachains/runtimes/bridge-hubs/README.md index 56b6ad3ed620..7600c52d3530 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/README.md +++ b/cumulus/parachains/runtimes/bridge-hubs/README.md @@ -266,7 +266,9 @@ This initialization does several things: - drips SA for AssetHubKusama on AssetHubPolkadot (and vice versa) which holds reserved assets on source chains ``` ./scripts/bridges_kusama_polkadot.sh init-asset-hub-kusama-local +./scripts/bridges_kusama_polkadot.sh init-bridge-hub-kusama-local ./scripts/bridges_kusama_polkadot.sh init-asset-hub-polkadot-local +./scripts/bridges_kusama_polkadot.sh init-bridge-hub-polkadot-local ``` ### 4. Send messages - transfer asset over bridge (DOTs/KSMs) diff --git a/cumulus/parachains/runtimes/test-utils/src/lib.rs b/cumulus/parachains/runtimes/test-utils/src/lib.rs index 3f13b78fb59b..1e73de9f53d3 100644 --- a/cumulus/parachains/runtimes/test-utils/src/lib.rs +++ b/cumulus/parachains/runtimes/test-utils/src/lib.rs @@ -410,16 +410,20 @@ impl) -> Option>>, assert_outcome: fn(Outcome), ) { - let outcome = >::events() + assert_outcome(Self::get_pallet_xcm_event_outcome(unwrap_pallet_xcm_event)); + } + + pub fn get_pallet_xcm_event_outcome( + unwrap_pallet_xcm_event: &Box) -> Option>>, + ) -> Outcome { + >::events() .into_iter() .filter_map(|e| unwrap_pallet_xcm_event(e.event.encode())) .find_map(|e| match e { pallet_xcm::Event::Attempted { outcome } => Some(outcome), _ => None, }) - .expect("No `pallet_xcm::Event::Attempted(outcome)` event found!"); - - assert_outcome(outcome); + .expect("No `pallet_xcm::Event::Attempted(outcome)` event found!") } } diff --git a/cumulus/scripts/bridges_kusama_polkadot.sh b/cumulus/scripts/bridges_kusama_polkadot.sh index 43ca5356d2c0..a417ef49a9ca 100755 --- a/cumulus/scripts/bridges_kusama_polkadot.sh +++ b/cumulus/scripts/bridges_kusama_polkadot.sh @@ -36,6 +36,12 @@ ASSET_HUB_POLKADOT_ACCOUNT_ADDRESS_FOR_LOCAL="5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNe # &MultiLocation { parents: 2, interior: X2(GlobalConsensus(Kusama), Parachain(1000)) }).unwrap() # ).to_ss58check_with_version(0_u16.into()) # ); +# println!("ASSET_HUB_POLKADOT_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_POLKADOT=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# SiblingParachainConvertsVia::::convert_location( +# &MultiLocation { parents: 1, interior: X1(Parachain(1000)) }).unwrap() +# ).to_ss58check_with_version(0_u16.into()) +# ); # # // SS58=2 # println!("GLOBAL_CONSENSUS_POLKADOT_SOVEREIGN_ACCOUNT=\"{}\"", @@ -50,11 +56,19 @@ ASSET_HUB_POLKADOT_ACCOUNT_ADDRESS_FOR_LOCAL="5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNe # &MultiLocation { parents: 2, interior: X2(GlobalConsensus(Polkadot), Parachain(1000)) }).unwrap() # ).to_ss58check_with_version(2_u16.into()) # ); +# println!("ASSET_HUB_KUSAMA_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_KUSAMA=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# SiblingParachainConvertsVia::::convert_location( +# &MultiLocation { parents: 1, interior: X1(Parachain(1000)) }).unwrap() +# ).to_ss58check_with_version(2_u16.into()) +# ); # } GLOBAL_CONSENSUS_KUSAMA_SOVEREIGN_ACCOUNT="14zcUAhP5XypiFQWA3b1AnGKrhZqR4XWUo4deWkwuN5y983G" GLOBAL_CONSENSUS_KUSAMA_ASSET_HUB_KUSAMA_1000_SOVEREIGN_ACCOUNT="12GvRkNCmXFuaaziTJ2ZKAfa7MArKfLT2HYvLjQuepP3JuHf" +ASSET_HUB_POLKADOT_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_POLKADOT="13cKp89SgdtqUngo2WiEijPrQWdHFhzYZLf2TJePKRvExk7o" GLOBAL_CONSENSUS_POLKADOT_SOVEREIGN_ACCOUNT="FxqimVubBRPqJ8kTwb3wL7G4q645hEkBEnXPyttLsTrFc5Q" GLOBAL_CONSENSUS_POLKADOT_ASSET_HUB_POLKADOT_1000_SOVEREIGN_ACCOUNT="FwGjEp7GXJXT9NjH8r4sqdyd8XZVogbxSs3iFakx4wFwJ5Y" +ASSET_HUB_KUSAMA_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_KUSAMA="FBeL7EFTDeHnuViqaUHUXvhhUusN5FawDmHgfvzF97DXFr3" function init_ksm_dot() { ensure_relayer @@ -136,6 +150,14 @@ case "$1" in "$GLOBAL_CONSENSUS_POLKADOT_ASSET_HUB_POLKADOT_1000_SOVEREIGN_ACCOUNT" \ $((1000000000 + 50000000000 * 20)) ;; + init-bridge-hub-kusama-local) + # SA of sibling asset hub pays for the execution + transfer_balance \ + "ws://127.0.0.1:8943" \ + "//Alice" \ + "$ASSET_HUB_KUSAMA_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_KUSAMA" \ + $((1000000000 + 50000000000 * 20)) + ;; init-asset-hub-polkadot-local) # create foreign assets for native Polkadot token (governance call on Kusama) force_create_foreign_asset \ @@ -154,6 +176,14 @@ case "$1" in "$GLOBAL_CONSENSUS_KUSAMA_ASSET_HUB_KUSAMA_1000_SOVEREIGN_ACCOUNT" \ $((1000000000 + 50000000000 * 20)) ;; + init-bridge-hub-polkadot-local) + # SA of sibling asset hub pays for the execution + transfer_balance \ + "ws://127.0.0.1:8945" \ + "//Alice" \ + "$ASSET_HUB_POLKADOT_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_POLKADOT" \ + $((1000000000 + 50000000000 * 20)) + ;; reserve-transfer-assets-from-asset-hub-kusama-local) ensure_polkadot_js_api # send KSMs to Alice account on AHP @@ -187,7 +217,9 @@ case "$1" in Local (zombienet) run: - run-relay - init-asset-hub-kusama-local + - init-bridge-hub-kusama-local - init-asset-hub-polkadot-local + - init-bridge-hub-polkadot-local - reserve-transfer-assets-from-asset-hub-kusama-local - reserve-transfer-assets-from-asset-hub-polkadot-local"; exit 1 From 945ea7fa3dcbc8a48b024cd52fb126e853311780 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Mon, 4 Sep 2023 12:31:21 +0200 Subject: [PATCH 03/17] Kusama/Polkadot BridgeHub allows bridging between Kusama/Polkadot (relay, para) chains Add bridging pallets to Bridge Hub runtime configuration: - `pallet-bridge-grandpa` is an on-chain GRANDPA light client, used for verifying GRANDPA finality proofs on-chain. - `pallet-bridge-parachains` is a Parachain finality module. - `pallet-bridge-messages` module that allows sending and receiving messages using lane concept. - `pallet-bridge-relayers` module that is used to store relayer rewards. Kusma Bridge Hub and Polkadot Bridge Hub runtimes are configred with those pallets in the way that: - allows to verify bridged relay chain GRANDPA finality proofs, e.g. Kusama Bridge Hub can track and verify Polkadot relay chain GRANDPA proofs and Polkadot Bridge Hub can track and verify Kusama relay chain GRANDPA proofs. - allows to verify bridged parachain finality proofs e.g. Kusama Bridge Hub can track and verify Polkadot Bridge Hub proofs and vice versa. - allows to relay messages between them which can be verified with mentioned finality modules. Add tests for simulation: - handling `ExportMessage` on both sides - handling message dispatch and routing to target on both side - relayer can submit proofs with `submit_finality_proof` / `submit_parachain_heads` and relay messages with `receive_messages_proof` To the lane concept mentioned above, actual bridging configuration allows to send/relay/receive messages only with one hard-coded lane `[0, 0, 0, 0]`, which is dedicated lane for Kusama Asset Hub and Polkadot Asset Hub communication. Next stage will be focused on adding support to allow bridging between arbitrary parachains. More about [Bridges V2](https://github.com/paritytech/parity-bridges-common/milestone/17). 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 | 35 +- .../emulated/common/src/constants.rs | 16 + .../bridge-hubs/bridge-hub-kusama/Cargo.toml | 43 +++ .../src/bridge_hub_config.rs | 236 +++++++++++++ .../bridge-hubs/bridge-hub-kusama/src/lib.rs | 320 ++++++++++++++++- .../bridge-hub-kusama/src/weights/mod.rs | 33 ++ .../src/weights/pallet_bridge_grandpa.rs | 80 +++++ .../src/weights/pallet_bridge_messages.rs | 231 +++++++++++++ .../src/weights/pallet_bridge_parachains.rs | 113 ++++++ .../src/weights/pallet_bridge_relayers.rs | 124 +++++++ .../bridge-hub-kusama/src/weights/xcm/mod.rs | 6 +- .../xcm/pallet_xcm_benchmarks_generic.rs | 20 ++ .../bridge-hub-kusama/src/xcm_config.rs | 41 ++- .../bridge-hub-kusama/tests/tests.rs | 227 ++++++++++++- .../bridge-hub-polkadot/Cargo.toml | 43 +++ .../src/bridge_hub_config.rs | 235 +++++++++++++ .../bridge-hub-polkadot/src/lib.rs | 321 +++++++++++++++++- .../bridge-hub-polkadot/src/weights/mod.rs | 33 ++ .../src/weights/pallet_bridge_grandpa.rs | 80 +++++ .../src/weights/pallet_bridge_messages.rs | 231 +++++++++++++ .../src/weights/pallet_bridge_parachains.rs | 115 +++++++ .../src/weights/pallet_bridge_relayers.rs | 124 +++++++ .../src/weights/xcm/mod.rs | 6 +- .../xcm/pallet_xcm_benchmarks_generic.rs | 20 ++ .../bridge-hub-polkadot/src/xcm_config.rs | 48 ++- .../bridge-hub-polkadot/tests/tests.rs | 228 ++++++++++++- .../src/bridge_hub_rococo_config.rs | 4 +- .../src/bridge_hub_wococo_config.rs | 4 +- .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 12 +- .../bridge-hub-rococo/tests/tests.rs | 2 +- .../bridge-hubs/test-utils/Cargo.toml | 1 - .../bridge-hubs/test-utils/src/test_cases.rs | 39 ++- .../src/chain_spec/bridge_hubs.rs | 34 +- 33 files changed, 3035 insertions(+), 70 deletions(-) create mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/bridge_hub_config.rs create mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_grandpa.rs create mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_messages.rs create mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_parachains.rs create mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_relayers.rs create mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/bridge_hub_config.rs create mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_grandpa.rs create mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_messages.rs create mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_parachains.rs create mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_relayers.rs diff --git a/Cargo.lock b/Cargo.lock index 1f9a68787bf2..611c53cf67a4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1822,7 +1822,18 @@ dependencies = [ name = "bridge-hub-kusama-runtime" version = "0.1.0" dependencies = [ + "bp-bridge-hub-kusama", + "bp-bridge-hub-polkadot", + "bp-header-chain", + "bp-kusama", + "bp-messages", + "bp-parachains", + "bp-polkadot", + "bp-polkadot-core", + "bp-relayers", + "bp-runtime", "bridge-hub-test-utils", + "bridge-runtime-common", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", @@ -1844,6 +1855,10 @@ dependencies = [ "pallet-aura", "pallet-authorship", "pallet-balances", + "pallet-bridge-grandpa", + "pallet-bridge-messages", + "pallet-bridge-parachains", + "pallet-bridge-relayers", "pallet-collator-selection", "pallet-multisig", "pallet-session", @@ -1868,6 +1883,7 @@ dependencies = [ "sp-core", "sp-inherents", "sp-io", + "sp-keyring", "sp-offchain", "sp-runtime", "sp-session", @@ -1878,6 +1894,7 @@ dependencies = [ "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", + "static_assertions", "substrate-wasm-builder", ] @@ -1885,7 +1902,18 @@ dependencies = [ name = "bridge-hub-polkadot-runtime" version = "0.1.0" dependencies = [ + "bp-bridge-hub-kusama", + "bp-bridge-hub-polkadot", + "bp-header-chain", + "bp-kusama", + "bp-messages", + "bp-parachains", + "bp-polkadot", + "bp-polkadot-core", + "bp-relayers", + "bp-runtime", "bridge-hub-test-utils", + "bridge-runtime-common", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", @@ -1906,6 +1934,10 @@ dependencies = [ "pallet-aura", "pallet-authorship", "pallet-balances", + "pallet-bridge-grandpa", + "pallet-bridge-messages", + "pallet-bridge-parachains", + "pallet-bridge-relayers", "pallet-collator-selection", "pallet-multisig", "pallet-session", @@ -1931,6 +1963,7 @@ dependencies = [ "sp-core", "sp-inherents", "sp-io", + "sp-keyring", "sp-offchain", "sp-runtime", "sp-session", @@ -1941,6 +1974,7 @@ dependencies = [ "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", + "static_assertions", "substrate-wasm-builder", ] @@ -2049,7 +2083,6 @@ dependencies = [ name = "bridge-hub-test-utils" version = "0.1.0" dependencies = [ - "assert_matches", "asset-test-utils", "bp-bridge-hub-rococo", "bp-bridge-hub-wococo", diff --git a/cumulus/parachains/integration-tests/emulated/common/src/constants.rs b/cumulus/parachains/integration-tests/emulated/common/src/constants.rs index 8725ebd140b9..b2f6915c0a90 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/constants.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/constants.rs @@ -966,6 +966,14 @@ pub mod bridge_hub_kusama { safe_xcm_version: Some(SAFE_XCM_VERSION), ..Default::default() }, + bridge_polkadot_grandpa: bridge_hub_kusama_runtime::BridgePolkadotGrandpaConfig { + owner: Some(get_account_id_from_seed::(accounts::BOB)), + ..Default::default() + }, + bridge_polkadot_messages: bridge_hub_kusama_runtime::BridgePolkadotMessagesConfig { + owner: Some(get_account_id_from_seed::(accounts::BOB)), + ..Default::default() + }, ..Default::default() }; @@ -1023,6 +1031,14 @@ pub mod bridge_hub_polkadot { safe_xcm_version: Some(SAFE_XCM_VERSION), ..Default::default() }, + bridge_kusama_grandpa: bridge_hub_polkadot_runtime::BridgeKusamaGrandpaConfig { + owner: Some(get_account_id_from_seed::(accounts::BOB)), + ..Default::default() + }, + bridge_kusama_messages: bridge_hub_polkadot_runtime::BridgeKusamaMessagesConfig { + owner: Some(get_account_id_from_seed::(accounts::BOB)), + ..Default::default() + }, ..Default::default() }; 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 91eb7adc61fe..61a5ec19a71f 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/Cargo.toml @@ -71,12 +71,42 @@ pallet-collator-selection = { path = "../../../../pallets/collator-selection", d parachain-info = { path = "../../../pallets/parachain-info", default-features = false } parachains-common = { path = "../../../common", default-features = false } +# Bridges +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 } +bp-messages = { path = "../../../../bridges/primitives/messages", default-features = false } +bp-parachains = { path = "../../../../bridges/primitives/parachains", default-features = false } +bp-polkadot-core = { path = "../../../../bridges/primitives/polkadot-core", default-features = false } +bp-relayers = { path = "../../../../bridges/primitives/relayers", default-features = false } +bp-runtime = { path = "../../../../bridges/primitives/runtime", default-features = false } +bp-polkadot = { path = "../../../../bridges/primitives/chain-polkadot", default-features = false } +bridge-runtime-common = { path = "../../../../bridges/bin/runtime-common", default-features = false } +pallet-bridge-grandpa = { path = "../../../../bridges/modules/grandpa", default-features = false } +pallet-bridge-messages = { path = "../../../../bridges/modules/messages", default-features = false } +pallet-bridge-parachains = { path = "../../../../bridges/modules/parachains", default-features = false } +pallet-bridge-relayers = { path = "../../../../bridges/modules/relayers", default-features = false } + [dev-dependencies] +static_assertions = "1.1" bridge-hub-test-utils = { path = "../test-utils" } +bridge-runtime-common = { path = "../../../../bridges/bin/runtime-common", features = ["integrity-test"] } +bp-kusama = { path = "../../../../bridges/primitives/chain-kusama" } +sp-keyring = { path = "../../../../../substrate/primitives/keyring" } [features] default = [ "std" ] std = [ + "bp-bridge-hub-kusama/std", + "bp-bridge-hub-polkadot/std", + "bp-header-chain/std", + "bp-messages/std", + "bp-parachains/std", + "bp-polkadot-core/std", + "bp-polkadot/std", + "bp-relayers/std", + "bp-runtime/std", + "bridge-runtime-common/std", "codec/std", "cumulus-pallet-aura-ext/std", "cumulus-pallet-dmp-queue/std", @@ -98,6 +128,10 @@ std = [ "pallet-aura/std", "pallet-authorship/std", "pallet-balances/std", + "pallet-bridge-grandpa/std", + "pallet-bridge-messages/std", + "pallet-bridge-parachains/std", + "pallet-bridge-relayers/std", "pallet-collator-selection/std", "pallet-multisig/std", "pallet-session/std", @@ -134,6 +168,7 @@ std = [ ] runtime-benchmarks = [ + "bridge-runtime-common/runtime-benchmarks", "cumulus-pallet-parachain-system/runtime-benchmarks", "cumulus-pallet-session-benchmarking/runtime-benchmarks", "cumulus-pallet-xcmp-queue/runtime-benchmarks", @@ -142,6 +177,10 @@ runtime-benchmarks = [ "frame-system-benchmarking/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", + "pallet-bridge-grandpa/runtime-benchmarks", + "pallet-bridge-messages/runtime-benchmarks", + "pallet-bridge-parachains/runtime-benchmarks", + "pallet-bridge-relayers/runtime-benchmarks", "pallet-collator-selection/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", @@ -168,6 +207,10 @@ try-runtime = [ "pallet-aura/try-runtime", "pallet-authorship/try-runtime", "pallet-balances/try-runtime", + "pallet-bridge-grandpa/try-runtime", + "pallet-bridge-messages/try-runtime", + "pallet-bridge-parachains/try-runtime", + "pallet-bridge-relayers/try-runtime", "pallet-collator-selection/try-runtime", "pallet-multisig/try-runtime", "pallet-session/try-runtime", 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 new file mode 100644 index 000000000000..51fbd6e3bac9 --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/bridge_hub_config.rs @@ -0,0 +1,236 @@ +// Copyright 2022 Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see . + +//! Bridge definitions. + +use crate::{ + BridgeParachainPolkadotInstance, BridgePolkadotMessages, Runtime, + WithBridgeHubPolkadotMessagesInstance, XcmRouter, +}; +use bp_messages::LaneId; +use bridge_runtime_common::{ + messages, + messages::{ + source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, + MessageBridge, ThisChainWithMessages, UnderlyingChainProvider, + }, + messages_xcm_extension::{SenderAndLane, XcmBlobHauler, XcmBlobHaulerAdapter}, + refund_relayer_extension::{ + ActualFeeRefund, RefundBridgedParachainMessages, RefundableMessagesLane, + RefundableParachain, + }, +}; +use frame_support::{parameter_types, traits::PalletInfoAccess}; +use sp_runtime::RuntimeDebug; +use xcm::{latest::prelude::*, prelude::NetworkId}; +use xcm_builder::{BridgeBlobDispatcher, HaulBlobExporter}; + +parameter_types! { + pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_messages::MessageNonce = + bp_bridge_hub_kusama::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce = + bp_bridge_hub_kusama::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + pub const BridgeHubPolkadotChainId: bp_runtime::ChainId = bp_runtime::BRIDGE_HUB_POLKADOT_CHAIN_ID; + pub BridgePolkadotMessagesPalletInstance: InteriorMultiLocation = X1(PalletInstance(::index() as u8)); + pub PolkadotGlobalConsensusNetwork: NetworkId = NetworkId::Polkadot; + // see the `FEE_BOOST_PER_MESSAGE` constant to get the meaning of this value + pub PriorityBoostPerMessage: u64 = 91_022_222_222_222; + + pub AssetHubKusamaParaId: cumulus_primitives_core::ParaId = 1000.into(); + + pub FromAssetHubKusamaToAssetHubPolkadotRoute: SenderAndLane = SenderAndLane::new( + ParentThen(X1(Parachain(AssetHubKusamaParaId::get().into()))).into(), + ASSET_HUB_KUSAMA_TO_ASSET_HUB_POLKADOT_LANE_ID, + ); +} + +/// Proof of messages, coming from BridgeHubPolkadot. +pub type FromBridgeHubPolkadotMessagesProof = + FromBridgedChainMessagesProof; +/// Message delivery proof for `BridgeHubPolkadot` messages. +pub type ToBridgeHubPolkadotMessagesDeliveryProof = + FromBridgedChainMessagesDeliveryProof; + +/// Dispatches received XCM messages from other bridge +pub type OnThisChainBlobDispatcher = + BridgeBlobDispatcher; + +/// Export XCM messages to be relayed to the other side. +pub type ToBridgeHubPolkadotHaulBlobExporter = HaulBlobExporter< + XcmBlobHaulerAdapter, + PolkadotGlobalConsensusNetwork, + (), +>; +pub struct ToBridgeHubPolkadotXcmBlobHauler; +impl XcmBlobHauler for ToBridgeHubPolkadotXcmBlobHauler { + type Runtime = Runtime; + type MessagesInstance = WithBridgeHubPolkadotMessagesInstance; + type SenderAndLane = FromAssetHubKusamaToAssetHubPolkadotRoute; + + type ToSourceChainSender = crate::XcmRouter; + type CongestedMessage = (); + type UncongestedMessage = (); +} + +/// Messaging Bridge configuration for ThisChain -> BridgeHubPolkadot +pub struct WithBridgeHubPolkadotMessageBridge; +impl MessageBridge for WithBridgeHubPolkadotMessageBridge { + const BRIDGED_MESSAGES_PALLET_NAME: &'static str = + bp_bridge_hub_kusama::WITH_BRIDGE_HUB_KUSAMA_MESSAGES_PALLET_NAME; + type ThisChain = ThisChain; + type BridgedChain = BridgeHubPolkadot; + type BridgedHeaderChain = pallet_bridge_parachains::ParachainHeaders< + Runtime, + BridgeParachainPolkadotInstance, + bp_bridge_hub_polkadot::BridgeHubPolkadot, + >; +} + +/// Message verifier for BridgeHubPolkadot messages sent from ThisChain +pub type ToBridgeHubPolkadotMessageVerifier = + messages::source::FromThisChainMessageVerifier; + +/// Maximal outbound payload size of ThisChain -> BridgeHubPolkadot messages. +pub type ToBridgeHubPolkadotMaximalOutboundPayloadSize = + messages::source::FromThisChainMaximalOutboundPayloadSize; + +/// BridgeHubPolkadot chain from message lane point of view. +#[derive(RuntimeDebug, Clone, Copy)] +pub struct BridgeHubPolkadot; + +impl UnderlyingChainProvider for BridgeHubPolkadot { + type Chain = bp_bridge_hub_polkadot::BridgeHubPolkadot; +} + +impl messages::BridgedChainWithMessages for BridgeHubPolkadot {} + +/// ThisChain chain from message lane point of view. +#[derive(RuntimeDebug, Clone, Copy)] +pub struct ThisChain; + +impl UnderlyingChainProvider for ThisChain { + type Chain = bp_bridge_hub_kusama::BridgeHubKusama; +} + +impl ThisChainWithMessages for ThisChain { + type RuntimeOrigin = crate::RuntimeOrigin; +} + +// TODO: rework once dynamic lanes are supported (https://github.com/paritytech/parity-bridges-common/issues/1760) +/// Signed extension that refunds relayers that are delivering messages from the Polkadot BridgeHub. +pub type BridgeRefundBridgeHubPolkadotMessages = RefundBridgedParachainMessages< + Runtime, + RefundableParachain, + RefundableMessagesLane, + ActualFeeRefund, + PriorityBoostPerMessage, + StrBridgeRefundBridgeHubPolkadotMessages, +>; +bp_runtime::generate_static_str_provider!(BridgeRefundBridgeHubPolkadotMessages); + +// TODO: rework once dynamic lanes are supported (https://github.com/paritytech/parity-bridges-common/issues/1760) +// now we support only StatemineToStatemint +/// Lanes setup +pub const ASSET_HUB_KUSAMA_TO_ASSET_HUB_POLKADOT_LANE_ID: LaneId = LaneId([0, 0, 0, 0]); +parameter_types! { + pub ActiveOutboundLanesToBridgeHubPolkadot: &'static [bp_messages::LaneId] = &[ASSET_HUB_KUSAMA_TO_ASSET_HUB_POLKADOT_LANE_ID]; + pub const StatemineToStatemintMessageLane: bp_messages::LaneId = ASSET_HUB_KUSAMA_TO_ASSET_HUB_POLKADOT_LANE_ID; +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{constants, BridgeGrandpaPolkadotInstance}; + use bridge_runtime_common::{ + assert_complete_bridge_types, + integrity::{ + assert_complete_bridge_constants, check_message_lane_weights, + AssertBridgeMessagesPalletConstants, AssertBridgePalletNames, AssertChainConstants, + AssertCompleteBridgeConstants, + }, + }; + use parachains_common::Balance; + + /// Every additional message in the message delivery transaction boosts its priority. + /// So the priority of transaction with `N+1` messages is larger than priority of + /// transaction with `N` messages by the `PriorityBoostPerMessage`. + /// + /// Economically, it is an equivalent of adding tip to the transaction with `N` messages. + /// The `FEE_BOOST_PER_MESSAGE` constant is the value of this tip. + /// + /// We want this tip to be large enough (delivery transactions with more messages = less + /// operational costs and a faster bridge), so this value should be significant. + const FEE_BOOST_PER_MESSAGE: Balance = constants::currency::UNITS; + + #[test] + fn ensure_lane_weights_are_correct() { + check_message_lane_weights::< + bp_bridge_hub_kusama::BridgeHubKusama, + Runtime, + WithBridgeHubPolkadotMessagesInstance, + >( + bp_bridge_hub_polkadot::EXTRA_STORAGE_PROOF_SIZE, + bp_bridge_hub_kusama::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + bp_bridge_hub_kusama::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + true, + ); + } + + #[test] + fn ensure_bridge_integrity() { + assert_complete_bridge_types!( + runtime: Runtime, + with_bridged_chain_grandpa_instance: BridgeGrandpaPolkadotInstance, + with_bridged_chain_messages_instance: WithBridgeHubPolkadotMessagesInstance, + bridge: WithBridgeHubPolkadotMessageBridge, + this_chain: bp_kusama::Kusama, + bridged_chain: bp_polkadot::Polkadot, + ); + + assert_complete_bridge_constants::< + Runtime, + BridgeGrandpaPolkadotInstance, + WithBridgeHubPolkadotMessagesInstance, + WithBridgeHubPolkadotMessageBridge, + >(AssertCompleteBridgeConstants { + this_chain_constants: AssertChainConstants { + block_length: bp_bridge_hub_kusama::BlockLength::get(), + block_weights: bp_bridge_hub_kusama::BlockWeights::get(), + }, + messages_pallet_constants: AssertBridgeMessagesPalletConstants { + max_unrewarded_relayers_in_bridged_confirmation_tx: + bp_bridge_hub_polkadot::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + max_unconfirmed_messages_in_bridged_confirmation_tx: + bp_bridge_hub_polkadot::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + bridged_chain_id: bp_runtime::BRIDGE_HUB_POLKADOT_CHAIN_ID, + }, + pallet_names: AssertBridgePalletNames { + with_this_chain_messages_pallet_name: + bp_bridge_hub_kusama::WITH_BRIDGE_HUB_KUSAMA_MESSAGES_PALLET_NAME, + with_bridged_chain_grandpa_pallet_name: + bp_polkadot::WITH_POLKADOT_GRANDPA_PALLET_NAME, + with_bridged_chain_messages_pallet_name: + bp_bridge_hub_polkadot::WITH_BRIDGE_HUB_POLKADOT_MESSAGES_PALLET_NAME, + }, + }); + + bridge_runtime_common::priority_calculator::ensure_priority_boost_is_sane::< + Runtime, + WithBridgeHubPolkadotMessagesInstance, + PriorityBoostPerMessage, + >(FEE_BOOST_PER_MESSAGE); + } +} 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 54b15e6b327b..c0c3edb37cf1 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 @@ -22,6 +22,7 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +pub mod bridge_hub_config; mod weights; pub mod xcm_config; @@ -59,6 +60,9 @@ use xcm_config::{ FellowshipLocation, GovernanceLocation, XcmConfig, XcmOriginToTransactDispatchOrigin, }; +use bp_parachains::SingleParaStoredHeaderDataBuilder; +use bp_runtime::HeaderId; + #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; @@ -73,7 +77,19 @@ use parachains_common::{ HOURS, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, SLOT_DURATION, }; -// XCM Imports +use crate::{ + bridge_hub_config::{ + BridgeRefundBridgeHubPolkadotMessages, OnThisChainBlobDispatcher, + WithBridgeHubPolkadotMessageBridge, + }, + xcm_config::{UniversalLocation, XcmRouter}, +}; + +use bridge_runtime_common::{ + messages::{source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter}, + messages_xcm_extension::{XcmAsPlainPayload, XcmBlobMessageDispatch}, +}; + use xcm::latest::prelude::BodyId; use xcm_executor::XcmExecutor; @@ -99,6 +115,8 @@ pub type SignedExtra = ( frame_system::CheckNonce, frame_system::CheckWeight, pallet_transaction_payment::ChargeTransactionPayment, + BridgeRejectObsoleteHeadersAndMessages, + BridgeRefundBridgeHubPolkadotMessages, ); /// Unchecked extrinsic type as expected by this runtime. @@ -401,6 +419,102 @@ impl pallet_utility::Config for Runtime { type WeightInfo = weights::pallet_utility::WeightInfo; } +// Add bridge pallets (GPA) +/// Add GRANDPA bridge pallet to track Polkadot relay chain on Kusama BridgeHub +pub type BridgeGrandpaPolkadotInstance = pallet_bridge_grandpa::Instance1; +impl pallet_bridge_grandpa::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type BridgedChain = bp_polkadot::Polkadot; + type MaxFreeMandatoryHeadersPerBlock = ConstU32<4>; + type HeadersToKeep = RelayChainHeadersToKeep; + type WeightInfo = weights::pallet_bridge_grandpa::WeightInfo; +} + +parameter_types! { + pub const RelayChainHeadersToKeep: u32 = 600; + pub const ParachainHeadsToKeep: u32 = 300; + /// Delay (in blocks) before registered relayer could get its stake back. It guarantees + /// that all pending delivery transactions are either dropped or mined and relayer is + /// slashed in case of misbehavior. So this value should be large enough (e.g. 24 hours). + pub const RelayerStakeLease: u32 = parachains_common::DAYS; + pub const PolkadotBridgeParachainPalletName: &'static str = bp_polkadot::PARAS_PALLET_NAME; + pub const MaxPolkadotParaHeadDataSize: u32 = bp_polkadot::MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE; + + pub const RelayerStakeReserveId: [u8; 8] = *b"brdgrlrs"; + // Just initial value, and concrete values will be set up by governance call (`set_storage`) with `initialize` bridge call as a part of cutover plan (https://github.com/paritytech/parity-bridges-common/issues/1730) + pub storage DeliveryRewardInBalance: u64 = 1_000_000; +} + +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub storage RequiredStakeForStakeAndSlash: Balance = 1; +} +#[cfg(not(feature = "runtime-benchmarks"))] +parameter_types! { + // Just initial value, and concrete values will be set up by governance call (`set_storage`) with `initialize` bridge call as a part of cutover plan (https://github.com/paritytech/parity-bridges-common/issues/1730) + pub storage RequiredStakeForStakeAndSlash: Balance = Balance::MAX; +} + +/// Add parachain bridge pallet to track Polkadot BridgeHub parachain +pub type BridgeParachainPolkadotInstance = pallet_bridge_parachains::Instance1; +impl pallet_bridge_parachains::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = weights::pallet_bridge_parachains::WeightInfo; + type BridgesGrandpaPalletInstance = BridgeGrandpaPolkadotInstance; + type ParasPalletName = PolkadotBridgeParachainPalletName; + type ParaStoredHeaderDataBuilder = + SingleParaStoredHeaderDataBuilder; + type HeadsToKeep = ParachainHeadsToKeep; + type MaxParaHeadDataSize = MaxPolkadotParaHeadDataSize; +} + +/// Add XCM messages support for Kusama<->Polkadot XCM messages +pub type WithBridgeHubPolkadotMessagesInstance = pallet_bridge_messages::Instance1; +impl pallet_bridge_messages::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = weights::pallet_bridge_messages::WeightInfo; + type BridgedChainId = bridge_hub_config::BridgeHubPolkadotChainId; + type ActiveOutboundLanes = bridge_hub_config::ActiveOutboundLanesToBridgeHubPolkadot; + type MaxUnrewardedRelayerEntriesAtInboundLane = + bridge_hub_config::MaxUnrewardedRelayerEntriesAtInboundLane; + type MaxUnconfirmedMessagesAtInboundLane = + bridge_hub_config::MaxUnconfirmedMessagesAtInboundLane; + type MaximalOutboundPayloadSize = + bridge_hub_config::ToBridgeHubPolkadotMaximalOutboundPayloadSize; + type OutboundPayload = XcmAsPlainPayload; + type InboundPayload = XcmAsPlainPayload; + type InboundRelayer = AccountId; + type DeliveryPayments = (); + type TargetHeaderChain = TargetHeaderChainAdapter; + type LaneMessageVerifier = bridge_hub_config::ToBridgeHubPolkadotMessageVerifier; + type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< + Runtime, + WithBridgeHubPolkadotMessagesInstance, + DeliveryRewardInBalance, + >; + type SourceHeaderChain = SourceHeaderChainAdapter; + type MessageDispatch = + XcmBlobMessageDispatch, Self::WeightInfo, ()>; + type OnMessagesDelivered = (); +} + +/// Allows collect and claim rewards for relayers +impl pallet_bridge_relayers::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Reward = Balance; + type PaymentProcedure = + bp_relayers::PayRewardFromAccount, AccountId>; + type StakeAndSlash = pallet_bridge_relayers::StakeAndSlashNamed< + AccountId, + BlockNumber, + Balances, + RelayerStakeReserveId, + RequiredStakeForStakeAndSlash, + RelayerStakeLease, + >; + type WeightInfo = weights::pallet_bridge_relayers::WeightInfo; +} + // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub enum Runtime @@ -433,9 +547,25 @@ construct_runtime!( // Handy utilities. Utility: pallet_utility::{Pallet, Call, Event} = 40, Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 41, + + // Kusama<>Polkadot bridge pallets// Bridging pallets + BridgePolkadotGrandpa: pallet_bridge_grandpa::::{Pallet, Call, Storage, Event, Config} = 51, + BridgePolkadotParachain: pallet_bridge_parachains::::{Pallet, Call, Storage, Event} = 52, + BridgePolkadotMessages: pallet_bridge_messages::::{Pallet, Call, Storage, Event, Config} = 53, + BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event} = 54, } ); +bridge_runtime_common::generate_bridge_reject_obsolete_headers_and_messages! { + RuntimeCall, AccountId, + // Grandpa + BridgePolkadotGrandpa, + // Parachains + BridgePolkadotParachain, + // Messages + BridgePolkadotMessages +} + #[cfg(feature = "runtime-benchmarks")] #[macro_use] extern crate frame_benchmarking; @@ -456,6 +586,12 @@ mod benches { // NOTE: Make sure you point to the individual modules below. [pallet_xcm_benchmarks::fungible, XcmBalances] [pallet_xcm_benchmarks::generic, XcmGeneric] + // Bridge pallets for Polkadot + [pallet_bridge_grandpa, BridgePolkadotGrandpa] + [pallet_bridge_parachains, BridgeParachainsBench::] + [pallet_bridge_messages, BridgeMessagesBench::] + // Bridge relayer pallets + [pallet_bridge_relayers, BridgeRelayersBench::] ); } @@ -603,6 +739,49 @@ impl_runtime_apis! { } } + impl bp_polkadot::PolkadotFinalityApi for Runtime { + fn best_finalized() -> Option> { + BridgePolkadotGrandpa::best_finalized() + } + fn synced_headers_grandpa_info( + ) -> Vec> { + BridgePolkadotGrandpa::synced_headers_grandpa_info() + } + } + + impl bp_bridge_hub_polkadot::BridgeHubPolkadotFinalityApi for Runtime { + fn best_finalized() -> Option> { + BridgePolkadotParachain::best_parachain_head_id::< + bp_bridge_hub_polkadot::BridgeHubPolkadot + >().unwrap_or(None) + } + } + + impl bp_bridge_hub_polkadot::FromBridgeHubPolkadotInboundLaneApi for Runtime { + fn message_details( + lane: bp_messages::LaneId, + messages: Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>, + ) -> Vec { + bridge_runtime_common::messages_api::inbound_message_details::< + Runtime, + WithBridgeHubPolkadotMessagesInstance, + >(lane, messages) + } + } + + impl bp_bridge_hub_polkadot::ToBridgeHubPolkadotOutboundLaneApi for Runtime { + fn message_details( + lane: bp_messages::LaneId, + begin: bp_messages::MessageNonce, + end: bp_messages::MessageNonce, + ) -> Vec { + bridge_runtime_common::messages_api::outbound_message_details::< + Runtime, + WithBridgeHubPolkadotMessagesInstance, + >(lane, begin, end) + } + } + #[cfg(feature = "try-runtime")] impl frame_try_runtime::TryRuntime for Runtime { fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { @@ -639,6 +818,10 @@ impl_runtime_apis! { type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::; type XcmGeneric = pallet_xcm_benchmarks::generic::Pallet::; + use pallet_bridge_parachains::benchmarking::Pallet as BridgeParachainsBench; + use pallet_bridge_messages::benchmarking::Pallet as BridgeMessagesBench; + use pallet_bridge_relayers::benchmarking::Pallet as BridgeRelayersBench; + let mut list = Vec::::new(); list_benchmarks!(list, extra); @@ -748,7 +931,7 @@ impl_runtime_apis! { fn export_message_origin_and_destination( ) -> Result<(MultiLocation, NetworkId, InteriorMultiLocation), BenchmarkError> { - Err(BenchmarkError::Skip) + Ok((KsmRelayLocation::get(), bridge_hub_config::PolkadotGlobalConsensusNetwork::get(), X1(Parachain(100)))) } fn alias_origin() -> Result<(MultiLocation, MultiLocation), BenchmarkError> { @@ -759,6 +942,102 @@ 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 pallet_bridge_messages::benchmarking::{ + Config as BridgeMessagesConfig, + Pallet as BridgeMessagesBench, + MessageDeliveryProofParams, + MessageProofParams, + }; + impl BridgeMessagesConfig for Runtime { + fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool { + let bench_lane_id = >::bench_lane_id(); + let bridged_chain_id = bp_runtime::BRIDGE_HUB_POLKADOT_CHAIN_ID; + pallet_bridge_relayers::Pallet::::relayer_reward( + relayer, + bp_relayers::RewardsAccountParams::new( + bench_lane_id, + bridged_chain_id, + bp_relayers::RewardsAccountOwner::BridgedChain + ) + ).is_some() + } + fn prepare_message_proof( + params: MessageProofParams, + ) -> (bridge_hub_config::FromBridgeHubPolkadotMessagesProof, Weight) { + use cumulus_primitives_core::XcmpMessageSource; + assert!(XcmpQueue::take_outbound_messages(usize::MAX).is_empty()); + ParachainSystem::open_outbound_hrmp_channel_for_benchmarks(42.into()); + prepare_message_proof_from_parachain::< + Runtime, + BridgeGrandpaPolkadotInstance, + bridge_hub_config::WithBridgeHubPolkadotMessageBridge, + >(params, X2(GlobalConsensus(xcm_config::RelayNetwork::get().unwrap()), Parachain(42))) + } + fn prepare_message_delivery_proof( + params: MessageDeliveryProofParams, + ) -> bridge_hub_config::ToBridgeHubPolkadotMessagesDeliveryProof { + prepare_message_delivery_proof_from_parachain::< + Runtime, + BridgeGrandpaPolkadotInstance, + bridge_hub_config::WithBridgeHubPolkadotMessageBridge, + >(params) + } + fn is_message_successfully_dispatched(_nonce: bp_messages::MessageNonce) -> bool { + use cumulus_primitives_core::XcmpMessageSource; + !XcmpQueue::take_outbound_messages(usize::MAX).is_empty() + } + } + + use bridge_runtime_common::parachains_benchmarking::prepare_parachain_heads_proof; + use pallet_bridge_parachains::benchmarking::{ + Config as BridgeParachainsConfig, + Pallet as BridgeParachainsBench, + }; + use pallet_bridge_relayers::benchmarking::{ + Pallet as BridgeRelayersBench, + Config as BridgeRelayersConfig, + }; + impl BridgeParachainsConfig for Runtime { + fn parachains() -> Vec { + use bp_runtime::Parachain; + vec![bp_polkadot_core::parachains::ParaId(bp_bridge_hub_polkadot::BridgeHubPolkadot::PARACHAIN_ID)] + } + fn prepare_parachain_heads_proof( + parachains: &[bp_polkadot_core::parachains::ParaId], + parachain_head_size: u32, + proof_size: bp_runtime::StorageProofSize, + ) -> ( + pallet_bridge_parachains::RelayBlockNumber, + pallet_bridge_parachains::RelayBlockHash, + bp_polkadot_core::parachains::ParaHeadsProof, + Vec<(bp_polkadot_core::parachains::ParaId, bp_polkadot_core::parachains::ParaHash)>, + ) { + prepare_parachain_heads_proof::( + parachains, + parachain_head_size, + proof_size, + ) + } + } + + impl BridgeRelayersConfig for Runtime { + fn prepare_rewards_account( + account_params: bp_relayers::RewardsAccountParams, + reward: Balance, + ) { + let rewards_account = bp_relayers::PayRewardFromAccount::< + Balances, + AccountId + >::rewards_account(account_params); + Self::deposit_account(rewards_account, reward); + } + fn deposit_account(account: AccountId, balance: Balance) { + use frame_support::traits::fungible::Mutate; + Balances::mint_into(&account, balance.saturating_add(ExistentialDeposit::get())).unwrap(); + } + } + let whitelist: Vec = vec![ // Block Number hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(), @@ -785,3 +1064,40 @@ cumulus_pallet_parachain_system::register_validate_block! { Runtime = Runtime, BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::, } + +#[cfg(test)] +mod tests { + use super::*; + use bp_runtime::TransactionEra; + use bridge_hub_test_utils::test_header; + use codec::Encode; + + pub type TestBlockHeader = + generic::Header; + + #[test] + fn ensure_signed_extension_definition_is_compatible_with_relay() { + let payload: SignedExtra = ( + frame_system::CheckNonZeroSender::new(), + frame_system::CheckSpecVersion::new(), + frame_system::CheckTxVersion::new(), + frame_system::CheckGenesis::new(), + frame_system::CheckEra::from(sp_runtime::generic::Era::Immortal), + frame_system::CheckNonce::from(10), + frame_system::CheckWeight::new(), + pallet_transaction_payment::ChargeTransactionPayment::from(10), + BridgeRejectObsoleteHeadersAndMessages::default(), + BridgeRefundBridgeHubPolkadotMessages::default(), + ); + use bp_bridge_hub_kusama::BridgeHubSignedExtension; + let bh_indirect_payload = bp_bridge_hub_kusama::SignedExtension::from_params( + 10, + 10, + TransactionEra::Immortal, + test_header::(1).hash(), + 10, + 10, + ); + assert_eq!(payload.encode(), bh_indirect_payload.encode()); + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/mod.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/mod.rs index e226021e77ab..759aa1eac63c 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/mod.rs @@ -22,6 +22,10 @@ pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; pub mod pallet_balances; +pub mod pallet_bridge_grandpa; +pub mod pallet_bridge_messages; +pub mod pallet_bridge_parachains; +pub mod pallet_bridge_relayers; pub mod pallet_collator_selection; pub mod pallet_multisig; pub mod pallet_session; @@ -36,3 +40,32 @@ pub use block_weights::constants::BlockExecutionWeight; pub use extrinsic_weights::constants::ExtrinsicBaseWeight; pub use paritydb_weights::constants::ParityDbWeight; pub use rocksdb_weights::constants::RocksDbWeight; + +use frame_support::weights::Weight; + +// import trait from dependency module +use ::pallet_bridge_relayers::WeightInfoExt as _; + +impl ::pallet_bridge_messages::WeightInfoExt + for pallet_bridge_messages::WeightInfo +{ + fn expected_extra_storage_proof_size() -> u32 { + bp_bridge_hub_polkadot::EXTRA_STORAGE_PROOF_SIZE + } + + fn receive_messages_proof_overhead_from_runtime() -> Weight { + pallet_bridge_relayers::WeightInfo::::receive_messages_proof_overhead_from_runtime() + } + + fn receive_messages_delivery_proof_overhead_from_runtime() -> Weight { + pallet_bridge_relayers::WeightInfo::::receive_messages_delivery_proof_overhead_from_runtime() + } +} + +impl ::pallet_bridge_parachains::WeightInfoExt + for pallet_bridge_parachains::WeightInfo +{ + fn expected_extra_storage_proof_size() -> u32 { + bp_bridge_hub_polkadot::EXTRA_STORAGE_PROOF_SIZE + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_grandpa.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_grandpa.rs new file mode 100644 index 000000000000..b9d4f0a17e0a --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_grandpa.rs @@ -0,0 +1,80 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see . + +//! Autogenerated weights for `pallet_bridge_grandpa` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `bm3`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-kusama-dev"), DB CACHE: 1024 + +// Executed Command: +// target/production/polkadot-parachain +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/var/lib/gitlab-runner/builds/zyw4fam_/0/parity/mirrors/cumulus/.git/.artifacts/bench.json +// --pallet=pallet_bridge_grandpa +// --chain=bridge-hub-kusama-dev +// --header=./file_header.txt +// --output=./parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_bridge_grandpa`. +pub struct WeightInfo(PhantomData); +impl pallet_bridge_grandpa::WeightInfo for WeightInfo { + /// Storage: BridgePolkadotGrandpa PalletOperatingMode (r:1 w:0) + /// Proof: BridgePolkadotGrandpa PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: BridgePolkadotGrandpa BestFinalized (r:1 w:1) + /// Proof: BridgePolkadotGrandpa BestFinalized (max_values: Some(1), max_size: Some(36), added: 531, mode: MaxEncodedLen) + /// Storage: BridgePolkadotGrandpa CurrentAuthoritySet (r:1 w:0) + /// Proof: BridgePolkadotGrandpa CurrentAuthoritySet (max_values: Some(1), max_size: Some(50250), added: 50745, mode: MaxEncodedLen) + /// Storage: BridgePolkadotGrandpa ImportedHashesPointer (r:1 w:1) + /// Proof: BridgePolkadotGrandpa ImportedHashesPointer (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: BridgePolkadotGrandpa ImportedHashes (r:1 w:1) + /// Proof: BridgePolkadotGrandpa ImportedHashes (max_values: Some(1024), max_size: Some(36), added: 1521, mode: MaxEncodedLen) + /// Storage: BridgePolkadotGrandpa ImportedHeaders (r:0 w:2) + /// Proof: BridgePolkadotGrandpa ImportedHeaders (max_values: Some(1024), max_size: Some(68), added: 1553, mode: MaxEncodedLen) + /// The range of component `p` is `[1, 838]`. + /// The range of component `v` is `[50, 100]`. + fn submit_finality_proof(p: u32, v: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `231 + p * (60 ±0)` + // Estimated: `51735` + // Minimum execution time: 229_674_000 picoseconds. + Weight::from_parts(110_662_672, 0) + .saturating_add(Weight::from_parts(0, 51735)) + // Standard Error: 16_268 + .saturating_add(Weight::from_parts(47_526_047, 0).saturating_mul(p.into())) + // Standard Error: 271_338 + .saturating_add(Weight::from_parts(743_913, 0).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(5)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_messages.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_messages.rs new file mode 100644 index 000000000000..f083169f513a --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_messages.rs @@ -0,0 +1,231 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see . + +//! Autogenerated weights for `pallet_bridge_messages` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `bm3`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-kusama-dev"), DB CACHE: 1024 + +// Executed Command: +// target/production/polkadot-parachain +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/var/lib/gitlab-runner/builds/zyw4fam_/0/parity/mirrors/cumulus/.git/.artifacts/bench.json +// --pallet=pallet_bridge_messages +// --chain=bridge-hub-kusama-dev +// --header=./file_header.txt +// --output=./parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_bridge_messages`. +pub struct WeightInfo(PhantomData); +impl pallet_bridge_messages::WeightInfo for WeightInfo { + /// Storage: BridgePolkadotMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgePolkadotMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgePolkadotParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgePolkadotMessages InboundLanes (r:1 w:1) + /// Proof: BridgePolkadotMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn receive_single_message_proof() -> Weight { + // Proof Size summary in bytes: + // Measured: `403` + // Estimated: `52645` + // Minimum execution time: 44_142_000 picoseconds. + Weight::from_parts(44_925_000, 0) + .saturating_add(Weight::from_parts(0, 52645)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgePolkadotMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgePolkadotMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgePolkadotParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgePolkadotMessages InboundLanes (r:1 w:1) + /// Proof: BridgePolkadotMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn receive_two_messages_proof() -> Weight { + // Proof Size summary in bytes: + // Measured: `403` + // Estimated: `52645` + // Minimum execution time: 54_901_000 picoseconds. + Weight::from_parts(55_357_000, 0) + .saturating_add(Weight::from_parts(0, 52645)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgePolkadotMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgePolkadotMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgePolkadotParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgePolkadotMessages InboundLanes (r:1 w:1) + /// Proof: BridgePolkadotMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn receive_single_message_proof_with_outbound_lane_state() -> Weight { + // Proof Size summary in bytes: + // Measured: `403` + // Estimated: `52645` + // Minimum execution time: 49_037_000 picoseconds. + Weight::from_parts(49_616_000, 0) + .saturating_add(Weight::from_parts(0, 52645)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgePolkadotMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgePolkadotMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgePolkadotParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgePolkadotMessages InboundLanes (r:1 w:1) + /// Proof: BridgePolkadotMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + fn receive_single_message_proof_1_kb() -> Weight { + // Proof Size summary in bytes: + // Measured: `372` + // Estimated: `52645` + // Minimum execution time: 42_180_000 picoseconds. + Weight::from_parts(42_666_000, 0) + .saturating_add(Weight::from_parts(0, 52645)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgePolkadotMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgePolkadotMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgePolkadotParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgePolkadotMessages InboundLanes (r:1 w:1) + /// Proof: BridgePolkadotMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + fn receive_single_message_proof_16_kb() -> Weight { + // Proof Size summary in bytes: + // Measured: `372` + // Estimated: `52645` + // Minimum execution time: 69_307_000 picoseconds. + Weight::from_parts(69_871_000, 0) + .saturating_add(Weight::from_parts(0, 52645)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgePolkadotMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgePolkadotMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgePolkadotParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgePolkadotMessages OutboundLanes (r:1 w:1) + /// Proof: BridgePolkadotMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) + /// Storage: unknown `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Proof Skipped: unknown `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + fn receive_delivery_proof_for_single_message() -> Weight { + // Proof Size summary in bytes: + // Measured: `376` + // Estimated: `3841` + // Minimum execution time: 33_354_000 picoseconds. + Weight::from_parts(34_244_000, 0) + .saturating_add(Weight::from_parts(0, 3841)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: BridgePolkadotMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgePolkadotMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgePolkadotParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgePolkadotMessages OutboundLanes (r:1 w:1) + /// Proof: BridgePolkadotMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) + /// Storage: unknown `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Proof Skipped: unknown `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { + // Proof Size summary in bytes: + // Measured: `376` + // Estimated: `3841` + // Minimum execution time: 33_264_000 picoseconds. + Weight::from_parts(33_675_000, 0) + .saturating_add(Weight::from_parts(0, 3841)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: BridgePolkadotMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgePolkadotMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgePolkadotParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgePolkadotMessages OutboundLanes (r:1 w:1) + /// Proof: BridgePolkadotMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) + /// Storage: unknown `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Proof Skipped: unknown `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Storage: BridgeRelayers RelayerRewards (r:2 w:2) + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { + // Proof Size summary in bytes: + // Measured: `376` + // Estimated: `6086` + // Minimum execution time: 35_608_000 picoseconds. + Weight::from_parts(36_142_000, 0) + .saturating_add(Weight::from_parts(0, 6086)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: BridgePolkadotMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgePolkadotMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgePolkadotParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgePolkadotMessages InboundLanes (r:1 w:1) + /// Proof: BridgePolkadotMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem RelevantMessagingState (r:1 w:0) + /// Proof Skipped: ParachainSystem RelevantMessagingState (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: XcmpQueue OutboundXcmpStatus (r:1 w:1) + /// Proof Skipped: XcmpQueue OutboundXcmpStatus (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: XcmpQueue OutboundXcmpMessages (r:0 w:1) + /// Proof Skipped: XcmpQueue OutboundXcmpMessages (max_values: None, max_size: None, mode: Measured) + /// The range of component `i` is `[128, 2048]`. + fn receive_single_message_proof_with_dispatch(i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `634` + // Estimated: `52645` + // Minimum execution time: 130_265_000 picoseconds. + Weight::from_parts(100_110_870, 0) + .saturating_add(Weight::from_parts(0, 52645)) + // Standard Error: 3_659 + .saturating_add(Weight::from_parts(547_474, 0).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(4)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_parachains.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_parachains.rs new file mode 100644 index 000000000000..82a19eccba46 --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_parachains.rs @@ -0,0 +1,113 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see . + +//! Autogenerated weights for `pallet_bridge_parachains` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `bm3`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-kusama-dev"), DB CACHE: 1024 + +// Executed Command: +// target/production/polkadot-parachain +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/var/lib/gitlab-runner/builds/zyw4fam_/0/parity/mirrors/cumulus/.git/.artifacts/bench.json +// --pallet=pallet_bridge_parachains +// --chain=bridge-hub-kusama-dev +// --header=./file_header.txt +// --output=./parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_bridge_parachains`. +pub struct WeightInfo(PhantomData); +impl pallet_bridge_parachains::WeightInfo for WeightInfo { + /// Storage: BridgePolkadotParachain PalletOperatingMode (r:1 w:0) + /// Proof: BridgePolkadotParachain PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: BridgePolkadotGrandpa ImportedHeaders (r:1 w:0) + /// Proof: BridgePolkadotGrandpa ImportedHeaders (max_values: Some(1024), max_size: Some(68), added: 1553, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ParasInfo (r:1 w:1) + /// Proof: BridgePolkadotParachain ParasInfo (max_values: Some(1), max_size: Some(60), added: 555, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHashes (r:1 w:1) + /// Proof: BridgePolkadotParachain ImportedParaHashes (max_values: Some(64), max_size: Some(64), added: 1054, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHeads (r:0 w:1) + /// Proof: BridgePolkadotParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// The range of component `p` is `[1, 2]`. + fn submit_parachain_heads_with_n_parachains(_p: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `330` + // Estimated: `2543` + // Minimum execution time: 33_988_000 picoseconds. + Weight::from_parts(35_239_510, 0) + .saturating_add(Weight::from_parts(0, 2543)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: BridgePolkadotParachain PalletOperatingMode (r:1 w:0) + /// Proof: BridgePolkadotParachain PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: BridgePolkadotGrandpa ImportedHeaders (r:1 w:0) + /// Proof: BridgePolkadotGrandpa ImportedHeaders (max_values: Some(1024), max_size: Some(68), added: 1553, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ParasInfo (r:1 w:1) + /// Proof: BridgePolkadotParachain ParasInfo (max_values: Some(1), max_size: Some(60), added: 555, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHashes (r:1 w:1) + /// Proof: BridgePolkadotParachain ImportedParaHashes (max_values: Some(64), max_size: Some(64), added: 1054, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHeads (r:0 w:1) + /// Proof: BridgePolkadotParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + fn submit_parachain_heads_with_1kb_proof() -> Weight { + // Proof Size summary in bytes: + // Measured: `330` + // Estimated: `2543` + // Minimum execution time: 35_298_000 picoseconds. + Weight::from_parts(36_119_000, 0) + .saturating_add(Weight::from_parts(0, 2543)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: BridgePolkadotParachain PalletOperatingMode (r:1 w:0) + /// Proof: BridgePolkadotParachain PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: BridgePolkadotGrandpa ImportedHeaders (r:1 w:0) + /// Proof: BridgePolkadotGrandpa ImportedHeaders (max_values: Some(1024), max_size: Some(68), added: 1553, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ParasInfo (r:1 w:1) + /// Proof: BridgePolkadotParachain ParasInfo (max_values: Some(1), max_size: Some(60), added: 555, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHashes (r:1 w:1) + /// Proof: BridgePolkadotParachain ImportedParaHashes (max_values: Some(64), max_size: Some(64), added: 1054, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHeads (r:0 w:1) + /// Proof: BridgePolkadotParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + fn submit_parachain_heads_with_16kb_proof() -> Weight { + // Proof Size summary in bytes: + // Measured: `330` + // Estimated: `2543` + // Minimum execution time: 61_503_000 picoseconds. + Weight::from_parts(61_999_000, 0) + .saturating_add(Weight::from_parts(0, 2543)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_relayers.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_relayers.rs new file mode 100644 index 000000000000..d51f44aee56b --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_relayers.rs @@ -0,0 +1,124 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see . + +//! Autogenerated weights for `pallet_bridge_relayers` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-05, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `bkontur-ThinkPad-P14s-Gen-2i`, CPU: `11th Gen Intel(R) Core(TM) i7-1185G7 @ 3.00GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-kusama-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/production/polkadot-parachain +// benchmark +// pallet +// --steps=2 +// --repeat=2 +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=./bench.json +// --header=./file_header.txt +// --chain=bridge-hub-kusama-dev +// --pallet=pallet_bridge_relayers +// --output=./parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_bridge_relayers`. +pub struct WeightInfo(PhantomData); +impl pallet_bridge_relayers::WeightInfo for WeightInfo { + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + fn claim_rewards() -> Weight { + // Proof Size summary in bytes: + // Measured: `207` + // Estimated: `3593` + // Minimum execution time: 52_874_000 picoseconds. + Weight::from_parts(72_930_000, 0) + .saturating_add(Weight::from_parts(0, 3593)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: BridgeRelayers RegisteredRelayers (r:1 w:1) + /// Proof: BridgeRelayers RegisteredRelayers (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) + /// Storage: unknown `0x1e8445dc201eeb8560e5579a5dd54655` (r:1 w:0) + /// Proof Skipped: unknown `0x1e8445dc201eeb8560e5579a5dd54655` (r:1 w:0) + /// Storage: Balances Reserves (r:1 w:1) + /// Proof: Balances Reserves (max_values: None, max_size: Some(1249), added: 3724, mode: MaxEncodedLen) + fn register() -> Weight { + // Proof Size summary in bytes: + // Measured: `61` + // Estimated: `4714` + // Minimum execution time: 28_476_000 picoseconds. + Weight::from_parts(32_338_000, 0) + .saturating_add(Weight::from_parts(0, 4714)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: BridgeRelayers RegisteredRelayers (r:1 w:1) + /// Proof: BridgeRelayers RegisteredRelayers (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) + /// Storage: Balances Reserves (r:1 w:1) + /// Proof: Balances Reserves (max_values: None, max_size: Some(1249), added: 3724, mode: MaxEncodedLen) + fn deregister() -> Weight { + // Proof Size summary in bytes: + // Measured: `160` + // Estimated: `4714` + // Minimum execution time: 28_815_000 picoseconds. + Weight::from_parts(30_180_000, 0) + .saturating_add(Weight::from_parts(0, 4714)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: BridgeRelayers RegisteredRelayers (r:1 w:1) + /// Proof: BridgeRelayers RegisteredRelayers (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) + /// Storage: Balances Reserves (r:1 w:1) + /// Proof: Balances Reserves (max_values: None, max_size: Some(1249), added: 3724, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + fn slash_and_deregister() -> Weight { + // Proof Size summary in bytes: + // Measured: `263` + // Estimated: `4714` + // Minimum execution time: 29_426_000 picoseconds. + Weight::from_parts(31_393_000, 0) + .saturating_add(Weight::from_parts(0, 4714)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + fn register_relayer_reward() -> Weight { + // Proof Size summary in bytes: + // Measured: `6` + // Estimated: `3538` + // Minimum execution time: 3_035_000 picoseconds. + Weight::from_parts(3_572_000, 0) + .saturating_add(Weight::from_parts(0, 3538)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/xcm/mod.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/xcm/mod.rs index 0e740922f339..8d65067d95d1 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/xcm/mod.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/xcm/mod.rs @@ -18,6 +18,7 @@ mod pallet_xcm_benchmarks_fungible; mod pallet_xcm_benchmarks_generic; use crate::{xcm_config::MaxAssetsIntoHolding, Runtime}; +use codec::Encode; use frame_support::weights::Weight; use pallet_xcm_benchmarks_fungible::WeightInfo as XcmFungibleWeight; use pallet_xcm_benchmarks_generic::WeightInfo as XcmGeneric; @@ -222,8 +223,9 @@ impl XcmWeightInfo for BridgeHubKusamaXcmWeight { fn universal_origin(_: &Junction) -> Weight { Weight::MAX } - fn export_message(_: &NetworkId, _: &Junctions, _: &Xcm<()>) -> Weight { - Weight::MAX + fn export_message(_: &NetworkId, _: &Junctions, inner: &Xcm<()>) -> Weight { + let inner_encoded_len = inner.encode().len() as u32; + XcmGeneric::::export_message(inner_encoded_len) } fn lock_asset(_: &MultiAsset, _: &MultiLocation) -> Weight { Weight::MAX diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/xcm/pallet_xcm_benchmarks_generic.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/xcm/pallet_xcm_benchmarks_generic.rs index b1e8107b30bb..5b88094a867c 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/xcm/pallet_xcm_benchmarks_generic.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/xcm/pallet_xcm_benchmarks_generic.rs @@ -312,6 +312,26 @@ impl WeightInfo { // Minimum execution time: 2_576_000 picoseconds. Weight::from_parts(2_701_000, 0) } + // Storage: ParachainInfo ParachainId (r:1 w:0) + // Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + // Storage: BridgePolkadotMessages PalletOperatingMode (r:1 w:0) + // Proof: BridgePolkadotMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + // Storage: BridgePolkadotMessages OutboundLanes (r:1 w:1) + // Proof: BridgePolkadotMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) + // Storage: BridgePolkadotMessages OutboundMessages (r:0 w:1) + // Proof: BridgePolkadotMessages OutboundMessages (max_values: None, max_size: Some(2621472), added: 2623947, mode: MaxEncodedLen) + /// The range of component `x` is `[1, 1000]`. + pub fn export_message(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `132` + // Estimated: `1529` + // Minimum execution time: 29_796_000 picoseconds. + Weight::from_parts(32_947_104, 1529) + // Standard Error: 930 + .saturating_add(Weight::from_parts(177_649, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) + } pub fn set_fees_mode() -> Weight { // Proof Size summary in bytes: // Measured: `0` 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 696462be9c45..028dd5329ca1 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 @@ -18,6 +18,10 @@ use super::{ AccountId, AllPalletsWithSystem, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, }; +use crate::{ + bridge_hub_config::ToBridgeHubPolkadotHaulBlobExporter, BridgeGrandpaPolkadotInstance, + DeliveryRewardInBalance, RequiredStakeForStakeAndSlash, +}; use frame_support::{ match_types, parameter_types, traits::{ConstU32, Contains, Everything, Nothing}, @@ -83,7 +87,7 @@ pub type XcmOriginToTransactDispatchOrigin = ( // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for // foreign chains who want to have a local sovereign account on this chain which they control. SovereignSignedViaLocation, - // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when + // Native converter for Relay-chain (Parent) location; will convert to a `Relay` origin when // recognized. RelayChainAsNative, // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when @@ -108,7 +112,14 @@ 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 /// account for proof size weights. /// @@ -126,6 +137,17 @@ impl Contains for SafeCallFilter { } } + // Allow to change dedicated storage items (called by governance-like) + match call { + RuntimeCall::System(frame_system::Call::set_storage { items }) + if items.iter().any(|(k, _)| { + k.eq(&DeliveryRewardInBalance::key()) | + k.eq(&RequiredStakeForStakeAndSlash::key()) + }) => + return true, + _ => (), + }; + matches!( call, RuntimeCall::PolkadotXcm(pallet_xcm::Call::force_xcm_version { .. }) | @@ -147,7 +169,11 @@ impl Contains for SafeCallFilter { pallet_collator_selection::Call::remove_invulnerable { .. }, ) | RuntimeCall::Session(pallet_session::Call::purge_keys { .. }) | RuntimeCall::XcmpQueue(..) | - RuntimeCall::DmpQueue(..) + RuntimeCall::DmpQueue(..) | + RuntimeCall::BridgePolkadotGrandpa(pallet_bridge_grandpa::Call::< + Runtime, + BridgeGrandpaPolkadotInstance, + >::initialize { .. }) ) } } @@ -165,8 +191,9 @@ pub type Barrier = TrailingSetTopicAsId< // If the message is one that immediately attemps to pay for execution, then // allow it. AllowTopLevelPaidExecutionFrom, - // Parent and its pluralities (i.e. governance bodies) get free execution. - AllowExplicitUnpaidExecutionFrom, + // Parent, its pluralities (i.e. governance bodies) and system parachains get + // free execution. + AllowExplicitUnpaidExecutionFrom<(ParentOrParentsPlurality, SystemParachains)>, // Subscriptions for version tracking are OK. AllowSubscriptionsFrom, ), @@ -199,14 +226,14 @@ impl xcm_executor::Config for XcmConfig { UsingComponents>; type ResponseHandler = PolkadotXcm; type AssetTrap = PolkadotXcm; + type AssetLocker = (); + type AssetExchanger = (); type AssetClaims = PolkadotXcm; type SubscriptionService = PolkadotXcm; type PalletInstancesInfo = AllPalletsWithSystem; type MaxAssetsIntoHolding = MaxAssetsIntoHolding; - type AssetLocker = (); - type AssetExchanger = (); type FeeManager = (); - type MessageExporter = (); + type MessageExporter = ToBridgeHubPolkadotHaulBlobExporter; type UniversalAliases = Nothing; type CallDispatcher = WithOriginFilter; type SafeCallFilter = SafeCallFilter; 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 893524e12f66..e4d92f180bcc 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 @@ -14,18 +14,84 @@ // You should have received a copy of the GNU General Public License // along with Cumulus. If not, see . +use bp_polkadot_core::Signature; pub use bridge_hub_kusama_runtime::{ - xcm_config::XcmConfig, AllPalletsWithoutSystem, Balances, ExistentialDeposit, ParachainSystem, - PolkadotXcm, Runtime, RuntimeEvent, SessionKeys, + bridge_hub_config, + xcm_config::{RelayNetwork, XcmConfig}, + AllPalletsWithoutSystem, Balances, BridgeGrandpaPolkadotInstance, + BridgeRejectObsoleteHeadersAndMessages, ExistentialDeposit, ParachainSystem, PolkadotXcm, + Runtime, RuntimeCall, RuntimeEvent, SessionKeys, WithBridgeHubPolkadotMessagesInstance, }; -use codec::Decode; +use bridge_hub_kusama_runtime::{ + bridge_hub_config::WithBridgeHubPolkadotMessageBridge, BridgeParachainPolkadotInstance, + DeliveryRewardInBalance, Executive, RequiredStakeForStakeAndSlash, SignedExtra, + UncheckedExtrinsic, +}; +use codec::{Decode, Encode}; use frame_support::parameter_types; -use parachains_common::{kusama::fee::WeightToFee, AccountId, AuraId}; +use parachains_common::{kusama::fee::WeightToFee, AccountId, AuraId, Balance}; +use sp_keyring::AccountKeyring::Alice; +use sp_runtime::{ + generic::{Era, SignedPayload}, + traits::Block as BlockT, + AccountId32, +}; +use xcm::latest::prelude::*; -const ALICE: [u8; 32] = [1u8; 32]; +// Para id of sibling chain (e.g. Statemine) used in tests. +pub const SIBLING_PARACHAIN_ID: u32 = 1000; parameter_types! { pub CheckingAccount: AccountId = PolkadotXcm::check_account(); + pub RuntimeNetwork: NetworkId = RelayNetwork::get().unwrap(); +} + +fn construct_extrinsic( + sender: sp_keyring::AccountKeyring, + call: RuntimeCall, +) -> UncheckedExtrinsic { + let extra: SignedExtra = ( + frame_system::CheckNonZeroSender::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(Era::immortal()), + frame_system::CheckNonce::::from(0), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(0), + BridgeRejectObsoleteHeadersAndMessages::default(), + bridge_hub_config::BridgeRefundBridgeHubPolkadotMessages::default(), + ); + let payload = SignedPayload::new(call.clone(), extra.clone()).unwrap(); + let signature = payload.using_encoded(|e| sender.sign(e)); + UncheckedExtrinsic::new_signed( + call, + AccountId32::from(sender.public()).into(), + Signature::Sr25519(signature.clone()), + extra, + ) +} + +fn construct_and_apply_extrinsic( + relayer_at_target: sp_keyring::AccountKeyring, + batch: pallet_utility::Call, +) -> sp_runtime::DispatchOutcome { + let batch_call = RuntimeCall::Utility(batch); + let xt = construct_extrinsic(relayer_at_target, batch_call); + let r = Executive::apply_extrinsic(xt); + r.unwrap() +} + +fn executive_init_block(header: &<::Block as BlockT>::Header) { + Executive::initialize_block(header) +} + +fn collator_session_keys() -> bridge_hub_test_utils::CollatorSessionKeys { + bridge_hub_test_utils::CollatorSessionKeys::new( + AccountId::from(Alice), + AccountId::from(Alice), + SessionKeys { aura: AuraId::from(Alice.public()) }, + ) } bridge_hub_test_utils::test_cases::include_teleports_for_native_asset_works!( @@ -35,11 +101,7 @@ bridge_hub_test_utils::test_cases::include_teleports_for_native_asset_works!( CheckingAccount, WeightToFee, ParachainSystem, - bridge_hub_test_utils::CollatorSessionKeys::new( - AccountId::from(ALICE), - AccountId::from(ALICE), - SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) } - ), + collator_session_keys(), ExistentialDeposit::get(), Box::new(|runtime_event_encoded: Vec| { match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { @@ -55,3 +117,148 @@ bridge_hub_test_utils::test_cases::include_teleports_for_native_asset_works!( }), 1002 ); + +#[test] +fn initialize_bridge_by_governance_works() { + bridge_hub_test_utils::test_cases::initialize_bridge_by_governance_works::< + Runtime, + BridgeGrandpaPolkadotInstance, + >( + collator_session_keys(), + bp_bridge_hub_kusama::BRIDGE_HUB_KUSAMA_PARACHAIN_ID, + Box::new(|call| RuntimeCall::BridgePolkadotGrandpa(call).encode()), + ) +} + +#[test] +fn change_delivery_reward_by_governance_works() { + bridge_hub_test_utils::test_cases::change_storage_constant_by_governance_works::< + Runtime, + DeliveryRewardInBalance, + u64, + >( + collator_session_keys(), + bp_bridge_hub_kusama::BRIDGE_HUB_KUSAMA_PARACHAIN_ID, + Box::new(|call| RuntimeCall::System(call).encode()), + || (DeliveryRewardInBalance::key().to_vec(), DeliveryRewardInBalance::get()), + |old_value| old_value.checked_mul(2).unwrap(), + ) +} + +#[test] +fn change_required_stake_by_governance_works() { + bridge_hub_test_utils::test_cases::change_storage_constant_by_governance_works::< + Runtime, + RequiredStakeForStakeAndSlash, + Balance, + >( + collator_session_keys(), + bp_bridge_hub_kusama::BRIDGE_HUB_KUSAMA_PARACHAIN_ID, + Box::new(|call| RuntimeCall::System(call).encode()), + || (RequiredStakeForStakeAndSlash::key().to_vec(), RequiredStakeForStakeAndSlash::get()), + |old_value| { + if let Some(new_value) = old_value.checked_add(1) { + new_value + } else { + old_value.checked_sub(1).unwrap() + } + }, + ) +} + +#[test] +fn handle_export_message_from_system_parachain_add_to_outbound_queue_works() { + bridge_hub_test_utils::test_cases::handle_export_message_from_system_parachain_to_outbound_queue_works::< + Runtime, + XcmConfig, + WithBridgeHubPolkadotMessagesInstance, + >( + collator_session_keys(), + bp_bridge_hub_kusama::BRIDGE_HUB_KUSAMA_PARACHAIN_ID, + SIBLING_PARACHAIN_ID, + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::BridgePolkadotMessages(event)) => Some(event), + _ => None, + } + }), + || ExportMessage { network: Polkadot, destination: X1(Parachain(1234)), xcm: Xcm(vec![]) }, + bridge_hub_config::ASSET_HUB_KUSAMA_TO_ASSET_HUB_POLKADOT_LANE_ID + ) +} + +#[test] +fn message_dispatch_routing_works() { + bridge_hub_test_utils::test_cases::message_dispatch_routing_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ParachainSystem, + WithBridgeHubPolkadotMessagesInstance, + RuntimeNetwork, + bridge_hub_config::PolkadotGlobalConsensusNetwork, + >( + collator_session_keys(), + bp_bridge_hub_kusama::BRIDGE_HUB_KUSAMA_PARACHAIN_ID, + SIBLING_PARACHAIN_ID, + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::ParachainSystem(event)) => Some(event), + _ => None, + } + }), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::XcmpQueue(event)) => Some(event), + _ => None, + } + }), + bridge_hub_config::ASSET_HUB_KUSAMA_TO_ASSET_HUB_POLKADOT_LANE_ID, + ) +} + +#[test] +fn relayed_incoming_message_works() { + bridge_hub_test_utils::test_cases::relayed_incoming_message_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ParachainSystem, + BridgeGrandpaPolkadotInstance, + BridgeParachainPolkadotInstance, + WithBridgeHubPolkadotMessagesInstance, + WithBridgeHubPolkadotMessageBridge, + >( + collator_session_keys(), + bp_bridge_hub_kusama::BRIDGE_HUB_KUSAMA_PARACHAIN_ID, + bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID, + SIBLING_PARACHAIN_ID, + RuntimeNetwork::get(), + bridge_hub_config::ASSET_HUB_KUSAMA_TO_ASSET_HUB_POLKADOT_LANE_ID, + ) +} + +#[test] +pub fn complex_relay_extrinsic_works() { + bridge_hub_test_utils::test_cases::complex_relay_extrinsic_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ParachainSystem, + BridgeGrandpaPolkadotInstance, + BridgeParachainPolkadotInstance, + WithBridgeHubPolkadotMessagesInstance, + WithBridgeHubPolkadotMessageBridge, + >( + collator_session_keys(), + bp_bridge_hub_kusama::BRIDGE_HUB_KUSAMA_PARACHAIN_ID, + bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID, + SIBLING_PARACHAIN_ID, + bridge_hub_config::BridgeHubPolkadotChainId::get(), + RuntimeNetwork::get(), + bridge_hub_config::ASSET_HUB_KUSAMA_TO_ASSET_HUB_POLKADOT_LANE_ID, + ExistentialDeposit::get(), + executive_init_block, + construct_and_apply_extrinsic, + ); +} 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 52a866b70971..19c678bc57eb 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/Cargo.toml @@ -71,12 +71,42 @@ pallet-collator-selection = { path = "../../../../pallets/collator-selection", d parachain-info = { path = "../../../pallets/parachain-info", default-features = false } parachains-common = { path = "../../../common", default-features = false } +# Bridges +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 } +bp-messages = { path = "../../../../bridges/primitives/messages", default-features = false } +bp-parachains = { path = "../../../../bridges/primitives/parachains", default-features = false } +bp-polkadot-core = { path = "../../../../bridges/primitives/polkadot-core", default-features = false } +bp-relayers = { path = "../../../../bridges/primitives/relayers", default-features = false } +bp-runtime = { path = "../../../../bridges/primitives/runtime", default-features = false } +bp-kusama = { path = "../../../../bridges/primitives/chain-kusama", default-features = false } +bridge-runtime-common = { path = "../../../../bridges/bin/runtime-common", default-features = false } +pallet-bridge-grandpa = { path = "../../../../bridges/modules/grandpa", default-features = false } +pallet-bridge-messages = { path = "../../../../bridges/modules/messages", default-features = false } +pallet-bridge-parachains = { path = "../../../../bridges/modules/parachains", default-features = false } +pallet-bridge-relayers = { path = "../../../../bridges/modules/relayers", default-features = false } + [dev-dependencies] +static_assertions = "1.1" bridge-hub-test-utils = { path = "../test-utils" } +bridge-runtime-common = { path = "../../../../bridges/bin/runtime-common", features = ["integrity-test"] } +bp-polkadot = { path = "../../../../bridges/primitives/chain-polkadot" } +sp-keyring = { path = "../../../../../substrate/primitives/keyring" } [features] default = [ "std" ] std = [ + "bp-bridge-hub-kusama/std", + "bp-bridge-hub-polkadot/std", + "bp-header-chain/std", + "bp-kusama/std", + "bp-messages/std", + "bp-parachains/std", + "bp-polkadot-core/std", + "bp-relayers/std", + "bp-runtime/std", + "bridge-runtime-common/std", "codec/std", "cumulus-pallet-aura-ext/std", "cumulus-pallet-dmp-queue/std", @@ -97,6 +127,10 @@ std = [ "pallet-aura/std", "pallet-authorship/std", "pallet-balances/std", + "pallet-bridge-grandpa/std", + "pallet-bridge-messages/std", + "pallet-bridge-parachains/std", + "pallet-bridge-relayers/std", "pallet-collator-selection/std", "pallet-multisig/std", "pallet-session/std", @@ -134,6 +168,7 @@ std = [ ] runtime-benchmarks = [ + "bridge-runtime-common/runtime-benchmarks", "cumulus-pallet-parachain-system/runtime-benchmarks", "cumulus-pallet-session-benchmarking/runtime-benchmarks", "cumulus-pallet-xcmp-queue/runtime-benchmarks", @@ -142,6 +177,10 @@ runtime-benchmarks = [ "frame-system-benchmarking/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", + "pallet-bridge-grandpa/runtime-benchmarks", + "pallet-bridge-messages/runtime-benchmarks", + "pallet-bridge-parachains/runtime-benchmarks", + "pallet-bridge-relayers/runtime-benchmarks", "pallet-collator-selection/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", @@ -168,6 +207,10 @@ try-runtime = [ "pallet-aura/try-runtime", "pallet-authorship/try-runtime", "pallet-balances/try-runtime", + "pallet-bridge-grandpa/try-runtime", + "pallet-bridge-messages/try-runtime", + "pallet-bridge-parachains/try-runtime", + "pallet-bridge-relayers/try-runtime", "pallet-collator-selection/try-runtime", "pallet-multisig/try-runtime", "pallet-session/try-runtime", 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 new file mode 100644 index 000000000000..8414e532f5b7 --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/bridge_hub_config.rs @@ -0,0 +1,235 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see . + +//! Bridge definitions. + +use crate::{ + BridgeKusamaMessages, BridgeParachainKusamaInstance, Runtime, + WithBridgeHubKusamaMessagesInstance, XcmRouter, +}; +use bp_messages::LaneId; +use bridge_runtime_common::{ + messages, + messages::{ + source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, + MessageBridge, ThisChainWithMessages, UnderlyingChainProvider, + }, + messages_xcm_extension::{SenderAndLane, XcmBlobHauler, XcmBlobHaulerAdapter}, + refund_relayer_extension::{ + ActualFeeRefund, RefundBridgedParachainMessages, RefundableMessagesLane, + RefundableParachain, + }, +}; +use frame_support::{parameter_types, traits::PalletInfoAccess}; +use sp_runtime::RuntimeDebug; +use xcm::{latest::prelude::*, prelude::NetworkId}; +use xcm_builder::{BridgeBlobDispatcher, HaulBlobExporter}; + +parameter_types! { + pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_messages::MessageNonce = + bp_bridge_hub_polkadot::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce = + bp_bridge_hub_polkadot::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + pub const BridgeHubKusamaChainId: bp_runtime::ChainId = bp_runtime::BRIDGE_HUB_KUSAMA_CHAIN_ID; + pub BridgeKusamaMessagesPalletInstance: InteriorMultiLocation = X1(PalletInstance(::index() as u8)); + pub KusamaGlobalConsensusNetwork: NetworkId = NetworkId::Kusama; + // see the `FEE_BOOST_PER_MESSAGE` constant to get the meaning of this value + pub PriorityBoostPerMessage: u64 = 4_551_111_111_111; + + pub AssetHubPolkadotParaId: cumulus_primitives_core::ParaId = 1000.into(); + + pub FromAssetHubPolkadotToAssetHubKusamaRoute: SenderAndLane = SenderAndLane::new( + ParentThen(X1(Parachain(AssetHubPolkadotParaId::get().into()))).into(), + ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA_LANE_ID, + ); +} + +/// Proof of messages, coming from BridgeHubKusama. +pub type FromBridgeHubKusamaMessagesProof = + FromBridgedChainMessagesProof; +/// Message delivery proof for `BridgeHubKusama` messages. +pub type ToBridgeHubKusamaMessagesDeliveryProof = + FromBridgedChainMessagesDeliveryProof; + +/// Dispatches received XCM messages from other bridge +pub type OnThisChainBlobDispatcher = + BridgeBlobDispatcher; + +/// Export XCM messages to be relayed to the other side. +pub type ToBridgeHubKusamaHaulBlobExporter = HaulBlobExporter< + XcmBlobHaulerAdapter, + KusamaGlobalConsensusNetwork, + (), +>; +pub struct ToBridgeHubKusamaXcmBlobHauler; +impl XcmBlobHauler for ToBridgeHubKusamaXcmBlobHauler { + type Runtime = Runtime; + type MessagesInstance = WithBridgeHubKusamaMessagesInstance; + type SenderAndLane = FromAssetHubPolkadotToAssetHubKusamaRoute; + + type ToSourceChainSender = crate::XcmRouter; + type CongestedMessage = (); + type UncongestedMessage = (); +} + +/// Messaging Bridge configuration for ThisChain -> BridgeHubKusama +pub struct WithBridgeHubKusamaMessageBridge; +impl MessageBridge for WithBridgeHubKusamaMessageBridge { + const BRIDGED_MESSAGES_PALLET_NAME: &'static str = + bp_bridge_hub_polkadot::WITH_BRIDGE_HUB_POLKADOT_MESSAGES_PALLET_NAME; + type ThisChain = ThisChain; + type BridgedChain = BridgeHubKusama; + type BridgedHeaderChain = pallet_bridge_parachains::ParachainHeaders< + Runtime, + BridgeParachainKusamaInstance, + bp_bridge_hub_kusama::BridgeHubKusama, + >; +} + +/// Message verifier for BridgeHubKusama messages sent from ThisChain +pub type ToBridgeHubKusamaMessageVerifier = + messages::source::FromThisChainMessageVerifier; + +/// Maximal outbound payload size of ThisChain -> BridgeHubKusama messages. +pub type ToBridgeHubKusamaMaximalOutboundPayloadSize = + messages::source::FromThisChainMaximalOutboundPayloadSize; + +/// BridgeHubKusama chain from message lane point of view. +#[derive(RuntimeDebug, Clone, Copy)] +pub struct BridgeHubKusama; + +impl UnderlyingChainProvider for BridgeHubKusama { + type Chain = bp_bridge_hub_kusama::BridgeHubKusama; +} + +impl messages::BridgedChainWithMessages for BridgeHubKusama {} + +/// ThisChain chain from message lane point of view. +#[derive(RuntimeDebug, Clone, Copy)] +pub struct ThisChain; + +impl UnderlyingChainProvider for ThisChain { + type Chain = bp_bridge_hub_polkadot::BridgeHubPolkadot; +} + +impl ThisChainWithMessages for ThisChain { + type RuntimeOrigin = crate::RuntimeOrigin; +} + +// TODO: rework once dynamic lanes are supported (https://github.com/paritytech/parity-bridges-common/issues/1760) +/// Signed extension that refunds relayers that are delivering messages from the kusama BridgeHub. +pub type BridgeRefundBridgeHubKusamaMessages = RefundBridgedParachainMessages< + Runtime, + RefundableParachain, + RefundableMessagesLane, + ActualFeeRefund, + PriorityBoostPerMessage, + StrBridgeRefundBridgeHubKusamaMessages, +>; +bp_runtime::generate_static_str_provider!(BridgeRefundBridgeHubKusamaMessages); + +// TODO: rework once dynamic lanes are supported (https://github.com/paritytech/parity-bridges-common/issues/1760) +// now we support only StatemineToStatemint +/// Lanes setup +pub const ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA_LANE_ID: LaneId = LaneId([0, 0, 0, 0]); +parameter_types! { + pub ActiveOutboundLanesToBridgeHubKusama: &'static [bp_messages::LaneId] = &[ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA_LANE_ID]; + pub const StatemintToStatemineMessageLane: bp_messages::LaneId = ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA_LANE_ID; +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{constants, BridgeGrandpaKusamaInstance}; + use bridge_runtime_common::{ + assert_complete_bridge_types, + integrity::{ + assert_complete_bridge_constants, check_message_lane_weights, + AssertBridgeMessagesPalletConstants, AssertBridgePalletNames, AssertChainConstants, + AssertCompleteBridgeConstants, + }, + }; + use parachains_common::Balance; + + /// Every additional message in the message delivery transaction boosts its priority. + /// So the priority of transaction with `N+1` messages is larger than priority of + /// transaction with `N` messages by the `PriorityBoostPerMessage`. + /// + /// Economically, it is an equivalent of adding tip to the transaction with `N` messages. + /// The `FEE_BOOST_PER_MESSAGE` constant is the value of this tip. + /// + /// We want this tip to be large enough (delivery transactions with more messages = less + /// operational costs and a faster bridge), so this value should be significant. + const FEE_BOOST_PER_MESSAGE: Balance = 5 * constants::currency::UNITS; + + #[test] + fn ensure_lane_weights_are_correct() { + check_message_lane_weights::< + bp_bridge_hub_polkadot::BridgeHubPolkadot, + Runtime, + WithBridgeHubKusamaMessagesInstance, + >( + bp_bridge_hub_kusama::EXTRA_STORAGE_PROOF_SIZE, + bp_bridge_hub_polkadot::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + bp_bridge_hub_polkadot::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + true, + ); + } + + #[test] + fn ensure_bridge_integrity() { + assert_complete_bridge_types!( + runtime: Runtime, + with_bridged_chain_grandpa_instance: BridgeGrandpaKusamaInstance, + with_bridged_chain_messages_instance: WithBridgeHubKusamaMessagesInstance, + bridge: WithBridgeHubKusamaMessageBridge, + this_chain: bp_polkadot::Polkadot, + bridged_chain: bp_kusama::Kusama, + ); + + assert_complete_bridge_constants::< + Runtime, + BridgeGrandpaKusamaInstance, + WithBridgeHubKusamaMessagesInstance, + WithBridgeHubKusamaMessageBridge, + >(AssertCompleteBridgeConstants { + this_chain_constants: AssertChainConstants { + block_length: bp_bridge_hub_polkadot::BlockLength::get(), + block_weights: bp_bridge_hub_polkadot::BlockWeights::get(), + }, + messages_pallet_constants: AssertBridgeMessagesPalletConstants { + max_unrewarded_relayers_in_bridged_confirmation_tx: + bp_bridge_hub_kusama::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + max_unconfirmed_messages_in_bridged_confirmation_tx: + bp_bridge_hub_kusama::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + bridged_chain_id: bp_runtime::BRIDGE_HUB_KUSAMA_CHAIN_ID, + }, + pallet_names: AssertBridgePalletNames { + with_this_chain_messages_pallet_name: + bp_bridge_hub_polkadot::WITH_BRIDGE_HUB_POLKADOT_MESSAGES_PALLET_NAME, + with_bridged_chain_grandpa_pallet_name: bp_kusama::WITH_KUSAMA_GRANDPA_PALLET_NAME, + with_bridged_chain_messages_pallet_name: + bp_bridge_hub_kusama::WITH_BRIDGE_HUB_KUSAMA_MESSAGES_PALLET_NAME, + }, + }); + + bridge_runtime_common::priority_calculator::ensure_priority_boost_is_sane::< + Runtime, + WithBridgeHubKusamaMessagesInstance, + PriorityBoostPerMessage, + >(FEE_BOOST_PER_MESSAGE); + } +} 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 dbfdc249a3cd..83938606ac36 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 @@ -22,6 +22,7 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +pub mod bridge_hub_config; mod weights; pub mod xcm_config; @@ -59,6 +60,9 @@ use xcm_config::{ FellowshipLocation, GovernanceLocation, XcmConfig, XcmOriginToTransactDispatchOrigin, }; +use bp_parachains::SingleParaStoredHeaderDataBuilder; +use bp_runtime::HeaderId; + #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; @@ -73,7 +77,20 @@ use parachains_common::{ AccountId, Balance, BlockNumber, Hash, Header, Nonce, Signature, AVERAGE_ON_INITIALIZE_RATIO, HOURS, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, SLOT_DURATION, }; -// XCM Imports + +use crate::{ + bridge_hub_config::{ + BridgeRefundBridgeHubKusamaMessages, OnThisChainBlobDispatcher, + WithBridgeHubKusamaMessageBridge, + }, + xcm_config::{UniversalLocation, XcmRouter}, +}; + +use bridge_runtime_common::{ + messages::{source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter}, + messages_xcm_extension::{XcmAsPlainPayload, XcmBlobMessageDispatch}, +}; + use xcm::latest::prelude::BodyId; use xcm_executor::XcmExecutor; @@ -99,6 +116,8 @@ pub type SignedExtra = ( frame_system::CheckNonce, frame_system::CheckWeight, pallet_transaction_payment::ChargeTransactionPayment, + BridgeRejectObsoleteHeadersAndMessages, + BridgeRefundBridgeHubKusamaMessages, ); /// Unchecked extrinsic type as expected by this runtime. @@ -401,6 +420,102 @@ impl pallet_utility::Config for Runtime { type WeightInfo = weights::pallet_utility::WeightInfo; } +// Add bridge pallets (GPA) +/// Add GRANDPA bridge pallet to track Kusama relay chain on Polkadot BridgeHub +pub type BridgeGrandpaKusamaInstance = pallet_bridge_grandpa::Instance1; +impl pallet_bridge_grandpa::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type BridgedChain = bp_kusama::Kusama; + type MaxFreeMandatoryHeadersPerBlock = ConstU32<4>; + type HeadersToKeep = RelayChainHeadersToKeep; + type WeightInfo = weights::pallet_bridge_grandpa::WeightInfo; +} + +parameter_types! { + pub const RelayChainHeadersToKeep: u32 = 600; + pub const ParachainHeadsToKeep: u32 = 300; + /// Delay (in blocks) before registered relayer could get its stake back. It guarantees + /// that all pending delivery transactions are either dropped or mined and relayer is + /// slashed in case of misbehavior. So this value should be large enough (e.g. 24 hours). + pub const RelayerStakeLease: u32 = parachains_common::DAYS; + pub const KusamaBridgeParachainPalletName: &'static str = bp_kusama::PARAS_PALLET_NAME; + pub const MaxKusamaParaHeadDataSize: u32 = bp_kusama::MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE; + + pub const RelayerStakeReserveId: [u8; 8] = *b"brdgrlrs"; + // Just initial value, and concrete values will be set up by governance call (`set_storage`) with `initialize` bridge call as a part of cutover plan (https://github.com/paritytech/parity-bridges-common/issues/1730) + pub storage DeliveryRewardInBalance: u64 = 1_000_000; +} + +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub storage RequiredStakeForStakeAndSlash: Balance = 1; +} +#[cfg(not(feature = "runtime-benchmarks"))] +parameter_types! { + // Just initial value, and concrete values will be set up by governance call (`set_storage`) with `initialize` bridge call as a part of cutover plan (https://github.com/paritytech/parity-bridges-common/issues/1730) + pub storage RequiredStakeForStakeAndSlash: Balance = Balance::MAX; +} + +/// Add parachain bridge pallet to track Kusama BridgeHub parachain +pub type BridgeParachainKusamaInstance = pallet_bridge_parachains::Instance1; +impl pallet_bridge_parachains::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = weights::pallet_bridge_parachains::WeightInfo; + type BridgesGrandpaPalletInstance = BridgeGrandpaKusamaInstance; + type ParasPalletName = KusamaBridgeParachainPalletName; + type ParaStoredHeaderDataBuilder = + SingleParaStoredHeaderDataBuilder; + type HeadsToKeep = ParachainHeadsToKeep; + type MaxParaHeadDataSize = MaxKusamaParaHeadDataSize; +} + +/// Add XCM messages support for Polkadot<->Kusama XCM messages +pub type WithBridgeHubKusamaMessagesInstance = pallet_bridge_messages::Instance1; +impl pallet_bridge_messages::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = weights::pallet_bridge_messages::WeightInfo; + type BridgedChainId = bridge_hub_config::BridgeHubKusamaChainId; + type ActiveOutboundLanes = bridge_hub_config::ActiveOutboundLanesToBridgeHubKusama; + type MaxUnrewardedRelayerEntriesAtInboundLane = + bridge_hub_config::MaxUnrewardedRelayerEntriesAtInboundLane; + type MaxUnconfirmedMessagesAtInboundLane = + bridge_hub_config::MaxUnconfirmedMessagesAtInboundLane; + type MaximalOutboundPayloadSize = + bridge_hub_config::ToBridgeHubKusamaMaximalOutboundPayloadSize; + type OutboundPayload = XcmAsPlainPayload; + type InboundPayload = XcmAsPlainPayload; + type InboundRelayer = AccountId; + type DeliveryPayments = (); + type TargetHeaderChain = TargetHeaderChainAdapter; + type LaneMessageVerifier = bridge_hub_config::ToBridgeHubKusamaMessageVerifier; + type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< + Runtime, + WithBridgeHubKusamaMessagesInstance, + DeliveryRewardInBalance, + >; + type SourceHeaderChain = SourceHeaderChainAdapter; + type MessageDispatch = + XcmBlobMessageDispatch, Self::WeightInfo, ()>; + type OnMessagesDelivered = (); +} + +/// Allows collect and claim rewards for relayers +impl pallet_bridge_relayers::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Reward = Balance; + type PaymentProcedure = + bp_relayers::PayRewardFromAccount, AccountId>; + type StakeAndSlash = pallet_bridge_relayers::StakeAndSlashNamed< + AccountId, + BlockNumber, + Balances, + RelayerStakeReserveId, + RequiredStakeForStakeAndSlash, + RelayerStakeLease, + >; + type WeightInfo = weights::pallet_bridge_relayers::WeightInfo; +} + // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub enum Runtime @@ -433,9 +548,25 @@ construct_runtime!( // Handy utilities. Utility: pallet_utility::{Pallet, Call, Event} = 40, Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 41, + + // Polkadot<>Kusama bridge pallets + BridgeKusamaGrandpa: pallet_bridge_grandpa::::{Pallet, Call, Storage, Event, Config} = 51, + BridgeKusamaParachain: pallet_bridge_parachains::::{Pallet, Call, Storage, Event} = 52, + BridgeKusamaMessages: pallet_bridge_messages::::{Pallet, Call, Storage, Event, Config} = 53, + BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event} = 54, } ); +bridge_runtime_common::generate_bridge_reject_obsolete_headers_and_messages! { + RuntimeCall, AccountId, + // Grandpa + BridgeKusamaGrandpa, + // Parachains + BridgeKusamaParachain, + // Messages + BridgeKusamaMessages +} + #[cfg(feature = "runtime-benchmarks")] #[macro_use] extern crate frame_benchmarking; @@ -456,6 +587,12 @@ mod benches { // NOTE: Make sure you point to the individual modules below. [pallet_xcm_benchmarks::fungible, XcmBalances] [pallet_xcm_benchmarks::generic, XcmGeneric] + // Bridge pallets for Polkadot + [pallet_bridge_grandpa, BridgeKusamaGrandpa] + [pallet_bridge_parachains, BridgeParachainsBench::] + [pallet_bridge_messages, BridgeMessagesBench::] + // Bridge relayer pallets + [pallet_bridge_relayers, BridgeRelayersBench::] ); } @@ -603,6 +740,49 @@ impl_runtime_apis! { } } + impl bp_kusama::KusamaFinalityApi for Runtime { + fn best_finalized() -> Option> { + BridgeKusamaGrandpa::best_finalized() + } + fn synced_headers_grandpa_info( + ) -> Vec> { + BridgeKusamaGrandpa::synced_headers_grandpa_info() + } + } + + impl bp_bridge_hub_kusama::BridgeHubKusamaFinalityApi for Runtime { + fn best_finalized() -> Option> { + BridgeKusamaParachain::best_parachain_head_id::< + bp_bridge_hub_kusama::BridgeHubKusama + >().unwrap_or(None) + } + } + + impl bp_bridge_hub_kusama::FromBridgeHubKusamaInboundLaneApi for Runtime { + fn message_details( + lane: bp_messages::LaneId, + messages: Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>, + ) -> Vec { + bridge_runtime_common::messages_api::inbound_message_details::< + Runtime, + WithBridgeHubKusamaMessagesInstance, + >(lane, messages) + } + } + + impl bp_bridge_hub_kusama::ToBridgeHubKusamaOutboundLaneApi for Runtime { + fn message_details( + lane: bp_messages::LaneId, + begin: bp_messages::MessageNonce, + end: bp_messages::MessageNonce, + ) -> Vec { + bridge_runtime_common::messages_api::outbound_message_details::< + Runtime, + WithBridgeHubKusamaMessagesInstance, + >(lane, begin, end) + } + } + #[cfg(feature = "try-runtime")] impl frame_try_runtime::TryRuntime for Runtime { fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { @@ -639,6 +819,10 @@ impl_runtime_apis! { type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::; type XcmGeneric = pallet_xcm_benchmarks::generic::Pallet::; + use pallet_bridge_parachains::benchmarking::Pallet as BridgeParachainsBench; + use pallet_bridge_messages::benchmarking::Pallet as BridgeMessagesBench; + use pallet_bridge_relayers::benchmarking::Pallet as BridgeRelayersBench; + let mut list = Vec::::new(); list_benchmarks!(list, extra); @@ -748,7 +932,7 @@ impl_runtime_apis! { fn export_message_origin_and_destination( ) -> Result<(MultiLocation, NetworkId, InteriorMultiLocation), BenchmarkError> { - Err(BenchmarkError::Skip) + Ok((DotRelayLocation::get(), bridge_hub_config::KusamaGlobalConsensusNetwork::get(), X1(Parachain(100)))) } fn alias_origin() -> Result<(MultiLocation, MultiLocation), BenchmarkError> { @@ -759,6 +943,102 @@ 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 pallet_bridge_messages::benchmarking::{ + Config as BridgeMessagesConfig, + Pallet as BridgeMessagesBench, + MessageDeliveryProofParams, + MessageProofParams, + }; + impl BridgeMessagesConfig for Runtime { + fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool { + let bench_lane_id = >::bench_lane_id(); + let bridged_chain_id = bp_runtime::BRIDGE_HUB_KUSAMA_CHAIN_ID; + pallet_bridge_relayers::Pallet::::relayer_reward( + relayer, + bp_relayers::RewardsAccountParams::new( + bench_lane_id, + bridged_chain_id, + bp_relayers::RewardsAccountOwner::BridgedChain + ) + ).is_some() + } + fn prepare_message_proof( + params: MessageProofParams, + ) -> (bridge_hub_config::FromBridgeHubKusamaMessagesProof, Weight) { + use cumulus_primitives_core::XcmpMessageSource; + assert!(XcmpQueue::take_outbound_messages(usize::MAX).is_empty()); + ParachainSystem::open_outbound_hrmp_channel_for_benchmarks(42.into()); + prepare_message_proof_from_parachain::< + Runtime, + BridgeGrandpaKusamaInstance, + bridge_hub_config::WithBridgeHubKusamaMessageBridge, + >(params, X2(GlobalConsensus(xcm_config::RelayNetwork::get().unwrap()), Parachain(42))) + } + fn prepare_message_delivery_proof( + params: MessageDeliveryProofParams, + ) -> bridge_hub_config::ToBridgeHubKusamaMessagesDeliveryProof { + prepare_message_delivery_proof_from_parachain::< + Runtime, + BridgeGrandpaKusamaInstance, + bridge_hub_config::WithBridgeHubKusamaMessageBridge, + >(params) + } + fn is_message_successfully_dispatched(_nonce: bp_messages::MessageNonce) -> bool { + use cumulus_primitives_core::XcmpMessageSource; + !XcmpQueue::take_outbound_messages(usize::MAX).is_empty() + } + } + + use bridge_runtime_common::parachains_benchmarking::prepare_parachain_heads_proof; + use pallet_bridge_parachains::benchmarking::{ + Config as BridgeParachainsConfig, + Pallet as BridgeParachainsBench, + }; + use pallet_bridge_relayers::benchmarking::{ + Pallet as BridgeRelayersBench, + Config as BridgeRelayersConfig, + }; + impl BridgeParachainsConfig for Runtime { + fn parachains() -> Vec { + use bp_runtime::Parachain; + vec![bp_polkadot_core::parachains::ParaId(bp_bridge_hub_kusama::BridgeHubKusama::PARACHAIN_ID)] + } + fn prepare_parachain_heads_proof( + parachains: &[bp_polkadot_core::parachains::ParaId], + parachain_head_size: u32, + proof_size: bp_runtime::StorageProofSize, + ) -> ( + pallet_bridge_parachains::RelayBlockNumber, + pallet_bridge_parachains::RelayBlockHash, + bp_polkadot_core::parachains::ParaHeadsProof, + Vec<(bp_polkadot_core::parachains::ParaId, bp_polkadot_core::parachains::ParaHash)>, + ) { + prepare_parachain_heads_proof::( + parachains, + parachain_head_size, + proof_size, + ) + } + } + + impl BridgeRelayersConfig for Runtime { + fn prepare_rewards_account( + account_params: bp_relayers::RewardsAccountParams, + reward: Balance, + ) { + let rewards_account = bp_relayers::PayRewardFromAccount::< + Balances, + AccountId + >::rewards_account(account_params); + Self::deposit_account(rewards_account, reward); + } + fn deposit_account(account: AccountId, balance: Balance) { + use frame_support::traits::fungible::Mutate; + Balances::mint_into(&account, balance.saturating_add(ExistentialDeposit::get())).unwrap(); + } + } + let whitelist: Vec = vec![ // Block Number hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(), @@ -785,3 +1065,40 @@ cumulus_pallet_parachain_system::register_validate_block! { Runtime = Runtime, BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::, } + +#[cfg(test)] +mod tests { + use super::*; + use bp_runtime::TransactionEra; + use bridge_hub_test_utils::test_header; + use codec::Encode; + + pub type TestBlockHeader = + generic::Header; + + #[test] + fn ensure_signed_extension_definition_is_compatible_with_relay() { + let payload: SignedExtra = ( + frame_system::CheckNonZeroSender::new(), + frame_system::CheckSpecVersion::new(), + frame_system::CheckTxVersion::new(), + frame_system::CheckGenesis::new(), + frame_system::CheckEra::from(sp_runtime::generic::Era::Immortal), + frame_system::CheckNonce::from(10), + frame_system::CheckWeight::new(), + pallet_transaction_payment::ChargeTransactionPayment::from(10), + BridgeRejectObsoleteHeadersAndMessages::default(), + BridgeRefundBridgeHubKusamaMessages::default(), + ); + use bp_bridge_hub_polkadot::BridgeHubSignedExtension; + let bh_indirect_payload = bp_bridge_hub_polkadot::SignedExtension::from_params( + 10, + 10, + TransactionEra::Immortal, + test_header::(1).hash(), + 10, + 10, + ); + assert_eq!(payload.encode(), bh_indirect_payload.encode()); + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/mod.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/mod.rs index e226021e77ab..75f7c2376741 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/mod.rs @@ -22,6 +22,10 @@ pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; pub mod pallet_balances; +pub mod pallet_bridge_grandpa; +pub mod pallet_bridge_messages; +pub mod pallet_bridge_parachains; +pub mod pallet_bridge_relayers; pub mod pallet_collator_selection; pub mod pallet_multisig; pub mod pallet_session; @@ -36,3 +40,32 @@ pub use block_weights::constants::BlockExecutionWeight; pub use extrinsic_weights::constants::ExtrinsicBaseWeight; pub use paritydb_weights::constants::ParityDbWeight; pub use rocksdb_weights::constants::RocksDbWeight; + +use frame_support::weights::Weight; + +// import trait from dependency module +use ::pallet_bridge_relayers::WeightInfoExt as _; + +impl ::pallet_bridge_messages::WeightInfoExt + for pallet_bridge_messages::WeightInfo +{ + fn expected_extra_storage_proof_size() -> u32 { + bp_bridge_hub_kusama::EXTRA_STORAGE_PROOF_SIZE + } + + fn receive_messages_proof_overhead_from_runtime() -> Weight { + pallet_bridge_relayers::WeightInfo::::receive_messages_proof_overhead_from_runtime() + } + + fn receive_messages_delivery_proof_overhead_from_runtime() -> Weight { + pallet_bridge_relayers::WeightInfo::::receive_messages_delivery_proof_overhead_from_runtime() + } +} + +impl ::pallet_bridge_parachains::WeightInfoExt + for pallet_bridge_parachains::WeightInfo +{ + fn expected_extra_storage_proof_size() -> u32 { + bp_bridge_hub_kusama::EXTRA_STORAGE_PROOF_SIZE + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_grandpa.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_grandpa.rs new file mode 100644 index 000000000000..3df4f7673ddd --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_grandpa.rs @@ -0,0 +1,80 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see . + +//! Autogenerated weights for `pallet_bridge_grandpa` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `bm3`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-polkadot-dev"), DB CACHE: 1024 + +// Executed Command: +// target/production/polkadot-parachain +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/var/lib/gitlab-runner/builds/zyw4fam_/0/parity/mirrors/cumulus/.git/.artifacts/bench.json +// --pallet=pallet_bridge_grandpa +// --chain=bridge-hub-polkadot-dev +// --header=./file_header.txt +// --output=./parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_bridge_grandpa`. +pub struct WeightInfo(PhantomData); +impl pallet_bridge_grandpa::WeightInfo for WeightInfo { + /// Storage: BridgeKusamaGrandpa PalletOperatingMode (r:1 w:0) + /// Proof: BridgeKusamaGrandpa PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: BridgeKusamaGrandpa BestFinalized (r:1 w:1) + /// Proof: BridgeKusamaGrandpa BestFinalized (max_values: Some(1), max_size: Some(36), added: 531, mode: MaxEncodedLen) + /// Storage: BridgeKusamaGrandpa CurrentAuthoritySet (r:1 w:0) + /// Proof: BridgeKusamaGrandpa CurrentAuthoritySet (max_values: Some(1), max_size: Some(50250), added: 50745, mode: MaxEncodedLen) + /// Storage: BridgeKusamaGrandpa ImportedHashesPointer (r:1 w:1) + /// Proof: BridgeKusamaGrandpa ImportedHashesPointer (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: BridgeKusamaGrandpa ImportedHashes (r:1 w:1) + /// Proof: BridgeKusamaGrandpa ImportedHashes (max_values: Some(1024), max_size: Some(36), added: 1521, mode: MaxEncodedLen) + /// Storage: BridgeKusamaGrandpa ImportedHeaders (r:0 w:2) + /// Proof: BridgeKusamaGrandpa ImportedHeaders (max_values: Some(1024), max_size: Some(68), added: 1553, mode: MaxEncodedLen) + /// The range of component `p` is `[1, 838]`. + /// The range of component `v` is `[50, 100]`. + fn submit_finality_proof(p: u32, v: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `302 + p * (60 ±0)` + // Estimated: `51735` + // Minimum execution time: 233_697_000 picoseconds. + Weight::from_parts(112_259_940, 0) + .saturating_add(Weight::from_parts(0, 51735)) + // Standard Error: 15_026 + .saturating_add(Weight::from_parts(47_393_046, 0).saturating_mul(p.into())) + // Standard Error: 250_621 + .saturating_add(Weight::from_parts(755_255, 0).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(5)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_messages.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_messages.rs new file mode 100644 index 000000000000..4679e9da87fe --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_messages.rs @@ -0,0 +1,231 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see . + +//! Autogenerated weights for `pallet_bridge_messages` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `bm3`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-polkadot-dev"), DB CACHE: 1024 + +// Executed Command: +// target/production/polkadot-parachain +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/var/lib/gitlab-runner/builds/zyw4fam_/0/parity/mirrors/cumulus/.git/.artifacts/bench.json +// --pallet=pallet_bridge_messages +// --chain=bridge-hub-polkadot-dev +// --header=./file_header.txt +// --output=./parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_bridge_messages`. +pub struct WeightInfo(PhantomData); +impl pallet_bridge_messages::WeightInfo for WeightInfo { + /// Storage: BridgeKusamaMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeKusamaMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgeKusamaParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgeKusamaMessages InboundLanes (r:1 w:1) + /// Proof: BridgeKusamaMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn receive_single_message_proof() -> Weight { + // Proof Size summary in bytes: + // Measured: `548` + // Estimated: `52645` + // Minimum execution time: 45_129_000 picoseconds. + Weight::from_parts(66_835_000, 0) + .saturating_add(Weight::from_parts(0, 52645)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgeKusamaMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeKusamaMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgeKusamaParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgeKusamaMessages InboundLanes (r:1 w:1) + /// Proof: BridgeKusamaMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn receive_two_messages_proof() -> Weight { + // Proof Size summary in bytes: + // Measured: `548` + // Estimated: `52645` + // Minimum execution time: 56_593_000 picoseconds. + Weight::from_parts(76_972_000, 0) + .saturating_add(Weight::from_parts(0, 52645)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgeKusamaMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeKusamaMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgeKusamaParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgeKusamaMessages InboundLanes (r:1 w:1) + /// Proof: BridgeKusamaMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn receive_single_message_proof_with_outbound_lane_state() -> Weight { + // Proof Size summary in bytes: + // Measured: `548` + // Estimated: `52645` + // Minimum execution time: 51_050_000 picoseconds. + Weight::from_parts(75_275_000, 0) + .saturating_add(Weight::from_parts(0, 52645)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgeKusamaMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeKusamaMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgeKusamaParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgeKusamaMessages InboundLanes (r:1 w:1) + /// Proof: BridgeKusamaMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + fn receive_single_message_proof_1_kb() -> Weight { + // Proof Size summary in bytes: + // Measured: `516` + // Estimated: `52645` + // Minimum execution time: 43_320_000 picoseconds. + Weight::from_parts(51_994_000, 0) + .saturating_add(Weight::from_parts(0, 52645)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgeKusamaMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeKusamaMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgeKusamaParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgeKusamaMessages InboundLanes (r:1 w:1) + /// Proof: BridgeKusamaMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + fn receive_single_message_proof_16_kb() -> Weight { + // Proof Size summary in bytes: + // Measured: `516` + // Estimated: `52645` + // Minimum execution time: 69_124_000 picoseconds. + Weight::from_parts(81_677_000, 0) + .saturating_add(Weight::from_parts(0, 52645)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgeKusamaMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeKusamaMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgeKusamaParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgeKusamaMessages OutboundLanes (r:1 w:1) + /// Proof: BridgeKusamaMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) + /// Storage: unknown `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Proof Skipped: unknown `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + fn receive_delivery_proof_for_single_message() -> Weight { + // Proof Size summary in bytes: + // Measured: `517` + // Estimated: `3982` + // Minimum execution time: 33_813_000 picoseconds. + Weight::from_parts(34_488_000, 0) + .saturating_add(Weight::from_parts(0, 3982)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: BridgeKusamaMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeKusamaMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgeKusamaParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgeKusamaMessages OutboundLanes (r:1 w:1) + /// Proof: BridgeKusamaMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) + /// Storage: unknown `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Proof Skipped: unknown `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { + // Proof Size summary in bytes: + // Measured: `517` + // Estimated: `3982` + // Minimum execution time: 34_317_000 picoseconds. + Weight::from_parts(34_792_000, 0) + .saturating_add(Weight::from_parts(0, 3982)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: BridgeKusamaMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeKusamaMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgeKusamaParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgeKusamaMessages OutboundLanes (r:1 w:1) + /// Proof: BridgeKusamaMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) + /// Storage: unknown `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Proof Skipped: unknown `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Storage: BridgeRelayers RelayerRewards (r:2 w:2) + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { + // Proof Size summary in bytes: + // Measured: `517` + // Estimated: `6086` + // Minimum execution time: 36_468_000 picoseconds. + Weight::from_parts(36_905_000, 0) + .saturating_add(Weight::from_parts(0, 6086)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: BridgeKusamaMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeKusamaMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgeKusamaParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgeKusamaMessages InboundLanes (r:1 w:1) + /// Proof: BridgeKusamaMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem RelevantMessagingState (r:1 w:0) + /// Proof Skipped: ParachainSystem RelevantMessagingState (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: XcmpQueue OutboundXcmpStatus (r:1 w:1) + /// Proof Skipped: XcmpQueue OutboundXcmpStatus (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: XcmpQueue OutboundXcmpMessages (r:0 w:1) + /// Proof Skipped: XcmpQueue OutboundXcmpMessages (max_values: None, max_size: None, mode: Measured) + /// The range of component `i` is `[128, 2048]`. + fn receive_single_message_proof_with_dispatch(i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `706` + // Estimated: `52645` + // Minimum execution time: 130_562_000 picoseconds. + Weight::from_parts(100_661_765, 0) + .saturating_add(Weight::from_parts(0, 52645)) + // Standard Error: 3_792 + .saturating_add(Weight::from_parts(545_755, 0).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(4)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_parachains.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_parachains.rs new file mode 100644 index 000000000000..ecc884bcc0fc --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_parachains.rs @@ -0,0 +1,115 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see . + +//! Autogenerated weights for `pallet_bridge_parachains` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `bm3`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-polkadot-dev"), DB CACHE: 1024 + +// Executed Command: +// target/production/polkadot-parachain +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/var/lib/gitlab-runner/builds/zyw4fam_/0/parity/mirrors/cumulus/.git/.artifacts/bench.json +// --pallet=pallet_bridge_parachains +// --chain=bridge-hub-polkadot-dev +// --header=./file_header.txt +// --output=./parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_bridge_parachains`. +pub struct WeightInfo(PhantomData); +impl pallet_bridge_parachains::WeightInfo for WeightInfo { + /// Storage: BridgeKusamaParachain PalletOperatingMode (r:1 w:0) + /// Proof: BridgeKusamaParachain PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: BridgeKusamaGrandpa ImportedHeaders (r:1 w:0) + /// Proof: BridgeKusamaGrandpa ImportedHeaders (max_values: Some(1024), max_size: Some(68), added: 1553, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ParasInfo (r:1 w:1) + /// Proof: BridgeKusamaParachain ParasInfo (max_values: Some(1), max_size: Some(60), added: 555, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHashes (r:1 w:1) + /// Proof: BridgeKusamaParachain ImportedParaHashes (max_values: Some(64), max_size: Some(64), added: 1054, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHeads (r:0 w:1) + /// Proof: BridgeKusamaParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// The range of component `p` is `[1, 2]`. + fn submit_parachain_heads_with_n_parachains(p: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `473` + // Estimated: `2543` + // Minimum execution time: 35_849_000 picoseconds. + Weight::from_parts(36_706_800, 0) + .saturating_add(Weight::from_parts(0, 2543)) + // Standard Error: 54_685 + .saturating_add(Weight::from_parts(1_700, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: BridgeKusamaParachain PalletOperatingMode (r:1 w:0) + /// Proof: BridgeKusamaParachain PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: BridgeKusamaGrandpa ImportedHeaders (r:1 w:0) + /// Proof: BridgeKusamaGrandpa ImportedHeaders (max_values: Some(1024), max_size: Some(68), added: 1553, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ParasInfo (r:1 w:1) + /// Proof: BridgeKusamaParachain ParasInfo (max_values: Some(1), max_size: Some(60), added: 555, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHashes (r:1 w:1) + /// Proof: BridgeKusamaParachain ImportedParaHashes (max_values: Some(64), max_size: Some(64), added: 1054, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHeads (r:0 w:1) + /// Proof: BridgeKusamaParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + fn submit_parachain_heads_with_1kb_proof() -> Weight { + // Proof Size summary in bytes: + // Measured: `473` + // Estimated: `2543` + // Minimum execution time: 37_271_000 picoseconds. + Weight::from_parts(37_692_000, 0) + .saturating_add(Weight::from_parts(0, 2543)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: BridgeKusamaParachain PalletOperatingMode (r:1 w:0) + /// Proof: BridgeKusamaParachain PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: BridgeKusamaGrandpa ImportedHeaders (r:1 w:0) + /// Proof: BridgeKusamaGrandpa ImportedHeaders (max_values: Some(1024), max_size: Some(68), added: 1553, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ParasInfo (r:1 w:1) + /// Proof: BridgeKusamaParachain ParasInfo (max_values: Some(1), max_size: Some(60), added: 555, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHashes (r:1 w:1) + /// Proof: BridgeKusamaParachain ImportedParaHashes (max_values: Some(64), max_size: Some(64), added: 1054, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHeads (r:0 w:1) + /// Proof: BridgeKusamaParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + fn submit_parachain_heads_with_16kb_proof() -> Weight { + // Proof Size summary in bytes: + // Measured: `473` + // Estimated: `2543` + // Minimum execution time: 63_033_000 picoseconds. + Weight::from_parts(63_704_000, 0) + .saturating_add(Weight::from_parts(0, 2543)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_relayers.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_relayers.rs new file mode 100644 index 000000000000..f2cc9490ee34 --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_relayers.rs @@ -0,0 +1,124 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see . + +//! Autogenerated weights for `pallet_bridge_relayers` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `bm3`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-polkadot-dev"), DB CACHE: 1024 + +// Executed Command: +// target/production/polkadot-parachain +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/var/lib/gitlab-runner/builds/zyw4fam_/0/parity/mirrors/cumulus/.git/.artifacts/bench.json +// --pallet=pallet_bridge_relayers +// --chain=bridge-hub-polkadot-dev +// --header=./file_header.txt +// --output=./parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_bridge_relayers`. +pub struct WeightInfo(PhantomData); +impl pallet_bridge_relayers::WeightInfo for WeightInfo { + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + fn claim_rewards() -> Weight { + // Proof Size summary in bytes: + // Measured: `278` + // Estimated: `3593` + // Minimum execution time: 52_513_000 picoseconds. + Weight::from_parts(53_314_000, 0) + .saturating_add(Weight::from_parts(0, 3593)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: BridgeRelayers RegisteredRelayers (r:1 w:1) + /// Proof: BridgeRelayers RegisteredRelayers (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) + /// Storage: unknown `0x1e8445dc201eeb8560e5579a5dd54655` (r:1 w:0) + /// Proof Skipped: unknown `0x1e8445dc201eeb8560e5579a5dd54655` (r:1 w:0) + /// Storage: Balances Reserves (r:1 w:1) + /// Proof: Balances Reserves (max_values: None, max_size: Some(1249), added: 3724, mode: MaxEncodedLen) + fn register() -> Weight { + // Proof Size summary in bytes: + // Measured: `131` + // Estimated: `4714` + // Minimum execution time: 29_576_000 picoseconds. + Weight::from_parts(30_157_000, 0) + .saturating_add(Weight::from_parts(0, 4714)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: BridgeRelayers RegisteredRelayers (r:1 w:1) + /// Proof: BridgeRelayers RegisteredRelayers (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) + /// Storage: Balances Reserves (r:1 w:1) + /// Proof: Balances Reserves (max_values: None, max_size: Some(1249), added: 3724, mode: MaxEncodedLen) + fn deregister() -> Weight { + // Proof Size summary in bytes: + // Measured: `231` + // Estimated: `4714` + // Minimum execution time: 31_146_000 picoseconds. + Weight::from_parts(31_774_000, 0) + .saturating_add(Weight::from_parts(0, 4714)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: BridgeRelayers RegisteredRelayers (r:1 w:1) + /// Proof: BridgeRelayers RegisteredRelayers (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) + /// Storage: Balances Reserves (r:1 w:1) + /// Proof: Balances Reserves (max_values: None, max_size: Some(1249), added: 3724, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + fn slash_and_deregister() -> Weight { + // Proof Size summary in bytes: + // Measured: `334` + // Estimated: `4714` + // Minimum execution time: 30_665_000 picoseconds. + Weight::from_parts(31_435_000, 0) + .saturating_add(Weight::from_parts(0, 4714)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + fn register_relayer_reward() -> Weight { + // Proof Size summary in bytes: + // Measured: `76` + // Estimated: `3538` + // Minimum execution time: 3_524_000 picoseconds. + Weight::from_parts(3_723_000, 0) + .saturating_add(Weight::from_parts(0, 3538)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/xcm/mod.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/xcm/mod.rs index 4f8c2dec7a8c..24f28fbbd3a3 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/xcm/mod.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/xcm/mod.rs @@ -18,6 +18,7 @@ mod pallet_xcm_benchmarks_fungible; mod pallet_xcm_benchmarks_generic; use crate::{xcm_config::MaxAssetsIntoHolding, Runtime}; +use codec::Encode; use frame_support::weights::Weight; use pallet_xcm_benchmarks_fungible::WeightInfo as XcmFungibleWeight; use pallet_xcm_benchmarks_generic::WeightInfo as XcmGeneric; @@ -225,8 +226,9 @@ impl XcmWeightInfo for BridgeHubPolkadotXcmWeight { fn universal_origin(_: &Junction) -> Weight { Weight::MAX } - fn export_message(_: &NetworkId, _: &Junctions, _: &Xcm<()>) -> Weight { - Weight::MAX + fn export_message(_: &NetworkId, _: &Junctions, inner: &Xcm<()>) -> Weight { + let inner_encoded_len = inner.encode().len() as u32; + XcmGeneric::::export_message(inner_encoded_len) } fn lock_asset(_: &MultiAsset, _: &MultiLocation) -> Weight { Weight::MAX diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/xcm/pallet_xcm_benchmarks_generic.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/xcm/pallet_xcm_benchmarks_generic.rs index 7968649d143c..7752a0533625 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/xcm/pallet_xcm_benchmarks_generic.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/xcm/pallet_xcm_benchmarks_generic.rs @@ -312,6 +312,26 @@ impl WeightInfo { // Minimum execution time: 2_611_000 picoseconds. Weight::from_parts(2_707_000, 0) } + // Storage: ParachainInfo ParachainId (r:1 w:0) + // Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + // Storage: BridgeKusamaMessages PalletOperatingMode (r:1 w:0) + // Proof: BridgeKusamaMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + // Storage: BridgeKusamaMessages OutboundLanes (r:1 w:1) + // Proof: BridgeKusamaMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) + // Storage: BridgeKusamaMessages OutboundMessages (r:0 w:1) + // Proof: BridgeKusamaMessages OutboundMessages (max_values: None, max_size: Some(2621472), added: 2623947, mode: MaxEncodedLen) + /// The range of component `x` is `[1, 1000]`. + pub fn export_message(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `167` + // Estimated: `1529` + // Minimum execution time: 30_323_000 picoseconds. + Weight::from_parts(32_469_359, 1529) + // Standard Error: 208 + .saturating_add(Weight::from_parts(176_327, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) + } pub fn set_fees_mode() -> Weight { // Proof Size summary in bytes: // Measured: `0` 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 0965600c2468..1880c649f57f 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 @@ -18,6 +18,10 @@ use super::{ AccountId, AllPalletsWithSystem, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, }; +use crate::{ + bridge_hub_config::ToBridgeHubKusamaHaulBlobExporter, BridgeGrandpaKusamaInstance, + DeliveryRewardInBalance, RequiredStakeForStakeAndSlash, +}; use frame_support::{ match_types, parameter_types, traits::{ConstU32, Contains, Everything, Nothing}, @@ -83,7 +87,7 @@ pub type XcmOriginToTransactDispatchOrigin = ( // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for // foreign chains who want to have a local sovereign account on this chain which they control. SovereignSignedViaLocation, - // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when + // Native converter for Relay-chain (Parent) location; will convert to a `Relay` origin when // recognized. RelayChainAsNative, // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when @@ -111,7 +115,16 @@ 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 /// account for proof size weights. /// @@ -129,6 +142,17 @@ impl Contains for SafeCallFilter { } } + // Allow to change dedicated storage items (called by governance-like) + match call { + RuntimeCall::System(frame_system::Call::set_storage { items }) + if items.iter().any(|(k, _)| { + k.eq(&DeliveryRewardInBalance::key()) | + k.eq(&RequiredStakeForStakeAndSlash::key()) + }) => + return true, + _ => (), + }; + matches!( call, RuntimeCall::PolkadotXcm(pallet_xcm::Call::force_xcm_version { .. }) | @@ -150,7 +174,11 @@ impl Contains for SafeCallFilter { pallet_collator_selection::Call::remove_invulnerable { .. }, ) | RuntimeCall::Session(pallet_session::Call::purge_keys { .. }) | RuntimeCall::XcmpQueue(..) | - RuntimeCall::DmpQueue(..) + RuntimeCall::DmpQueue(..) | + RuntimeCall::BridgeKusamaGrandpa(pallet_bridge_grandpa::Call::< + Runtime, + BridgeGrandpaKusamaInstance, + >::initialize { .. }) ) } } @@ -168,9 +196,13 @@ 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 the Fellows plurality - // get free execution. - AllowExplicitUnpaidExecutionFrom<(ParentOrParentsPlurality, FellowsPlurality)>, + // Parent, its pluralities (i.e. governance bodies), the Fellows plurality + // and system parachains get free execution. + AllowExplicitUnpaidExecutionFrom<( + ParentOrParentsPlurality, + FellowsPlurality, + SystemParachains, + )>, // Subscriptions for version tracking are OK. AllowSubscriptionsFrom, ), @@ -203,14 +235,14 @@ impl xcm_executor::Config for XcmConfig { UsingComponents>; type ResponseHandler = PolkadotXcm; type AssetTrap = PolkadotXcm; + type AssetLocker = (); + type AssetExchanger = (); type AssetClaims = PolkadotXcm; type SubscriptionService = PolkadotXcm; type PalletInstancesInfo = AllPalletsWithSystem; type MaxAssetsIntoHolding = MaxAssetsIntoHolding; - type AssetLocker = (); - type AssetExchanger = (); type FeeManager = (); - type MessageExporter = (); + type MessageExporter = ToBridgeHubKusamaHaulBlobExporter; type UniversalAliases = Nothing; type CallDispatcher = WithOriginFilter; type SafeCallFilter = SafeCallFilter; 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 0be87bd46fac..d300e52c4b8f 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 @@ -14,18 +14,85 @@ // You should have received a copy of the GNU General Public License // along with Cumulus. If not, see . +use bp_polkadot_core::Signature; pub use bridge_hub_polkadot_runtime::{ - xcm_config::XcmConfig, AllPalletsWithoutSystem, Balances, ExistentialDeposit, ParachainSystem, - PolkadotXcm, Runtime, RuntimeEvent, SessionKeys, + bridge_hub_config, + constants::fee::WeightToFee, + xcm_config::{RelayNetwork, XcmConfig}, + AllPalletsWithoutSystem, Balances, BridgeGrandpaKusamaInstance, + BridgeRejectObsoleteHeadersAndMessages, ExistentialDeposit, ParachainSystem, PolkadotXcm, + Runtime, RuntimeCall, RuntimeEvent, SessionKeys, WithBridgeHubKusamaMessagesInstance, }; -use codec::Decode; +use bridge_hub_polkadot_runtime::{ + bridge_hub_config::WithBridgeHubKusamaMessageBridge, BridgeParachainKusamaInstance, + DeliveryRewardInBalance, Executive, RequiredStakeForStakeAndSlash, SignedExtra, + UncheckedExtrinsic, +}; +use codec::{Decode, Encode}; use frame_support::parameter_types; -use parachains_common::{polkadot::fee::WeightToFee, AccountId, AuraId}; +use parachains_common::{polkadot::fee::WeightToFee, AccountId, AuraId, Balance}; +use sp_keyring::AccountKeyring::Alice; +use sp_runtime::{ + generic::{Era, SignedPayload}, + traits::Block as BlockT, + AccountId32, +}; +use xcm::latest::prelude::*; -const ALICE: [u8; 32] = [1u8; 32]; +// Para id of sibling chain (e.g. Statemint) used in tests. +pub const SIBLING_PARACHAIN_ID: u32 = 1000; parameter_types! { pub CheckingAccount: AccountId = PolkadotXcm::check_account(); + pub RuntimeNetwork: NetworkId = RelayNetwork::get().unwrap(); +} + +fn construct_extrinsic( + sender: sp_keyring::AccountKeyring, + call: RuntimeCall, +) -> UncheckedExtrinsic { + let extra: SignedExtra = ( + frame_system::CheckNonZeroSender::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(Era::immortal()), + frame_system::CheckNonce::::from(0), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(0), + BridgeRejectObsoleteHeadersAndMessages::default(), + bridge_hub_config::BridgeRefundBridgeHubKusamaMessages::default(), + ); + let payload = SignedPayload::new(call.clone(), extra.clone()).unwrap(); + let signature = payload.using_encoded(|e| sender.sign(e)); + UncheckedExtrinsic::new_signed( + call, + AccountId32::from(sender.public()).into(), + Signature::Sr25519(signature.clone()), + extra, + ) +} + +fn construct_and_apply_extrinsic( + relayer_at_target: sp_keyring::AccountKeyring, + batch: pallet_utility::Call, +) -> sp_runtime::DispatchOutcome { + let batch_call = RuntimeCall::Utility(batch); + let xt = construct_extrinsic(relayer_at_target, batch_call); + let r = Executive::apply_extrinsic(xt); + r.unwrap() +} + +fn executive_init_block(header: &<::Block as BlockT>::Header) { + Executive::initialize_block(header) +} + +fn collator_session_keys() -> bridge_hub_test_utils::CollatorSessionKeys { + bridge_hub_test_utils::CollatorSessionKeys::new( + AccountId::from(Alice), + AccountId::from(Alice), + SessionKeys { aura: AuraId::from(Alice.public()) }, + ) } bridge_hub_test_utils::test_cases::include_teleports_for_native_asset_works!( @@ -35,11 +102,7 @@ bridge_hub_test_utils::test_cases::include_teleports_for_native_asset_works!( CheckingAccount, WeightToFee, ParachainSystem, - bridge_hub_test_utils::CollatorSessionKeys::new( - AccountId::from(ALICE), - AccountId::from(ALICE), - SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) } - ), + collator_session_keys(), ExistentialDeposit::get(), Box::new(|runtime_event_encoded: Vec| { match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { @@ -55,3 +118,148 @@ bridge_hub_test_utils::test_cases::include_teleports_for_native_asset_works!( }), 1002 ); + +#[test] +fn initialize_bridge_by_governance_works() { + bridge_hub_test_utils::test_cases::initialize_bridge_by_governance_works::< + Runtime, + BridgeGrandpaKusamaInstance, + >( + collator_session_keys(), + bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID, + Box::new(|call| RuntimeCall::BridgeKusamaGrandpa(call).encode()), + ) +} + +#[test] +fn change_delivery_reward_by_governance_works() { + bridge_hub_test_utils::test_cases::change_storage_constant_by_governance_works::< + Runtime, + DeliveryRewardInBalance, + u64, + >( + collator_session_keys(), + bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID, + Box::new(|call| RuntimeCall::System(call).encode()), + || (DeliveryRewardInBalance::key().to_vec(), DeliveryRewardInBalance::get()), + |old_value| old_value.checked_mul(2).unwrap(), + ) +} + +#[test] +fn change_required_stake_by_governance_works() { + bridge_hub_test_utils::test_cases::change_storage_constant_by_governance_works::< + Runtime, + RequiredStakeForStakeAndSlash, + Balance, + >( + collator_session_keys(), + bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID, + Box::new(|call| RuntimeCall::System(call).encode()), + || (RequiredStakeForStakeAndSlash::key().to_vec(), RequiredStakeForStakeAndSlash::get()), + |old_value| { + if let Some(new_value) = old_value.checked_add(1) { + new_value + } else { + old_value.checked_sub(1).unwrap() + } + }, + ) +} + +#[test] +fn handle_export_message_from_system_parachain_add_to_outbound_queue_works() { + bridge_hub_test_utils::test_cases::handle_export_message_from_system_parachain_to_outbound_queue_works::< + Runtime, + XcmConfig, + WithBridgeHubKusamaMessagesInstance, + >( + collator_session_keys(), + bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID, + SIBLING_PARACHAIN_ID, + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::BridgeKusamaMessages(event)) => Some(event), + _ => None, + } + }), + || ExportMessage { network: Kusama, destination: X1(Parachain(1234)), xcm: Xcm(vec![]) }, + bridge_hub_config::ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA_LANE_ID + ) +} + +#[test] +fn message_dispatch_routing_works() { + bridge_hub_test_utils::test_cases::message_dispatch_routing_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ParachainSystem, + WithBridgeHubKusamaMessagesInstance, + RuntimeNetwork, + bridge_hub_config::KusamaGlobalConsensusNetwork, + >( + collator_session_keys(), + bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID, + SIBLING_PARACHAIN_ID, + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::ParachainSystem(event)) => Some(event), + _ => None, + } + }), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::XcmpQueue(event)) => Some(event), + _ => None, + } + }), + bridge_hub_config::ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA_LANE_ID, + ) +} + +#[test] +fn relayed_incoming_message_works() { + bridge_hub_test_utils::test_cases::relayed_incoming_message_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ParachainSystem, + BridgeGrandpaKusamaInstance, + BridgeParachainKusamaInstance, + WithBridgeHubKusamaMessagesInstance, + WithBridgeHubKusamaMessageBridge, + >( + collator_session_keys(), + bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID, + bp_bridge_hub_kusama::BRIDGE_HUB_KUSAMA_PARACHAIN_ID, + SIBLING_PARACHAIN_ID, + RuntimeNetwork::get(), + bridge_hub_config::ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA_LANE_ID, + ) +} + +#[test] +pub fn complex_relay_extrinsic_works() { + bridge_hub_test_utils::test_cases::complex_relay_extrinsic_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ParachainSystem, + BridgeGrandpaKusamaInstance, + BridgeParachainKusamaInstance, + WithBridgeHubKusamaMessagesInstance, + WithBridgeHubKusamaMessageBridge, + >( + collator_session_keys(), + bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID, + bp_bridge_hub_kusama::BRIDGE_HUB_KUSAMA_PARACHAIN_ID, + SIBLING_PARACHAIN_ID, + bridge_hub_config::BridgeHubKusamaChainId::get(), + RuntimeNetwork::get(), + bridge_hub_config::ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA_LANE_ID, + ExistentialDeposit::get(), + executive_init_block, + construct_and_apply_extrinsic, + ); +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_hub_rococo_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_hub_rococo_config.rs index bc8f97ad97c1..8ef6d9fca85d 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_hub_rococo_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_hub_rococo_config.rs @@ -62,7 +62,7 @@ parameter_types! { /// Proof of messages, coming from Wococo. pub type FromWococoBridgeHubMessagesProof = FromBridgedChainMessagesProof; -/// Messages delivery proof for Rococo Bridge Hub -> Wococo Bridge Hub messages. +/// Messages delivery proof for Rococo BridgeHub -> Wococo BridgeHub messages. pub type ToWococoBridgeHubMessagesDeliveryProof = FromBridgedChainMessagesDeliveryProof; @@ -73,7 +73,7 @@ pub type OnBridgeHubRococoBlobDispatcher = BridgeBlobDispatcher< BridgeWococoMessagesPalletInstance, >; -/// Export XCM messages to be relayed to the otherside +/// Export XCM messages to be relayed to the other side. pub type ToBridgeHubWococoHaulBlobExporter = HaulBlobExporter< XcmBlobHaulerAdapter, WococoGlobalConsensusNetwork, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_hub_wococo_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_hub_wococo_config.rs index 5178b75c3039..a11f80f2a9cb 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_hub_wococo_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_hub_wococo_config.rs @@ -62,7 +62,7 @@ parameter_types! { /// Proof of messages, coming from Rococo. pub type FromRococoBridgeHubMessagesProof = FromBridgedChainMessagesProof; -/// Messages delivery proof for Rococo Bridge Hub -> Wococo Bridge Hub messages. +/// Messages delivery proof for Rococo BridgeHub -> Wococo BridgeHub messages. pub type ToRococoBridgeHubMessagesDeliveryProof = FromBridgedChainMessagesDeliveryProof; @@ -73,7 +73,7 @@ pub type OnBridgeHubWococoBlobDispatcher = BridgeBlobDispatcher< BridgeRococoMessagesPalletInstance, >; -/// Export XCM messages to be relayed to the otherside +/// Export XCM messages to be relayed to the other side. pub type ToBridgeHubRococoHaulBlobExporter = HaulBlobExporter< XcmBlobHaulerAdapter, RococoGlobalConsensusNetwork, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index 4311a6a629f9..dc821bcdfe29 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -439,7 +439,7 @@ parameter_types! { pub const RelayerStakeReserveId: [u8; 8] = *b"brdgrlrs"; } -/// Add parachain bridge pallet to track Wococo bridge hub parachain +/// Add parachain bridge pallet to track Wococo BridgeHub parachain pub type BridgeParachainWococoInstance = pallet_bridge_parachains::Instance1; impl pallet_bridge_parachains::Config for Runtime { type RuntimeEvent = RuntimeEvent; @@ -452,7 +452,7 @@ impl pallet_bridge_parachains::Config for Runtime type MaxParaHeadDataSize = MaxWococoParaHeadDataSize; } -/// Add parachain bridge pallet to track Rococo bridge hub parachain +/// Add parachain bridge pallet to track Rococo BridgeHub parachain pub type BridgeParachainRococoInstance = pallet_bridge_parachains::Instance2; impl pallet_bridge_parachains::Config for Runtime { type RuntimeEvent = RuntimeEvent; @@ -583,16 +583,16 @@ construct_runtime!( Utility: pallet_utility::{Pallet, Call, Event} = 40, Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 36, - // Rococo and Wococo Bridge Hubs are sharing the runtime, so this runtime has two sets of + // Rococo and Wococo BridgeHubs are sharing the runtime, so this runtime has two sets of // bridge pallets. Both are deployed at both runtimes, but only one set is actually used // at particular runtime. - // With-Wococo bridge modules that are active (used) at Rococo Bridge Hub runtime. + // With-Wococo bridge modules that are active (used) at Rococo BridgeHub runtime. BridgeWococoGrandpa: pallet_bridge_grandpa::::{Pallet, Call, Storage, Event, Config} = 41, BridgeWococoParachain: pallet_bridge_parachains::::{Pallet, Call, Storage, Event} = 42, BridgeWococoMessages: pallet_bridge_messages::::{Pallet, Call, Storage, Event, Config} = 46, - // With-Rococo bridge modules that are active (used) at Wococo Bridge Hub runtime. + // With-Rococo bridge modules that are active (used) at Wococo BridgeHub runtime. BridgeRococoGrandpa: pallet_bridge_grandpa::::{Pallet, Call, Storage, Event, Config} = 43, BridgeRococoParachain: pallet_bridge_parachains::::{Pallet, Call, Storage, Event} = 44, BridgeRococoMessages: pallet_bridge_messages::::{Pallet, Call, Storage, Event, Config} = 45, @@ -1261,7 +1261,7 @@ mod tests { frame_system::CheckNonce::from(10), frame_system::CheckWeight::new(), pallet_transaction_payment::ChargeTransactionPayment::from(10), - BridgeRejectObsoleteHeadersAndMessages {}, + BridgeRejectObsoleteHeadersAndMessages::default(), ( BridgeRefundBridgeHubRococoMessages::default(), BridgeRefundBridgeHubWococoMessages::default(), 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 e5fe67f2a8e5..76ee77496649 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 @@ -55,7 +55,7 @@ fn construct_extrinsic( frame_system::CheckNonce::::from(0), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(0), - BridgeRejectObsoleteHeadersAndMessages {}, + BridgeRejectObsoleteHeadersAndMessages::default(), ( bridge_hub_wococo_config::BridgeRefundBridgeHubRococoMessages::default(), bridge_hub_rococo_config::BridgeRefundBridgeHubWococoMessages::default(), diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml index 73678e8f91a3..a6509c58ee21 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml @@ -9,7 +9,6 @@ publish = false [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } log = { version = "0.4.20", default-features = false } -assert_matches = "1.4.0" # Substrate frame-benchmarking = { path = "../../../../../substrate/frame/benchmarking", default-features = false, optional = true } 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 a3e36a39fd1e..3ecccc3988f5 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 @@ -16,7 +16,6 @@ //! Module contains predefined test-case scenarios for `Runtime` with bridging capabilities. -use assert_matches::assert_matches; use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch, SourceHeaderChain}, LaneId, MessageKey, OutboundLaneData, Weight, @@ -380,7 +379,6 @@ pub fn relayed_incoming_message_works>::InboundRelayer: From, { assert_ne!(runtime_para_id, sibling_parachain_id); - assert_ne!(runtime_para_id, bridged_para_id); ExtBuilder::::default() .with_collators(collator_session_key.collators()) @@ -530,15 +528,24 @@ pub fn relayed_incoming_message_works>::take_xcm( sibling_parachain_id.into(), ) .unwrap(); - let mut dispatched = xcm::latest::Xcm::<()>::try_from(dispatched).unwrap(); - // We use `WithUniqueTopic`, so expect a trailing `SetTopic`. - assert_matches!(dispatched.0.pop(), Some(SetTopic(..))); - assert_eq!(dispatched, expected_dispatch); + // verify contains original message + let dispatched = xcm::latest::Xcm::<()>::try_from(dispatched).unwrap(); + let mut dispatched_clone = dispatched.clone(); + for (idx, expected_instr) in expected_dispatch.0.iter().enumerate() { + assert_eq!(expected_instr, &dispatched.0[idx]); + assert_eq!(expected_instr, &dispatched_clone.0.remove(0)); + } + match dispatched_clone.0.len() { + 0 => (), + 1 => assert!(matches!(dispatched_clone.0[0], SetTopic(_))), + count => assert!(false, "Unexpected messages count: {:?}", count), + } }) } @@ -601,7 +608,6 @@ pub fn complex_relay_extrinsic_works> { assert_ne!(runtime_para_id, sibling_parachain_id); - assert_ne!(runtime_para_id, bridged_para_id); // Relayer account at local/this BH. let relayer_at_target = Bob; @@ -681,7 +687,7 @@ pub fn complex_relay_extrinsic_works, MB, ()>( lane_id, - xcm.into(), + xcm.clone().into(), message_nonce, message_destination, para_header_number, @@ -772,15 +778,24 @@ pub fn complex_relay_extrinsic_works>::take_xcm( sibling_parachain_id.into(), ) .unwrap(); - let mut dispatched = xcm::latest::Xcm::<()>::try_from(dispatched).unwrap(); - // We use `WithUniqueTopic`, so expect a trailing `SetTopic`. - assert_matches!(dispatched.0.pop(), Some(SetTopic(..))); - assert_eq!(dispatched, expected_dispatch); + // verify contains original message + let dispatched = xcm::latest::Xcm::<()>::try_from(dispatched).unwrap(); + let mut dispatched_clone = dispatched.clone(); + for (idx, expected_instr) in expected_dispatch.0.iter().enumerate() { + assert_eq!(expected_instr, &dispatched.0[idx]); + assert_eq!(expected_instr, &dispatched_clone.0.remove(0)); + } + match dispatched_clone.0.len() { + 0 => (), + 1 => assert!(matches!(dispatched_clone.0[0], SetTopic(_))), + count => assert!(false, "Unexpected messages count: {:?}", count), + } }) } diff --git a/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs b/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs index 5de4a49f8275..b3ae5bec6222 100644 --- a/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs +++ b/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs @@ -104,12 +104,14 @@ impl BridgeHubRuntimeType { "Polkadot BridgeHub Local", "polkadot-local", ParaId::new(1002), + Some("Bob".to_string()), ))), BridgeHubRuntimeType::PolkadotDevelopment => Ok(Box::new(polkadot::local_config( polkadot::BRIDGE_HUB_POLKADOT_DEVELOPMENT, "Polkadot BridgeHub Development", "polkadot-dev", ParaId::new(1002), + Some("Bob".to_string()), ))), BridgeHubRuntimeType::Kusama => Ok(Box::new(kusama::BridgeHubChainSpec::from_json_bytes( @@ -119,13 +121,15 @@ impl BridgeHubRuntimeType { kusama::BRIDGE_HUB_KUSAMA_LOCAL, "Kusama BridgeHub Local", "kusama-local", - ParaId::new(1003), + ParaId::new(1002), + Some("Bob".to_string()), ))), BridgeHubRuntimeType::KusamaDevelopment => Ok(Box::new(kusama::local_config( kusama::BRIDGE_HUB_KUSAMA_DEVELOPMENT, "Kusama BridgeHub Development", "kusama-dev", - ParaId::new(1003), + ParaId::new(1002), + Some("Bob".to_string()), ))), BridgeHubRuntimeType::Westend => Ok(Box::new(westend::BridgeHubChainSpec::from_json_bytes( @@ -384,6 +388,7 @@ pub mod kusama { chain_name: &str, relay_chain: &str, para_id: ParaId, + bridges_pallet_owner_seed: Option, ) -> BridgeHubChainSpec { let mut properties = sc_chain_spec::Properties::new(); properties.insert("ss58Format".into(), 2.into()); @@ -424,6 +429,9 @@ pub mod kusama { get_account_id_from_seed::("Ferdie//stash"), ], para_id, + bridges_pallet_owner_seed + .as_ref() + .map(|seed| get_account_id_from_seed::(&seed)), ) }, Vec::new(), @@ -439,6 +447,7 @@ pub mod kusama { invulnerables: Vec<(AccountId, AuraId)>, endowed_accounts: Vec, id: ParaId, + bridges_pallet_owner: Option, ) -> bridge_hub_kusama_runtime::RuntimeGenesisConfig { bridge_hub_kusama_runtime::RuntimeGenesisConfig { system: bridge_hub_kusama_runtime::SystemConfig { @@ -482,6 +491,14 @@ pub mod kusama { safe_xcm_version: Some(SAFE_XCM_VERSION), ..Default::default() }, + bridge_polkadot_grandpa: bridge_hub_kusama_runtime::BridgePolkadotGrandpaConfig { + owner: bridges_pallet_owner.clone(), + ..Default::default() + }, + bridge_polkadot_messages: bridge_hub_kusama_runtime::BridgePolkadotMessagesConfig { + owner: bridges_pallet_owner, + ..Default::default() + }, } } } @@ -521,6 +538,7 @@ pub mod polkadot { chain_name: &str, relay_chain: &str, para_id: ParaId, + bridges_pallet_owner_seed: Option, ) -> BridgeHubChainSpec { let mut properties = sc_chain_spec::Properties::new(); properties.insert("ss58Format".into(), 0.into()); @@ -561,6 +579,9 @@ pub mod polkadot { get_account_id_from_seed::("Ferdie//stash"), ], para_id, + bridges_pallet_owner_seed + .as_ref() + .map(|seed| get_account_id_from_seed::(&seed)), ) }, Vec::new(), @@ -576,6 +597,7 @@ pub mod polkadot { invulnerables: Vec<(AccountId, AuraId)>, endowed_accounts: Vec, id: ParaId, + bridges_pallet_owner: Option, ) -> bridge_hub_polkadot_runtime::RuntimeGenesisConfig { bridge_hub_polkadot_runtime::RuntimeGenesisConfig { system: bridge_hub_polkadot_runtime::SystemConfig { @@ -619,6 +641,14 @@ pub mod polkadot { safe_xcm_version: Some(SAFE_XCM_VERSION), ..Default::default() }, + bridge_kusama_grandpa: bridge_hub_polkadot_runtime::BridgeKusamaGrandpaConfig { + owner: bridges_pallet_owner.clone(), + ..Default::default() + }, + bridge_kusama_messages: bridge_hub_polkadot_runtime::BridgeKusamaMessagesConfig { + owner: bridges_pallet_owner, + ..Default::default() + }, } } } From 4af6519d678841fbb822e6791df90357b0d07d09 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Mon, 4 Sep 2023 12:48:07 +0200 Subject: [PATCH 04/17] 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; From 867321c2d2ef7480ff12c762ad5e876924b73759 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Tue, 5 Sep 2023 12:40:03 +0200 Subject: [PATCH 05/17] Update review comments from Adrian Update cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/xcm_config.rs Co-authored-by: Adrian Catangiu Update cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/bridge_hub_config.rs Co-authored-by: Adrian Catangiu Update cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/bridge_hub_config.rs Co-authored-by: Adrian Catangiu Update cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/xcm_config.rs Co-authored-by: Adrian Catangiu Update cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/bridge_hub_config.rs Co-authored-by: Adrian Catangiu Update cumulus/parachains/runtimes/assets/common/src/matching.rs Co-authored-by: Adrian Catangiu Update cumulus/parachains/runtimes/assets/common/src/matching.rs Co-authored-by: Adrian Catangiu Update cumulus/parachains/runtimes/assets/common/src/matching.rs Co-authored-by: Adrian Catangiu Update cumulus/parachains/runtimes/assets/common/src/matching.rs Co-authored-by: Adrian Catangiu Update cumulus/parachains/runtimes/assets/common/src/matching.rs Co-authored-by: Adrian Catangiu Update cumulus/parachains/runtimes/assets/common/src/matching.rs Co-authored-by: Adrian Catangiu Update cumulus/parachains/runtimes/assets/common/src/matching.rs Co-authored-by: Adrian Catangiu Update cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs Co-authored-by: Adrian Catangiu Update cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs Co-authored-by: Adrian Catangiu Update cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs Co-authored-by: Adrian Catangiu Update cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs Co-authored-by: Adrian Catangiu Update cumulus/parachains/runtimes/assets/common/src/matching.rs Co-authored-by: Adrian Catangiu Fmt + one any to all Co-authored-by: Adrian Catangiu --- .../assets/asset-hub-kusama/src/xcm_config.rs | 10 +++--- .../asset-hub-polkadot/src/xcm_config.rs | 10 +++--- .../runtimes/assets/common/src/matching.rs | 34 +++++++++---------- .../src/bridge_hub_config.rs | 8 ++--- .../bridge-hub-kusama/src/xcm_config.rs | 2 +- .../src/bridge_hub_config.rs | 11 +++--- .../bridge-hub-polkadot/src/xcm_config.rs | 2 +- .../bridge-hub-polkadot/tests/tests.rs | 1 - .../bridge-hub-rococo/src/xcm_config.rs | 2 +- 9 files changed, 39 insertions(+), 41 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs index 183940956f52..c81b7a632dbf 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs @@ -608,8 +608,7 @@ impl pallet_xcm::Config for Runtime { type XcmTeleportFilter = Everything; // Allow reserve based transfer to everywhere except for bridging, here we strictly check what // assets are allowed. - type XcmReserveTransferFilter = - EverythingBut; + type XcmReserveTransferFilter = EverythingBut; type Weigher = WeightInfoBounds< crate::weights::xcm::AssetHubKusamaXcmWeight, RuntimeCall, @@ -775,11 +774,12 @@ pub mod bridging { >; /// Filter out those assets which are not allowed for bridged reserve based transfer. - /// (asset, location) filter for `pallet_xcm::Config::XcmReserveTransferFilter`. - pub type IsNotAllowedExplicitlyForReserveTransfer = ExcludeOnlyForRemoteDestination< + /// Filter is made of (asset, location) and used by + /// `pallet_xcm::Config::XcmReserveTransferFilter`. + pub type DisallowForReserveTransfer = ExcludeOnlyForRemoteDestination< UniversalLocation, FilteredNetworkExportTable, - IsNotAllowedConcreteAssetBy, + DisallowConcreteAssetUnless, >; impl Contains for ToPolkadotXcmRouter { diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs index 5479eb82d70e..860cdbfd50a5 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs @@ -528,8 +528,7 @@ impl pallet_xcm::Config for Runtime { type XcmTeleportFilter = Everything; // Allow reserve based transfer to everywhere except for bridging, here we strictly check what // assets are allowed. - type XcmReserveTransferFilter = - EverythingBut; + type XcmReserveTransferFilter = EverythingBut; type Weigher = WeightInfoBounds< crate::weights::xcm::AssetHubPolkadotXcmWeight, RuntimeCall, @@ -682,11 +681,12 @@ pub mod bridging { >; /// Filter out those assets which are not allowed for bridged reserve based transfer. - /// (asset, location) filter for `pallet_xcm::Config::XcmReserveTransferFilter`. - pub type IsNotAllowedExplicitlyForReserveTransfer = ExcludeOnlyForRemoteDestination< + /// Filter is made of (asset, location) and used by + /// `pallet_xcm::Config::XcmReserveTransferFilter`. + pub type DisallowForReserveTransfer = ExcludeOnlyForRemoteDestination< UniversalLocation, FilteredNetworkExportTable, - IsNotAllowedConcreteAssetBy, + DisallowConcreteAssetUnless, >; impl Contains for ToKusamaXcmRouter { diff --git a/cumulus/parachains/runtimes/assets/common/src/matching.rs b/cumulus/parachains/runtimes/assets/common/src/matching.rs index 0402e7a560ed..9a4e203264c9 100644 --- a/cumulus/parachains/runtimes/assets/common/src/matching.rs +++ b/cumulus/parachains/runtimes/assets/common/src/matching.rs @@ -126,10 +126,8 @@ impl< // check asset according to the configured reserve locations for (reserve_location, asset_filter) in Reserves::get() { - if origin.eq(&reserve_location) { - if asset_filter.matches(asset_location) { - return true - } + if origin.eq(&reserve_location) && asset_filter.matches(asset_location) { + return true } } @@ -137,20 +135,22 @@ impl< } } -/// Filter assets that are explicitly not allowed for destination. +/// Disallow all assets the are either not `Concrete`, or not explicitly allowed by +/// `LocationAssetFilters`, iff `dest` matches any location in `LocationAssetFilters`. /// -/// Returns true if asset is not `Concrete` or is explicitly not allowed by `LocationAssetFilters`. -/// Returns false if `dest` does not match any location in `LocationAssetFilters`. -pub struct IsNotAllowedConcreteAssetBy( +/// Returns `false` regardless of `assets`, if `dest` does not match any location in +/// `LocationAssetFilters`. Otherwise, returns `true` if asset is either not `Concrete` or is not +/// explicitly allowed by `LocationAssetFilters`, otherwise returns `false`. +pub struct DisallowConcreteAssetUnless( sp_std::marker::PhantomData, ); impl>> Contains<(MultiLocation, sp_std::vec::Vec)> - for IsNotAllowedConcreteAssetBy + for DisallowConcreteAssetUnless { fn contains((dest, assets): &(MultiLocation, sp_std::vec::Vec)) -> bool { for (allowed_dest, asset_filter) in LocationAssetFilters::get().iter() { - // we care only about explicitly configured destinations + // we only disallow `assets` on explicitly configured destinations if !allowed_dest.eq(dest) { continue } @@ -162,22 +162,21 @@ impl>> _ => return true, }; - // filter have to match for all assets if !asset_filter.matches(asset_location) { - // if asset does not match filter, we found explicitly not allowed asset + // if asset does not match filter, disallow it return true } } } - // by default, everything is allowed + // if we got here, allow it false } } -/// Adapter for `Contains<(MultiLocation, sp_std::vec::Vec)>` which checks -/// if `Exporters` contains exporter for **remote** `MultiLocation` and iff so, then checks -/// `Filter`, anyway return false. +/// Adapter for `Contains<(MultiLocation, sp_std::vec::Vec)>` which returns `true` +/// iff `Exporters` contains exporter for **remote** `MultiLocation` _and_ +///`assets` also pass`Filter`, otherwise returns `false`. /// /// Note: Assumes that `Exporters` do not depend on `XCM program` and works for `Xcm::default()`. pub struct ExcludeOnlyForRemoteDestination( @@ -204,6 +203,7 @@ where if Exporters::exporter_for(&remote_network, &remote_destination, &Xcm::default()) .is_some() { + // destination is remote, and has configured exporter, now check filter Exclude::contains(dest_and_assets) } else { log::trace!( @@ -221,7 +221,7 @@ where "CheckOnlyForRemoteDestination dest: {:?} is not remote to the universal_source: {:?}", dest_and_assets.0, universal_source ); - // + // not a remote destination, do not exclude false }, } 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 7d973c2cebad..efbb34a66d39 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 @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Cumulus. If not, see . -//! Bridge definitions. +//! Kusama BridgeHub definitions. use crate::{ BridgeParachainPolkadotInstance, BridgePolkadotMessages, Runtime, @@ -179,7 +179,7 @@ parameter_types! { #[cfg(test)] mod tests { use super::*; - use crate::{constants, BridgeGrandpaPolkadotInstance}; + use crate::BridgeGrandpaPolkadotInstance; use bridge_runtime_common::{ assert_complete_bridge_types, integrity::{ @@ -188,7 +188,7 @@ mod tests { AssertCompleteBridgeConstants, }, }; - use parachains_common::Balance; + use parachains_common::{kusama, Balance}; /// Every additional message in the message delivery transaction boosts its priority. /// So the priority of transaction with `N+1` messages is larger than priority of @@ -199,7 +199,7 @@ mod tests { /// /// We want this tip to be large enough (delivery transactions with more messages = less /// operational costs and a faster bridge), so this value should be significant. - const FEE_BOOST_PER_MESSAGE: Balance = constants::currency::UNITS; + const FEE_BOOST_PER_MESSAGE: Balance = kusama::currency::UNITS; #[test] fn ensure_lane_weights_are_correct() { 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 7b8e3fa5aada..75e7454b727d 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 @@ -134,7 +134,7 @@ impl Contains for SafeCallFilter { // Allow to change dedicated storage items (called by governance-like) match call { RuntimeCall::System(frame_system::Call::set_storage { items }) - if items.iter().any(|(k, _)| { + if items.iter().all(|(k, _)| { k.eq(&DeliveryRewardInBalance::key()) | k.eq(&RequiredStakeForStakeAndSlash::key()) }) => 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 26a4a2c2175e..19beba195c87 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 @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Cumulus. If not, see . -//! Bridge definitions. +//! Polkadot BridgeHub definitions. use crate::{ BridgeKusamaMessages, BridgeParachainKusamaInstance, Runtime, @@ -168,8 +168,7 @@ pub type BridgeRefundBridgeHubKusamaMessages = RefundBridgedParachainMessages< bp_runtime::generate_static_str_provider!(BridgeRefundBridgeHubKusamaMessages); // TODO: rework once dynamic lanes are supported (https://github.com/paritytech/parity-bridges-common/issues/1760) -// now we support only StatemineToStatemint -/// Lanes setup +// now we support only AHP<>AHK Lanes setup pub const ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA_LANE_ID: LaneId = LaneId([0, 0, 0, 0]); parameter_types! { pub ActiveOutboundLanesToBridgeHubKusama: &'static [bp_messages::LaneId] = &[ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA_LANE_ID]; @@ -179,7 +178,7 @@ parameter_types! { #[cfg(test)] mod tests { use super::*; - use crate::{constants, BridgeGrandpaKusamaInstance}; + use crate::BridgeGrandpaKusamaInstance; use bridge_runtime_common::{ assert_complete_bridge_types, integrity::{ @@ -188,7 +187,7 @@ mod tests { AssertCompleteBridgeConstants, }, }; - use parachains_common::Balance; + use parachains_common::{polkadot, Balance}; /// Every additional message in the message delivery transaction boosts its priority. /// So the priority of transaction with `N+1` messages is larger than priority of @@ -199,7 +198,7 @@ mod tests { /// /// We want this tip to be large enough (delivery transactions with more messages = less /// operational costs and a faster bridge), so this value should be significant. - const FEE_BOOST_PER_MESSAGE: Balance = 5 * constants::currency::UNITS; + const FEE_BOOST_PER_MESSAGE: Balance = 5 * polkadot::currency::UNITS; #[test] fn ensure_lane_weights_are_correct() { 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 ab6643995efa..5154a28a1dcd 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 @@ -137,7 +137,7 @@ impl Contains for SafeCallFilter { // Allow to change dedicated storage items (called by governance-like) match call { RuntimeCall::System(frame_system::Call::set_storage { items }) - if items.iter().any(|(k, _)| { + if items.iter().all(|(k, _)| { k.eq(&DeliveryRewardInBalance::key()) | k.eq(&RequiredStakeForStakeAndSlash::key()) }) => 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 1cc160c0925f..38f6462579f4 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 @@ -17,7 +17,6 @@ use bp_polkadot_core::Signature; pub use bridge_hub_polkadot_runtime::{ bridge_hub_config, - constants::fee::WeightToFee, xcm_config::{DotRelayLocation, RelayNetwork, XcmConfig}, AllPalletsWithoutSystem, Balances, BridgeGrandpaKusamaInstance, BridgeRejectObsoleteHeadersAndMessages, ExistentialDeposit, ParachainSystem, PolkadotXcm, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs index e3d8645d49e7..55064af74a8e 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs @@ -154,7 +154,7 @@ impl Contains for SafeCallFilter { // Allow to change dedicated storage items (called by governance-like) match call { RuntimeCall::System(frame_system::Call::set_storage { items }) - if items.iter().any(|(k, _)| { + if items.iter().all(|(k, _)| { k.eq(&DeliveryRewardInBalance::key()) | k.eq(&RequiredStakeForStakeAndSlash::key()) }) => From a3d1264b86368788bdf4ffc1217fc4b3787dac99 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Mon, 11 Sep 2023 11:02:20 +0200 Subject: [PATCH 06/17] Fixed local run for AssetHubKusama/AssetHubPolkadot asset transfer (KSMs/DOTs) --- .../parachains/runtimes/bridge-hubs/README.md | 79 ++++++++++--------- cumulus/scripts/bridges_kusama_polkadot.sh | 43 +++++++--- cumulus/scripts/bridges_rococo_wococo.sh | 36 ++++++++- .../bridge_hub_kusama_local_network.toml | 22 +++--- .../bridge_hub_polkadot_local_network.toml | 22 +++--- .../statemine_kusama_local_network.toml | 2 +- 6 files changed, 129 insertions(+), 75 deletions(-) diff --git a/cumulus/parachains/runtimes/bridge-hubs/README.md b/cumulus/parachains/runtimes/bridge-hubs/README.md index 7600c52d3530..ac9b9122942d 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/README.md +++ b/cumulus/parachains/runtimes/bridge-hubs/README.md @@ -45,17 +45,28 @@ Copy the apropriate binary (zombienet-linux) from the latest release to ~/local_ --- # 2. Build polkadot binary -git clone https://github.com/paritytech/polkadot.git -cd polkadot -# if you want to test Kusama/Polkadot bridge, we need "sudo pallet + fast-runtime", -# so please, find the latest polkadot's repository branch `it/release-vX.Y.Z-fast-sudo` -# e.g: -# git checkout -b it/release-v0.9.43-fast-sudo --track origin/it/release-v0.9.43-fast-sudo +# If you want to test Kusama/Polkadot bridge, we need "sudo pallet + fast-runtime", +# so we need to use sudoif in polkadot directory. +# +# Install sudoif: (skip if already installed) +# cd +# git clone https://github.com/paritytech/parachain-utils.git +# cd parachain-utils # -> this is +# cargo build --release --bin sudofi +# +# cd /pokladot +# /target/release/sudoif -cargo build --release --features fast-runtime +cd +cargo build --release --features fast-runtime --bin polkadot cp target/release/polkadot ~/local_bridge_testing/bin/polkadot +cargo build --release --features fast-runtime --bin polkadot-prepare-worker +cp target/release/polkadot-prepare-worker ~/local_bridge_testing/bin/polkadot-prepare-worker + +cargo build --release --features fast-runtime --bin polkadot-execute-worker +cp target/release/polkadot-execute-worker ~/local_bridge_testing/bin/polkadot-execute-worker --- # 3. Build substrate-relay binary @@ -74,7 +85,7 @@ cp target/release/substrate-relay ~/local_bridge_testing/bin/substrate-relay --- # 4. Build cumulus polkadot-parachain binary -cd +cd # checkout desired branch or use master: # git checkout -b master --track origin/master @@ -83,25 +94,7 @@ cargo build --release --locked --bin polkadot-parachain cp target/release/polkadot-parachain ~/local_bridge_testing/bin/polkadot-parachain cp target/release/polkadot-parachain ~/local_bridge_testing/bin/polkadot-parachain-asset-hub - - -# !!! READ HERE (TODO remove once all mentioned branches bellow are merged) -# The use case "moving assets over bridge" is not merged yet and is implemented in separate branches. -# So, if you want to try it, you need to checkout different branch and continue with these instructions there. - -# For Kusama/Polkadot local bridge testing: -# -# build BridgeHubs (polkadot-parachain) from branch: -# git checkout -b bridge-hub-kusama-polkadot --track origin/bridge-hub-kusama-polkadot -# cargo build --release --locked --bin polkadot-parachain -# cp target/release/polkadot-parachain ~/local_bridge_testing/bin/polkadot-parachain -# -# build AssetHubs (polkadot-parachain-asset-hub) from branch: -# git checkout -b bko-transfer-asset-via-bridge-pallet-xcm --track origin/bko-transfer-asset-via-bridge-pallet-xcm -# cargo build --release --locked --bin polkadot-parachain -# cp target/release/polkadot-parachain ~/local_bridge_testing/bin/polkadot-parachain-asset-hub - -# For Rococo/Wococo local bridge testing: +# For Rococo/Wococo local bridge testing: (obsolete) # # build AssetHubs (polkadot-parachain-asset-hub) from branch: # git checkout -b bko-transfer-asset-via-bridge-pallet-xcm-ro-wo --track origin/bko-transfer-asset-via-bridge-pallet-xcm-ro-wo @@ -236,27 +229,33 @@ Check [requirements](#requirements-for-local-runtesting) for "sudo pallet + fast ### 1. Run chains (Kusama + BridgeHub + AssetHub, Polkadot + BridgeHub + AssetHub) with zombienet + ``` +cd + # Kusama + BridgeHubKusama + AssetHubKusama POLKADOT_BINARY_PATH=~/local_bridge_testing/bin/polkadot \ POLKADOT_PARACHAIN_BINARY_PATH=~/local_bridge_testing/bin/polkadot-parachain \ POLKADOT_PARACHAIN_BINARY_PATH_FOR_ASSET_HUB_KUSAMA=~/local_bridge_testing/bin/polkadot-parachain-asset-hub \ - ~/local_bridge_testing/bin/zombienet-linux --provider native spawn ./zombienet/bridge-hubs/bridge_hub_kusama_local_network.toml + ~/local_bridge_testing/bin/zombienet-linux --provider native spawn ./cumulus/zombienet/bridge-hubs/bridge_hub_kusama_local_network.toml ``` ``` +cd + # Polkadot + BridgeHubPolkadot + AssetHubPolkadot POLKADOT_BINARY_PATH=~/local_bridge_testing/bin/polkadot \ POLKADOT_PARACHAIN_BINARY_PATH=~/local_bridge_testing/bin/polkadot-parachain \ POLKADOT_PARACHAIN_BINARY_PATH_FOR_ASSET_HUB_POLKADOT=~/local_bridge_testing/bin/polkadot-parachain-asset-hub \ - ~/local_bridge_testing/bin/zombienet-linux --provider native spawn ./zombienet/bridge-hubs/bridge_hub_polkadot_local_network.toml + ~/local_bridge_testing/bin/zombienet-linux --provider native spawn ./cumulus/zombienet/bridge-hubs/bridge_hub_polkadot_local_network.toml ``` ### 2. Init bridge and run relayer (BridgeHubKusama, BridgeHubPolkadot) ``` -cd -./scripts/bridges_kusama_polkadot.sh run-relay +cd + +./cumulus/scripts/bridges_kusama_polkadot.sh run-relay ``` ### 3. Initialize transfer asset over bridge (DOTs/KSMs) @@ -265,22 +264,28 @@ This initialization does several things: - creates `ForeignAssets` for wrappedDOTs/wrappedKSMs - drips SA for AssetHubKusama on AssetHubPolkadot (and vice versa) which holds reserved assets on source chains ``` -./scripts/bridges_kusama_polkadot.sh init-asset-hub-kusama-local -./scripts/bridges_kusama_polkadot.sh init-bridge-hub-kusama-local -./scripts/bridges_kusama_polkadot.sh init-asset-hub-polkadot-local -./scripts/bridges_kusama_polkadot.sh init-bridge-hub-polkadot-local +cd + +./cumulus/scripts/bridges_kusama_polkadot.sh init-asset-hub-kusama-local +./cumulus/scripts/bridges_kusama_polkadot.sh init-bridge-hub-kusama-local +./cumulus/scripts/bridges_kusama_polkadot.sh init-asset-hub-polkadot-local +./cumulus/scripts/bridges_kusama_polkadot.sh init-bridge-hub-polkadot-local ``` ### 4. Send messages - transfer asset over bridge (DOTs/KSMs) Do (asset) transfers: ``` +cd + # KSMs from Kusama's Asset Hub to Polkadot's. -./scripts/bridges_kusama_polkadot.sh reserve-transfer-assets-from-asset-hub-kusama-local +./cumulus/scripts/bridges_kusama_polkadot.sh reserve-transfer-assets-from-asset-hub-kusama-local ``` ``` +cd + # DOTs from Polkadot's Asset Hub to Kusama's. -./scripts/bridges_kusama_polkadot.sh reserve-transfer-assets-from-asset-hub-polkadot-local +./cumulus/scripts/bridges_kusama_polkadot.sh reserve-transfer-assets-from-asset-hub-polkadot-local ``` - open explorers: (see zombienets) diff --git a/cumulus/scripts/bridges_kusama_polkadot.sh b/cumulus/scripts/bridges_kusama_polkadot.sh index a417ef49a9ca..4aa2f010bf4c 100755 --- a/cumulus/scripts/bridges_kusama_polkadot.sh +++ b/cumulus/scripts/bridges_kusama_polkadot.sh @@ -133,6 +133,7 @@ case "$1" in run_relay ;; init-asset-hub-kusama-local) + ensure_polkadot_js_api # create foreign assets for native Polkadot token (governance call on Kusama) force_create_foreign_asset \ "ws://127.0.0.1:9942" \ @@ -149,8 +150,18 @@ case "$1" in "//Alice" \ "$GLOBAL_CONSENSUS_POLKADOT_ASSET_HUB_POLKADOT_1000_SOVEREIGN_ACCOUNT" \ $((1000000000 + 50000000000 * 20)) + # HRMP + open_hrmp_channels \ + "ws://127.0.0.1:9942" \ + "//Alice" \ + 1000 1002 4 524288 + open_hrmp_channels \ + "ws://127.0.0.1:9942" \ + "//Alice" \ + 1002 1000 4 524288 ;; init-bridge-hub-kusama-local) + ensure_polkadot_js_api # SA of sibling asset hub pays for the execution transfer_balance \ "ws://127.0.0.1:8943" \ @@ -159,22 +170,32 @@ case "$1" in $((1000000000 + 50000000000 * 20)) ;; init-asset-hub-polkadot-local) + ensure_polkadot_js_api # create foreign assets for native Polkadot token (governance call on Kusama) - force_create_foreign_asset \ - "ws://127.0.0.1:9945" \ - "//Alice" \ - 1000 \ - "ws://127.0.0.1:9010" \ - "$(jq --null-input '{ "parents": 2, "interior": { "X1": { "GlobalConsensus": "Kusama" } } }')" \ - "$GLOBAL_CONSENSUS_KUSAMA_SOVEREIGN_ACCOUNT" \ - 1000000000 \ - true + force_create_foreign_asset \ + "ws://127.0.0.1:9945" \ + "//Alice" \ + 1000 \ + "ws://127.0.0.1:9010" \ + "$(jq --null-input '{ "parents": 2, "interior": { "X1": { "GlobalConsensus": "Kusama" } } }')" \ + "$GLOBAL_CONSENSUS_KUSAMA_SOVEREIGN_ACCOUNT" \ + 10000000000 \ + true # drip SA which holds reserves transfer_balance \ "ws://127.0.0.1:9010" \ "//Alice" \ "$GLOBAL_CONSENSUS_KUSAMA_ASSET_HUB_KUSAMA_1000_SOVEREIGN_ACCOUNT" \ $((1000000000 + 50000000000 * 20)) + # HRMP + open_hrmp_channels \ + "ws://127.0.0.1:9945" \ + "//Alice" \ + 1000 1002 4 524288 + open_hrmp_channels \ + "ws://127.0.0.1:9945" \ + "//Alice" \ + 1002 1000 4 524288 ;; init-bridge-hub-polkadot-local) # SA of sibling asset hub pays for the execution @@ -192,7 +213,7 @@ case "$1" in "//Alice" \ "$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Polkadot" }, { "Parachain": 1000 } ] } } }')" \ "$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "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] } } } } }')" \ - "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 1, "interior": "Here" } }, "fun": { "Fungible": 1000000000000 } } ] }')" \ + "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 1, "interior": "Here" } }, "fun": { "Fungible": 200000000000 } } ] }')" \ 0 \ "Unlimited" ;; @@ -204,7 +225,7 @@ case "$1" in "//Alice" \ "$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Kusama" }, { "Parachain": 1000 } ] } } }')" \ "$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "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] } } } } }')" \ - "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 1, "interior": "Here" } }, "fun": { "Fungible": 2000000000000 } } ] }')" \ + "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 1, "interior": "Here" } }, "fun": { "Fungible": 3000000000 } } ] }')" \ 0 \ "Unlimited" ;; diff --git a/cumulus/scripts/bridges_rococo_wococo.sh b/cumulus/scripts/bridges_rococo_wococo.sh index 2ed43a4be64e..f0e54be1591b 100755 --- a/cumulus/scripts/bridges_rococo_wococo.sh +++ b/cumulus/scripts/bridges_rococo_wococo.sh @@ -87,8 +87,8 @@ function ensure_polkadot_js_api() { echo "" echo "" echo "-------------------" - echo "Installing (nodejs) sub module: ./scripts/generate_hex_encoded_call" - pushd ./scripts/generate_hex_encoded_call + echo "Installing (nodejs) sub module: $(dirname "$0")/generate_hex_encoded_call" + pushd $(dirname "$0")/generate_hex_encoded_call npm install popd fi @@ -103,7 +103,7 @@ function generate_hex_encoded_call_data() { shift echo "Input params: $@" - node ./scripts/generate_hex_encoded_call "$type" "$endpoint" "$output" "$@" + node $(dirname "$0")/generate_hex_encoded_call "$type" "$endpoint" "$output" "$@" local retVal=$? if [ $type != "check" ]; then @@ -129,7 +129,7 @@ function transfer_balance() { polkadot-js-api \ --ws "${runtime_para_endpoint}" \ --seed "${seed?}" \ - tx.balances.transfer \ + tx.balances.transferAllowDeath \ "${target_account}" \ "${amount}" } @@ -200,6 +200,34 @@ function send_governance_transact() { "${message}" } +function open_hrmp_channels() { + local relay_url=$1 + local relay_chain_seed=$2 + local sender_para_id=$3 + local recipient_para_id=$4 + local max_capacity=$5 + local max_message_size=$6 + echo " calling open_hrmp_channels:" + echo " relay_url: ${relay_url}" + echo " relay_chain_seed: ${relay_chain_seed}" + echo " sender_para_id: ${sender_para_id}" + echo " recipient_para_id: ${recipient_para_id}" + echo " max_capacity: ${max_capacity}" + echo " max_message_size: ${max_message_size}" + echo " params:" + echo "--------------------------------------------------" + + polkadot-js-api \ + --ws "${relay_url?}" \ + --seed "${relay_chain_seed?}" \ + --sudo \ + tx.hrmp.forceOpenHrmpChannel \ + ${sender_para_id} \ + ${recipient_para_id} \ + ${max_capacity} \ + ${max_message_size} +} + function allow_assets_transfer_send() { local relay_url=$1 local relay_chain_seed=$2 diff --git a/cumulus/zombienet/bridge-hubs/bridge_hub_kusama_local_network.toml b/cumulus/zombienet/bridge-hubs/bridge_hub_kusama_local_network.toml index 7f753d6dd504..d4b264c89911 100644 --- a/cumulus/zombienet/bridge-hubs/bridge_hub_kusama_local_network.toml +++ b/cumulus/zombienet/bridge-hubs/bridge_hub_kusama_local_network.toml @@ -94,14 +94,14 @@ cumulus_based = true "-- --port 51433 --rpc-port 58833 --ws-port 58843 --no-mdns", "--bootnodes {{'alice-validator'|zombie('multiAddress')}}" ] -[[hrmp_channels]] -sender = 1000 -recipient = 1002 -max_capacity = 4 -max_message_size = 524288 - -[[hrmp_channels]] -sender = 1002 -recipient = 1000 -max_capacity = 4 -max_message_size = 524288 +#[[hrmp_channels]] +#sender = 1000 +#recipient = 1002 +#max_capacity = 4 +#max_message_size = 524288 +# +#[[hrmp_channels]] +#sender = 1002 +#recipient = 1000 +#max_capacity = 4 +#max_message_size = 524288 diff --git a/cumulus/zombienet/bridge-hubs/bridge_hub_polkadot_local_network.toml b/cumulus/zombienet/bridge-hubs/bridge_hub_polkadot_local_network.toml index 320456a25652..800b9c41c70d 100644 --- a/cumulus/zombienet/bridge-hubs/bridge_hub_polkadot_local_network.toml +++ b/cumulus/zombienet/bridge-hubs/bridge_hub_polkadot_local_network.toml @@ -94,14 +94,14 @@ cumulus_based = true "-- --port 31433 --rpc-port 38833 --ws-port 38843 --no-mdns", "--bootnodes {{'alice-validator-dot'|zombie('multiAddress')}}" ] -[[hrmp_channels]] -sender = 1000 -recipient = 1002 -max_capacity = 4 -max_message_size = 524288 - -[[hrmp_channels]] -sender = 1002 -recipient = 1000 -max_capacity = 4 -max_message_size = 524288 +#[[hrmp_channels]] +#sender = 1000 +#recipient = 1002 +#max_capacity = 4 +#max_message_size = 524288 +# +#[[hrmp_channels]] +#sender = 1002 +#recipient = 1000 +#max_capacity = 4 +#max_message_size = 524288 diff --git a/cumulus/zombienet/examples/statemine_kusama_local_network.toml b/cumulus/zombienet/examples/statemine_kusama_local_network.toml index 1f3debfb9d29..f7de44a1fb63 100644 --- a/cumulus/zombienet/examples/statemine_kusama_local_network.toml +++ b/cumulus/zombienet/examples/statemine_kusama_local_network.toml @@ -1,5 +1,5 @@ [relaychain] -default_command = "../polkadot/target/release/polkadot" +default_command = "./target/release/polkadot" default_args = [ "-lparachain=debug" ] chain = "kusama-local" From c20f3e4f6131200b0327333b289568ddef5d3a83 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Tue, 19 Sep 2023 15:04:28 +0200 Subject: [PATCH 07/17] Zombienet nits --- .../assets/asset-hub-kusama/tests/tests.rs | 2 +- .../parachains/runtimes/bridge-hubs/README.md | 26 +- .../src/bridge_hub_config.rs | 7 +- .../bridge-hubs/bridge-hub-kusama/src/lib.rs | 63 +- .../src/bridge_hub_config.rs | 7 +- .../bridge-hub-polkadot/src/lib.rs | 63 +- cumulus/scripts/bridges_kusama_polkadot.sh | 11 +- cumulus/scripts/bridges_rococo_wococo.sh | 538 ++++++------------ .../bridge_hub_kusama_local_network.toml | 38 +- .../bridge_hub_polkadot_local_network.toml | 41 +- 10 files changed, 287 insertions(+), 509 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs index d62d7479f9df..4608ff78106b 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs @@ -697,7 +697,7 @@ fn receive_reserve_asset_deposited_dot_from_asset_hub_polkadot_works() { AccountId::from([73; 32]), AccountId::from(BLOCK_AUTHOR_ACCOUNT), // receiving DOTs - (MultiLocation { parents: 2, interior: X1(GlobalConsensus(Polkadot)) }, 1000000000000, 1_000_000_000), + (MultiLocation { parents: 2, interior: X1(GlobalConsensus(Polkadot)) }, 1000000000000, 1_00_000_000), bridging_to_asset_hub_polkadot, (X1(PalletInstance(53)), GlobalConsensus(Polkadot), X1(Parachain(1000))) ) diff --git a/cumulus/parachains/runtimes/bridge-hubs/README.md b/cumulus/parachains/runtimes/bridge-hubs/README.md index ac9b9122942d..4a4f6f8e8d50 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/README.md +++ b/cumulus/parachains/runtimes/bridge-hubs/README.md @@ -47,16 +47,16 @@ Copy the apropriate binary (zombienet-linux) from the latest release to ~/local_ # 2. Build polkadot binary # If you want to test Kusama/Polkadot bridge, we need "sudo pallet + fast-runtime", -# so we need to use sudoif in polkadot directory. +# so we need to use sudofi in polkadot directory. # -# Install sudoif: (skip if already installed) +# Install sudofi: (skip if already installed) # cd # git clone https://github.com/paritytech/parachain-utils.git # cd parachain-utils # -> this is # cargo build --release --bin sudofi # -# cd /pokladot -# /target/release/sudoif +# cd /polkadot +# /target/release/sudofi cd cargo build --release --features fast-runtime --bin polkadot @@ -68,6 +68,7 @@ cp target/release/polkadot-prepare-worker ~/local_bridge_testing/bin/polkadot-pr cargo build --release --features fast-runtime --bin polkadot-execute-worker cp target/release/polkadot-execute-worker ~/local_bridge_testing/bin/polkadot-execute-worker + --- # 3. Build substrate-relay binary git clone https://github.com/paritytech/parity-bridges-common.git @@ -87,21 +88,12 @@ cp target/release/substrate-relay ~/local_bridge_testing/bin/substrate-relay # 4. Build cumulus polkadot-parachain binary cd -# checkout desired branch or use master: -# git checkout -b master --track origin/master - -cargo build --release --locked --bin polkadot-parachain +cargo build --release -p polkadot-parachain-bin cp target/release/polkadot-parachain ~/local_bridge_testing/bin/polkadot-parachain cp target/release/polkadot-parachain ~/local_bridge_testing/bin/polkadot-parachain-asset-hub - -# For Rococo/Wococo local bridge testing: (obsolete) -# -# build AssetHubs (polkadot-parachain-asset-hub) from branch: -# git checkout -b bko-transfer-asset-via-bridge-pallet-xcm-ro-wo --track origin/bko-transfer-asset-via-bridge-pallet-xcm-ro-wo -# cargo build --release --locked --bin polkadot-parachain -# cp target/release/polkadot-parachain ~/local_bridge_testing/bin/polkadot-parachain-asset-hub ``` + ## How to test local Rococo <-> Wococo bridge ### Run chains (Rococo + BridgeHub + AssetHub, Wococo + BridgeHub + AssetHub) with zombienet @@ -278,13 +270,13 @@ Do (asset) transfers: ``` cd -# KSMs from Kusama's Asset Hub to Polkadot's. +# 2.5 KSMs from Kusama's Asset Hub to Polkadot's. ./cumulus/scripts/bridges_kusama_polkadot.sh reserve-transfer-assets-from-asset-hub-kusama-local ``` ``` cd -# DOTs from Polkadot's Asset Hub to Kusama's. +# 30 DOTs from Polkadot's Asset Hub to Kusama's. ./cumulus/scripts/bridges_kusama_polkadot.sh reserve-transfer-assets-from-asset-hub-polkadot-local ``` 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 efbb34a66d39..a7323ce42a8b 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 @@ -160,7 +160,10 @@ impl ThisChainWithMessages for ThisChain { pub type BridgeRefundBridgeHubPolkadotMessages = RefundBridgedParachainMessages< Runtime, RefundableParachain, - RefundableMessagesLane, + RefundableMessagesLane< + WithBridgeHubPolkadotMessagesInstance, + AssetHubKusamaToAssetHubPolkadotMessageLane, + >, ActualFeeRefund, PriorityBoostPerMessage, StrBridgeRefundBridgeHubPolkadotMessages, @@ -173,7 +176,7 @@ bp_runtime::generate_static_str_provider!(BridgeRefundBridgeHubPolkadotMessages) pub const ASSET_HUB_KUSAMA_TO_ASSET_HUB_POLKADOT_LANE_ID: LaneId = LaneId([0, 0, 0, 0]); parameter_types! { pub ActiveOutboundLanesToBridgeHubPolkadot: &'static [bp_messages::LaneId] = &[ASSET_HUB_KUSAMA_TO_ASSET_HUB_POLKADOT_LANE_ID]; - pub const StatemineToStatemintMessageLane: bp_messages::LaneId = ASSET_HUB_KUSAMA_TO_ASSET_HUB_POLKADOT_LANE_ID; + pub const AssetHubKusamaToAssetHubPolkadotMessageLane: bp_messages::LaneId = ASSET_HUB_KUSAMA_TO_ASSET_HUB_POLKADOT_LANE_ID; } #[cfg(test)] 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 b58cb8998fb7..b62638d02993 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 @@ -1078,36 +1078,45 @@ cumulus_pallet_parachain_system::register_validate_block! { #[cfg(test)] mod tests { use super::*; - use bp_runtime::TransactionEra; - use bridge_hub_test_utils::test_header; use codec::Encode; - - pub type TestBlockHeader = - generic::Header; + use sp_runtime::{ + generic::Era, + traits::{SignedExtension, Zero}, + }; #[test] fn ensure_signed_extension_definition_is_compatible_with_relay() { - let payload: SignedExtra = ( - frame_system::CheckNonZeroSender::new(), - frame_system::CheckSpecVersion::new(), - frame_system::CheckTxVersion::new(), - frame_system::CheckGenesis::new(), - frame_system::CheckEra::from(sp_runtime::generic::Era::Immortal), - frame_system::CheckNonce::from(10), - frame_system::CheckWeight::new(), - pallet_transaction_payment::ChargeTransactionPayment::from(10), - BridgeRejectObsoleteHeadersAndMessages::default(), - BridgeRefundBridgeHubPolkadotMessages::default(), - ); - use bp_bridge_hub_kusama::BridgeHubSignedExtension; - let bh_indirect_payload = bp_bridge_hub_kusama::SignedExtension::from_params( - 10, - 10, - TransactionEra::Immortal, - test_header::(1).hash(), - 10, - 10, - ); - assert_eq!(payload.encode(), bh_indirect_payload.encode()); + use bp_polkadot_core::SuffixedCommonSignedExtensionExt; + + sp_io::TestExternalities::default().execute_with(|| { + frame_system::BlockHash::::insert(BlockNumber::zero(), Hash::default()); + let payload: SignedExtra = ( + frame_system::CheckNonZeroSender::new(), + frame_system::CheckSpecVersion::new(), + frame_system::CheckTxVersion::new(), + frame_system::CheckGenesis::new(), + frame_system::CheckEra::from(Era::Immortal), + frame_system::CheckNonce::from(10), + frame_system::CheckWeight::new(), + pallet_transaction_payment::ChargeTransactionPayment::from(10), + BridgeRejectObsoleteHeadersAndMessages, + BridgeRefundBridgeHubPolkadotMessages::default(), + ); + + let bh_indirect_payload = bp_bridge_hub_polkadot::SignedExtension::from_params( + VERSION.spec_version, + VERSION.transaction_version, + bp_runtime::TransactionEra::Immortal, + System::block_hash(BlockNumber::zero()), + 10, + 10, + (((), ()), ((), ())), + ); + assert_eq!(payload.encode(), bh_indirect_payload.encode()); + assert_eq!( + payload.additional_signed().unwrap().encode(), + bh_indirect_payload.additional_signed().unwrap().encode() + ); + }) } } 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 19beba195c87..2131032f5b70 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 @@ -160,7 +160,10 @@ impl ThisChainWithMessages for ThisChain { pub type BridgeRefundBridgeHubKusamaMessages = RefundBridgedParachainMessages< Runtime, RefundableParachain, - RefundableMessagesLane, + RefundableMessagesLane< + WithBridgeHubKusamaMessagesInstance, + AssetHubPolkadotToAssetHubKusamaMessageLane, + >, ActualFeeRefund, PriorityBoostPerMessage, StrBridgeRefundBridgeHubKusamaMessages, @@ -172,7 +175,7 @@ bp_runtime::generate_static_str_provider!(BridgeRefundBridgeHubKusamaMessages); pub const ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA_LANE_ID: LaneId = LaneId([0, 0, 0, 0]); parameter_types! { pub ActiveOutboundLanesToBridgeHubKusama: &'static [bp_messages::LaneId] = &[ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA_LANE_ID]; - pub const StatemintToStatemineMessageLane: bp_messages::LaneId = ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA_LANE_ID; + pub const AssetHubPolkadotToAssetHubKusamaMessageLane: bp_messages::LaneId = ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA_LANE_ID; } #[cfg(test)] 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 968a89fc2cfe..9d42f303f5e4 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 @@ -1079,36 +1079,45 @@ cumulus_pallet_parachain_system::register_validate_block! { #[cfg(test)] mod tests { use super::*; - use bp_runtime::TransactionEra; - use bridge_hub_test_utils::test_header; use codec::Encode; - - pub type TestBlockHeader = - generic::Header; + use sp_runtime::{ + generic::Era, + traits::{SignedExtension, Zero}, + }; #[test] fn ensure_signed_extension_definition_is_compatible_with_relay() { - let payload: SignedExtra = ( - frame_system::CheckNonZeroSender::new(), - frame_system::CheckSpecVersion::new(), - frame_system::CheckTxVersion::new(), - frame_system::CheckGenesis::new(), - frame_system::CheckEra::from(sp_runtime::generic::Era::Immortal), - frame_system::CheckNonce::from(10), - frame_system::CheckWeight::new(), - pallet_transaction_payment::ChargeTransactionPayment::from(10), - BridgeRejectObsoleteHeadersAndMessages::default(), - BridgeRefundBridgeHubKusamaMessages::default(), - ); - use bp_bridge_hub_polkadot::BridgeHubSignedExtension; - let bh_indirect_payload = bp_bridge_hub_polkadot::SignedExtension::from_params( - 10, - 10, - TransactionEra::Immortal, - test_header::(1).hash(), - 10, - 10, - ); - assert_eq!(payload.encode(), bh_indirect_payload.encode()); + use bp_polkadot_core::SuffixedCommonSignedExtensionExt; + + sp_io::TestExternalities::default().execute_with(|| { + frame_system::BlockHash::::insert(BlockNumber::zero(), Hash::default()); + let payload: SignedExtra = ( + frame_system::CheckNonZeroSender::new(), + frame_system::CheckSpecVersion::new(), + frame_system::CheckTxVersion::new(), + frame_system::CheckGenesis::new(), + frame_system::CheckEra::from(Era::Immortal), + frame_system::CheckNonce::from(10), + frame_system::CheckWeight::new(), + pallet_transaction_payment::ChargeTransactionPayment::from(10), + BridgeRejectObsoleteHeadersAndMessages, + BridgeRefundBridgeHubKusamaMessages::default(), + ); + + let bh_indirect_payload = bp_bridge_hub_polkadot::SignedExtension::from_params( + VERSION.spec_version, + VERSION.transaction_version, + bp_runtime::TransactionEra::Immortal, + System::block_hash(BlockNumber::zero()), + 10, + 10, + (((), ()), ((), ())), + ); + assert_eq!(payload.encode(), bh_indirect_payload.encode()); + assert_eq!( + payload.additional_signed().unwrap().encode(), + bh_indirect_payload.additional_signed().unwrap().encode() + ); + }) } } diff --git a/cumulus/scripts/bridges_kusama_polkadot.sh b/cumulus/scripts/bridges_kusama_polkadot.sh index 4aa2f010bf4c..a189ef3bbcf1 100755 --- a/cumulus/scripts/bridges_kusama_polkadot.sh +++ b/cumulus/scripts/bridges_kusama_polkadot.sh @@ -14,9 +14,10 @@ ASSET_HUB_POLKADOT_ACCOUNT_ADDRESS_FOR_LOCAL="5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNe # # Generated by: # -# #[test] -# fn generate_sovereign_accounts() { +# #[test] +# fn generate_sovereign_accounts() { # use sp_core::crypto::Ss58Codec; +# use polkadot_parachain_primitives::primitives::Sibling; # # parameter_types! { # pub UniversalLocationAHK: InteriorMultiLocation = X2(GlobalConsensus(Kusama), Parachain(1000)); @@ -142,7 +143,7 @@ case "$1" in "ws://127.0.0.1:9910" \ "$(jq --null-input '{ "parents": 2, "interior": { "X1": { "GlobalConsensus": "Polkadot" } } }')" \ "$GLOBAL_CONSENSUS_POLKADOT_SOVEREIGN_ACCOUNT" \ - 1000000000 \ + 100000000 \ true # drip SA which holds reserves transfer_balance \ @@ -213,7 +214,7 @@ case "$1" in "//Alice" \ "$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Polkadot" }, { "Parachain": 1000 } ] } } }')" \ "$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "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] } } } } }')" \ - "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 1, "interior": "Here" } }, "fun": { "Fungible": 200000000000 } } ] }')" \ + "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 1, "interior": "Here" } }, "fun": { "Fungible": 2500000000000 } } ] }')" \ 0 \ "Unlimited" ;; @@ -225,7 +226,7 @@ case "$1" in "//Alice" \ "$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Kusama" }, { "Parachain": 1000 } ] } } }')" \ "$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "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] } } } } }')" \ - "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 1, "interior": "Here" } }, "fun": { "Fungible": 3000000000 } } ] }')" \ + "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 1, "interior": "Here" } }, "fun": { "Fungible": 300000000000 } } ] }')" \ 0 \ "Unlimited" ;; diff --git a/cumulus/scripts/bridges_rococo_wococo.sh b/cumulus/scripts/bridges_rococo_wococo.sh index f0e54be1591b..d1675b2c9688 100755 --- a/cumulus/scripts/bridges_rococo_wococo.sh +++ b/cumulus/scripts/bridges_rococo_wococo.sh @@ -1,44 +1,65 @@ #!/bin/bash -# Address: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY -# AccountId: [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] -ASSET_HUB_KUSAMA_ACCOUNT_SEED_FOR_LOCAL="//Alice" -# Address: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY -# AccountId: [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] -ASSET_HUB_WOCOCO_ACCOUNT_SEED_FOR_LOCAL="5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" - -# SovereignAccount for `MultiLocation { parents: 2, interior: X2(GlobalConsensus(Rococo), Parachain(1000)) }` => 5CfNu7eH3SJvqqPt3aJh38T8dcFvhGzEohp9tsd41ANhXDnQ +# Expected sovereign accounts. # -# use sp_core::crypto::Ss58Codec; -# println!("{}", -# frame_support::sp_runtime::AccountId32::new( -# GlobalConsensusParachainConvertsFor::::convert_ref( -# MultiLocation { parents: 2, interior: X2(GlobalConsensus(Kusama), Parachain(1000)) }).unwrap() -# ).to_ss58check_with_version(42_u16.into()) -# ); -ASSET_HUB_ROCOCO_1000_SOVEREIGN_ACCOUNT="5CfNu7eH3SJvqqPt3aJh38T8dcFvhGzEohp9tsd41ANhXDnQ" - -# Address: GegTpZJMyzkntLN7NJhRfHDk4GWukLbGSsag6PHrLSrCK4h -ASSET_HUB2_ROCOCO_1000_SOVEREIGN_ACCOUNT="scatter feed race company oxygen trip extra elbow slot bundle auto canoe" - -# Adress: 5Ge7YcbctWCP1CccugzxWDn9hFnTxvTh3bL6PNy4ubNJmp7Y / H9jCvwVWsDJkrS4gPp1QB99qr4hmbGsVyAqn3F2PPaoWyU3 -# AccountId: [202, 107, 198, 135, 15, 25, 193, 165, 172, 73, 137, 218, 115, 177, 204, 0, 5, 155, 215, 86, 208, 51, 50, 130, 190, 110, 184, 143, 124, 50, 160, 20] -ASSET_HUB_WOCOCO_ACCOUNT_ADDRESS_FOR_ROCOCO="5Ge7YcbctWCP1CccugzxWDn9hFnTxvTh3bL6PNy4ubNJmp7Y" -ASSET_HUB_WOCOCO_ACCOUNT_SEED_FOR_WOCOCO="tone spirit magnet sunset cannon poverty forget lock river east blouse random" - -function address_to_account_id_bytes() { - local address=$1 - local output=$2 - echo "address_to_account_id_bytes - address: $address, output: $output" - if [ $address == "$ASSET_HUB_WOCOCO_ACCOUNT_SEED_FOR_LOCAL" ]; then - jq --null-input '[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]' > $output - elif [ $address == "$ASSET_HUB_WOCOCO_ACCOUNT_ADDRESS_FOR_ROCOCO" ]; then - jq --null-input '[202, 107, 198, 135, 15, 25, 193, 165, 172, 73, 137, 218, 115, 177, 204, 0, 5, 155, 215, 86, 208, 51, 50, 130, 190, 110, 184, 143, 124, 50, 160, 20]' > $output - else - echo -n "Sorry, unknown address: $address - please, add bytes here or function for that!" - exit 1 - fi -} +# Generated by: +# +# #[test] +# fn generate_sovereign_accounts() { +# use sp_core::crypto::Ss58Codec; +# use polkadot_parachain_primitives::primitives::Sibling; +# +# parameter_types! { +# pub UniversalLocationAHR: InteriorMultiLocation = X2(GlobalConsensus(Rococo), Parachain(1000)); +# pub UniversalLocationAHW: InteriorMultiLocation = X2(GlobalConsensus(Wococo), Parachain(1000)); +# } +# +# // SS58=42 +# println!("GLOBAL_CONSENSUS_ROCOCO_SOVEREIGN_ACCOUNT=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# GlobalConsensusConvertsFor::::convert_location( +# &MultiLocation { parents: 2, interior: X1(GlobalConsensus(Rococo)) }).unwrap() +# ).to_ss58check_with_version(42_u16.into()) +# ); +# println!("GLOBAL_CONSENSUS_ROCOCO_ASSET_HUB_ROCOCO_1000_SOVEREIGN_ACCOUNT=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# GlobalConsensusParachainConvertsFor::::convert_location( +# &MultiLocation { parents: 2, interior: X2(GlobalConsensus(Rococo), Parachain(1000)) }).unwrap() +# ).to_ss58check_with_version(42_u16.into()) +# ); +# println!("ASSET_HUB_WOCOCO_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_WOCOCO=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# SiblingParachainConvertsVia::::convert_location( +# &MultiLocation { parents: 1, interior: X1(Parachain(1000)) }).unwrap() +# ).to_ss58check_with_version(42_u16.into()) +# ); +# +# // SS58=42 +# println!("GLOBAL_CONSENSUS_WOCOCO_SOVEREIGN_ACCOUNT=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# GlobalConsensusConvertsFor::::convert_location( +# &MultiLocation { parents: 2, interior: X1(GlobalConsensus(Wococo)) }).unwrap() +# ).to_ss58check_with_version(42_u16.into()) +# ); +# println!("GLOBAL_CONSENSUS_WOCOCO_ASSET_HUB_WOCOCO_1000_SOVEREIGN_ACCOUNT=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# GlobalConsensusParachainConvertsFor::::convert_location( +# &MultiLocation { parents: 2, interior: X2(GlobalConsensus(Wococo), Parachain(1000)) }).unwrap() +# ).to_ss58check_with_version(42_u16.into()) +# ); +# println!("ASSET_HUB_ROCOCO_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_ROCOCO=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# SiblingParachainConvertsVia::::convert_location( +# &MultiLocation { parents: 1, interior: X1(Parachain(1000)) }).unwrap() +# ).to_ss58check_with_version(42_u16.into()) +# ); +# } +GLOBAL_CONSENSUS_ROCOCO_SOVEREIGN_ACCOUNT="5GxRGwT8bU1JeBPTUXc7LEjZMxNrK8MyL2NJnkWFQJTQ4sii" +GLOBAL_CONSENSUS_ROCOCO_ASSET_HUB_ROCOCO_1000_SOVEREIGN_ACCOUNT="5CfNu7eH3SJvqqPt3aJh38T8dcFvhGzEohp9tsd41ANhXDnQ" +ASSET_HUB_WOCOCO_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_WOCOCO="5Eg2fntNprdN3FgH4sfEaaZhYtddZQSQUqvYJ1f2mLtinVhV" +GLOBAL_CONSENSUS_WOCOCO_SOVEREIGN_ACCOUNT="5EWw2NzfPr2DCahourp33cya6bGWEJViTnJN6Z2ruFevpJML" +GLOBAL_CONSENSUS_WOCOCO_ASSET_HUB_WOCOCO_1000_SOVEREIGN_ACCOUNT="5EJX8L4dwGyYnCsjZ91LfWAsm3rCN8vY2AYvT4mauMEjsrQz" +ASSET_HUB_ROCOCO_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_ROCOCO="5Eg2fntNprdN3FgH4sfEaaZhYtddZQSQUqvYJ1f2mLtinVhV" function ensure_binaries() { if [[ ! -f ~/local_bridge_testing/bin/polkadot ]]; then @@ -216,7 +237,6 @@ function open_hrmp_channels() { echo " max_message_size: ${max_message_size}" echo " params:" echo "--------------------------------------------------" - polkadot-js-api \ --ws "${relay_url?}" \ --seed "${relay_chain_seed?}" \ @@ -228,68 +248,26 @@ function open_hrmp_channels() { ${max_message_size} } -function allow_assets_transfer_send() { +function set_storage() { local relay_url=$1 local relay_chain_seed=$2 local runtime_para_id=$3 local runtime_para_endpoint=$4 - local bridge_hub_para_id=$5 - local bridged_para_network=$6 - local bridged_para_para_id=$7 - echo " calling allow_assets_transfer_send:" + local items=$5 + echo " calling set_storage:" echo " relay_url: ${relay_url}" echo " relay_chain_seed: ${relay_chain_seed}" echo " runtime_para_id: ${runtime_para_id}" echo " runtime_para_endpoint: ${runtime_para_endpoint}" - echo " bridge_hub_para_id: ${bridge_hub_para_id}" - echo " bridged_para_network: ${bridged_para_network}" - echo " bridged_para_para_id: ${bridged_para_para_id}" + echo " items: ${items}" echo " params:" - # 1. generate data for Transact (add_exporter_config) - local bridge_config=$(jq --null-input \ - --arg bridge_hub_para_id "$bridge_hub_para_id" \ - --arg bridged_para_network "$bridged_para_network" \ - --arg bridged_para_para_id "$bridged_para_para_id" \ - ' - { - "bridgeLocation": { - "parents": 1, - "interior": { - "X1": { "Parachain": $bridge_hub_para_id } - } - }, - "allowedTargetLocation": { - "parents": 2, - "interior": { - "X2": [ - { - "GlobalConsensus": $bridged_para_network, - }, - { - "Parachain": $bridged_para_para_id - } - ] - } - }, - "maxTargetLocationFee": { - "id": { - "Concrete": { - "parents": 1, - "interior": "Here" - } - }, - "fun": { - "Fungible": 50000000000 - } - } - } - ' - ) + # 1. generate data for Transact (System::set_storage) local tmp_output_file=$(mktemp) - generate_hex_encoded_call_data "add-exporter-config" "${runtime_para_endpoint}" "${tmp_output_file}" $bridged_para_network "$bridge_config" + generate_hex_encoded_call_data "set-storage" "${runtime_para_endpoint}" "${tmp_output_file}" "$items" local hex_encoded_data=$(cat $tmp_output_file) + # 2. trigger governance call send_governance_transact "${relay_url}" "${relay_chain_seed}" "${runtime_para_id}" "${hex_encoded_data}" 200000000 12000 } @@ -352,224 +330,6 @@ function limited_reserve_transfer_assets() { "${weight_limit}" } -function allow_assets_transfer_receive() { - local relay_url=$1 - local relay_chain_seed=$2 - local runtime_para_id=$3 - local runtime_para_endpoint=$4 - local bridge_hub_para_id=$5 - local bridged_network=$6 - local bridged_para_id=$7 - echo " calling allow_assets_transfer_receive:" - echo " relay_url: ${relay_url}" - echo " relay_chain_seed: ${relay_chain_seed}" - echo " runtime_para_id: ${runtime_para_id}" - echo " runtime_para_endpoint: ${runtime_para_endpoint}" - echo " bridge_hub_para_id: ${bridge_hub_para_id}" - echo " bridged_network: ${bridged_network}" - echo " bridged_para_id: ${bridged_para_id}" - echo " params:" - - # 1. generate data for Transact (add_universal_alias) - local location=$(jq --null-input \ - --arg bridge_hub_para_id "$bridge_hub_para_id" \ - '{ "V3": { "parents": 1, "interior": { "X1": { "Parachain": $bridge_hub_para_id } } } }') - - local junction=$(jq --null-input \ - --arg bridged_network "$bridged_network" \ - '{ "GlobalConsensus": $bridged_network } ') - - local tmp_output_file=$(mktemp) - generate_hex_encoded_call_data "add-universal-alias" "${runtime_para_endpoint}" "${tmp_output_file}" "$location" "$junction" - local hex_encoded_data=$(cat $tmp_output_file) - - send_governance_transact "${relay_url}" "${relay_chain_seed}" "${runtime_para_id}" "${hex_encoded_data}" 200000000 12000 - - # 2. generate data for Transact (add_reserve_location) - local reserve_location=$(jq --null-input \ - --arg bridged_network "$bridged_network" \ - --arg bridged_para_id "$bridged_para_id" \ - '{ "V3": { - "parents": 2, - "interior": { - "X2": [ - { - "GlobalConsensus": $bridged_network, - }, - { - "Parachain": $bridged_para_id - } - ] - } - } }') - - local tmp_output_file=$(mktemp) - generate_hex_encoded_call_data "add-reserve-location" "${runtime_para_endpoint}" "${tmp_output_file}" "$reserve_location" - local hex_encoded_data=$(cat $tmp_output_file) - - send_governance_transact "${relay_url}" "${relay_chain_seed}" "${runtime_para_id}" "${hex_encoded_data}" 200000000 12000 -} - -function remove_assets_transfer_send() { - local relay_url=$1 - local relay_chain_seed=$2 - local runtime_para_id=$3 - local runtime_para_endpoint=$4 - local bridged_network=$5 - echo " calling remove_assets_transfer_send:" - echo " relay_url: ${relay_url}" - echo " relay_chain_seed: ${relay_chain_seed}" - echo " runtime_para_id: ${runtime_para_id}" - echo " runtime_para_endpoint: ${runtime_para_endpoint}" - echo " bridged_network: ${bridged_network}" - echo " params:" - - local tmp_output_file=$(mktemp) - generate_hex_encoded_call_data "remove-exporter-config" "${runtime_para_endpoint}" "${tmp_output_file}" $bridged_network - local hex_encoded_data=$(cat $tmp_output_file) - - send_governance_transact "${relay_url}" "${relay_chain_seed}" "${runtime_para_id}" "${hex_encoded_data}" 200000000 12000 -} - -# TODO: we need to fill sovereign account for bridge-hub, because, small ammouts does not match ExistentialDeposit, so no reserve pass -# SA for BH: MultiLocation { parents: 1, interior: X1(Parachain(1013)) } - 5Eg2fntRRwLinojmk3sh5xscp7F3S6Zzm5oDVtoLTALKiypR on Kusama Asset Hub - -function transfer_asset_via_bridge() { - local url=$1 - local seed=$2 - local target_account=$3 - local target_global_consensus=$4 - echo " calling transfer_asset_via_bridge:" - echo " url: ${url}" - echo " seed: ${seed}" - echo " target_account: ${target_account}" - echo " target_global_consensus: ${target_global_consensus}" - echo " params:" - - local assets=$(jq --null-input \ - ' - { - "V3": [ - { - "id": { - "Concrete": { - "parents": 1, - "interior": "Here" - } - }, - "fun": { - "Fungible": 100000000 - } - } - ] - } - ' - ) - - local tmp_output_file=$(mktemp) - address_to_account_id_bytes "$target_account" "${tmp_output_file}" - local hex_encoded_data=$(cat $tmp_output_file) - - local destination=$(jq --null-input \ - --arg target_global_consensus "$target_global_consensus" \ - --argjson hex_encoded_data "$hex_encoded_data" \ - ' - { - "V3": { - "parents": 2, - "interior": { - "X3": [ - { - "GlobalConsensus": $target_global_consensus - }, - { - "Parachain": 1000 - }, - { - "AccountId32": { - "id": $hex_encoded_data - } - } - ] - } - } - } - ' - ) - - echo "" - echo " assets:" - echo "${assets}" - echo "" - echo " destination:" - echo "${destination}" - echo "" - echo "--------------------------------------------------" - - polkadot-js-api \ - --ws "${url?}" \ - --seed "${seed?}" \ - tx.bridgeTransfer.transferAssetViaBridge \ - "${assets}" \ - "${destination}" -} - -function ping_via_bridge() { - local url=$1 - local seed=$2 - local target_account=$3 - local target_global_consensus=$4 - echo " calling ping_via_bridge:" - echo " url: ${url}" - echo " seed: ${seed}" - echo " target_account: ${target_account}" - echo " target_global_consensus: ${target_global_consensus}" - echo " params:" - - local tmp_output_file=$(mktemp) - address_to_account_id_bytes "$target_account" "${tmp_output_file}" - local hex_encoded_data=$(cat $tmp_output_file) - - local destination=$(jq --null-input \ - --arg target_global_consensus "$target_global_consensus" \ - --argjson hex_encoded_data "$hex_encoded_data" \ - ' - { - "V3": { - "parents": 2, - "interior": { - "X3": [ - { - "GlobalConsensus": $target_global_consensus - }, - { - "Parachain": 1000 - }, - { - "AccountId32": { - "id": $hex_encoded_data - } - } - ] - } - } - } - ' - ) - - echo "" - echo " destination:" - echo "${destination}" - echo "" - echo "--------------------------------------------------" - - polkadot-js-api \ - --ws "${url?}" \ - --seed "${seed?}" \ - tx.bridgeTransfer.pingViaBridge \ - "${destination}" -} - function init_ro_wo() { ensure_relayer @@ -632,93 +392,120 @@ case "$1" in init_wo_ro run_relay ;; - allow-transfers-local) - # this allows send transfers on asset hub kusama local (by governance-like) - ./$0 "allow-transfer-on-asset-hub-kusama-local" - # this allows receive transfers on asset hub westend local (by governance-like) - ./$0 "allow-transfer-on-asset-hub-westend-local" - ;; - allow-transfer-on-asset-hub-kusama-local) + init-asset-hub-rococo-local) ensure_polkadot_js_api - allow_assets_transfer_send \ + # create foreign assets for native Wococo token (governance call on Rococo) + force_create_foreign_asset \ "ws://127.0.0.1:9942" \ "//Alice" \ 1000 \ "ws://127.0.0.1:9910" \ - 1013 \ - "Wococo" 1000 + "$(jq --null-input '{ "parents": 2, "interior": { "X1": { "GlobalConsensus": "Wococo" } } }')" \ + "$GLOBAL_CONSENSUS_WOCOCO_SOVEREIGN_ACCOUNT" \ + 10000000000 \ + true + # drip SA which holds reserves + transfer_balance \ + "ws://127.0.0.1:9910" \ + "//Alice" \ + "$GLOBAL_CONSENSUS_WOCOCO_ASSET_HUB_WOCOCO_1000_SOVEREIGN_ACCOUNT" \ + $((1000000000 + 50000000000 * 20)) + # HRMP + open_hrmp_channels \ + "ws://127.0.0.1:9942" \ + "//Alice" \ + 1000 1013 4 524288 + open_hrmp_channels \ + "ws://127.0.0.1:9942" \ + "//Alice" \ + 1013 1000 4 524288 ;; - allow-transfer-on-asset-hub-westend-local) + init-bridge-hub-rococo-local) ensure_polkadot_js_api - allow_assets_transfer_receive \ + # SA of sibling asset hub pays for the execution + transfer_balance \ + "ws://127.0.0.1:8943" \ + "//Alice" \ + "$ASSET_HUB_ROCOCO_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_ROCOCO" \ + $((1000000000 + 50000000000 * 20)) + ;; + init-asset-hub-wococo-local) + ensure_polkadot_js_api + # set Wococo flavor - set_storage with: + # - `key` is `HexDisplay::from(&asset_hub_rococo_runtime::xcm_config::Flavor::key())` + # - `value` is `HexDisplay::from(&asset_hub_rococo_runtime::RuntimeFlavor::Wococo.encode())` + set_storage \ "ws://127.0.0.1:9945" \ "//Alice" \ 1000 \ "ws://127.0.0.1:9010" \ - 1014 \ - "Rococo" \ - 1000 - transfer_balance \ - "ws://127.0.0.1:9010" \ - "//Alice" \ - "$ASSET_HUB_ROCOCO_1000_SOVEREIGN_ACCOUNT" \ - $((1000000000 + 50000000000 * 20)) # ExistentialDeposit + maxTargetLocationFee * 20 - # create foreign assets for native Kusama token (yes, Kusama, because we are using Kusama Asset Hub runtime on rococo) + "$(jq --null-input '[["0x48297505634037ef48c848c99c0b1f1b", "0x01"]]')" + # create foreign assets for native Rococo token (governance call on Wococo) force_create_foreign_asset \ "ws://127.0.0.1:9945" \ "//Alice" \ 1000 \ "ws://127.0.0.1:9010" \ - "Kusama" \ - "$ASSET_HUB_ROCOCO_1000_SOVEREIGN_ACCOUNT" - ;; - remove-assets-transfer-from-asset-hub-kusama-local) - ensure_polkadot_js_api - remove_assets_transfer_send \ - "ws://127.0.0.1:9942" \ + "$(jq --null-input '{ "parents": 2, "interior": { "X1": { "GlobalConsensus": "Rococo" } } }')" \ + "$GLOBAL_CONSENSUS_ROCOCO_SOVEREIGN_ACCOUNT" \ + 10000000000 \ + true + # drip SA which holds reserves + transfer_balance \ + "ws://127.0.0.1:9010" \ "//Alice" \ - 1000 \ - "ws://127.0.0.1:9910" \ - "Wococo" + "$GLOBAL_CONSENSUS_ROCOCO_ASSET_HUB_ROCOCO_1000_SOVEREIGN_ACCOUNT" \ + $((1000000000 + 50000000000 * 20)) + # HRMP + open_hrmp_channels \ + "ws://127.0.0.1:9945" \ + "//Alice" \ + 1000 1014 4 524288 + open_hrmp_channels \ + "ws://127.0.0.1:9945" \ + "//Alice" \ + 1014 1000 4 524288 ;; - transfer-asset-from-asset-hub-kusama-local) - ensure_polkadot_js_api - transfer_asset_via_bridge \ - "ws://127.0.0.1:9910" \ - "$ASSET_HUB_KUSAMA_ACCOUNT_SEED_FOR_LOCAL" \ - "$ASSET_HUB_WOCOCO_ACCOUNT_SEED_FOR_LOCAL" \ - "Wococo" + init-bridge-hub-wococo-local) + # set Wococo flavor - set_storage with: + # - `key` is `HexDisplay::from(&bridge_hub_rococo_runtime::xcm_config::Flavor::key())` + # - `value` is `HexDisplay::from(&bridge_hub_rococo_runtime::RuntimeFlavor::Wococo.encode())` + set_storage \ + "ws://127.0.0.1:9945" \ + "//Alice" \ + 1014 \ + "ws://127.0.0.1:8945" \ + "$(jq --null-input '[["0x48297505634037ef48c848c99c0b1f1b", "0x01"]]')" + # SA of sibling asset hub pays for the execution + transfer_balance \ + "ws://127.0.0.1:8945" \ + "//Alice" \ + "$ASSET_HUB_WOCOCO_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_WOCOCO" \ + $((1000000000 + 50000000000 * 20)) ;; - ping-via-bridge-from-asset-hub-kusama-local) + reserve-transfer-assets-from-asset-hub-rococo-local) ensure_polkadot_js_api - ping_via_bridge \ + # send ROCs to Alice account on AHW + limited_reserve_transfer_assets \ "ws://127.0.0.1:9910" \ - "$ASSET_HUB_KUSAMA_ACCOUNT_SEED_FOR_LOCAL" \ - "$ASSET_HUB_WOCOCO_ACCOUNT_SEED_FOR_LOCAL" \ - "Wococo" - ;; - transfer-asset-from-asset-hub-rococo) - ensure_polkadot_js_api - transfer_asset_via_bridge \ - "wss://ws-rococo-rockmine2-collator-node-0.parity-testnet.parity.io" \ - "$ASSET_HUB2_ROCOCO_1000_SOVEREIGN_ACCOUNT" \ - "$ASSET_HUB_WOCOCO_ACCOUNT_ADDRESS_FOR_ROCOCO" \ - "Wococo" + "//Alice" \ + "$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Wococo" }, { "Parachain": 1000 } ] } } }')" \ + "$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "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] } } } } }')" \ + "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 1, "interior": "Here" } }, "fun": { "Fungible": 200000000000 } } ] }')" \ + 0 \ + "Unlimited" ;; - ping-via-bridge-from-asset-hub-rococo) + reserve-transfer-assets-from-asset-hub-wococo-local) ensure_polkadot_js_api - ping_via_bridge \ - "wss://ws-rococo-rockmine2-collator-node-0.parity-testnet.parity.io" \ - "${ASSET_HUB2_ROCOCO_1000_SOVEREIGN_ACCOUNT}" \ - "$ASSET_HUB_WOCOCO_ACCOUNT_ADDRESS_FOR_ROCOCO" \ - "Wococo" - ;; - drip) - transfer_balance \ + # send WOCs to Alice account on AHR + limited_reserve_transfer_assets \ "ws://127.0.0.1:9010" \ "//Alice" \ - "$ASSET_HUB_ROCOCO_1000_SOVEREIGN_ACCOUNT" \ - $((1000000000 + 50000000000 * 20)) + "$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Rococo" }, { "Parachain": 1000 } ] } } }')" \ + "$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "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] } } } } }')" \ + "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 1, "interior": "Here" } }, "fun": { "Fungible": 150000000000 } } ] }')" \ + 0 \ + "Unlimited" ;; stop) pkill -f polkadot @@ -731,15 +518,12 @@ case "$1" in echo "A command is require. Supported commands for: Local (zombienet) run: - run-relay - - allow-transfers-local - - allow-transfer-on-asset-hub-kusama-local - - allow-transfer-on-asset-hub-westend-local - - remove-assets-transfer-from-asset-hub-kusama-local - - transfer-asset-from-asset-hub-kusama-local - - ping-via-bridge-from-asset-hub-kusama-local - Live Rococo/Wococo run: - - transfer-asset-from-asset-hub-rococo - - ping-via-bridge-from-asset-hub-rococo"; + - init-asset-hub-rococo-local + - init-bridge-hub-rococo-local + - init-asset-hub-wococo-local + - init-bridge-hub-wococo-local + - reserve-transfer-assets-from-asset-hub-rococo-local + - reserve-transfer-assets-from-asset-hub-wococo-local"; exit 1 ;; esac diff --git a/cumulus/zombienet/bridge-hubs/bridge_hub_kusama_local_network.toml b/cumulus/zombienet/bridge-hubs/bridge_hub_kusama_local_network.toml index d4b264c89911..378e636cc115 100644 --- a/cumulus/zombienet/bridge-hubs/bridge_hub_kusama_local_network.toml +++ b/cumulus/zombienet/bridge-hubs/bridge_hub_kusama_local_network.toml @@ -7,28 +7,25 @@ default_args = [ "-lparachain=debug,xcm=trace" ] chain = "kusama-local" [[relaychain.nodes]] - name = "alice-validator" + name = "alice-kusama-validator" validator = true rpc_port = 9932 ws_port = 9942 - extra_args = ["--no-mdns --bootnodes {{'bob-validator'|zombie('multiAddress')}}"] - balance = 2000000000000 + balance = 200000000000000 [[relaychain.nodes]] - name = "bob-validator" + name = "bob-kusama-validator" validator = true rpc_port = 9933 ws_port = 9943 - extra_args = ["--no-mdns --bootnodes {{'alice-validator'|zombie('multiAddress')}}"] - balance = 2000000000000 + balance = 200000000000000 [[relaychain.nodes]] - name = "charlie-validator" + name = "charlie-kusama-validator" validator = true rpc_port = 9934 ws_port = 9944 - extra_args = ["--no-mdns --bootnodes {{'alice-validator'|zombie('multiAddress')}}"] - balance = 2000000000000 + balance = 200000000000000 [[parachains]] id = 1002 @@ -37,32 +34,28 @@ cumulus_based = true # run alice as parachain collator [[parachains.collators]] - name = "alice-collator" + name = "bridge-hub-kusama-collator1" validator = true command = "{{POLKADOT_PARACHAIN_BINARY_PATH}}" rpc_port = 8933 ws_port = 8943 args = [ "-lparachain=debug,runtime::bridge-hub=trace,runtime::bridge=trace,runtime::bridge-dispatch=trace,bridge=trace,runtime::bridge-messages=trace,xcm=trace", - ] - extra_args = [ - "--force-authoring", "--no-mdns", "--bootnodes {{'bob-collator'|zombie('multiAddress')}}", - "-- --port 41333 --rpc-port 48933 --ws-port 48943 --no-mdns", "--bootnodes {{'alice-validator'|zombie('multiAddress')}}" + "--force-authoring", + "--", "--port 41333", "--rpc-port 48933", "--ws-port 48943" ] # run bob as parachain collator [[parachains.collators]] - name = "bob-collator" + name = "bridge-hub-kusama-collator2" validator = true command = "{{POLKADOT_PARACHAIN_BINARY_PATH}}" rpc_port = 8934 ws_port = 8944 args = [ "-lparachain=trace,runtime::bridge-hub=trace,runtime::bridge=trace,runtime::bridge-dispatch=trace,bridge=trace,runtime::bridge-messages=trace,xcm=trace", - ] - extra_args = [ - "--force-authoring", "--no-mdns", "--bootnodes {{'alice-collator'|zombie('multiAddress')}}", - "-- --port 41334 --rpc-port 48934 --ws-port 48944 --no-mdns", "--bootnodes {{'bob-validator'|zombie('multiAddress')}}" + "--force-authoring", + "--", "--port 41334", "--rpc-port 48934", "--ws-port 48944" ] [[parachains]] @@ -77,10 +70,7 @@ cumulus_based = true command = "{{POLKADOT_PARACHAIN_BINARY_PATH_FOR_ASSET_HUB_KUSAMA}}" args = [ "-lparachain=debug,xcm=trace,runtime::bridge-transfer=trace", - ] - extra_args = [ - "--no-mdns", "--bootnodes {{'asset-hub-kusama-collator2'|zombie('multiAddress')}}", - "-- --port 51333 --rpc-port 58933 --ws-port 58943 --no-mdns", "--bootnodes {{'alice-validator'|zombie('multiAddress')}}" + "--", "--port 51333", "--rpc-port 58933", "--ws-port 58943" ] [[parachains.collators]] @@ -91,7 +81,7 @@ cumulus_based = true ] extra_args = [ "--no-mdns", "--bootnodes {{'asset-hub-kusama-collator1'|zombie('multiAddress')}}", - "-- --port 51433 --rpc-port 58833 --ws-port 58843 --no-mdns", "--bootnodes {{'alice-validator'|zombie('multiAddress')}}" + "--", "--port 51433", "--rpc-port 58833", "--ws-port 58843" ] #[[hrmp_channels]] diff --git a/cumulus/zombienet/bridge-hubs/bridge_hub_polkadot_local_network.toml b/cumulus/zombienet/bridge-hubs/bridge_hub_polkadot_local_network.toml index 800b9c41c70d..51e654f95c92 100644 --- a/cumulus/zombienet/bridge-hubs/bridge_hub_polkadot_local_network.toml +++ b/cumulus/zombienet/bridge-hubs/bridge_hub_polkadot_local_network.toml @@ -7,28 +7,25 @@ default_args = [ "-lparachain=debug,xcm=trace" ] chain = "polkadot-local" [[relaychain.nodes]] - name = "alice-validator-dot" + name = "alice-polkadot-validator" validator = true rpc_port = 9935 ws_port = 9945 - extra_args = ["--no-mdns --bootnodes {{'bob-validator-dot'|zombie('multiAddress')}}"] - balance = 2000000000000 + balance = 20000000000000 [[relaychain.nodes]] - name = "bob-validator-dot" + name = "bob-polkadot-validator" validator = true rpc_port = 9936 ws_port = 9946 - extra_args = ["--no-mdns --bootnodes {{'alice-validator-dot'|zombie('multiAddress')}}"] - balance = 2000000000000 + balance = 20000000000000 [[relaychain.nodes]] - name = "charlie-validator-dot" + name = "charlie-polkadot-validator" validator = true rpc_port = 9937 ws_port = 9947 - extra_args = ["--no-mdns --bootnodes {{'alice-validator-dot'|zombie('multiAddress')}}"] - balance = 2000000000000 + balance = 20000000000000 [[parachains]] id = 1002 @@ -37,32 +34,28 @@ cumulus_based = true # run alice as parachain collator [[parachains.collators]] - name = "alice-collator-dot" + name = "bridge-hub-polkadot-collator1" validator = true command = "{{POLKADOT_PARACHAIN_BINARY_PATH}}" rpc_port = 8935 ws_port = 8945 args = [ "-lparachain=debug,runtime::mmr=info,substrate=info,runtime=info,runtime::bridge-hub=trace,runtime::bridge=trace,runtime::bridge-dispatch=trace,bridge=trace,runtime::bridge-messages=trace,xcm=trace", - ] - extra_args = [ - "--force-authoring", "--no-mdns", "--bootnodes {{'bob-collator-dot'|zombie('multiAddress')}}", - "-- --port 41335 --rpc-port 48935 --ws-port 48945 --no-mdns", "--bootnodes {{'alice-validator-dot'|zombie('multiAddress')}}" + "--force-authoring", + "--", "--port 41335", "--rpc-port 48935", "--ws-port 48945" ] # run bob as parachain collator [[parachains.collators]] - name = "bob-collator-dot" + name = "bridge-hub-polkadot-collator2" validator = true command = "{{POLKADOT_PARACHAIN_BINARY_PATH}}" rpc_port = 8936 ws_port = 8946 args = [ "-lparachain=trace,runtime::mmr=info,substrate=info,runtime=info,runtime::bridge-hub=trace,runtime::bridge=trace,runtime::bridge-dispatch=trace,bridge=trace,runtime::bridge-messages=trace,xcm=trace", - ] - extra_args = [ - "--force-authoring", "--no-mdns", "--bootnodes {{'alice-collator-dot'|zombie('multiAddress')}}", - "-- --port 41336 --rpc-port 48936 --ws-port 48946 --no-mdns", "--bootnodes {{'bob-validator-dot'|zombie('multiAddress')}}" + "--force-authoring", + "--", "--port 41336", "--rpc-port 48936", "--ws-port 48946" ] [[parachains]] @@ -77,10 +70,7 @@ cumulus_based = true command = "{{POLKADOT_PARACHAIN_BINARY_PATH_FOR_ASSET_HUB_POLKADOT}}" args = [ "-lparachain=debug,xcm=trace,runtime::bridge-transfer=trace", - ] - extra_args = [ - "--no-mdns", "--bootnodes {{'asset-hub-polkadot-collator2'|zombie('multiAddress')}}", - "-- --port 31333 --rpc-port 38933 --ws-port 38943 --no-mdns", "--bootnodes {{'alice-validator-dot'|zombie('multiAddress')}}" + "--", "--port 31333", "--rpc-port 38933", "--ws-port 38943" ] [[parachains.collators]] @@ -88,10 +78,7 @@ cumulus_based = true command = "{{POLKADOT_PARACHAIN_BINARY_PATH_FOR_ASSET_HUB_POLKADOT}}" args = [ "-lparachain=debug,xcm=trace,runtime::bridge-transfer=trace", - ] - extra_args = [ - "--no-mdns", "--bootnodes {{'asset-hub-polkadot-collator1'|zombie('multiAddress')}}", - "-- --port 31433 --rpc-port 38833 --ws-port 38843 --no-mdns", "--bootnodes {{'alice-validator-dot'|zombie('multiAddress')}}" + "--", "--port 31433", "--rpc-port 38833", "--ws-port 38843" ] #[[hrmp_channels]] From b2015dc73ca24b4ea5eb731469a5061ad6f28cbe Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Tue, 19 Sep 2023 15:50:46 +0200 Subject: [PATCH 08/17] Fix benchmarks --- .../runtimes/bridge-hubs/bridge-hub-kusama/src/lib.rs | 2 +- .../runtimes/bridge-hubs/bridge-hub-polkadot/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 b62638d02993..cb1c7b04097a 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 @@ -977,7 +977,7 @@ impl_runtime_apis! { ) -> (bridge_hub_config::FromBridgeHubPolkadotMessagesProof, Weight) { use cumulus_primitives_core::XcmpMessageSource; assert!(XcmpQueue::take_outbound_messages(usize::MAX).is_empty()); - ParachainSystem::open_outbound_hrmp_channel_for_benchmarks(42.into()); + ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(42.into()); prepare_message_proof_from_parachain::< Runtime, BridgeGrandpaPolkadotInstance, 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 9d42f303f5e4..54b8ae37872b 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 @@ -978,7 +978,7 @@ impl_runtime_apis! { ) -> (bridge_hub_config::FromBridgeHubKusamaMessagesProof, Weight) { use cumulus_primitives_core::XcmpMessageSource; assert!(XcmpQueue::take_outbound_messages(usize::MAX).is_empty()); - ParachainSystem::open_outbound_hrmp_channel_for_benchmarks(42.into()); + ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(42.into()); prepare_message_proof_from_parachain::< Runtime, BridgeGrandpaKusamaInstance, From 1fd7aaa76cff942a42a5d40ceea281fc2ac8262d Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Tue, 19 Sep 2023 16:03:01 +0200 Subject: [PATCH 09/17] Fix benchmarks --- cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs | 2 +- .../parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs index 44d6d81edd76..320261a507b5 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs @@ -1255,7 +1255,7 @@ impl_runtime_apis! { ); } fn ensure_bridged_target_destination() -> MultiLocation { - ParachainSystem::open_outbound_hrmp_channel_for_benchmarks( + ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests( xcm_config::bridging::BridgeHubKusamaParaId::get().into() ); xcm_config::bridging::AssetHubPolkadot::get() diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs index cadd44c46c40..8b205a9ffbe0 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs @@ -1134,7 +1134,7 @@ impl_runtime_apis! { ); } fn ensure_bridged_target_destination() -> MultiLocation { - ParachainSystem::open_outbound_hrmp_channel_for_benchmarks( + ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests( xcm_config::bridging::BridgeHubPolkadotParaId::get().into() ); xcm_config::bridging::AssetHubKusama::get() From 791d6ddee02da2b5f378b6348ce8d8c985b92c27 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Thu, 21 Sep 2023 15:44:43 +0200 Subject: [PATCH 10/17] Backporting nits from https://github.com/paritytech/polkadot-sdk/pull/1215 --- cumulus/pallets/xcmp-queue/src/bridging.rs | 79 +++++-------- cumulus/pallets/xcmp-queue/src/lib.rs | 35 +++--- cumulus/parachains/common/src/xcm_config.rs | 110 +++++++++++++++--- .../assets/asset-hub-kusama/src/lib.rs | 2 +- .../assets/asset-hub-kusama/src/xcm_config.rs | 12 +- .../assets/asset-hub-polkadot/src/lib.rs | 2 +- .../asset-hub-polkadot/src/xcm_config.rs | 12 +- .../runtimes/assets/common/src/matching.rs | 31 ++--- .../bridge-hubs/bridge-hub-kusama/src/lib.rs | 2 +- .../bridge-hub-polkadot/src/lib.rs | 2 +- 10 files changed, 165 insertions(+), 122 deletions(-) diff --git a/cumulus/pallets/xcmp-queue/src/bridging.rs b/cumulus/pallets/xcmp-queue/src/bridging.rs index bd36ded8d628..0fc3f1f39ea3 100644 --- a/cumulus/pallets/xcmp-queue/src/bridging.rs +++ b/cumulus/pallets/xcmp-queue/src/bridging.rs @@ -13,100 +13,79 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::pallet; +use crate::{pallet, OutboundState}; use cumulus_primitives_core::ParaId; use frame_support::pallet_prelude::Get; /// Adapter implementation for `bp_xcm_bridge_hub_router::XcmChannelStatusProvider` which checks /// both `OutboundXcmpStatus` and `InboundXcmpStatus` for defined `ParaId` if any of those is /// suspended. -pub struct InboundAndOutboundXcmpChannelCongestionStatusProvider( +pub struct InAndOutXcmpChannelStatusProvider( sp_std::marker::PhantomData<(SiblingBridgeHubParaId, Runtime)>, ); impl, Runtime: crate::Config> bp_xcm_bridge_hub_router::XcmChannelStatusProvider - for InboundAndOutboundXcmpChannelCongestionStatusProvider + for InAndOutXcmpChannelStatusProvider { fn is_congested() -> bool { - // if the outbound channel with recipient is suspended, it means that one of further - // bridge queues (e.g. bridge queue between two bridge hubs) is overloaded, so we shall - // take larger fee for our outbound messages - let sibling_bridge_hub_id: ParaId = SiblingBridgeHubParaId::get(); - let outbound_channels = pallet::OutboundXcmpStatus::::get(); - let outbound_channel = - outbound_channels.iter().find(|c| c.recipient == sibling_bridge_hub_id); - let is_outbound_channel_suspended = - outbound_channel.map(|c| c.is_suspended()).unwrap_or(false); - if is_outbound_channel_suspended { - return true - } - // if the inbound channel with recipient is suspended, it means that we are unable to // receive congestion reports from the bridge hub. So we assume the bridge pipeline is // congested too - let inbound_channels = pallet::InboundXcmpStatus::::get(); - let inbound_channel = inbound_channels.iter().find(|c| c.sender == sibling_bridge_hub_id); - let is_inbound_channel_suspended = - inbound_channel.map(|c| c.is_suspended()).unwrap_or(false); - if is_inbound_channel_suspended { + if pallet::Pallet::::is_inbound_channel_suspended(SiblingBridgeHubParaId::get()) { return true } - // TODO: https://github.com/paritytech/cumulus/pull/2342 - once this PR is merged, we may - // remove the following code - // - // if the outbound channel has at least `N` pages enqueued, let's assume it is congested. - // Normally, the chain with a few opened HRMP channels, will "send" pages at every block. - // Having `N` pages means that for last `N` blocks we either have not sent any messages, - // or have sent signals. - const MAX_OUTBOUND_PAGES_BEFORE_CONGESTION: u16 = 4; - let is_outbound_channel_congested = outbound_channel.map(|c| c.queued_pages()).unwrap_or(0); - is_outbound_channel_congested > MAX_OUTBOUND_PAGES_BEFORE_CONGESTION + // if the outbound channel with recipient is suspended, it means that one of further + // bridge queues (e.g. bridge queue between two bridge hubs) is overloaded, so we shall + // take larger fee for our outbound messages + OutXcmpChannelStatusProvider::::is_congested() } } /// Adapter implementation for `bp_xcm_bridge_hub_router::XcmChannelStatusProvider` which checks /// only `OutboundXcmpStatus` for defined `SiblingParaId` if is suspended. -pub struct OutboundXcmpChannelCongestionStatusProvider( +pub struct OutXcmpChannelStatusProvider( sp_std::marker::PhantomData<(SiblingBridgeHubParaId, Runtime)>, ); -impl, Runtime: crate::Config> +impl, Runtime: crate::Config> bp_xcm_bridge_hub_router::XcmChannelStatusProvider - for OutboundXcmpChannelCongestionStatusProvider + for OutXcmpChannelStatusProvider { fn is_congested() -> bool { - // let's find the channel with the sibling parachain - let sibling_para_id: cumulus_primitives_core::ParaId = SiblingParaId::get(); - let outbound_channels = pallet::OutboundXcmpStatus::::get(); - let channel_with_sibling_parachain = - outbound_channels.iter().find(|c| c.recipient == sibling_para_id); + let sibling_bridge_hub_id: ParaId = SiblingBridgeHubParaId::get(); - // no channel => it is empty, so not congested - let channel_with_sibling_parachain = match channel_with_sibling_parachain { - Some(channel_with_sibling_parachain) => channel_with_sibling_parachain, - None => return false, + // let's find the channel's state with the sibling parachain, + let Some((outbound_state, queued_pages)) = pallet::Pallet::::outbound_channel_state(sibling_bridge_hub_id) else { + return false }; - // suspended channel => it is congested - if channel_with_sibling_parachain.is_suspended() { + if outbound_state == OutboundState::Suspended { return true } + // TODO: https://github.com/paritytech/polkadot-sdk/pull/1556 - once this PR is merged, we may + // remove the following code. // TODO: the following restriction is arguable, we may live without that, assuming that - // there can't be more than some `N` messages queued at the bridge queue (at the source BH) + // There can't be more than some `N` messages queued at the bridge queue (at the source BH) // AND before accepting next (or next-after-next) delivery transaction, we'll receive the - // suspension signal from the target parachain and stop accepting delivery transactions + // suspension signal from the target parachain and stop accepting delivery transactions. - // it takes some time for target parachain to suspend inbound channel with the target BH and + // It takes some time for target parachain to suspend inbound channel with the target BH and // during that we will keep accepting new message delivery transactions. Let's also reject // new deliveries if there are too many "pages" (concatenated XCM messages) in the target BH // -> target parachain queue. + + // If the outbound channel has at least `N` pages enqueued, let's assume it is congested. + // Normally, the chain with a few opened HRMP channels, will "send" pages at every block. + // Having `N` pages means that for last `N` blocks we either have not sent any messages, + // or have sent signals. + const MAX_QUEUED_PAGES_BEFORE_DEACTIVATION: u16 = 4; - if channel_with_sibling_parachain.queued_pages() > MAX_QUEUED_PAGES_BEFORE_DEACTIVATION { + if queued_pages > MAX_QUEUED_PAGES_BEFORE_DEACTIVATION { return true } - true + false } } diff --git a/cumulus/pallets/xcmp-queue/src/lib.rs b/cumulus/pallets/xcmp-queue/src/lib.rs index db9c433b52d3..4a1a643b3505 100644 --- a/cumulus/pallets/xcmp-queue/src/lib.rs +++ b/cumulus/pallets/xcmp-queue/src/lib.rs @@ -402,13 +402,6 @@ pub struct InboundChannelDetails { message_metadata: Vec<(RelayBlockNumber, XcmpMessageFormat)>, } -impl InboundChannelDetails { - #[cfg(feature = "bridging")] - pub(crate) fn is_suspended(&self) -> bool { - self.state == InboundState::Suspended - } -} - /// Struct containing detailed information about the outbound channel. #[derive(Clone, Eq, PartialEq, Encode, Decode, TypeInfo)] pub struct OutboundChannelDetails { @@ -444,16 +437,6 @@ impl OutboundChannelDetails { self.state = OutboundState::Suspended; self } - - #[cfg(feature = "bridging")] - pub(crate) fn is_suspended(&self) -> bool { - self.state == OutboundState::Suspended - } - - #[cfg(feature = "bridging")] - pub(crate) fn queued_pages(&self) -> u16 { - self.last_index.saturating_sub(self.first_index) - } } #[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] @@ -966,6 +949,24 @@ impl Pallet { } }); } + + #[cfg(feature = "bridging")] + fn is_inbound_channel_suspended(sender: ParaId) -> bool { + >::get() + .iter() + .find(|c| c.sender == sender) + .map(|c| c.state == InboundState::Suspended) + .unwrap_or(false) + } + + #[cfg(feature = "bridging")] + /// Returns tuple of `OutboundState` and number of queued pages. + fn outbound_channel_state(target: ParaId) -> Option<(OutboundState, u16)> { + >::get().iter().find(|c| c.recipient == target).map(|c| { + let queued_pages = c.last_index.saturating_sub(c.first_index); + (c.state, queued_pages) + }) + } } impl XcmpMessageHandler for Pallet { diff --git a/cumulus/parachains/common/src/xcm_config.rs b/cumulus/parachains/common/src/xcm_config.rs index 984cce297adf..7dee75975f97 100644 --- a/cumulus/parachains/common/src/xcm_config.rs +++ b/cumulus/parachains/common/src/xcm_config.rs @@ -27,7 +27,7 @@ use frame_support::{ }; use log; use sp_runtime::traits::Get; -use xcm::{latest::prelude::*, DoubleEncoded}; +use xcm::latest::prelude::*; use xcm_builder::{CreateMatcher, ExporterFor, MatchXcm}; use xcm_executor::traits::ShouldExecute; @@ -92,7 +92,7 @@ pub trait MatchesLocation { fn matches(&self, location: &Location) -> bool; } -/// Simple `MultiLocation` filter utility. +/// Simple `Location` filter utility. #[derive(Debug, DefaultNoBound)] pub struct LocationFilter { /// Requested location equals to `Location`. @@ -177,8 +177,8 @@ impl< } } -/// Allows execution from `origin` if it is contained in `AllowedOrigin` -/// and if it is just a straight `Transact` which contains `AllowedCall`. +/// Allows execution from `origin` (only with `OriginKind::Xcm`) if it is contained in +/// `AllowedOrigin` and if it is just a straight `Transact` which passes `AllowedCall` matcher. pub struct AllowUnpaidTransactsFrom( sp_std::marker::PhantomData<(RuntimeCall, AllowedCall, AllowedOrigin)>, ); @@ -191,13 +191,13 @@ impl< fn should_execute( origin: &MultiLocation, instructions: &mut [Instruction], - max_weight: Weight, + _max_weight: Weight, _properties: &mut xcm_executor::traits::Properties, ) -> Result<(), ProcessMessageError> { log::trace!( target: "xcm::barriers", "AllowUnpaidTransactFrom origin: {:?}, instructions: {:?}, max_weight: {:?}, properties: {:?}", - origin, instructions, max_weight, _properties, + origin, instructions, _max_weight, _properties, ); // we only allow from configured origins @@ -209,17 +209,15 @@ impl< .assert_remaining_insts(1)? .match_next_inst(|inst| match inst { Transact { origin_kind: OriginKind::Xcm, call: encoded_call, .. } => { - // this is a hack - don't know if there's a way to do that properly - // or else we can simply allow all calls - let mut decoded_call = DoubleEncoded::::from(encoded_call.clone()); - ensure!( - AllowedCall::contains( - decoded_call - .ensure_decoded() - .map_err(|_| ProcessMessageError::BadFormat)? - ), - ProcessMessageError::BadFormat, - ); + // Generic `Call` to `RuntimeCall` conversion - don't know if there's a way to + // do that properly? + let runtime_call: RuntimeCall = encoded_call + .clone() + .into::() + .try_into() + .map_err(|_| ProcessMessageError::BadFormat)?; + + ensure!(AllowedCall::contains(&runtime_call), ProcessMessageError::Unsupported); Ok(()) }, @@ -233,6 +231,7 @@ impl< #[cfg(test)] mod tests { use super::*; + use codec::{Decode, Encode}; #[test] fn filtered_network_export_table_works() { @@ -276,4 +275,81 @@ mod tests { ) } } + + #[test] + fn allow_unpaid_transacts_from_works() { + #[derive(Encode, Decode)] + enum RuntimeCall { + CallA, + CallB, + } + frame_support::match_types! { + pub type AcceptOnlyFromSibling1002: impl Contains = { + MultiLocation { parents: 1, interior: X1(Parachain(1002)) } + }; + pub type AcceptOnlyRuntimeCallA: impl Contains = { RuntimeCall::CallA }; + } + + fn transact(origin_kind: OriginKind, encoded_data: impl Encode) -> Instruction<()> { + Transact { + origin_kind, + require_weight_at_most: Default::default(), + call: encoded_data.encode().into(), + } + } + + type Barrier = AllowUnpaidTransactsFrom< + RuntimeCall, + AcceptOnlyRuntimeCallA, + AcceptOnlyFromSibling1002, + >; + + let test_data: Vec<(MultiLocation, Vec>, Result<(), ProcessMessageError>)> = vec![ + // success case + ( + MultiLocation { parents: 1, interior: X1(Parachain(1002)) }, + vec![transact(OriginKind::Xcm, RuntimeCall::CallA)], + Ok(()), + ), + // invalid message - more instruction than just one `Transact` + ( + MultiLocation { parents: 1, interior: X1(Parachain(1002)) }, + vec![transact(OriginKind::Xcm, RuntimeCall::CallA), ClearOrigin], + Err(ProcessMessageError::BadFormat), + ), + // invalid `OriginKind` + ( + MultiLocation { parents: 1, interior: X1(Parachain(1002)) }, + vec![transact(OriginKind::Native, RuntimeCall::CallA)], + Err(ProcessMessageError::BadFormat), + ), + // unsupported call + ( + MultiLocation { parents: 1, interior: X1(Parachain(1002)) }, + vec![transact(OriginKind::Xcm, RuntimeCall::CallB)], + Err(ProcessMessageError::Unsupported), + ), + // unsupported origin + ( + MultiLocation { parents: 1, interior: X1(Parachain(2105)) }, + vec![transact(OriginKind::Xcm, RuntimeCall::CallA)], + Err(ProcessMessageError::Unsupported), + ), + ]; + + for (origin, mut xcm, expected_result) in test_data { + assert_eq!( + Barrier::should_execute( + &origin, + &mut xcm, + Default::default(), + &mut xcm_executor::traits::Properties { + weight_credit: Default::default(), + message_id: None, + }, + ), + expected_result, + ) + } + } } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs index 320261a507b5..2cea4c1939f0 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs @@ -838,7 +838,7 @@ impl pallet_xcm_bridge_hub_router::Config for Runti type ToBridgeHubSender = XcmpQueue; type WithBridgeHubChannel = - cumulus_pallet_xcmp_queue::bridging::InboundAndOutboundXcmpChannelCongestionStatusProvider< + cumulus_pallet_xcmp_queue::bridging::InAndOutXcmpChannelStatusProvider< xcm_config::bridging::BridgeHubKusamaParaId, Runtime, >; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs index c81b7a632dbf..78d971c27567 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs @@ -720,16 +720,14 @@ pub mod bridging { /// Set up trusted bridged reserve locations. /// Locations from which the runtime accepts reserved assets. - pub TrustedBridgedReserveLocations: sp_std::vec::Vec = sp_std::vec![ + pub TrustedBridgedReserveLocations: sp_std::vec::Vec = sp_std::vec![ // trust assets from AssetHubPolkadot ( AssetHubPolkadot::get(), - AssetFilter::ByMultiLocation( - LocationFilter::default() - // allow receive DOT - .add_equals(DotLocation::get()) - // and nothing else - ) + LocationFilter::default() + // allow receive DOT + .add_equals(DotLocation::get()) + // and nothing else ) ]; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs index 8b205a9ffbe0..725f9f1aee0c 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs @@ -752,7 +752,7 @@ impl pallet_xcm_bridge_hub_router::Config for Runtime type ToBridgeHubSender = XcmpQueue; type WithBridgeHubChannel = - cumulus_pallet_xcmp_queue::bridging::InboundAndOutboundXcmpChannelCongestionStatusProvider< + cumulus_pallet_xcmp_queue::bridging::InAndOutXcmpChannelStatusProvider< xcm_config::bridging::BridgeHubPolkadotParaId, Runtime, >; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs index 860cdbfd50a5..82fde34414df 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs @@ -628,16 +628,14 @@ pub mod bridging { /// Set up trusted bridged reserve locations. /// Locations from which the runtime accepts reserved assets. - pub TrustedBridgedReserveLocations: sp_std::vec::Vec = sp_std::vec![ + pub TrustedBridgedReserveLocations: sp_std::vec::Vec = sp_std::vec![ // trust assets from AssetHubKusama ( AssetHubKusama::get(), - AssetFilter::ByMultiLocation( - LocationFilter::default() - // allow receive KSM - .add_equals(KsmLocation::get()) - // and nothing else - ) + LocationFilter::default() + // allow receive KSM + .add_equals(KsmLocation::get()) + // and nothing else ) ]; diff --git a/cumulus/parachains/runtimes/assets/common/src/matching.rs b/cumulus/parachains/runtimes/assets/common/src/matching.rs index 9a4e203264c9..5854ccf2e81f 100644 --- a/cumulus/parachains/runtimes/assets/common/src/matching.rs +++ b/cumulus/parachains/runtimes/assets/common/src/matching.rs @@ -93,7 +93,7 @@ pub struct IsTrustedBridgedReserveLocationForConcreteAsset, - Reserves: Get>, + Reserves: Get>, > ContainsPair for IsTrustedBridgedReserveLocationForConcreteAsset { @@ -144,7 +144,7 @@ impl< pub struct DisallowConcreteAssetUnless( sp_std::marker::PhantomData, ); -impl>> +impl>> Contains<(MultiLocation, sp_std::vec::Vec)> for DisallowConcreteAssetUnless { @@ -193,7 +193,7 @@ where let universal_source = UniversalLocation::get(); log::trace!( target: "xcm::contains", - "CheckOnlyForRemoteDestination dest: {:?}, assets: {:?}, universal_source: {:?}", + "ExcludeOnlyForRemoteDestination dest: {:?}, assets: {:?}, universal_source: {:?}", dest_and_assets.0, dest_and_assets.1, universal_source ); @@ -208,7 +208,7 @@ where } else { log::trace!( target: "xcm::contains", - "CheckOnlyForRemoteDestination no exporter for dest: {:?}", + "ExcludeOnlyForRemoteDestination no exporter for dest: {:?}", dest_and_assets.0 ); // no exporter means that we exclude by default @@ -218,7 +218,7 @@ where Err(_) => { log::trace!( target: "xcm::contains", - "CheckOnlyForRemoteDestination dest: {:?} is not remote to the universal_source: {:?}", + "ExcludeOnlyForRemoteDestination dest: {:?} is not remote to the universal_source: {:?}", dest_and_assets.0, universal_source ); // not a remote destination, do not exclude @@ -228,19 +228,10 @@ where } } -/// Location as `MultiLocation` with `AssetFilter`. -pub type FilteredLocation = (MultiLocation, AssetFilter); +/// A type alias for referring to the `LocationFilter`. +/// (`MultiLocation` represents here `AssetId::Concrete(location)`). +pub type AssetFilter = LocationFilter; -/// Simple asset location filter. -#[derive(Debug)] -pub enum AssetFilter { - ByMultiLocation(LocationFilter), -} - -impl MatchesLocation for AssetFilter { - fn matches(&self, asset_location: &MultiLocation) -> bool { - match self { - AssetFilter::ByMultiLocation(by_location) => by_location.matches(asset_location), - } - } -} +/// A type alias for referring to the `MultiLocation` with `AssetFilter` capabilities. +/// E.g. for `MultiLocation` we can accept assets that match `AssetFilter`. +pub type LocationWithAssetFilter = (MultiLocation, AssetFilter); 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 cb1c7b04097a..a2c39872088e 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 @@ -496,7 +496,7 @@ impl pallet_bridge_messages::Config for R type MessageDispatch = XcmBlobMessageDispatch< OnThisChainBlobDispatcher, Self::WeightInfo, - cumulus_pallet_xcmp_queue::bridging::OutboundXcmpChannelCongestionStatusProvider< + cumulus_pallet_xcmp_queue::bridging::OutXcmpChannelStatusProvider< bridge_hub_config::AssetHubKusamaParaId, Runtime, >, 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 54b8ae37872b..a2f59931af0c 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 @@ -497,7 +497,7 @@ impl pallet_bridge_messages::Config for Run type MessageDispatch = XcmBlobMessageDispatch< OnThisChainBlobDispatcher, Self::WeightInfo, - cumulus_pallet_xcmp_queue::bridging::OutboundXcmpChannelCongestionStatusProvider< + cumulus_pallet_xcmp_queue::bridging::OutXcmpChannelStatusProvider< bridge_hub_config::AssetHubPolkadotParaId, Runtime, >, From 344e0b0c030ae6f4f4cc4a56ff424e5b02b3457e Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Thu, 21 Sep 2023 15:59:35 +0200 Subject: [PATCH 11/17] ParaIds as constants to primitives --- Cargo.lock | 2 ++ bridges/primitives/chain-asset-hub-kusama/src/lib.rs | 3 +++ bridges/primitives/chain-asset-hub-polkadot/src/lib.rs | 3 +++ cumulus/parachains/runtimes/assets/asset-hub-kusama/Cargo.toml | 2 ++ .../runtimes/assets/asset-hub-kusama/src/xcm_config.rs | 2 +- .../parachains/runtimes/assets/asset-hub-polkadot/Cargo.toml | 2 ++ .../runtimes/assets/asset-hub-polkadot/src/xcm_config.rs | 2 +- .../bridge-hubs/bridge-hub-kusama/src/bridge_hub_config.rs | 2 +- .../bridge-hubs/bridge-hub-polkadot/src/bridge_hub_config.rs | 2 +- 9 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cf30ec1b7cba..b0997dabc077 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -723,6 +723,7 @@ dependencies = [ "asset-test-utils", "assets-common", "bp-asset-hub-kusama", + "bp-asset-hub-polkadot", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", @@ -820,6 +821,7 @@ version = "0.9.420" dependencies = [ "asset-test-utils", "assets-common", + "bp-asset-hub-kusama", "bp-asset-hub-polkadot", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", diff --git a/bridges/primitives/chain-asset-hub-kusama/src/lib.rs b/bridges/primitives/chain-asset-hub-kusama/src/lib.rs index 94016c1da0cb..f60ade71d9ce 100644 --- a/bridges/primitives/chain-asset-hub-kusama/src/lib.rs +++ b/bridges/primitives/chain-asset-hub-kusama/src/lib.rs @@ -47,3 +47,6 @@ frame_support::parameter_types! { /// (initially was calculated `170733333` + `10%` by test `BridgeHubKusama::can_calculate_weight_for_paid_export_message_with_reserve_transfer`) pub const BridgeHubKusamaBaseFeeInDots: u128 = 187806666; } + +/// Identifier of AssetHubKusama in the Kusama relay chain. +pub const ASSET_HUB_KUSAMA_PARACHAIN_ID: u32 = 1000; diff --git a/bridges/primitives/chain-asset-hub-polkadot/src/lib.rs b/bridges/primitives/chain-asset-hub-polkadot/src/lib.rs index 486fba60e1f8..5d5ea82de4c3 100644 --- a/bridges/primitives/chain-asset-hub-polkadot/src/lib.rs +++ b/bridges/primitives/chain-asset-hub-polkadot/src/lib.rs @@ -47,3 +47,6 @@ frame_support::parameter_types! { /// (initially was calculated `51220000` + `10%` by test `BridgeHubPolkadot::can_calculate_weight_for_paid_export_message_with_reserve_transfer`) pub const BridgeHubPolkadotBaseFeeInDots: u128 = 56342000; } + +/// Identifier of AssetHubPolkadot in the Polkadot relay chain. +pub const ASSET_HUB_POLKADOT_PARACHAIN_ID: u32 = 1000; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-kusama/Cargo.toml index f29c874edaa5..88e9a0c47a50 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/Cargo.toml @@ -82,6 +82,7 @@ assets-common = { path = "../common", default-features = false } # Bridges pallet-xcm-bridge-hub-router = { path = "../../../../../bridges/modules/xcm-bridge-hub-router", default-features = false } bp-asset-hub-kusama = { path = "../../../../../bridges/primitives/chain-asset-hub-kusama", default-features = false } +bp-asset-hub-polkadot = { path = "../../../../../bridges/primitives/chain-asset-hub-polkadot", default-features = false } [dev-dependencies] asset-test-utils = { path = "../test-utils" } @@ -167,6 +168,7 @@ try-runtime = [ std = [ "assets-common/std", "bp-asset-hub-kusama/std", + "bp-asset-hub-polkadot/std", "codec/std", "cumulus-pallet-aura-ext/std", "cumulus-pallet-dmp-queue/std", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs index 78d971c27567..ea5288525fe7 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs @@ -691,7 +691,7 @@ pub mod bridging { pub BridgeHubKusama: MultiLocation = MultiLocation::new(1, X1(Parachain(BridgeHubKusamaParaId::get()))); pub BridgeHubKusamaWithBridgeHubPolkadotInstance: MultiLocation = MultiLocation::new(1, X2(Parachain(BridgeHubKusamaParaId::get()), PalletInstance(53))); pub const PolkadotNetwork: NetworkId = NetworkId::Polkadot; - pub AssetHubPolkadot: MultiLocation = MultiLocation::new(2, X2(GlobalConsensus(PolkadotNetwork::get()), Parachain(1000))); + pub AssetHubPolkadot: MultiLocation = MultiLocation::new(2, X2(GlobalConsensus(PolkadotNetwork::get()), Parachain(bp_asset_hub_polkadot::ASSET_HUB_POLKADOT_PARACHAIN_ID))); pub DotLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(PolkadotNetwork::get()))); /// Router expects payment with this `AssetId`. diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/Cargo.toml index bdf143122ae2..9afbf2776326 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/Cargo.toml @@ -77,6 +77,7 @@ assets-common = { path = "../common", default-features = false } # Bridges pallet-xcm-bridge-hub-router = { path = "../../../../../bridges/modules/xcm-bridge-hub-router", default-features = false } bp-asset-hub-polkadot = { path = "../../../../../bridges/primitives/chain-asset-hub-polkadot", default-features = false } +bp-asset-hub-kusama = { path = "../../../../../bridges/primitives/chain-asset-hub-kusama", default-features = false } [dev-dependencies] hex-literal = "0.4.1" @@ -150,6 +151,7 @@ try-runtime = [ ] std = [ "assets-common/std", + "bp-asset-hub-kusama/std", "bp-asset-hub-polkadot/std", "codec/std", "cumulus-pallet-aura-ext/std", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs index 7d8039106eb8..a20d6571503b 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs @@ -603,7 +603,7 @@ pub mod bridging { pub BridgeHubPolkadot: MultiLocation = MultiLocation::new(1, X1(Parachain(BridgeHubPolkadotParaId::get()))); pub BridgeHubPolkadotWithBridgeHubKusamaInstance: MultiLocation = MultiLocation::new(1, X2(Parachain(BridgeHubPolkadotParaId::get()), PalletInstance(53))); pub const KusamaNetwork: NetworkId = NetworkId::Kusama; - pub AssetHubKusama: MultiLocation = MultiLocation::new(2, X2(GlobalConsensus(KusamaNetwork::get()), Parachain(1000))); + pub AssetHubKusama: MultiLocation = MultiLocation::new(2, X2(GlobalConsensus(KusamaNetwork::get()), Parachain(bp_asset_hub_kusama::ASSET_HUB_KUSAMA_PARACHAIN_ID))); pub KsmLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(KusamaNetwork::get()))); /// Router expects payment with this `AssetId`. 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 a7323ce42a8b..7edc7274cadc 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 @@ -50,7 +50,7 @@ parameter_types! { // see the `FEE_BOOST_PER_MESSAGE` constant to get the meaning of this value pub PriorityBoostPerMessage: u64 = 91_022_222_222_222; - pub AssetHubKusamaParaId: cumulus_primitives_core::ParaId = 1000.into(); + pub AssetHubKusamaParaId: cumulus_primitives_core::ParaId = bp_asset_hub_kusama::ASSET_HUB_KUSAMA_PARACHAIN_ID.into(); pub FromAssetHubKusamaToAssetHubPolkadotRoute: SenderAndLane = SenderAndLane::new( ParentThen(X1(Parachain(AssetHubKusamaParaId::get().into()))).into(), 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 2131032f5b70..dfbab5930d36 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 @@ -50,7 +50,7 @@ parameter_types! { // see the `FEE_BOOST_PER_MESSAGE` constant to get the meaning of this value pub PriorityBoostPerMessage: u64 = 4_551_111_111_111; - pub AssetHubPolkadotParaId: cumulus_primitives_core::ParaId = 1000.into(); + pub AssetHubPolkadotParaId: cumulus_primitives_core::ParaId = bp_asset_hub_polkadot::ASSET_HUB_POLKADOT_PARACHAIN_ID.into(); pub FromAssetHubPolkadotToAssetHubKusamaRoute: SenderAndLane = SenderAndLane::new( ParentThen(X1(Parachain(AssetHubPolkadotParaId::get().into()))).into(), From d42e481323bf912093bcad7c70e8bfcfa5642bd4 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Thu, 21 Sep 2023 16:08:00 +0200 Subject: [PATCH 12/17] Fix --- .../runtimes/assets/asset-hub-kusama/src/xcm_config.rs | 10 ++++------ .../assets/asset-hub-polkadot/src/xcm_config.rs | 10 ++++------ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs index ea5288525fe7..8dc78263ca44 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs @@ -737,12 +737,10 @@ pub mod bridging { // allow to transfer assets to AssetHubPolkadot ( AssetHubPolkadot::get(), - AssetFilter::ByMultiLocation( - LocationFilter::default() - // allow send only KSM - .add_equals(KsmLocation::get()) - // and nothing else - ) + LocationFilter::default() + // allow send only KSM + .add_equals(KsmLocation::get()) + // and nothing else ) ]; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs index a20d6571503b..1ebf8a8a37f2 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs @@ -649,12 +649,10 @@ pub mod bridging { // allow to transfer assets to AssetHubKusama ( AssetHubKusama::get(), - AssetFilter::ByMultiLocation( - LocationFilter::default() - // allow send only DOT - .add_equals(DotLocation::get()) - // and nothing else - ) + LocationFilter::default() + // allow send only DOT + .add_equals(DotLocation::get()) + // and nothing else ) ]; From 76ca00ba1b1fe6b2681fa7a10d54f6da05517475 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Thu, 21 Sep 2023 16:17:20 +0200 Subject: [PATCH 13/17] Fix --- .../runtimes/assets/asset-hub-kusama/src/xcm_config.rs | 2 +- .../runtimes/assets/asset-hub-polkadot/src/xcm_config.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs index 8dc78263ca44..fc5a27c7d96c 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs @@ -733,7 +733,7 @@ pub mod bridging { /// Allowed reserve transfer assets per destination. /// Means that runtime allows to transfer reserve assets to these locations. - pub AllowedReserveTransferAssetsLocations: sp_std::vec::Vec = sp_std::vec![ + pub AllowedReserveTransferAssetsLocations: sp_std::vec::Vec = sp_std::vec![ // allow to transfer assets to AssetHubPolkadot ( AssetHubPolkadot::get(), diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs index 1ebf8a8a37f2..bf6ae6387651 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs @@ -645,7 +645,7 @@ pub mod bridging { /// Allowed reserve transfer assets per destination. /// Means that runtime allows to transfer reserve assets to these locations. - pub AllowedReserveTransferAssetsLocations: sp_std::vec::Vec = sp_std::vec![ + pub AllowedReserveTransferAssetsLocations: sp_std::vec::Vec = sp_std::vec![ // allow to transfer assets to AssetHubKusama ( AssetHubKusama::get(), From 03511e0c80c1efa9e732867c23f4682e0da9bd52 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Fri, 22 Sep 2023 10:28:59 +0200 Subject: [PATCH 14/17] ensure_configuration -> prepare_configuration --- .../test-utils/src/test_cases_over_bridge.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs index a0ec6bb4f7d1..39a77d8cdea2 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs @@ -56,7 +56,7 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works< unwrap_xcmp_queue_event: Box< dyn Fn(Vec) -> Option>, >, - ensure_configuration: fn() -> TestBridgingConfig, + prepare_configuration: fn() -> TestBridgingConfig, weight_limit: WeightLimit, maybe_paid_export_message: Option, ) where @@ -108,7 +108,7 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works< local_bridge_hub_para_id, bridged_target_location: target_location_from_different_consensus, .. - } = ensure_configuration(); + } = prepare_configuration(); let reserve_account = LocationToAccountId::convert_location(&target_location_from_different_consensus) @@ -286,7 +286,7 @@ pub fn receive_reserve_asset_deposited_from_different_consensus_works< transfered_foreign_asset_id_amount, foreign_asset_id_minimum_balance, ): (MultiLocation, u128, u128), - ensure_configuration: fn() -> TestBridgingConfig, + prepare_configuration: fn() -> TestBridgingConfig, (bridge_instance, universal_origin, descend_origin): (Junctions, Junction, Junctions), /* bridge adds origin manipulation on the way */ ) where Runtime: frame_system::Config @@ -330,7 +330,7 @@ pub fn receive_reserve_asset_deposited_from_different_consensus_works< ); // prepare bridge config - let TestBridgingConfig { local_bridge_hub_location, .. } = ensure_configuration(); + let TestBridgingConfig { local_bridge_hub_location, .. } = prepare_configuration(); // drip 'ED' user target account let _ = >::deposit_creating( @@ -537,7 +537,7 @@ pub fn report_bridge_status_from_xcm_bridge_router_works< unwrap_xcmp_queue_event: Box< dyn Fn(Vec) -> Option>, >, - ensure_configuration: fn() -> TestBridgingConfig, + prepare_configuration: fn() -> TestBridgingConfig, weight_limit: WeightLimit, maybe_paid_export_message: Option, congested_message: fn() -> Xcm, @@ -591,14 +591,14 @@ pub fn report_bridge_status_from_xcm_bridge_router_works< alice_account, unwrap_pallet_xcm_event, unwrap_xcmp_queue_event, - ensure_configuration, + prepare_configuration, weight_limit, maybe_paid_export_message, ); let report_brigde_status = |is_congested: bool| { // prepare bridge config - let TestBridgingConfig { local_bridge_hub_location, .. } = ensure_configuration(); + let TestBridgingConfig { local_bridge_hub_location, .. } = prepare_configuration(); // Call received XCM execution let xcm = if is_congested { congested_message() } else { uncongested_message() }; From fc9727c43f4dede62a8b159666ed855b26f73e67 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Fri, 22 Sep 2023 13:36:03 +0200 Subject: [PATCH 15/17] Constants nit --- bridges/primitives/chain-bridge-hub-kusama/src/lib.rs | 3 +++ bridges/primitives/chain-bridge-hub-polkadot/src/lib.rs | 3 +++ .../runtimes/assets/asset-hub-kusama/src/xcm_config.rs | 8 +++++++- .../runtimes/assets/asset-hub-polkadot/src/xcm_config.rs | 8 +++++++- .../bridge-hub-kusama/src/bridge_hub_config.rs | 5 +++++ .../bridge-hub-polkadot/src/bridge_hub_config.rs | 5 +++++ 6 files changed, 30 insertions(+), 2 deletions(-) diff --git a/bridges/primitives/chain-bridge-hub-kusama/src/lib.rs b/bridges/primitives/chain-bridge-hub-kusama/src/lib.rs index 3a919648df47..80c233943fd8 100644 --- a/bridges/primitives/chain-bridge-hub-kusama/src/lib.rs +++ b/bridges/primitives/chain-bridge-hub-kusama/src/lib.rs @@ -78,5 +78,8 @@ pub const WITH_BRIDGE_HUB_KUSAMA_MESSAGES_PALLET_NAME: &str = "BridgeKusamaMessa /// chains. pub const WITH_BRIDGE_HUB_KUSAMA_RELAYERS_PALLET_NAME: &str = "BridgeRelayers"; +/// Pallet index of `BridgePolkadotMessages: pallet_bridge_messages::`. +pub const WITH_BRIDGE_POLKADOT_MESSAGES_PALLET_INDEX: u8 = 53; + decl_bridge_finality_runtime_apis!(bridge_hub_kusama); decl_bridge_messages_runtime_apis!(bridge_hub_kusama); diff --git a/bridges/primitives/chain-bridge-hub-polkadot/src/lib.rs b/bridges/primitives/chain-bridge-hub-polkadot/src/lib.rs index bf8d8e07c3a6..96d6cc7ea26b 100644 --- a/bridges/primitives/chain-bridge-hub-polkadot/src/lib.rs +++ b/bridges/primitives/chain-bridge-hub-polkadot/src/lib.rs @@ -69,5 +69,8 @@ pub const WITH_BRIDGE_HUB_POLKADOT_MESSAGES_PALLET_NAME: &str = "BridgePolkadotM /// chains. pub const WITH_BRIDGE_HUB_POLKADOT_RELAYERS_PALLET_NAME: &str = "BridgeRelayers"; +/// Pallet index of `BridgeKusamaMessages: pallet_bridge_messages::`. +pub const WITH_BRIDGE_KUSAMA_MESSAGES_PALLET_INDEX: u8 = 53; + decl_bridge_finality_runtime_apis!(bridge_hub_polkadot); decl_bridge_messages_runtime_apis!(bridge_hub_polkadot); diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs index fc5a27c7d96c..6ec716a4e453 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs @@ -689,7 +689,13 @@ pub mod bridging { parameter_types! { pub BridgeHubKusamaParaId: u32 = 1002; pub BridgeHubKusama: MultiLocation = MultiLocation::new(1, X1(Parachain(BridgeHubKusamaParaId::get()))); - pub BridgeHubKusamaWithBridgeHubPolkadotInstance: MultiLocation = MultiLocation::new(1, X2(Parachain(BridgeHubKusamaParaId::get()), PalletInstance(53))); + pub BridgeHubKusamaWithBridgeHubPolkadotInstance: MultiLocation = MultiLocation::new( + 1, + X2( + Parachain(BridgeHubKusamaParaId::get()), + PalletInstance(bp_bridge_hub_kusama::WITH_BRIDGE_POLKADOT_MESSAGES_PALLET_INDEX) + ) + ); pub const PolkadotNetwork: NetworkId = NetworkId::Polkadot; pub AssetHubPolkadot: MultiLocation = MultiLocation::new(2, X2(GlobalConsensus(PolkadotNetwork::get()), Parachain(bp_asset_hub_polkadot::ASSET_HUB_POLKADOT_PARACHAIN_ID))); pub DotLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(PolkadotNetwork::get()))); diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs index bf6ae6387651..c3610656e851 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs @@ -601,7 +601,13 @@ pub mod bridging { parameter_types! { pub BridgeHubPolkadotParaId: u32 = 1002; pub BridgeHubPolkadot: MultiLocation = MultiLocation::new(1, X1(Parachain(BridgeHubPolkadotParaId::get()))); - pub BridgeHubPolkadotWithBridgeHubKusamaInstance: MultiLocation = MultiLocation::new(1, X2(Parachain(BridgeHubPolkadotParaId::get()), PalletInstance(53))); + pub BridgeHubPolkadotWithBridgeHubKusamaInstance: MultiLocation = MultiLocation::new( + 1, + X2( + Parachain(BridgeHubPolkadotParaId::get()), + PalletInstance(bp_bridge_hub_polkadot::WITH_BRIDGE_KUSAMA_MESSAGES_PALLET_INDEX) + ) + ); pub const KusamaNetwork: NetworkId = NetworkId::Kusama; pub AssetHubKusama: MultiLocation = MultiLocation::new(2, X2(GlobalConsensus(KusamaNetwork::get()), Parachain(bp_asset_hub_kusama::ASSET_HUB_KUSAMA_PARACHAIN_ID))); pub KsmLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(KusamaNetwork::get()))); 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 7edc7274cadc..d0b999dc6732 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 @@ -261,5 +261,10 @@ mod tests { WithBridgeHubPolkadotMessagesInstance, PriorityBoostPerMessage, >(FEE_BOOST_PER_MESSAGE); + + assert_eq!( + BridgePolkadotMessagesPalletInstance::get(), + X1(PalletInstance(bp_bridge_hub_kusama::WITH_BRIDGE_POLKADOT_MESSAGES_PALLET_INDEX)) + ); } } 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 dfbab5930d36..bc9547e1601e 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 @@ -259,5 +259,10 @@ mod tests { WithBridgeHubKusamaMessagesInstance, PriorityBoostPerMessage, >(FEE_BOOST_PER_MESSAGE); + + assert_eq!( + BridgeKusamaMessagesPalletInstance::get(), + X1(PalletInstance(bp_bridge_hub_polkadot::WITH_BRIDGE_KUSAMA_MESSAGES_PALLET_INDEX)) + ); } } From 534c71849fe98083d5a82b8f60aa15716f7970a6 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Fri, 22 Sep 2023 13:44:34 +0200 Subject: [PATCH 16/17] Deps --- cumulus/parachains/runtimes/assets/asset-hub-kusama/Cargo.toml | 2 ++ .../parachains/runtimes/assets/asset-hub-polkadot/Cargo.toml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-kusama/Cargo.toml index 88e9a0c47a50..99bf7bc1733d 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/Cargo.toml @@ -83,6 +83,7 @@ assets-common = { path = "../common", default-features = false } pallet-xcm-bridge-hub-router = { path = "../../../../../bridges/modules/xcm-bridge-hub-router", default-features = false } bp-asset-hub-kusama = { path = "../../../../../bridges/primitives/chain-asset-hub-kusama", default-features = false } 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 } [dev-dependencies] asset-test-utils = { path = "../test-utils" } @@ -169,6 +170,7 @@ std = [ "assets-common/std", "bp-asset-hub-kusama/std", "bp-asset-hub-polkadot/std", + "bp-bridge-hub-kusama/std", "codec/std", "cumulus-pallet-aura-ext/std", "cumulus-pallet-dmp-queue/std", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/Cargo.toml index 9afbf2776326..2c94f4fe5574 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/Cargo.toml @@ -78,6 +78,7 @@ assets-common = { path = "../common", default-features = false } pallet-xcm-bridge-hub-router = { path = "../../../../../bridges/modules/xcm-bridge-hub-router", default-features = false } bp-asset-hub-polkadot = { path = "../../../../../bridges/primitives/chain-asset-hub-polkadot", default-features = false } bp-asset-hub-kusama = { path = "../../../../../bridges/primitives/chain-asset-hub-kusama", default-features = false } +bp-bridge-hub-polkadot = { path = "../../../../../bridges/primitives/chain-bridge-hub-polkadot", default-features = false } [dev-dependencies] hex-literal = "0.4.1" @@ -153,6 +154,7 @@ std = [ "assets-common/std", "bp-asset-hub-kusama/std", "bp-asset-hub-polkadot/std", + "bp-bridge-hub-polkadot/std", "codec/std", "cumulus-pallet-aura-ext/std", "cumulus-pallet-dmp-queue/std", From 58d63195f001551b29858c7ea940185c3c22ad5a Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Fri, 22 Sep 2023 14:13:41 +0200 Subject: [PATCH 17/17] Cargo.lock --- Cargo.lock | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index b0997dabc077..b1c4db58446c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -724,6 +724,7 @@ dependencies = [ "assets-common", "bp-asset-hub-kusama", "bp-asset-hub-polkadot", + "bp-bridge-hub-kusama", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", @@ -823,6 +824,7 @@ dependencies = [ "assets-common", "bp-asset-hub-kusama", "bp-asset-hub-polkadot", + "bp-bridge-hub-polkadot", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system",