From d9fb228f9dc97fa09b6599cc7272c66a144f3204 Mon Sep 17 00:00:00 2001 From: Francisco Aguirre Date: Thu, 5 Dec 2024 17:27:39 +0100 Subject: [PATCH] Added fallback_max_weight to Transact for sending messages to V4 chains (#6643) Closes: https://github.com/paritytech/polkadot-sdk/issues/6585 Removing the `require_weight_at_most` parameter in V5 Transact had only one problem. Converting a message from V5 to V4 to send to chains that didn't upgrade yet. The conversion would not know what weight to give to the Transact, since V4 and below require it. To fix this, I added back the weight in the form of an `Option` called `fallback_max_weight`. This can be set to `None` if you don't intend to deal with a chain that hasn't upgraded yet. If you set it to `Some(_)`, the behaviour is the same. The plan is to totally remove this in V6 since there will be a good conversion path from V6 to V5. --------- Co-authored-by: GitHub Action Co-authored-by: Adrian Catangiu --- .../pallets/inbound-queue/src/test.rs | 4 +- .../primitives/router/src/inbound/mod.rs | 1 + .../emulated/common/src/xcm_helpers.rs | 4 +- .../asset-hub-westend/src/tests/transact.rs | 2 +- .../bridge-hub-rococo/src/tests/snowbridge.rs | 18 ++++- .../bridge-hub-westend/src/tests/transact.rs | 2 +- .../src/tests/fellowship.rs | 1 + .../people-westend/src/tests/governance.rs | 43 +++++++++-- cumulus/parachains/pallets/ping/src/lib.rs | 2 + .../asset-hub-rococo/src/weights/xcm/mod.rs | 6 +- .../asset-hub-westend/src/weights/xcm/mod.rs | 6 +- .../assets/test-utils/src/test_cases.rs | 14 +++- .../bridge-hub-rococo/src/weights/xcm/mod.rs | 6 +- .../bridge-hub-westend/src/weights/xcm/mod.rs | 6 +- .../coretime/coretime-rococo/src/coretime.rs | 4 + .../coretime-rococo/src/weights/xcm/mod.rs | 6 +- .../coretime/coretime-westend/src/coretime.rs | 16 ++++ .../coretime-westend/src/weights/xcm/mod.rs | 6 +- .../people-rococo/src/weights/xcm/mod.rs | 6 +- .../people-westend/src/weights/xcm/mod.rs | 6 +- .../parachains/runtimes/test-utils/src/lib.rs | 8 +- .../runtime/parachains/src/coretime/mod.rs | 6 ++ polkadot/runtime/parachains/src/mock.rs | 2 + polkadot/runtime/rococo/src/impls.rs | 14 +++- polkadot/runtime/rococo/src/lib.rs | 2 + .../runtime/rococo/src/weights/xcm/mod.rs | 6 +- polkadot/runtime/test-runtime/src/lib.rs | 2 + polkadot/runtime/westend/src/impls.rs | 14 +++- polkadot/runtime/westend/src/lib.rs | 2 + .../runtime/westend/src/weights/xcm/mod.rs | 6 +- .../src/generic/benchmarking.rs | 1 + polkadot/xcm/src/v4/mod.rs | 16 +++- polkadot/xcm/src/v5/mod.rs | 76 +++++++++++++++++-- polkadot/xcm/src/v5/traits.rs | 1 + .../xcm/xcm-builder/src/tests/transacting.rs | 11 +++ .../xcm-executor/integration-tests/src/lib.rs | 6 +- polkadot/xcm/xcm-executor/src/lib.rs | 3 +- .../xcm/xcm-simulator/example/src/tests.rs | 4 + prdoc/pr_6643.prdoc | 47 ++++++++++++ 39 files changed, 341 insertions(+), 45 deletions(-) create mode 100644 prdoc/pr_6643.prdoc diff --git a/bridges/snowbridge/pallets/inbound-queue/src/test.rs b/bridges/snowbridge/pallets/inbound-queue/src/test.rs index 76d0b98e9eb46..5386b845f2ec1 100644 --- a/bridges/snowbridge/pallets/inbound-queue/src/test.rs +++ b/bridges/snowbridge/pallets/inbound-queue/src/test.rs @@ -40,8 +40,8 @@ fn test_submit_happy_path() { .into(), nonce: 1, message_id: [ - 11, 25, 133, 51, 23, 68, 111, 211, 132, 94, 254, 17, 194, 252, 198, 233, 10, 193, - 156, 93, 72, 140, 65, 69, 79, 155, 154, 28, 141, 166, 171, 255, + 97, 161, 116, 204, 182, 115, 192, 144, 130, 243, 240, 193, 122, 154, 108, 91, 247, + 41, 226, 237, 202, 158, 238, 239, 210, 8, 147, 131, 84, 146, 171, 176, ], fee_burned: 110000000000, } diff --git a/bridges/snowbridge/primitives/router/src/inbound/mod.rs b/bridges/snowbridge/primitives/router/src/inbound/mod.rs index e03560f66e244..54a578b988a45 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 9125c976525ee..380f4983ad987 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 3c53cfb261be4..592c2845255c9 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/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs index d59553574c26a..c72d5045ddc07 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs @@ -84,7 +84,11 @@ fn create_agent() { let remote_xcm = VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, DescendOrigin(Parachain(origin_para).into()), - Transact { origin_kind: OriginKind::Xcm, call: create_agent_call.encode().into() }, + Transact { + origin_kind: OriginKind::Xcm, + call: create_agent_call.encode().into(), + fallback_max_weight: None, + }, ])); // Rococo Global Consensus @@ -138,7 +142,11 @@ fn create_channel() { let create_agent_xcm = VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, DescendOrigin(Parachain(origin_para).into()), - Transact { origin_kind: OriginKind::Xcm, call: create_agent_call.encode().into() }, + Transact { + origin_kind: OriginKind::Xcm, + call: create_agent_call.encode().into(), + fallback_max_weight: None, + }, ])); let create_channel_call = @@ -147,7 +155,11 @@ fn create_channel() { let create_channel_xcm = VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, DescendOrigin(Parachain(origin_para).into()), - Transact { origin_kind: OriginKind::Xcm, call: create_channel_call.encode().into() }, + Transact { + origin_kind: OriginKind::Xcm, + call: create_channel_call.encode().into(), + fallback_max_weight: None, + }, ])); // Rococo Global Consensus diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/transact.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/transact.rs index db42704dae614..7831c8d663577 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/transact.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/transact.rs @@ -49,7 +49,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/integration-tests/emulated/tests/collectives/collectives-westend/src/tests/fellowship.rs b/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/tests/fellowship.rs index 80b82e0c446f7..802fed1e681da 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/tests/fellowship.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/collectives/collectives-westend/src/tests/fellowship.rs @@ -41,6 +41,7 @@ fn fellows_whitelist_call() { ) .encode() .into(), + fallback_max_weight: None } ]))), }); diff --git a/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/governance.rs b/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/governance.rs index 3dadcdd948705..1ba787aaec528 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/governance.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/governance.rs @@ -48,7 +48,11 @@ fn relay_commands_add_registrar() { dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))), message: bx!(VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, - Transact { origin_kind, call: add_registrar_call.encode().into() } + Transact { + origin_kind, + call: add_registrar_call.encode().into(), + fallback_max_weight: None + } ]))), }); @@ -107,7 +111,11 @@ fn relay_commands_add_registrar_wrong_origin() { dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))), message: bx!(VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, - Transact { origin_kind, call: add_registrar_call.encode().into() } + Transact { + origin_kind, + call: add_registrar_call.encode().into(), + fallback_max_weight: None + } ]))), }); @@ -194,7 +202,11 @@ fn relay_commands_kill_identity() { dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))), message: bx!(VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, - Transact { origin_kind, call: kill_identity_call.encode().into() } + Transact { + origin_kind, + call: kill_identity_call.encode().into(), + fallback_max_weight: None + } ]))), }); @@ -252,7 +264,11 @@ fn relay_commands_kill_identity_wrong_origin() { dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))), message: bx!(VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, - Transact { origin_kind, call: kill_identity_call.encode().into() } + Transact { + origin_kind, + call: kill_identity_call.encode().into(), + fallback_max_weight: None + } ]))), }); @@ -298,7 +314,11 @@ fn relay_commands_add_remove_username_authority() { dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))), message: bx!(VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, - Transact { origin_kind, call: add_username_authority.encode().into() } + Transact { + origin_kind, + call: add_username_authority.encode().into(), + fallback_max_weight: None + } ]))), }); @@ -383,7 +403,11 @@ fn relay_commands_add_remove_username_authority() { dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))), message: bx!(VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, - Transact { origin_kind, call: remove_username_authority.encode().into() } + Transact { + origin_kind, + call: remove_username_authority.encode().into(), + fallback_max_weight: None + } ]))), }); @@ -443,7 +467,11 @@ fn relay_commands_add_remove_username_authority_wrong_origin() { dest: bx!(VersionedLocation::from(Location::new(0, [Parachain(1004)]))), message: bx!(VersionedXcm::from(Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, - Transact { origin_kind, call: add_username_authority.encode().into() } + Transact { + origin_kind, + call: add_username_authority.encode().into(), + fallback_max_weight: None + } ]))), }); @@ -483,6 +511,7 @@ fn relay_commands_add_remove_username_authority_wrong_origin() { Transact { origin_kind: OriginKind::SovereignAccount, call: remove_username_authority.encode().into(), + fallback_max_weight: None, } ]))), }); diff --git a/cumulus/parachains/pallets/ping/src/lib.rs b/cumulus/parachains/pallets/ping/src/lib.rs index 2cf32c891fc0b..b6423a81db3c9 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 025c39bcee078..74f5640374009 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 35ff2dc367c0d..ff99f1242b229 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 aeacc1a5471e4..b1577e0ca7f68 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 288aac38563c4..e5c6f493d6dcf 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 fa1304d11c6f1..939b1c7a287b7 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 d76ac443a147d..35c3dd8836a80 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 f69736e314514..2c4a97601c644 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 f0c03849750ad..985e64fb76f9a 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 1640baa38c995..906088a1df86f 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 631cc7b7f0b02..47008a2943e56 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 4b51a3ba411b0..27fd499ebba72 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 3f2e721d13f62..5c33809ba67b1 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 966b7997a2775..5656e92b90be0 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 d701e1f9bd80f..ee1990a7b618a 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 ab796edc54b1a..7d7e9fa9f06c5 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 5da9da86f02e0..c832ace91c078 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 a28b468008742..16f51a778917c 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 69ce187dce409..d4031f7ac57ae 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 d7281dad56d4c..8cb597cbaa95e 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 9f0b701f20bef..f25ed33012a22 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 5be9bad824da3..60265445334d3 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 f4836b7cdde1a..285322891c63a 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 9baf58eacfb03..3ae94b6ede884 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 830b23cc44b76..193b82b6c223e 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 dd067b774fcd3..71b67e97d5fec 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 8963e7147fdc0..ba932beaeb3d9 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 9b918fd7eeed9..699a081e4f224 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 4e051f24050c7..11fd4e04761f0 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 bbac44ed8a1f1..f971812f4f4d6 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 0000000000000..c111f6356519e --- /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