diff --git a/bridges/snowbridge/primitives/router/src/inbound/mod.rs b/bridges/snowbridge/primitives/router/src/inbound/mod.rs index e03560f66e24..54a578b988a4 100644 --- a/bridges/snowbridge/primitives/router/src/inbound/mod.rs +++ b/bridges/snowbridge/primitives/router/src/inbound/mod.rs @@ -279,6 +279,7 @@ where // Call create_asset on foreign assets pallet. Transact { origin_kind: OriginKind::Xcm, + fallback_max_weight: None, call: ( create_call_index, asset_id, diff --git a/cumulus/parachains/integration-tests/emulated/common/src/xcm_helpers.rs b/cumulus/parachains/integration-tests/emulated/common/src/xcm_helpers.rs index 9125c976525e..380f4983ad98 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/xcm_helpers.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/xcm_helpers.rs @@ -31,7 +31,7 @@ pub fn xcm_transact_paid_execution( VersionedXcm::from(Xcm(vec![ WithdrawAsset(fees.clone().into()), BuyExecution { fees, weight_limit }, - Transact { origin_kind, call }, + Transact { origin_kind, call, fallback_max_weight: None }, RefundSurplus, DepositAsset { assets: All.into(), @@ -53,7 +53,7 @@ pub fn xcm_transact_unpaid_execution( VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit, check_origin }, - Transact { origin_kind, call }, + Transact { origin_kind, call, fallback_max_weight: None }, ])) } diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/transact.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/transact.rs index 3c53cfb261be..592c2845255c 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/transact.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/transact.rs @@ -43,7 +43,7 @@ fn transfer_and_transact_in_same_xcm( // xcm to be executed at dest let xcm_on_dest = Xcm(vec![ - Transact { origin_kind: OriginKind::Xcm, call }, + Transact { origin_kind: OriginKind::Xcm, call, fallback_max_weight: None }, ExpectTransactStatus(MaybeErrorCode::Success), // since this is the last hop, we don't need to further use any assets previously // reserved for fees (there are no further hops to cover transport fees for); we diff --git a/cumulus/parachains/pallets/ping/src/lib.rs b/cumulus/parachains/pallets/ping/src/lib.rs index 2cf32c891fc0..b6423a81db3c 100644 --- a/cumulus/parachains/pallets/ping/src/lib.rs +++ b/cumulus/parachains/pallets/ping/src/lib.rs @@ -114,6 +114,7 @@ pub mod pallet { }) .encode() .into(), + fallback_max_weight: None, }]), ) { Ok((hash, cost)) => { @@ -214,6 +215,7 @@ pub mod pallet { }) .encode() .into(), + fallback_max_weight: None, }]), ) { Ok((hash, cost)) => diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/xcm/mod.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/xcm/mod.rs index 025c39bcee07..74f564037400 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/xcm/mod.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/xcm/mod.rs @@ -84,7 +84,11 @@ impl XcmWeightInfo for AssetHubRococoXcmWeight { fn transfer_reserve_asset(assets: &Assets, _dest: &Location, _xcm: &Xcm<()>) -> Weight { assets.weigh_assets(XcmFungibleWeight::::transfer_reserve_asset()) } - fn transact(_origin_type: &OriginKind, _call: &DoubleEncoded) -> Weight { + fn transact( + _origin_type: &OriginKind, + _fallback_max_weight: &Option, + _call: &DoubleEncoded, + ) -> Weight { XcmGeneric::::transact() } fn hrmp_new_channel_open_request( diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/xcm/mod.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/xcm/mod.rs index 35ff2dc367c0..ff99f1242b22 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/xcm/mod.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/xcm/mod.rs @@ -83,7 +83,11 @@ impl XcmWeightInfo for AssetHubWestendXcmWeight { fn transfer_reserve_asset(assets: &Assets, _dest: &Location, _xcm: &Xcm<()>) -> Weight { assets.weigh_assets(XcmFungibleWeight::::transfer_reserve_asset()) } - fn transact(_origin_type: &OriginKind, _call: &DoubleEncoded) -> Weight { + fn transact( + _origin_type: &OriginKind, + _fallback_max_weight: &Option, + _call: &DoubleEncoded, + ) -> Weight { XcmGeneric::::transact() } fn hrmp_new_channel_open_request( 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 aeacc1a5471e..b1577e0ca7f6 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs @@ -1205,14 +1205,20 @@ pub fn create_and_manage_foreign_assets_for_local_consensus_parachain_assets_wor let xcm = Xcm(vec![ WithdrawAsset(buy_execution_fee.clone().into()), BuyExecution { fees: buy_execution_fee.clone(), weight_limit: Unlimited }, - Transact { origin_kind: OriginKind::Xcm, call: foreign_asset_create.into() }, + Transact { + origin_kind: OriginKind::Xcm, + call: foreign_asset_create.into(), + fallback_max_weight: None, + }, Transact { origin_kind: OriginKind::SovereignAccount, call: foreign_asset_set_metadata.into(), + fallback_max_weight: None, }, Transact { origin_kind: OriginKind::SovereignAccount, call: foreign_asset_set_team.into(), + fallback_max_weight: None, }, ExpectTransactStatus(MaybeErrorCode::Success), ]); @@ -1318,7 +1324,11 @@ pub fn create_and_manage_foreign_assets_for_local_consensus_parachain_assets_wor let xcm = Xcm(vec![ WithdrawAsset(buy_execution_fee.clone().into()), BuyExecution { fees: buy_execution_fee.clone(), weight_limit: Unlimited }, - Transact { origin_kind: OriginKind::Xcm, call: foreign_asset_create.into() }, + Transact { + origin_kind: OriginKind::Xcm, + call: foreign_asset_create.into(), + fallback_max_weight: None, + }, ExpectTransactStatus(MaybeErrorCode::from(DispatchError::BadOrigin.encode())), ]); diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/xcm/mod.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/xcm/mod.rs index 288aac38563c..e5c6f493d6dc 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/xcm/mod.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/xcm/mod.rs @@ -84,7 +84,11 @@ impl XcmWeightInfo for BridgeHubRococoXcmWeight { fn transfer_reserve_asset(assets: &Assets, _dest: &Location, _xcm: &Xcm<()>) -> Weight { assets.weigh_assets(XcmFungibleWeight::::transfer_reserve_asset()) } - fn transact(_origin_type: &OriginKind, _call: &DoubleEncoded) -> Weight { + fn transact( + _origin_type: &OriginKind, + _fallback_max_weight: &Option, + _call: &DoubleEncoded, + ) -> Weight { XcmGeneric::::transact() } fn hrmp_new_channel_open_request( diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/xcm/mod.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/xcm/mod.rs index fa1304d11c6f..939b1c7a287b 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/xcm/mod.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/xcm/mod.rs @@ -85,7 +85,11 @@ impl XcmWeightInfo for BridgeHubWestendXcmWeight { fn transfer_reserve_asset(assets: &Assets, _dest: &Location, _xcm: &Xcm<()>) -> Weight { assets.weigh_assets(XcmFungibleWeight::::transfer_reserve_asset()) } - fn transact(_origin_type: &OriginKind, _call: &DoubleEncoded) -> Weight { + fn transact( + _origin_type: &OriginKind, + _fallback_max_weight: &Option, + _call: &DoubleEncoded, + ) -> Weight { XcmGeneric::::transact() } fn hrmp_new_channel_open_request( diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/coretime.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/coretime.rs index d76ac443a147..35c3dd8836a8 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/coretime.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/coretime.rs @@ -135,6 +135,7 @@ impl CoretimeInterface for CoretimeAllocator { Instruction::Transact { origin_kind: OriginKind::Native, call: request_core_count_call.encode().into(), + fallback_max_weight: Some(Weight::from_parts(1_000_000_000, 200_000)), }, ]); @@ -164,6 +165,7 @@ impl CoretimeInterface for CoretimeAllocator { Instruction::Transact { origin_kind: OriginKind::Native, call: request_revenue_info_at_call.encode().into(), + fallback_max_weight: Some(Weight::from_parts(1_000_000_000, 200_000)), }, ]); @@ -192,6 +194,7 @@ impl CoretimeInterface for CoretimeAllocator { Instruction::Transact { origin_kind: OriginKind::Native, call: credit_account_call.encode().into(), + fallback_max_weight: Some(Weight::from_parts(1_000_000_000, 200_000)), }, ]); @@ -256,6 +259,7 @@ impl CoretimeInterface for CoretimeAllocator { Instruction::Transact { origin_kind: OriginKind::Native, call: assign_core_call.encode().into(), + fallback_max_weight: Some(Weight::from_parts(1_000_000_000, 200_000)), }, ]); diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/xcm/mod.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/xcm/mod.rs index f69736e31451..2c4a97601c64 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/xcm/mod.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/xcm/mod.rs @@ -84,7 +84,11 @@ impl XcmWeightInfo for CoretimeRococoXcmWeight { fn transfer_reserve_asset(assets: &Assets, _dest: &Location, _xcm: &Xcm<()>) -> Weight { assets.weigh_assets(XcmFungibleWeight::::transfer_reserve_asset()) } - fn transact(_origin_type: &OriginKind, _call: &DoubleEncoded) -> Weight { + fn transact( + _origin_type: &OriginKind, + _fallback_max_weight: &Option, + _call: &DoubleEncoded, + ) -> Weight { XcmGeneric::::transact() } fn hrmp_new_channel_open_request( diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/coretime.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/coretime.rs index f0c03849750a..985e64fb76f9 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/coretime.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/coretime.rs @@ -127,6 +127,12 @@ impl CoretimeInterface for CoretimeAllocator { use crate::coretime::CoretimeProviderCalls::RequestCoreCount; let request_core_count_call = RelayRuntimePallets::Coretime(RequestCoreCount(count)); + // Weight for `request_core_count` from westend benchmarks: + // `ref_time` = 7889000 + (3 * 25000000) + (1 * 100000000) = 182889000 + // `proof_size` = 1636 + // Add 5% to each component and round to 2 significant figures. + let call_weight = Weight::from_parts(190_000_000, 1700); + let message = Xcm(vec![ Instruction::UnpaidExecution { weight_limit: WeightLimit::Unlimited, @@ -135,6 +141,7 @@ impl CoretimeInterface for CoretimeAllocator { Instruction::Transact { origin_kind: OriginKind::Native, call: request_core_count_call.encode().into(), + fallback_max_weight: Some(call_weight), }, ]); @@ -164,6 +171,7 @@ impl CoretimeInterface for CoretimeAllocator { Instruction::Transact { origin_kind: OriginKind::Native, call: request_revenue_info_at_call.encode().into(), + fallback_max_weight: Some(Weight::from_parts(1_000_000_000, 200_000)), }, ]); @@ -192,6 +200,7 @@ impl CoretimeInterface for CoretimeAllocator { Instruction::Transact { origin_kind: OriginKind::Native, call: credit_account_call.encode().into(), + fallback_max_weight: Some(Weight::from_parts(1_000_000_000, 200_000)), }, ]); @@ -216,6 +225,12 @@ impl CoretimeInterface for CoretimeAllocator { ) { use crate::coretime::CoretimeProviderCalls::AssignCore; + // Weight for `assign_core` from westend benchmarks: + // `ref_time` = 10177115 + (1 * 25000000) + (2 * 100000000) + (57600 * 13932) = 937660315 + // `proof_size` = 3612 + // Add 5% to each component and round to 2 significant figures. + let call_weight = Weight::from_parts(980_000_000, 3800); + // The relay chain currently only allows `assign_core` to be called with a complete mask // and only ever with increasing `begin`. The assignments must be truncated to avoid // dropping that core's assignment completely. @@ -256,6 +271,7 @@ impl CoretimeInterface for CoretimeAllocator { Instruction::Transact { origin_kind: OriginKind::Native, call: assign_core_call.encode().into(), + fallback_max_weight: Some(call_weight), }, ]); diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/xcm/mod.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/xcm/mod.rs index 1640baa38c99..906088a1df86 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/xcm/mod.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/xcm/mod.rs @@ -83,7 +83,11 @@ impl XcmWeightInfo for CoretimeWestendXcmWeight { fn transfer_reserve_asset(assets: &Assets, _dest: &Location, _xcm: &Xcm<()>) -> Weight { assets.weigh_assets(XcmFungibleWeight::::transfer_reserve_asset()) } - fn transact(_origin_type: &OriginKind, _call: &DoubleEncoded) -> Weight { + fn transact( + _origin_type: &OriginKind, + _fallback_max_weight: &Option, + _call: &DoubleEncoded, + ) -> Weight { XcmGeneric::::transact() } fn hrmp_new_channel_open_request( diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/weights/xcm/mod.rs b/cumulus/parachains/runtimes/people/people-rococo/src/weights/xcm/mod.rs index 631cc7b7f0b0..47008a2943e5 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/weights/xcm/mod.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/weights/xcm/mod.rs @@ -83,7 +83,11 @@ impl XcmWeightInfo for PeopleRococoXcmWeight { fn transfer_reserve_asset(assets: &Assets, _dest: &Location, _xcm: &Xcm<()>) -> Weight { assets.weigh_assets(XcmFungibleWeight::::transfer_reserve_asset()) } - fn transact(_origin_type: &OriginKind, _call: &DoubleEncoded) -> Weight { + fn transact( + _origin_type: &OriginKind, + _fallback_max_weight: &Option, + _call: &DoubleEncoded, + ) -> Weight { XcmGeneric::::transact() } fn hrmp_new_channel_open_request( diff --git a/cumulus/parachains/runtimes/people/people-westend/src/weights/xcm/mod.rs b/cumulus/parachains/runtimes/people/people-westend/src/weights/xcm/mod.rs index 4b51a3ba411b..27fd499ebba7 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/weights/xcm/mod.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/weights/xcm/mod.rs @@ -83,7 +83,11 @@ impl XcmWeightInfo for PeopleWestendXcmWeight { fn transfer_reserve_asset(assets: &Assets, _dest: &Location, _xcm: &Xcm<()>) -> Weight { assets.weigh_assets(XcmFungibleWeight::::transfer_reserve_asset()) } - fn transact(_origin_type: &OriginKind, _call: &DoubleEncoded) -> Weight { + fn transact( + _origin_type: &OriginKind, + _fallback_max_weight: &Option, + _call: &DoubleEncoded, + ) -> Weight { XcmGeneric::::transact() } fn hrmp_new_channel_open_request( diff --git a/cumulus/parachains/runtimes/test-utils/src/lib.rs b/cumulus/parachains/runtimes/test-utils/src/lib.rs index 3f2e721d13f6..5c33809ba67b 100644 --- a/cumulus/parachains/runtimes/test-utils/src/lib.rs +++ b/cumulus/parachains/runtimes/test-utils/src/lib.rs @@ -445,7 +445,11 @@ impl< // prepare xcm as governance will do let xcm = Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, - Transact { origin_kind: OriginKind::Superuser, call: call.into() }, + Transact { + origin_kind: OriginKind::Superuser, + call: call.into(), + fallback_max_weight: None, + }, ExpectTransactStatus(MaybeErrorCode::Success), ]); @@ -476,7 +480,7 @@ impl< // prepare `Transact` xcm instructions.extend(vec![ - Transact { origin_kind, call: call.encode().into() }, + Transact { origin_kind, call: call.encode().into(), fallback_max_weight: None }, ExpectTransactStatus(MaybeErrorCode::Success), ]); let xcm = Xcm(instructions); diff --git a/polkadot/runtime/parachains/src/coretime/mod.rs b/polkadot/runtime/parachains/src/coretime/mod.rs index 966b7997a277..5656e92b90be 100644 --- a/polkadot/runtime/parachains/src/coretime/mod.rs +++ b/polkadot/runtime/parachains/src/coretime/mod.rs @@ -136,6 +136,11 @@ pub mod pallet { type AssetTransactor: TransactAsset; /// AccountId to Location converter type AccountToLocation: for<'a> TryConvert<&'a Self::AccountId, Location>; + + /// Maximum weight for any XCM transact call that should be executed on the coretime chain. + /// + /// Basically should be `max_weight(set_leases, reserve, notify_core_count)`. + type MaxXcmTransactWeight: Get; } #[pallet::event] @@ -333,6 +338,7 @@ impl OnNewSession> for Pallet { fn mk_coretime_call(call: crate::coretime::CoretimeCalls) -> Instruction<()> { Instruction::Transact { origin_kind: OriginKind::Superuser, + fallback_max_weight: Some(T::MaxXcmTransactWeight::get()), call: BrokerRuntimePallets::Broker(call).encode().into(), } } diff --git a/polkadot/runtime/parachains/src/mock.rs b/polkadot/runtime/parachains/src/mock.rs index d701e1f9bd80..ee1990a7b618 100644 --- a/polkadot/runtime/parachains/src/mock.rs +++ b/polkadot/runtime/parachains/src/mock.rs @@ -421,6 +421,7 @@ impl assigner_coretime::Config for Test {} parameter_types! { pub const BrokerId: u32 = 10u32; + pub MaxXcmTransactWeight: Weight = Weight::from_parts(10_000_000, 10_000); } pub struct BrokerPot; @@ -437,6 +438,7 @@ impl coretime::Config for Test { type BrokerId = BrokerId; type WeightInfo = crate::coretime::TestWeightInfo; type SendXcm = DummyXcmSender; + type MaxXcmTransactWeight = MaxXcmTransactWeight; type BrokerPotLocation = BrokerPot; type AssetTransactor = (); type AccountToLocation = (); diff --git a/polkadot/runtime/rococo/src/impls.rs b/polkadot/runtime/rococo/src/impls.rs index ab796edc54b1..7d7e9fa9f06c 100644 --- a/polkadot/runtime/rococo/src/impls.rs +++ b/polkadot/runtime/rococo/src/impls.rs @@ -21,7 +21,7 @@ use core::marker::PhantomData; use frame_support::pallet_prelude::DispatchResult; use frame_system::RawOrigin; use polkadot_primitives::Balance; -use polkadot_runtime_common::identity_migrator::OnReapIdentity; +use polkadot_runtime_common::identity_migrator::{OnReapIdentity, WeightInfo}; use rococo_runtime_constants::currency::*; use xcm::{latest::prelude::*, VersionedLocation, VersionedXcm}; use xcm_executor::traits::TransactAsset; @@ -88,7 +88,10 @@ where AccountId: Into<[u8; 32]> + Clone + Encode, { fn on_reap_identity(who: &AccountId, fields: u32, subs: u32) -> DispatchResult { - use crate::impls::IdentityMigratorCalls::PokeDeposit; + use crate::{ + impls::IdentityMigratorCalls::PokeDeposit, + weights::polkadot_runtime_common_identity_migrator::WeightInfo as MigratorWeights, + }; let total_to_send = Self::calculate_remote_deposit(fields, subs); @@ -141,6 +144,7 @@ where .into(); let poke = PeopleRuntimePallets::::IdentityMigrator(PokeDeposit(who.clone())); + let remote_weight_limit = MigratorWeights::::poke_deposit().saturating_mul(2); // Actual program to execute on People Chain. let program: Xcm<()> = Xcm(vec![ @@ -157,7 +161,11 @@ where .into(), }, // Poke the deposit to reserve the appropriate amount on the parachain. - Transact { origin_kind: OriginKind::Superuser, call: poke.encode().into() }, + Transact { + origin_kind: OriginKind::Superuser, + fallback_max_weight: Some(remote_weight_limit), + call: poke.encode().into(), + }, ]); // send diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index 5da9da86f02e..c832ace91c07 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -1100,6 +1100,7 @@ impl parachains_scheduler::Config for Runtime { parameter_types! { pub const BrokerId: u32 = BROKER_ID; pub const BrokerPalletId: PalletId = PalletId(*b"py/broke"); + pub MaxXcmTransactWeight: Weight = Weight::from_parts(200_000_000, 20_000); } pub struct BrokerPot; @@ -1123,6 +1124,7 @@ impl coretime::Config for Runtime { xcm_config::ThisNetwork, ::AccountId, >; + type MaxXcmTransactWeight = MaxXcmTransactWeight; } parameter_types! { diff --git a/polkadot/runtime/rococo/src/weights/xcm/mod.rs b/polkadot/runtime/rococo/src/weights/xcm/mod.rs index a28b46800874..16f51a778917 100644 --- a/polkadot/runtime/rococo/src/weights/xcm/mod.rs +++ b/polkadot/runtime/rococo/src/weights/xcm/mod.rs @@ -111,7 +111,11 @@ impl XcmWeightInfo for RococoXcmWeight { fn transfer_reserve_asset(assets: &Assets, _dest: &Location, _xcm: &Xcm<()>) -> Weight { assets.weigh_assets(XcmBalancesWeight::::transfer_reserve_asset()) } - fn transact(_origin_kind: &OriginKind, _call: &DoubleEncoded) -> Weight { + fn transact( + _origin_kind: &OriginKind, + _fallback_max_weight: &Option, + _call: &DoubleEncoded, + ) -> Weight { XcmGeneric::::transact() } fn hrmp_new_channel_open_request( diff --git a/polkadot/runtime/test-runtime/src/lib.rs b/polkadot/runtime/test-runtime/src/lib.rs index 69ce187dce40..d4031f7ac57a 100644 --- a/polkadot/runtime/test-runtime/src/lib.rs +++ b/polkadot/runtime/test-runtime/src/lib.rs @@ -584,6 +584,7 @@ impl parachains_paras::Config for Runtime { parameter_types! { pub const BrokerId: u32 = 10u32; + pub MaxXcmTransactWeight: Weight = Weight::from_parts(10_000_000, 10_000); } pub struct BrokerPot; @@ -657,6 +658,7 @@ impl coretime::Config for Runtime { type BrokerId = BrokerId; type WeightInfo = crate::coretime::TestWeightInfo; type SendXcm = DummyXcmSender; + type MaxXcmTransactWeight = MaxXcmTransactWeight; type BrokerPotLocation = BrokerPot; type AssetTransactor = (); type AccountToLocation = (); diff --git a/polkadot/runtime/westend/src/impls.rs b/polkadot/runtime/westend/src/impls.rs index d7281dad56d4..8cb597cbaa95 100644 --- a/polkadot/runtime/westend/src/impls.rs +++ b/polkadot/runtime/westend/src/impls.rs @@ -21,7 +21,7 @@ use core::marker::PhantomData; use frame_support::pallet_prelude::DispatchResult; use frame_system::RawOrigin; use polkadot_primitives::Balance; -use polkadot_runtime_common::identity_migrator::OnReapIdentity; +use polkadot_runtime_common::identity_migrator::{OnReapIdentity, WeightInfo}; use westend_runtime_constants::currency::*; use xcm::{latest::prelude::*, VersionedLocation, VersionedXcm}; use xcm_executor::traits::TransactAsset; @@ -88,7 +88,10 @@ where AccountId: Into<[u8; 32]> + Clone + Encode, { fn on_reap_identity(who: &AccountId, fields: u32, subs: u32) -> DispatchResult { - use crate::impls::IdentityMigratorCalls::PokeDeposit; + use crate::{ + impls::IdentityMigratorCalls::PokeDeposit, + weights::polkadot_runtime_common_identity_migrator::WeightInfo as MigratorWeights, + }; let total_to_send = Self::calculate_remote_deposit(fields, subs); @@ -141,6 +144,7 @@ where .into(); let poke = PeopleRuntimePallets::::IdentityMigrator(PokeDeposit(who.clone())); + let remote_weight_limit = MigratorWeights::::poke_deposit().saturating_mul(2); // Actual program to execute on People Chain. let program: Xcm<()> = Xcm(vec![ @@ -157,7 +161,11 @@ where .into(), }, // Poke the deposit to reserve the appropriate amount on the parachain. - Transact { origin_kind: OriginKind::Superuser, call: poke.encode().into() }, + Transact { + origin_kind: OriginKind::Superuser, + call: poke.encode().into(), + fallback_max_weight: Some(remote_weight_limit), + }, ]); // send diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index 9f0b701f20be..f25ed33012a2 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -1326,6 +1326,7 @@ impl parachains_scheduler::Config for Runtime { parameter_types! { pub const BrokerId: u32 = BROKER_ID; pub const BrokerPalletId: PalletId = PalletId(*b"py/broke"); + pub MaxXcmTransactWeight: Weight = Weight::from_parts(200_000_000, 20_000); } pub struct BrokerPot; @@ -1349,6 +1350,7 @@ impl coretime::Config for Runtime { xcm_config::ThisNetwork, ::AccountId, >; + type MaxXcmTransactWeight = MaxXcmTransactWeight; } parameter_types! { diff --git a/polkadot/runtime/westend/src/weights/xcm/mod.rs b/polkadot/runtime/westend/src/weights/xcm/mod.rs index 5be9bad824da..60265445334d 100644 --- a/polkadot/runtime/westend/src/weights/xcm/mod.rs +++ b/polkadot/runtime/westend/src/weights/xcm/mod.rs @@ -114,7 +114,11 @@ impl XcmWeightInfo for WestendXcmWeight { fn transfer_reserve_asset(assets: &Assets, _dest: &Location, _xcm: &Xcm<()>) -> Weight { assets.weigh_assets(XcmBalancesWeight::::transfer_reserve_asset()) } - fn transact(_origin_kind: &OriginKind, _call: &DoubleEncoded) -> Weight { + fn transact( + _origin_kind: &OriginKind, + _fallback_max_weight: &Option, + _call: &DoubleEncoded, + ) -> Weight { XcmGeneric::::transact() } fn hrmp_new_channel_open_request( diff --git a/polkadot/xcm/pallet-xcm-benchmarks/src/generic/benchmarking.rs b/polkadot/xcm/pallet-xcm-benchmarks/src/generic/benchmarking.rs index f4836b7cdde1..285322891c63 100644 --- a/polkadot/xcm/pallet-xcm-benchmarks/src/generic/benchmarking.rs +++ b/polkadot/xcm/pallet-xcm-benchmarks/src/generic/benchmarking.rs @@ -186,6 +186,7 @@ mod benchmarks { let instruction = Instruction::Transact { origin_kind: OriginKind::SovereignAccount, call: double_encoded_noop_call, + fallback_max_weight: None, }; let xcm = Xcm(vec![instruction]); #[block] diff --git a/polkadot/xcm/src/v4/mod.rs b/polkadot/xcm/src/v4/mod.rs index 9baf58eacfb0..3ae94b6ede88 100644 --- a/polkadot/xcm/src/v4/mod.rs +++ b/polkadot/xcm/src/v4/mod.rs @@ -1314,8 +1314,20 @@ impl TryFrom> for Instructi HrmpChannelAccepted { recipient } => Self::HrmpChannelAccepted { recipient }, HrmpChannelClosing { initiator, sender, recipient } => Self::HrmpChannelClosing { initiator, sender, recipient }, - Transact { origin_kind, mut call } => { - let require_weight_at_most = call.take_decoded()?.get_dispatch_info().call_weight; + Transact { origin_kind, mut call, fallback_max_weight } => { + // We first try to decode the call, if we can't, we use the fallback weight, + // if there's no fallback, we just return `Weight::MAX`. + let require_weight_at_most = match call.take_decoded() { + Ok(decoded) => decoded.get_dispatch_info().call_weight, + Err(error) => { + log::error!( + target: "xcm::versions::v5Tov4", + "Couldn't decode call in Transact: {:?}, using fallback weight.", + error, + ); + fallback_max_weight.unwrap_or(Weight::MAX) + }, + }; Self::Transact { origin_kind, require_weight_at_most, call: call.into() } }, ReportError(response_info) => Self::ReportError(QueryResponseInfo { diff --git a/polkadot/xcm/src/v5/mod.rs b/polkadot/xcm/src/v5/mod.rs index 830b23cc44b7..193b82b6c223 100644 --- a/polkadot/xcm/src/v5/mod.rs +++ b/polkadot/xcm/src/v5/mod.rs @@ -493,13 +493,21 @@ pub enum Instruction { /// /// - `origin_kind`: The means of expressing the message origin as a dispatch origin. /// - `call`: The encoded transaction to be applied. + /// - `fallback_max_weight`: Used for compatibility with previous versions. Corresponds to the + /// `require_weight_at_most` parameter in previous versions. If you don't care about + /// compatibility you can just put `None`. WARNING: If you do, your XCM might not work with + /// older versions. Make sure to dry-run and validate. /// /// Safety: No concerns. /// /// Kind: *Command*. /// /// Errors: - Transact { origin_kind: OriginKind, call: DoubleEncoded }, + Transact { + origin_kind: OriginKind, + fallback_max_weight: Option, + call: DoubleEncoded, + }, /// A message to notify about a new incoming HRMP channel. This message is meant to be sent by /// the relay-chain to a para. @@ -1159,7 +1167,8 @@ impl Instruction { HrmpChannelAccepted { recipient } => HrmpChannelAccepted { recipient }, HrmpChannelClosing { initiator, sender, recipient } => HrmpChannelClosing { initiator, sender, recipient }, - Transact { origin_kind, call } => Transact { origin_kind, call: call.into() }, + Transact { origin_kind, call, fallback_max_weight } => + Transact { origin_kind, call: call.into(), fallback_max_weight }, ReportError(response_info) => ReportError(response_info), DepositAsset { assets, beneficiary } => DepositAsset { assets, beneficiary }, DepositReserveAsset { assets, dest, xcm } => DepositReserveAsset { assets, dest, xcm }, @@ -1227,7 +1236,8 @@ impl> GetWeight for Instruction { TransferAsset { assets, beneficiary } => W::transfer_asset(assets, beneficiary), TransferReserveAsset { assets, dest, xcm } => W::transfer_reserve_asset(&assets, dest, xcm), - Transact { origin_kind, call } => W::transact(origin_kind, call), + Transact { origin_kind, fallback_max_weight, call } => + W::transact(origin_kind, fallback_max_weight, call), HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity } => W::hrmp_new_channel_open_request(sender, max_message_size, max_capacity), HrmpChannelAccepted { recipient } => W::hrmp_channel_accepted(recipient), @@ -1343,8 +1353,11 @@ impl TryFrom> for Instruction { HrmpChannelAccepted { recipient } => Self::HrmpChannelAccepted { recipient }, HrmpChannelClosing { initiator, sender, recipient } => Self::HrmpChannelClosing { initiator, sender, recipient }, - Transact { origin_kind, require_weight_at_most: _, call } => - Self::Transact { origin_kind, call: call.into() }, + Transact { origin_kind, require_weight_at_most, call } => Self::Transact { + origin_kind, + call: call.into(), + fallback_max_weight: Some(require_weight_at_most), + }, ReportError(response_info) => Self::ReportError(QueryResponseInfo { query_id: response_info.query_id, destination: response_info.destination.try_into().map_err(|_| ())?, @@ -1577,6 +1590,59 @@ mod tests { assert_eq!(new_xcm, xcm); } + #[test] + fn transact_roundtrip_works() { + // We can convert as long as there's a fallback. + let xcm = Xcm::<()>(vec![ + WithdrawAsset((Here, 1u128).into()), + Transact { + origin_kind: OriginKind::SovereignAccount, + call: vec![200, 200, 200].into(), + fallback_max_weight: Some(Weight::from_parts(1_000_000, 1_024)), + }, + ]); + let old_xcm = OldXcm::<()>(vec![ + OldInstruction::WithdrawAsset((OldHere, 1u128).into()), + OldInstruction::Transact { + origin_kind: OriginKind::SovereignAccount, + call: vec![200, 200, 200].into(), + require_weight_at_most: Weight::from_parts(1_000_000, 1_024), + }, + ]); + assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap()); + let new_xcm: Xcm<()> = old_xcm.try_into().unwrap(); + assert_eq!(new_xcm, xcm); + + // If we have no fallback the resulting message won't know the weight. + let xcm_without_fallback = Xcm::<()>(vec![ + WithdrawAsset((Here, 1u128).into()), + Transact { + origin_kind: OriginKind::SovereignAccount, + call: vec![200, 200, 200].into(), + fallback_max_weight: None, + }, + ]); + let old_xcm = OldXcm::<()>(vec![ + OldInstruction::WithdrawAsset((OldHere, 1u128).into()), + OldInstruction::Transact { + origin_kind: OriginKind::SovereignAccount, + call: vec![200, 200, 200].into(), + require_weight_at_most: Weight::MAX, + }, + ]); + assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm_without_fallback.clone()).unwrap()); + let new_xcm: Xcm<()> = old_xcm.try_into().unwrap(); + let xcm_with_max_weight_fallback = Xcm::<()>(vec![ + WithdrawAsset((Here, 1u128).into()), + Transact { + origin_kind: OriginKind::SovereignAccount, + call: vec![200, 200, 200].into(), + fallback_max_weight: Some(Weight::MAX), + }, + ]); + assert_eq!(new_xcm, xcm_with_max_weight_fallback); + } + #[test] fn decoding_respects_limit() { let max_xcm = Xcm::<()>(vec![ClearOrigin; MAX_INSTRUCTIONS_TO_DECODE as usize]); diff --git a/polkadot/xcm/src/v5/traits.rs b/polkadot/xcm/src/v5/traits.rs index dd067b774fcd..71b67e97d5fe 100644 --- a/polkadot/xcm/src/v5/traits.rs +++ b/polkadot/xcm/src/v5/traits.rs @@ -428,6 +428,7 @@ pub type SendResult = result::Result<(T, Assets), SendError>; /// let message = Xcm(vec![Instruction::Transact { /// origin_kind: OriginKind::Superuser, /// call: call.into(), +/// fallback_max_weight: None, /// }]); /// let message_hash = message.using_encoded(sp_io::hashing::blake2_256); /// diff --git a/polkadot/xcm/xcm-builder/src/tests/transacting.rs b/polkadot/xcm/xcm-builder/src/tests/transacting.rs index 8963e7147fdc..ba932beaeb3d 100644 --- a/polkadot/xcm/xcm-builder/src/tests/transacting.rs +++ b/polkadot/xcm/xcm-builder/src/tests/transacting.rs @@ -23,6 +23,7 @@ fn transacting_should_work() { let message = Xcm::(vec![Transact { origin_kind: OriginKind::Native, call: TestCall::Any(Weight::from_parts(50, 50), None).encode().into(), + fallback_max_weight: None, }]); let mut hash = fake_message_hash(&message); let weight_limit = Weight::from_parts(60, 60); @@ -43,6 +44,7 @@ fn transacting_should_respect_max_weight_requirement() { let message = Xcm::(vec![Transact { origin_kind: OriginKind::Native, call: TestCall::Any(Weight::from_parts(50, 50), None).encode().into(), + fallback_max_weight: None, }]); let mut hash = fake_message_hash(&message); let weight_limit = Weight::from_parts(60, 60); @@ -65,6 +67,7 @@ fn transacting_should_refund_weight() { call: TestCall::Any(Weight::from_parts(50, 50), Some(Weight::from_parts(30, 30))) .encode() .into(), + fallback_max_weight: None, }]); let mut hash = fake_message_hash(&message); let weight_limit = Weight::from_parts(60, 60); @@ -96,6 +99,7 @@ fn paid_transacting_should_refund_payment_for_unused_weight() { call: TestCall::Any(Weight::from_parts(50, 50), Some(Weight::from_parts(10, 10))) .encode() .into(), + fallback_max_weight: None, }, RefundSurplus, DepositAsset { assets: AllCounted(1).into(), beneficiary: one }, @@ -124,6 +128,7 @@ fn report_successful_transact_status_should_work() { Transact { origin_kind: OriginKind::Native, call: TestCall::Any(Weight::from_parts(50, 50), None).encode().into(), + fallback_max_weight: None, }, ReportTransactStatus(QueryResponseInfo { destination: Parent.into(), @@ -159,6 +164,7 @@ fn report_failed_transact_status_should_work() { Transact { origin_kind: OriginKind::Native, call: TestCall::OnlyRoot(Weight::from_parts(50, 50), None).encode().into(), + fallback_max_weight: None, }, ReportTransactStatus(QueryResponseInfo { destination: Parent.into(), @@ -194,6 +200,7 @@ fn expect_successful_transact_status_should_work() { Transact { origin_kind: OriginKind::Native, call: TestCall::Any(Weight::from_parts(50, 50), None).encode().into(), + fallback_max_weight: None, }, ExpectTransactStatus(MaybeErrorCode::Success), ]); @@ -212,6 +219,7 @@ fn expect_successful_transact_status_should_work() { Transact { origin_kind: OriginKind::Native, call: TestCall::OnlyRoot(Weight::from_parts(50, 50), None).encode().into(), + fallback_max_weight: None, }, ExpectTransactStatus(MaybeErrorCode::Success), ]); @@ -238,6 +246,7 @@ fn expect_failed_transact_status_should_work() { Transact { origin_kind: OriginKind::Native, call: TestCall::OnlyRoot(Weight::from_parts(50, 50), None).encode().into(), + fallback_max_weight: None, }, ExpectTransactStatus(vec![2].into()), ]); @@ -256,6 +265,7 @@ fn expect_failed_transact_status_should_work() { Transact { origin_kind: OriginKind::Native, call: TestCall::Any(Weight::from_parts(50, 50), None).encode().into(), + fallback_max_weight: None, }, ExpectTransactStatus(vec![2].into()), ]); @@ -282,6 +292,7 @@ fn clear_transact_status_should_work() { Transact { origin_kind: OriginKind::Native, call: TestCall::OnlyRoot(Weight::from_parts(50, 50), None).encode().into(), + fallback_max_weight: None, }, ClearTransactStatus, ReportTransactStatus(QueryResponseInfo { diff --git a/polkadot/xcm/xcm-executor/integration-tests/src/lib.rs b/polkadot/xcm/xcm-executor/integration-tests/src/lib.rs index 9b918fd7eeed..699a081e4f22 100644 --- a/polkadot/xcm/xcm-executor/integration-tests/src/lib.rs +++ b/polkadot/xcm/xcm-executor/integration-tests/src/lib.rs @@ -79,7 +79,11 @@ fn transact_recursion_limit_works() { Xcm(vec![ WithdrawAsset((Here, 1_000).into()), BuyExecution { fees: (Here, 1).into(), weight_limit: Unlimited }, - Transact { origin_kind: OriginKind::Native, call: call.encode().into() }, + Transact { + origin_kind: OriginKind::Native, + call: call.encode().into(), + fallback_max_weight: None, + }, ]) }; let mut call: Option = None; diff --git a/polkadot/xcm/xcm-executor/src/lib.rs b/polkadot/xcm/xcm-executor/src/lib.rs index 4e051f24050c..11fd4e04761f 100644 --- a/polkadot/xcm/xcm-executor/src/lib.rs +++ b/polkadot/xcm/xcm-executor/src/lib.rs @@ -939,7 +939,8 @@ impl XcmExecutor { Ok(()) }) }, - Transact { origin_kind, mut call } => { + // `fallback_max_weight` is not used in the executor, it's only for conversions. + Transact { origin_kind, mut call, .. } => { // We assume that the Relay-chain is allowed to use transact on this parachain. let origin = self.cloned_origin().ok_or_else(|| { tracing::trace!( diff --git a/polkadot/xcm/xcm-simulator/example/src/tests.rs b/polkadot/xcm/xcm-simulator/example/src/tests.rs index bbac44ed8a1f..f971812f4f4d 100644 --- a/polkadot/xcm/xcm-simulator/example/src/tests.rs +++ b/polkadot/xcm/xcm-simulator/example/src/tests.rs @@ -47,6 +47,7 @@ fn dmp() { Xcm(vec![Transact { origin_kind: OriginKind::SovereignAccount, call: remark.encode().into(), + fallback_max_weight: None, }]), )); }); @@ -74,6 +75,7 @@ fn ump() { Xcm(vec![Transact { origin_kind: OriginKind::SovereignAccount, call: remark.encode().into(), + fallback_max_weight: None, }]), )); }); @@ -101,6 +103,7 @@ fn xcmp() { Xcm(vec![Transact { origin_kind: OriginKind::SovereignAccount, call: remark.encode().into(), + fallback_max_weight: None, }]), )); }); @@ -388,6 +391,7 @@ fn reserve_asset_class_create_and_reserve_transfer() { ) .encode() .into(), + fallback_max_weight: None, }]); // Send creation. assert_ok!(RelayChainPalletXcm::send_xcm(Here, Parachain(1), message)); diff --git a/prdoc/pr_6643.prdoc b/prdoc/pr_6643.prdoc new file mode 100644 index 000000000000..c111f6356519 --- /dev/null +++ b/prdoc/pr_6643.prdoc @@ -0,0 +1,47 @@ +title: Added fallback_max_weight to Transact for sending messages to V4 chains +doc: +- audience: Runtime Dev + description: |- + Removing the `require_weight_at_most` parameter in V5 Transact introduced a problem when converting a message from V5 to V4 to send to chains that didn't upgrade yet. + The local chain doesn't know how to decode calls for remote chains so it can't automatically populate `require_weight_at_most` required by V4 Transact. + To fix this, XCM v5 Transact now also takes a `fallback_max_weight: Option` parameter. + This can be set to `None` if the instruction is not meant to be sent to chains running XCM versions lower than V5. + If set to `Some(weight)`, a subsequent conversion to V4 will result in `Transact { require_weight_at_most: weight, .. }`. + The plan is to remove this workaround in V6 since there will be a good conversion path from V6 to V5. +crates: +- name: snowbridge-router-primitives + bump: major +- name: emulated-integration-tests-common + bump: major +- name: asset-hub-rococo-runtime + bump: major +- name: asset-hub-westend-runtime + bump: major +- name: asset-test-utils + bump: major +- name: bridge-hub-rococo-runtime + bump: major +- name: bridge-hub-westend-runtime + bump: major +- name: coretime-rococo-runtime + bump: major +- name: coretime-westend-runtime + bump: major +- name: people-rococo-runtime + bump: major +- name: people-westend-runtime + bump: major +- name: parachains-runtimes-test-utils + bump: major +- name: polkadot-runtime-parachains + bump: major +- name: rococo-runtime + bump: major +- name: westend-runtime + bump: major +- name: staging-xcm + bump: major +- name: staging-xcm-builder + bump: major +- name: staging-xcm-executor + bump: major