diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e8a91568ccfc..53f723dd6c73 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -21,7 +21,7 @@ workflow: - if: $CI_COMMIT_BRANCH variables: - CI_IMAGE: !reference [.ci-unified, variables, CI_IMAGE] + CI_IMAGE: "docker.io/paritytech/ci-unified:bullseye-1.74.0-2023-11-01-v20231204" # BUILDAH_IMAGE is defined in group variables BUILDAH_COMMAND: "buildah --storage-driver overlay2" RELENG_SCRIPTS_BRANCH: "master" diff --git a/Cargo.lock b/Cargo.lock index f3cb5e7fca63..27a24cb12245 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -724,6 +724,7 @@ dependencies = [ "assert_matches", "asset-hub-rococo-runtime", "asset-test-utils", + "cumulus-pallet-parachain-system", "emulated-integration-tests-common", "frame-support", "pallet-asset-conversion", @@ -17510,7 +17511,7 @@ dependencies = [ [[package]] name = "sp-runtime" -version = "30.0.0" +version = "30.0.1" dependencies = [ "docify", "either", diff --git a/cumulus/pallets/xcmp-queue/src/mock.rs b/cumulus/pallets/xcmp-queue/src/mock.rs index 755b685d5b80..23d5af8e23fa 100644 --- a/cumulus/pallets/xcmp-queue/src/mock.rs +++ b/cumulus/pallets/xcmp-queue/src/mock.rs @@ -30,7 +30,7 @@ use sp_runtime::{ BuildStorage, }; use xcm::prelude::*; -use xcm_builder::{CurrencyAdapter, FixedWeightBounds, IsConcrete, NativeAsset, ParentIsPreset}; +use xcm_builder::{CurrencyAdapter, FixedWeightBounds, FrameTransactionalProcessor, IsConcrete, NativeAsset, ParentIsPreset}; use xcm_executor::traits::ConvertOrigin; type Block = frame_system::mocking::MockBlock; @@ -172,6 +172,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } pub type XcmRouter = ( diff --git a/cumulus/parachain-template/runtime/src/xcm_config.rs b/cumulus/parachain-template/runtime/src/xcm_config.rs index 752137c96f18..3816e3b02097 100644 --- a/cumulus/parachain-template/runtime/src/xcm_config.rs +++ b/cumulus/parachain-template/runtime/src/xcm_config.rs @@ -15,7 +15,7 @@ use xcm::latest::prelude::*; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowTopLevelPaidExecutionFrom, CurrencyAdapter, DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, - FixedWeightBounds, IsConcrete, NativeAsset, ParentIsPreset, RelayChainAsNative, + FixedWeightBounds, FrameTransactionalProcessor, IsConcrete, NativeAsset, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, WithComputedOrigin, WithUniqueTopic, @@ -136,6 +136,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } /// No local origins on this chain are allowed to dispatch XCM sends/executions. diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml index effa3dffe453..09fcc3719941 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/Cargo.toml @@ -24,8 +24,11 @@ xcm = { package = "staging-xcm", path = "../../../../../../../polkadot/xcm", def pallet-xcm = { path = "../../../../../../../polkadot/xcm/pallet-xcm", default-features = false, version = "6.0.0" } xcm-executor = { package = "staging-xcm-executor", path = "../../../../../../../polkadot/xcm/xcm-executor", default-features = false, version = "6.0.0" } rococo-runtime = { version = "6.0.0", path = "../../../../../../../polkadot/runtime/rococo" } + +# Cumulus asset-test-utils = { version = "6.0.0", path = "../../../../../runtimes/assets/test-utils" } -parachains-common = { version = "6.0.0", path = "../../../../../common" } +parachains-common = { version = "6.0.0", path = "../../../../../../parachains/common" } +cumulus-pallet-parachain-system = { path = "../../../../../../pallets/parachain-system", default-features = false } asset-hub-rococo-runtime = { version = "0.11.0", path = "../../../../../runtimes/assets/asset-hub-rococo" } emulated-integration-tests-common = { path = "../../../common", default-features = false, version = "2.0.0" } rococo-system-emulated-network = { version = "0.1.0", path = "../../../networks/rococo-system" } diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/lib.rs index 3ff8c37c6465..9aaddaf9969a 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/lib.rs @@ -51,8 +51,8 @@ pub use rococo_system_emulated_network::{ AssetHubRococoParaSender as AssetHubRococoSender, BridgeHubRococoPara as BridgeHubRococo, BridgeHubRococoParaReceiver as BridgeHubRococoReceiver, PenpalAPara as PenpalA, PenpalAParaReceiver as PenpalAReceiver, PenpalAParaSender as PenpalASender, - RococoRelay as Rococo, RococoRelayReceiver as RococoReceiver, - RococoRelaySender as RococoSender, + PenpalBPara as PenpalB, PenpalBParaReceiver as PenpalBReceiver, RococoRelay as Rococo, + RococoRelayReceiver as RococoReceiver, RococoRelaySender as RococoSender, }; pub const ASSET_ID: u32 = 1; @@ -65,6 +65,7 @@ pub type RelayToParaTest = Test; pub type SystemParaToRelayTest = Test; pub type SystemParaToParaTest = Test; pub type ParaToSystemParaTest = Test; +pub type ParaToParaTest = Test; /// Returns a `TestArgs` instance to be used for the Relay Chain across integration tests pub fn relay_test_args( diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reserve_transfer.rs index e6142e29b7c8..534d46c64940 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-rococo/src/tests/reserve_transfer.rs @@ -152,6 +152,69 @@ fn system_para_to_para_assets_receiver_assertions(_: Test) { ); } +fn para_to_para_sender_assertions(t: ParaToParaTest) { + type RuntimeEvent = ::RuntimeEvent; + PenpalA::assert_xcm_pallet_attempted_complete(None); + assert_expected_events!( + PenpalA, + vec![ + // Amount to reserve transfer is transferred to Parachain's Sovereign account + RuntimeEvent::Balances( + pallet_balances::Event::Withdraw { who, amount } + ) => { + who: *who == t.sender.account_id, + amount: *amount == t.args.amount, + }, + // XCM sent to relay reserve + RuntimeEvent::ParachainSystem( + cumulus_pallet_parachain_system::Event::UpwardMessageSent { .. } + ) => {}, + ] + ); +} + +fn para_to_para_relay_hop_assertions(t: ParaToParaTest) { + type RuntimeEvent = ::RuntimeEvent; + let sov_penpal_a_on_rococo = + Rococo::sovereign_account_id_of(Rococo::child_location_of(PenpalA::para_id())); + let sov_penpal_b_on_rococo = + Rococo::sovereign_account_id_of(Rococo::child_location_of(PenpalB::para_id())); + assert_expected_events!( + Rococo, + vec![ + // Withdrawn from sender parachain SA + RuntimeEvent::Balances( + pallet_balances::Event::Withdraw { who, amount } + ) => { + who: *who == sov_penpal_a_on_rococo, + amount: *amount == t.args.amount, + }, + // Deposited to receiver parachain SA + RuntimeEvent::Balances( + pallet_balances::Event::Deposit { who, .. } + ) => { + who: *who == sov_penpal_b_on_rococo, + }, + RuntimeEvent::MessageQueue( + pallet_message_queue::Event::Processed { success: true, .. } + ) => {}, + ] + ); +} + +fn para_to_para_receiver_assertions(_: ParaToParaTest) { + type RuntimeEvent = ::RuntimeEvent; + assert_expected_events!( + PenpalB, + vec![ + RuntimeEvent::Balances(pallet_balances::Event::Deposit { .. }) => {}, + RuntimeEvent::MessageQueue( + pallet_message_queue::Event::Processed { success: true, .. } + ) => {}, + ] + ); +} + fn relay_to_para_reserve_transfer_assets(t: RelayToParaTest) -> DispatchResult { ::XcmPallet::limited_reserve_transfer_assets( t.signed_origin, @@ -185,6 +248,17 @@ fn para_to_system_para_reserve_transfer_assets(t: ParaToSystemParaTest) -> Dispa ) } +fn para_to_para_limited_reserve_transfer_assets(t: ParaToParaTest) -> DispatchResult { + ::PolkadotXcm::limited_reserve_transfer_assets( + t.signed_origin, + bx!(t.args.dest.into()), + bx!(t.args.beneficiary.into()), + bx!(t.args.assets.into()), + t.args.fee_asset_item, + t.args.weight_limit, + ) +} + /// Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't work #[test] fn reserve_transfer_native_asset_from_relay_to_system_para_fails() { @@ -493,3 +567,51 @@ fn reserve_transfer_assets_from_system_para_to_para() { // Receiver's balance is increased by exact amount assert_eq!(receiver_assets_after, receiver_assets_before + asset_amount_to_send); } + +/// Reserve Transfers of native asset from Parachain to Parachain (through Relay reserve) should +/// work +#[test] +fn reserve_transfer_native_asset_from_para_to_para() { + // Init values for Penpal Parachain + let destination = PenpalA::sibling_location_of(PenpalB::para_id()); + let beneficiary_id = PenpalBReceiver::get(); + let amount_to_send: Balance = ASSET_HUB_ROCOCO_ED * 10000; + let assets = (Parent, amount_to_send).into(); + + let test_args = TestContext { + sender: PenpalASender::get(), + receiver: PenpalBReceiver::get(), + args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None, 0), + }; + + let mut test = ParaToParaTest::new(test_args); + + let sender_balance_before = test.sender.balance; + let receiver_balance_before = test.receiver.balance; + + let sender_as_seen_by_relay = Rococo::child_location_of(PenpalA::para_id()); + let sov_of_sender_on_relay = Rococo::sovereign_account_id_of(sender_as_seen_by_relay); + + // fund the PenpalA's SA on Rococo with the native tokens held in reserve + Rococo::fund_accounts(vec![(sov_of_sender_on_relay.into(), amount_to_send * 2)]); + + test.set_assertion::(para_to_para_sender_assertions); + test.set_assertion::(para_to_para_relay_hop_assertions); + test.set_assertion::(para_to_para_receiver_assertions); + test.set_dispatchable::(para_to_para_limited_reserve_transfer_assets); + test.assert(); + + let sender_balance_after = test.sender.balance; + let receiver_balance_after = test.receiver.balance; + + let delivery_fees = PenpalA::execute_with(|| { + xcm_helpers::transfer_assets_delivery_fees::< + ::XcmSender, + >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) + }); + + // Sender's balance is reduced + assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); + // Receiver's balance is increased + assert!(receiver_balance_after > receiver_balance_before); +} diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs index e2c03d2f8f0d..75ae9f7a302f 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/lib.rs @@ -51,7 +51,9 @@ pub use westend_system_emulated_network::{ westend_emulated_chain::{genesis::ED as WESTEND_ED, WestendRelayPallet as WestendPallet}, AssetHubWestendPara as AssetHubWestend, AssetHubWestendParaReceiver as AssetHubWestendReceiver, AssetHubWestendParaSender as AssetHubWestendSender, BridgeHubWestendPara as BridgeHubWestend, - BridgeHubWestendParaReceiver as BridgeHubWestendReceiver, PenpalBPara as PenpalB, + BridgeHubWestendParaReceiver as BridgeHubWestendReceiver, + PenpalAPara as PenpalA, + PenpalAParaReceiver as PenpalAReceiver, PenpalBPara as PenpalB, PenpalBParaReceiver as PenpalBReceiver, PenpalBParaSender as PenpalBSender, WestendRelay as Westend, WestendRelayReceiver as WestendReceiver, WestendRelaySender as WestendSender, @@ -67,6 +69,7 @@ pub type RelayToParaTest = Test; pub type SystemParaToRelayTest = Test; pub type SystemParaToParaTest = Test; pub type ParaToSystemParaTest = Test; +pub type ParaToParaTest = Test; /// Returns a `TestArgs` instance to be used for the Relay Chain across integration tests pub fn relay_test_args( diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reserve_transfer.rs index 7472445c4ba7..424ec5366dc7 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/reserve_transfer.rs @@ -162,6 +162,69 @@ fn system_para_to_para_assets_receiver_assertions(_: Test) { ); } +fn para_to_para_sender_assertions(t: ParaToParaTest) { + type RuntimeEvent = ::RuntimeEvent; + PenpalB::assert_xcm_pallet_attempted_complete(None); + assert_expected_events!( + PenpalB, + vec![ + // Amount to reserve transfer is transferred to Parachain's Sovereign account + RuntimeEvent::Balances( + pallet_balances::Event::Withdraw { who, amount } + ) => { + who: *who == t.sender.account_id, + amount: *amount == t.args.amount, + }, + // XCM sent to relay reserve + RuntimeEvent::ParachainSystem( + cumulus_pallet_parachain_system::Event::UpwardMessageSent { .. } + ) => {}, + ] + ); +} + +fn para_to_para_relay_hop_assertions(t: ParaToParaTest) { + type RuntimeEvent = ::RuntimeEvent; + let sov_penpal_b_on_westend = + Westend::sovereign_account_id_of(Westend::child_location_of(PenpalB::para_id())); + let sov_penpal_a_on_westend = + Westend::sovereign_account_id_of(Westend::child_location_of(PenpalA::para_id())); + assert_expected_events!( + Westend, + vec![ + // Withdrawn from sender parachain SA + RuntimeEvent::Balances( + pallet_balances::Event::Withdraw { who, amount } + ) => { + who: *who == sov_penpal_b_on_westend, + amount: *amount == t.args.amount, + }, + // Deposited to receiver parachain SA + RuntimeEvent::Balances( + pallet_balances::Event::Deposit { who, .. } + ) => { + who: *who == sov_penpal_a_on_westend, + }, + RuntimeEvent::MessageQueue( + pallet_message_queue::Event::Processed { success: true, .. } + ) => {}, + ] + ); +} + +fn para_to_para_receiver_assertions(_: ParaToParaTest) { + type RuntimeEvent = ::RuntimeEvent; + assert_expected_events!( + PenpalA, + vec![ + RuntimeEvent::Balances(pallet_balances::Event::Deposit { .. }) => {}, + RuntimeEvent::MessageQueue( + pallet_message_queue::Event::Processed { success: true, .. } + ) => {}, + ] + ); +} + fn relay_to_para_reserve_transfer_assets(t: RelayToParaTest) -> DispatchResult { ::XcmPallet::limited_reserve_transfer_assets( t.signed_origin, @@ -195,6 +258,17 @@ fn para_to_system_para_reserve_transfer_assets(t: ParaToSystemParaTest) -> Dispa ) } +fn para_to_para_limited_reserve_transfer_assets(t: ParaToParaTest) -> DispatchResult { + ::PolkadotXcm::limited_reserve_transfer_assets( + t.signed_origin, + bx!(t.args.dest.into()), + bx!(t.args.beneficiary.into()), + bx!(t.args.assets.into()), + t.args.fee_asset_item, + t.args.weight_limit, + ) +} + /// Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't work #[test] fn reserve_transfer_native_asset_from_relay_to_system_para_fails() { @@ -503,3 +577,51 @@ fn reserve_transfer_assets_from_system_para_to_para() { // Receiver's balance is increased by exact amount assert_eq!(receiver_assets_after, receiver_assets_before + asset_amount_to_send); } + +/// Reserve Transfers of native asset from Parachain to Parachain (through Relay reserve) should +/// work +#[test] +fn reserve_transfer_native_asset_from_para_to_para() { + // Init values for Penpal Parachain + let destination = PenpalB::sibling_location_of(PenpalA::para_id()); + let beneficiary_id = PenpalAReceiver::get(); + let amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 1000; + let assets = (Parent, amount_to_send).into(); + + let test_args = TestContext { + sender: PenpalBSender::get(), + receiver: PenpalAReceiver::get(), + args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None, 0), + }; + + let mut test = ParaToParaTest::new(test_args); + + let sender_balance_before = test.sender.balance; + let receiver_balance_before = test.receiver.balance; + + let sender_as_seen_by_relay = Westend::child_location_of(PenpalB::para_id()); + let sov_of_sender_on_relay = Westend::sovereign_account_id_of(sender_as_seen_by_relay); + + // fund the PenpalB's SA on Westend with the native tokens held in reserve + Westend::fund_accounts(vec![(sov_of_sender_on_relay.into(), amount_to_send * 2)]); + + test.set_assertion::(para_to_para_sender_assertions); + test.set_assertion::(para_to_para_relay_hop_assertions); + test.set_assertion::(para_to_para_receiver_assertions); + test.set_dispatchable::(para_to_para_limited_reserve_transfer_assets); + test.assert(); + + let sender_balance_after = test.sender.balance; + let receiver_balance_after = test.receiver.balance; + + let delivery_fees = PenpalB::execute_with(|| { + xcm_helpers::transfer_assets_delivery_fees::< + ::XcmSender, + >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) + }); + + // Sender's balance is reduced + assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); + // Receiver's balance is increased + assert!(receiver_balance_after > receiver_balance_before); +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 86000a20b5b9..daa04d9607d7 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -1537,6 +1537,13 @@ impl_runtime_apis! { Ok((origin, ticket, assets)) } + fn fee_asset() -> Result { + Ok(MultiAsset { + id: Concrete(TokenLocation::get()), + fun: Fungible(1_000_000 * UNITS), + }) + } + fn unlockable_asset() -> Result<(MultiLocation, MultiLocation, MultiAsset), BenchmarkError> { Err(BenchmarkError::Skip) } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index 4da0a2500a54..69c3ccb4ea7c 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -46,7 +46,7 @@ use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, CurrencyAdapter, DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal, DescribeFamily, - EnsureXcmOrigin, FungiblesAdapter, GlobalConsensusParachainConvertsFor, HashedDescription, + EnsureXcmOrigin, FrameTransactionalProcessor, FungiblesAdapter, GlobalConsensusParachainConvertsFor, HashedDescription, IsConcrete, LocalMint, NetworkExportTableItem, NoChecking, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, StartsWith, @@ -607,6 +607,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = WithOriginFilter; type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } /// Converts a local signed origin into an XCM multilocation. diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index 6709a20b275e..bf0b0a90cd6c 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -1614,6 +1614,13 @@ impl_runtime_apis! { Ok((origin, ticket, assets)) } + fn fee_asset() -> Result { + Ok(MultiAsset { + id: Concrete(WestendLocation::get()), + fun: Fungible(1_000_000 * UNITS), + }) + } + fn unlockable_asset() -> Result<(MultiLocation, MultiLocation, MultiAsset), BenchmarkError> { Err(BenchmarkError::Skip) } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs index 4760e087e24f..b5a9e75412a8 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs @@ -46,6 +46,7 @@ use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, CurrencyAdapter, DenyReserveTransferToRelayChain, DenyThenTry, DescribeFamily, DescribePalletTerminal, + FrameTransactionalProcessor, EnsureXcmOrigin, FungiblesAdapter, GlobalConsensusParachainConvertsFor, HashedDescription, IsConcrete, LocalMint, NetworkExportTableItem, NoChecking, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, @@ -613,6 +614,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = WithOriginFilter; type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } /// Local origins on this chain are allowed to dispatch XCM sends/executions. 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 8bd5c196016a..2c82a755acaa 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 @@ -927,6 +927,13 @@ impl_runtime_apis! { Ok((origin, ticket, assets)) } + fn fee_asset() -> Result { + Ok(MultiAsset { + id: Concrete(TokenLocation::get()), + fun: Fungible(1_000_000 * UNITS), + }) + } + fn unlockable_asset() -> Result<(MultiLocation, MultiLocation, MultiAsset), BenchmarkError> { Err(BenchmarkError::Skip) } 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 de7b5315c883..b0290ee55ca1 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 @@ -46,7 +46,7 @@ use xcm::latest::prelude::*; use xcm_builder::{ deposit_or_burn_fee, AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, - CurrencyAdapter, DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, HandleFee, + CurrencyAdapter, DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, FrameTransactionalProcessor, HandleFee, IsConcrete, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, @@ -289,6 +289,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = WithOriginFilter; type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } pub type PriceForParentDelivery = diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs index 07e664d67be6..c94e0b3f6ac3 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs @@ -916,6 +916,13 @@ impl_runtime_apis! { Ok((origin, ticket, assets)) } + fn fee_asset() -> Result { + Ok(MultiAsset { + id: Concrete(WestendLocation::get()), + fun: Fungible(1_000_000 * UNITS), + }) + } + fn unlockable_asset() -> Result<(MultiLocation, MultiLocation, MultiAsset), BenchmarkError> { Err(BenchmarkError::Skip) } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs index c89ee91c5e44..8ef5cd16d4a4 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs @@ -39,7 +39,7 @@ use xcm::latest::prelude::*; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, CurrencyAdapter, - DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, IsConcrete, ParentAsSuperuser, + DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, FrameTransactionalProcessor, IsConcrete, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, @@ -268,6 +268,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = WithOriginFilter; type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } pub type PriceForParentDelivery = diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs index cefc099c96f9..a5321f11b0b8 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/xcm_config.rs @@ -36,7 +36,7 @@ use xcm::latest::prelude::*; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, CurrencyAdapter, - DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, FixedWeightBounds, IsConcrete, + DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, FixedWeightBounds, FrameTransactionalProcessor, IsConcrete, LocatableAssetId, OriginToPluralityVoice, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, @@ -305,6 +305,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = WithOriginFilter; type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } /// Converts a local signed origin into an XCM multilocation. diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs index 2ac93aed3f8d..23ea2404c8c1 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs @@ -38,7 +38,7 @@ use xcm::latest::prelude::*; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, CurrencyAdapter, - DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, FixedWeightBounds, IsConcrete, + DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, FixedWeightBounds, FrameTransactionalProcessor, IsConcrete, NativeAsset, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, @@ -209,6 +209,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } /// Converts a local signed origin into an XCM multilocation. diff --git a/cumulus/parachains/runtimes/glutton/glutton-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/glutton/glutton-westend/src/xcm_config.rs index 5ebb0ade1231..fb24162292e2 100644 --- a/cumulus/parachains/runtimes/glutton/glutton-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/glutton/glutton-westend/src/xcm_config.rs @@ -24,8 +24,8 @@ use frame_support::{ }; use xcm::latest::prelude::*; use xcm_builder::{ - AllowExplicitUnpaidExecutionFrom, FixedWeightBounds, ParentAsSuperuser, ParentIsPreset, - SovereignSignedViaLocation, + AllowExplicitUnpaidExecutionFrom, FixedWeightBounds, FrameTransactionalProcessor, + ParentAsSuperuser, ParentIsPreset, SovereignSignedViaLocation, }; parameter_types! { @@ -84,6 +84,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/starters/shell/src/xcm_config.rs b/cumulus/parachains/runtimes/starters/shell/src/xcm_config.rs index ff773ca78161..c878bb6a70cd 100644 --- a/cumulus/parachains/runtimes/starters/shell/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/starters/shell/src/xcm_config.rs @@ -84,6 +84,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = (); } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs index 21f421f82859..72783007015b 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs @@ -47,8 +47,8 @@ use xcm::latest::prelude::*; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, - ConvertedConcreteId, CurrencyAdapter, DenyReserveTransferToRelayChain, DenyThenTry, - EnsureXcmOrigin, FixedWeightBounds, FungiblesAdapter, IsConcrete, LocalMint, NativeAsset, + ConvertedConcreteId, CurrencyAdapter, EnsureXcmOrigin, FixedWeightBounds, + FrameTransactionalProcessor, FungiblesAdapter, IsConcrete, LocalMint, NativeAsset, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, @@ -167,34 +167,29 @@ match_types! { }; } -pub type Barrier = TrailingSetTopicAsId< - DenyThenTry< - DenyReserveTransferToRelayChain, +pub type Barrier = TrailingSetTopicAsId<( + TakeWeightCredit, + // Expected responses are OK. + AllowKnownQueryResponses, + // Allow XCMs with some computed origins to pass through. + WithComputedOrigin< ( - TakeWeightCredit, - // Expected responses are OK. - AllowKnownQueryResponses, - // Allow XCMs with some computed origins to pass through. - WithComputedOrigin< - ( - // If the message is one that immediately attempts to pay for execution, then - // allow it. - AllowTopLevelPaidExecutionFrom, - // System Assets parachain, parent and its exec plurality get free - // execution - AllowExplicitUnpaidExecutionFrom<( - CommonGoodAssetsParachain, - ParentOrParentsExecutivePlurality, - )>, - // Subscriptions for version tracking are OK. - AllowSubscriptionsFrom, - ), - UniversalLocation, - ConstU32<8>, - >, + // If the message is one that immediately attempts to pay for execution, then + // allow it. + AllowTopLevelPaidExecutionFrom, + // System Assets parachain, parent and its exec plurality get free + // execution + AllowExplicitUnpaidExecutionFrom<( + CommonGoodAssetsParachain, + ParentOrParentsExecutivePlurality, + )>, + // Subscriptions for version tracking are OK. + AllowSubscriptionsFrom, ), + UniversalLocation, + ConstU32<8>, >, ->; +)>; /// Type alias to conveniently refer to `frame_system`'s `Config::AccountId`. pub type AccountIdOf = ::AccountId; @@ -312,6 +307,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } /// No local origins on this chain are allowed to dispatch XCM sends/executions. diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs index 9d2ba98a67c4..235a8e5915ed 100644 --- a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs @@ -75,7 +75,8 @@ use parachains_common::{ }; use xcm_builder::{ AllowKnownQueryResponses, AllowSubscriptionsFrom, AsPrefixedGeneralIndex, ConvertedConcreteId, - FungiblesAdapter, LocalMint, TrailingSetTopicAsId, WithUniqueTopic, + FrameTransactionalProcessor, FungiblesAdapter, LocalMint, TrailingSetTopicAsId, + WithUniqueTopic, }; use xcm_executor::traits::JustTry; @@ -481,6 +482,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } /// Local origins on this chain are allowed to dispatch XCM sends/executions. diff --git a/cumulus/primitives/utility/src/lib.rs b/cumulus/primitives/utility/src/lib.rs index 03f827d7ee2f..77d414bee95e 100644 --- a/cumulus/primitives/utility/src/lib.rs +++ b/cumulus/primitives/utility/src/lib.rs @@ -27,6 +27,7 @@ use frame_support::{ Get, }, weights::Weight, + CloneNoBound, }; use polkadot_runtime_common::xcm_sender::PriceForMessageDelivery; use sp_runtime::{traits::Saturating, SaturatedConversion}; @@ -101,6 +102,7 @@ struct AssetTraderRefunder { /// later refund purposes /// Important: Errors if the Trader is being called twice by 2 BuyExecution instructions /// Alternatively we could just return payment in the aforementioned case +#[derive(CloneNoBound)] pub struct TakeFirstAssetTrader< AccountId: Eq, FeeCharger: ChargeWeightInFungibles, diff --git a/polkadot/node/core/prospective-parachains/src/tests.rs b/polkadot/node/core/prospective-parachains/src/tests.rs index d2cd23fe95fc..51a5ef622c04 100644 --- a/polkadot/node/core/prospective-parachains/src/tests.rs +++ b/polkadot/node/core/prospective-parachains/src/tests.rs @@ -101,11 +101,9 @@ fn test_harness>( let mut view = View::new(); let subsystem = async move { - loop { - match run_iteration(&mut context, &mut view, &Metrics(None)).await { - Ok(()) => break, - Err(e) => panic!("{:?}", e), - } + match run_iteration(&mut context, &mut view, &Metrics(None)).await { + Ok(()) => {}, + Err(e) => panic!("{:?}", e), } view diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index 26670cdcc238..3228fcf7aa8d 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -2354,6 +2354,13 @@ sp_api::impl_runtime_apis! { Ok((origin, ticket, assets)) } + fn fee_asset() -> Result { + Ok(MultiAsset { + id: Concrete(TokenLocation::get()), + fun: Fungible(1_000_000 * UNITS), + }) + } + fn unlockable_asset() -> Result<(MultiLocation, MultiLocation, MultiAsset), BenchmarkError> { // Rococo doesn't support asset locking Err(BenchmarkError::Skip) diff --git a/polkadot/runtime/rococo/src/xcm_config.rs b/polkadot/runtime/rococo/src/xcm_config.rs index c8f8f59dae99..e82dd39cfde8 100644 --- a/polkadot/runtime/rococo/src/xcm_config.rs +++ b/polkadot/runtime/rococo/src/xcm_config.rs @@ -40,7 +40,7 @@ use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, ChildParachainAsNative, ChildParachainConvertsVia, CurrencyAdapter as XcmCurrencyAdapter, DescribeBodyTerminal, - DescribeFamily, FixedWeightBounds, HashedDescription, IsChildSystemParachain, IsConcrete, + DescribeFamily, FixedWeightBounds, FrameTransactionalProcessor, HashedDescription, IsChildSystemParachain, IsConcrete, MintLocation, OriginToPluralityVoice, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents, @@ -201,6 +201,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } parameter_types! { diff --git a/polkadot/runtime/test-runtime/src/xcm_config.rs b/polkadot/runtime/test-runtime/src/xcm_config.rs index ae4faecf7001..041bf9822a15 100644 --- a/polkadot/runtime/test-runtime/src/xcm_config.rs +++ b/polkadot/runtime/test-runtime/src/xcm_config.rs @@ -22,8 +22,8 @@ use frame_support::{ use frame_system::EnsureRoot; use xcm::latest::prelude::*; use xcm_builder::{ - AllowUnpaidExecutionFrom, EnsureXcmOrigin, FixedWeightBounds, SignedAccountId32AsNative, - SignedToAccountId32, + AllowUnpaidExecutionFrom, EnsureXcmOrigin, FixedWeightBounds, FrameTransactionalProcessor, + SignedAccountId32AsNative, SignedToAccountId32, }; use xcm_executor::{ traits::{TransactAsset, WeightTrader}, @@ -78,6 +78,7 @@ impl TransactAsset for DummyAssetTransactor { } } +#[derive(Clone)] pub struct DummyWeightTrader; impl WeightTrader for DummyWeightTrader { fn new() -> Self { @@ -125,6 +126,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = super::RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } impl pallet_xcm::Config for crate::Runtime { diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index 04723ef0d9ba..ff30448d3b3b 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -2407,6 +2407,13 @@ sp_api::impl_runtime_apis! { Ok((origin, ticket, assets)) } + fn fee_asset() -> Result { + Ok(MultiAsset { + id: Concrete(TokenLocation::get()), + fun: Fungible(1_000_000 * UNITS), + }) + } + fn unlockable_asset() -> Result<(MultiLocation, MultiLocation, MultiAsset), BenchmarkError> { // Westend doesn't support asset locking Err(BenchmarkError::Skip) diff --git a/polkadot/runtime/westend/src/xcm_config.rs b/polkadot/runtime/westend/src/xcm_config.rs index 9ab6470f6dae..787b96192deb 100644 --- a/polkadot/runtime/westend/src/xcm_config.rs +++ b/polkadot/runtime/westend/src/xcm_config.rs @@ -41,7 +41,7 @@ use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, ChildParachainAsNative, ChildParachainConvertsVia, CurrencyAdapter as XcmCurrencyAdapter, DescribeBodyTerminal, - DescribeFamily, HashedDescription, IsConcrete, MintLocation, OriginToPluralityVoice, + DescribeFamily, FrameTransactionalProcessor, HashedDescription, IsConcrete, MintLocation, OriginToPluralityVoice, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents, XcmFeeToAccount, @@ -189,6 +189,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } parameter_types! { diff --git a/polkadot/xcm/pallet-xcm-benchmarks/src/fungible/mock.rs b/polkadot/xcm/pallet-xcm-benchmarks/src/fungible/mock.rs index 4d566fd585db..5c96469ee687 100644 --- a/polkadot/xcm/pallet-xcm-benchmarks/src/fungible/mock.rs +++ b/polkadot/xcm/pallet-xcm-benchmarks/src/fungible/mock.rs @@ -26,7 +26,7 @@ use frame_support::{ use sp_core::H256; use sp_runtime::traits::{BlakeTwo256, IdentityLookup}; use xcm::latest::prelude::*; -use xcm_builder::{AllowUnpaidExecutionFrom, MintLocation}; +use xcm_builder::{AllowUnpaidExecutionFrom, FrameTransactionalProcessor, MintLocation}; type Block = frame_system::mocking::MockBlock; @@ -144,6 +144,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } impl crate::Config for Test { diff --git a/polkadot/xcm/pallet-xcm-benchmarks/src/generic/benchmarking.rs b/polkadot/xcm/pallet-xcm-benchmarks/src/generic/benchmarking.rs index f1c48ba9b830..dfe63a0bf71f 100644 --- a/polkadot/xcm/pallet-xcm-benchmarks/src/generic/benchmarking.rs +++ b/polkadot/xcm/pallet-xcm-benchmarks/src/generic/benchmarking.rs @@ -125,11 +125,15 @@ benchmarks! { } refund_surplus { - let holding = T::worst_case_holding(0).into(); let mut executor = new_executor::(Default::default()); - executor.set_holding(holding); + let holding_assets = T::worst_case_holding(1); + // We can already buy execution since we'll load the holding register manually + let asset_for_fees = T::fee_asset().unwrap(); + let previous_xcm = Xcm(vec![BuyExecution { fees: asset_for_fees, weight_limit: Limited(Weight::from_parts(1337, 1337)) }]); + executor.set_holding(holding_assets.into()); executor.set_total_surplus(Weight::from_parts(1337, 1337)); executor.set_total_refunded(Weight::zero()); + executor.bench_process(previous_xcm).expect("Holding has been loaded, so we can buy execution here"); let instruction = Instruction::>::RefundSurplus; let xcm = Xcm(vec![instruction]); diff --git a/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mock.rs b/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mock.rs index 6efd2304e281..bb16893ea21d 100644 --- a/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mock.rs +++ b/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mock.rs @@ -30,7 +30,7 @@ use xcm_builder::{ Assets, TestAssetExchanger, TestAssetLocker, TestAssetTrap, TestSubscriptionService, TestUniversalAliases, }, - AliasForeignAccountId32, AllowUnpaidExecutionFrom, + AliasForeignAccountId32, AllowUnpaidExecutionFrom, FrameTransactionalProcessor, }; use xcm_executor::traits::ConvertOrigin; @@ -137,6 +137,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Aliasers; + type TransactionalProcessor = FrameTransactionalProcessor; } parameter_types! { @@ -199,6 +200,10 @@ impl generic::Config for Test { Ok((Default::default(), ticket, assets)) } + fn fee_asset() -> Result { + Ok(MultiAsset { id: Concrete(Here.into()), fun: Fungible(1_000_000) }) + } + fn unlockable_asset() -> Result<(MultiLocation, MultiLocation, MultiAsset), BenchmarkError> { let assets: MultiAsset = (Concrete(Here.into()), 100).into(); Ok((Default::default(), account_id_junction::(1).into(), assets)) diff --git a/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mod.rs b/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mod.rs index 11f7bba19a98..5f9aa1bfe6f3 100644 --- a/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mod.rs +++ b/polkadot/xcm/pallet-xcm-benchmarks/src/generic/mod.rs @@ -76,6 +76,10 @@ pub mod pallet { /// Return an origin, ticket, and assets that can be trapped and claimed. fn claimable_asset() -> Result<(MultiLocation, MultiLocation, MultiAssets), BenchmarkError>; + /// Asset used to pay for fees. Used to buy weight in benchmarks, for example in + /// `refund_surplus`. + fn fee_asset() -> Result; + /// Return an unlocker, owner and assets that can be locked and unlocked. fn unlockable_asset() -> Result<(MultiLocation, MultiLocation, MultiAsset), BenchmarkError>; diff --git a/polkadot/xcm/pallet-xcm/src/mock.rs b/polkadot/xcm/pallet-xcm/src/mock.rs index 9a734d0f276d..8e972d7f342c 100644 --- a/polkadot/xcm/pallet-xcm/src/mock.rs +++ b/polkadot/xcm/pallet-xcm/src/mock.rs @@ -36,7 +36,7 @@ use xcm_builder::{ AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, Case, ChildParachainAsNative, ChildParachainConvertsVia, ChildSystemParachainAsSuperuser, CurrencyAdapter as XcmCurrencyAdapter, DescribeAllTerminal, - FixedRateOfFungible, FixedWeightBounds, FungiblesAdapter, HashedDescription, IsConcrete, + FixedRateOfFungible, FixedWeightBounds, FrameTransactionalProcessor, FungiblesAdapter, HashedDescription, IsConcrete, MatchedConvertedConcreteId, NoChecking, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, XcmFeeManagerFromComponents, XcmFeeToAccount, }; @@ -513,6 +513,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } pub type LocalOriginToLocation = SignedToAccountId32; @@ -589,10 +590,23 @@ impl super::benchmarking::Config for Test { let asset_amount = 10u128; let fee_amount = 2u128; + let existential_deposit = ExistentialDeposit::get(); + let caller = frame_benchmarking::whitelisted_caller(); + + // Give some multiple of the existential deposit + let balance = asset_amount + existential_deposit * 1000; + let _ = >::make_free_balance_be( + &caller, balance, + ); // create sufficient foreign asset USDT let usdt_initial_local_amount = fee_amount * 10; - let (usdt_chain, _, usdt_id_multilocation) = - set_up_foreign_asset(USDT_PARA_ID, None, usdt_initial_local_amount, true); + let (usdt_chain, _, usdt_id_multilocation) = set_up_foreign_asset( + USDT_PARA_ID, + None, + caller.clone(), + usdt_initial_local_amount, + true, + ); // native assets transfer destination is USDT chain (teleport trust only for USDT) let dest = usdt_chain; @@ -602,20 +616,13 @@ impl super::benchmarking::Config for Test { // native asset to transfer (not used for fees) - local reserve (MultiLocation::here(), asset_amount).into(), ); - - let existential_deposit = ExistentialDeposit::get(); - let caller = frame_benchmarking::whitelisted_caller(); - // Give some multiple of the existential deposit - let balance = asset_amount + existential_deposit * 1000; - let _ = >::make_free_balance_be( - &caller, balance, - ); - // verify initial balance + // verify initial balances assert_eq!(Balances::free_balance(&caller), balance); + assert_eq!(Assets::balance(usdt_id_multilocation, &caller), usdt_initial_local_amount); // verify transferred successfully let verify = Box::new(move || { - // verify balance after transfer, decreased by transferred amount + // verify balances after transfer, decreased by transferred amounts assert_eq!(Balances::free_balance(&caller), balance - asset_amount); assert_eq!( Assets::balance(usdt_id_multilocation, &caller), diff --git a/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs b/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs index fb0bef26ebd6..6893bae2b6c1 100644 --- a/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs +++ b/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs @@ -244,6 +244,7 @@ fn reserve_transfer_assets_with_paid_router_works() { pub(crate) fn set_up_foreign_asset( reserve_para_id: u32, inner_junction: Option, + benficiary: AccountId, initial_amount: u128, is_sufficient: bool, ) -> (MultiLocation, AccountId, MultiLocation) { @@ -271,7 +272,7 @@ pub(crate) fn set_up_foreign_asset( assert_ok!(Assets::mint( RuntimeOrigin::signed(BOB), foreign_asset_id_multilocation, - ALICE, + benficiary, initial_amount )); @@ -440,6 +441,7 @@ fn destination_asset_reserve_and_local_fee_reserve_call( set_up_foreign_asset( FOREIGN_ASSET_RESERVE_PARA_ID, Some(FOREIGN_ASSET_INNER_JUNCTION), + ALICE, foreign_initial_amount, false, ); @@ -595,6 +597,7 @@ fn remote_asset_reserve_and_local_fee_reserve_call_disallowed( let (_, _, foreign_asset_id_multilocation) = set_up_foreign_asset( FOREIGN_ASSET_RESERVE_PARA_ID, Some(FOREIGN_ASSET_INNER_JUNCTION), + ALICE, foreign_initial_amount, false, ); @@ -712,6 +715,7 @@ fn local_asset_reserve_and_destination_fee_reserve_call( set_up_foreign_asset( USDC_RESERVE_PARA_ID, Some(USDC_INNER_JUNCTION), + ALICE, usdc_initial_local_amount, true, ); @@ -870,6 +874,7 @@ fn destination_asset_reserve_and_destination_fee_reserve_call( set_up_foreign_asset( FOREIGN_ASSET_RESERVE_PARA_ID, Some(FOREIGN_ASSET_INNER_JUNCTION), + ALICE, foreign_initial_amount, true, ); @@ -1013,6 +1018,7 @@ fn remote_asset_reserve_and_destination_fee_reserve_call_disallowed( let (usdc_chain, _, usdc_id_multilocation) = set_up_foreign_asset( USDC_RESERVE_PARA_ID, Some(USDC_INNER_JUNCTION), + ALICE, usdc_initial_local_amount, true, ); @@ -1022,6 +1028,7 @@ fn remote_asset_reserve_and_destination_fee_reserve_call_disallowed( let (_, _, foreign_asset_id_multilocation) = set_up_foreign_asset( FOREIGN_ASSET_RESERVE_PARA_ID, Some(FOREIGN_ASSET_INNER_JUNCTION), + ALICE, foreign_initial_amount, false, ); @@ -1135,6 +1142,7 @@ fn local_asset_reserve_and_remote_fee_reserve_call_disallowed( let (_, usdc_chain_sovereign_account, usdc_id_multilocation) = set_up_foreign_asset( USDC_RESERVE_PARA_ID, Some(USDC_INNER_JUNCTION), + ALICE, usdc_initial_local_amount, true, ); @@ -1244,6 +1252,7 @@ fn destination_asset_reserve_and_remote_fee_reserve_call_disallowed( let (_, usdc_chain_sovereign_account, usdc_id_multilocation) = set_up_foreign_asset( USDC_RESERVE_PARA_ID, Some(USDC_INNER_JUNCTION), + ALICE, usdc_initial_local_amount, true, ); @@ -1254,6 +1263,7 @@ fn destination_asset_reserve_and_remote_fee_reserve_call_disallowed( set_up_foreign_asset( FOREIGN_ASSET_RESERVE_PARA_ID, Some(FOREIGN_ASSET_INNER_JUNCTION), + ALICE, foreign_initial_amount, false, ); @@ -1383,6 +1393,7 @@ fn remote_asset_reserve_and_remote_fee_reserve_call( set_up_foreign_asset( USDC_RESERVE_PARA_ID, Some(USDC_INNER_JUNCTION), + ALICE, usdc_initial_local_amount, true, ); @@ -1526,7 +1537,7 @@ fn local_asset_reserve_and_teleported_fee_call( // create sufficient foreign asset USDT let usdt_initial_local_amount = 42; let (usdt_chain, usdt_chain_sovereign_account, usdt_id_multilocation) = - set_up_foreign_asset(USDT_PARA_ID, None, usdt_initial_local_amount, true); + set_up_foreign_asset(USDT_PARA_ID, None, ALICE, usdt_initial_local_amount, true); // native assets transfer destination is USDT chain (teleport trust only for USDT) let dest = usdt_chain; @@ -1675,7 +1686,7 @@ fn destination_asset_reserve_and_teleported_fee_call( // create sufficient foreign asset USDT let usdt_initial_local_amount = 42; let (_, usdt_chain_sovereign_account, usdt_id_multilocation) = - set_up_foreign_asset(USDT_PARA_ID, None, usdt_initial_local_amount, true); + set_up_foreign_asset(USDT_PARA_ID, None, ALICE, usdt_initial_local_amount, true); // create non-sufficient foreign asset BLA let foreign_initial_amount = 142; @@ -1683,6 +1694,7 @@ fn destination_asset_reserve_and_teleported_fee_call( set_up_foreign_asset( FOREIGN_ASSET_RESERVE_PARA_ID, Some(FOREIGN_ASSET_INNER_JUNCTION), + ALICE, foreign_initial_amount, false, ); @@ -1845,13 +1857,14 @@ fn remote_asset_reserve_and_teleported_fee_reserve_call_disallowed( // create sufficient foreign asset USDT let usdt_initial_local_amount = 42; let (usdt_chain, usdt_chain_sovereign_account, usdt_id_multilocation) = - set_up_foreign_asset(USDT_PARA_ID, None, usdt_initial_local_amount, true); + set_up_foreign_asset(USDT_PARA_ID, None, ALICE, usdt_initial_local_amount, true); // create non-sufficient foreign asset BLA let foreign_initial_amount = 142; let (_, reserve_sovereign_account, foreign_asset_id_multilocation) = set_up_foreign_asset( FOREIGN_ASSET_RESERVE_PARA_ID, Some(FOREIGN_ASSET_INNER_JUNCTION), + ALICE, foreign_initial_amount, false, ); @@ -1952,7 +1965,7 @@ fn reserve_transfer_assets_with_teleportable_asset_disallowed() { // create sufficient foreign asset USDT let usdt_initial_local_amount = 42; let (usdt_chain, usdt_chain_sovereign_account, usdt_id_multilocation) = - set_up_foreign_asset(USDT_PARA_ID, None, usdt_initial_local_amount, true); + set_up_foreign_asset(USDT_PARA_ID, None, ALICE, usdt_initial_local_amount, true); // transfer destination is USDT chain (foreign asset needs to go through its reserve chain) let dest = usdt_chain; @@ -2037,6 +2050,7 @@ fn intermediary_error_reverts_side_effects() { let (_, usdc_chain_sovereign_account, usdc_id_multilocation) = set_up_foreign_asset( USDC_RESERVE_PARA_ID, Some(USDC_INNER_JUNCTION), + ALICE, usdc_initial_local_amount, true, ); @@ -2106,7 +2120,7 @@ fn teleport_asset_using_local_fee_reserve_call( // create non-sufficient foreign asset USDT let usdt_initial_local_amount = 42; let (usdt_chain, usdt_chain_sovereign_account, usdt_id_multilocation) = - set_up_foreign_asset(USDT_PARA_ID, None, usdt_initial_local_amount, false); + set_up_foreign_asset(USDT_PARA_ID, None, ALICE, usdt_initial_local_amount, false); // transfer destination is reserve location (no teleport trust) let dest = usdt_chain; @@ -2258,6 +2272,7 @@ fn teleported_asset_using_destination_reserve_fee_call( set_up_foreign_asset( FOREIGN_ASSET_RESERVE_PARA_ID, Some(FOREIGN_ASSET_INNER_JUNCTION), + ALICE, foreign_initial_amount, true, ); @@ -2265,7 +2280,7 @@ fn teleported_asset_using_destination_reserve_fee_call( // create non-sufficient foreign asset USDT let usdt_initial_local_amount = 42; let (_, usdt_chain_sovereign_account, usdt_id_multilocation) = - set_up_foreign_asset(USDT_PARA_ID, None, usdt_initial_local_amount, false); + set_up_foreign_asset(USDT_PARA_ID, None, ALICE, usdt_initial_local_amount, false); // transfer destination is BLA reserve location let dest = reserve_location; diff --git a/polkadot/xcm/src/v3/multiasset.rs b/polkadot/xcm/src/v3/multiasset.rs index 454120a1a7b9..c23fc82a92e3 100644 --- a/polkadot/xcm/src/v3/multiasset.rs +++ b/polkadot/xcm/src/v3/multiasset.rs @@ -504,7 +504,7 @@ impl TryFrom for MultiAsset { /// A `Vec` of `MultiAsset`s. /// /// There are a number of invariants which the construction and mutation functions must ensure are -/// maintained: +/// maintained in order to maintain polynomial time complexity during iteration: /// - It may contain no items of duplicate asset class; /// - All items must be ordered; /// - The number of items should grow no larger than `MAX_ITEMS_IN_MULTIASSETS`. diff --git a/polkadot/xcm/src/v3/traits.rs b/polkadot/xcm/src/v3/traits.rs index 6054bf1456a5..b91493b0e408 100644 --- a/polkadot/xcm/src/v3/traits.rs +++ b/polkadot/xcm/src/v3/traits.rs @@ -519,7 +519,7 @@ pub trait SendXcm { /// Intermediate value which connects the two phases of the send operation. type Ticket; - /// Check whether the given `_message` is deliverable to the given `_destination` and if so + /// Check whether the given `message` is deliverable to the given `destination` and if so /// determine the cost which will be paid by this chain to do so, returning a `Validated` token /// which can be used to enact delivery. /// diff --git a/polkadot/xcm/xcm-builder/src/lib.rs b/polkadot/xcm/xcm-builder/src/lib.rs index 455f17a5348c..a8bcdefcccfc 100644 --- a/polkadot/xcm/xcm-builder/src/lib.rs +++ b/polkadot/xcm/xcm-builder/src/lib.rs @@ -26,26 +26,6 @@ mod tests; #[cfg(feature = "std")] pub mod test_utils; -mod location_conversion; -#[allow(deprecated)] -pub use location_conversion::ForeignChainAliasAccount; -pub use location_conversion::{ - Account32Hash, AccountId32Aliases, AccountKey20Aliases, AliasesIntoAccountId32, - ChildParachainConvertsVia, DescribeAccountId32Terminal, DescribeAccountIdTerminal, - DescribeAccountKey20Terminal, DescribeAllTerminal, DescribeBodyTerminal, DescribeFamily, - DescribeLocation, DescribePalletTerminal, DescribeTerminus, DescribeTreasuryVoiceTerminal, - GlobalConsensusConvertsFor, GlobalConsensusParachainConvertsFor, HashedDescription, - LocalTreasuryVoiceConvertsVia, ParentIsPreset, SiblingParachainConvertsVia, -}; - -mod origin_conversion; -pub use origin_conversion::{ - BackingToPlurality, ChildParachainAsNative, ChildSystemParachainAsSuperuser, EnsureXcmOrigin, - OriginToPluralityVoice, ParentAsSuperuser, RelayChainAsNative, SiblingParachainAsNative, - SiblingSystemParachainAsSuperuser, SignedAccountId32AsNative, SignedAccountKey20AsNative, - SignedToAccountId32, SovereignSignedViaLocation, -}; - mod asset_conversion; pub use asset_conversion::{ AsPrefixedGeneralIndex, ConvertedAbstractId, ConvertedConcreteId, MatchedConvertedConcreteId, @@ -61,8 +41,11 @@ pub use barriers::{ WithComputedOrigin, }; -mod process_xcm_message; -pub use process_xcm_message::ProcessXcmMessage; +mod controller; +pub use controller::{ + Controller, ExecuteController, ExecuteControllerWeightInfo, QueryController, + QueryControllerWeightInfo, QueryHandler, SendController, SendControllerWeightInfo, +}; mod currency_adapter; pub use currency_adapter::CurrencyAdapter; @@ -78,14 +61,16 @@ pub use fungibles_adapter::{ LocalMint, MintLocation, NoChecking, NonLocalMint, }; -mod nonfungibles_adapter; -pub use nonfungibles_adapter::{ - NonFungiblesAdapter, NonFungiblesMutateAdapter, NonFungiblesTransferAdapter, -}; - -mod weight; -pub use weight::{ - FixedRateOfFungible, FixedWeightBounds, TakeRevenue, UsingComponents, WeightInfoBounds, +mod location_conversion; +#[allow(deprecated)] +pub use location_conversion::ForeignChainAliasAccount; +pub use location_conversion::{ + Account32Hash, AccountId32Aliases, AccountKey20Aliases, AliasesIntoAccountId32, + ChildParachainConvertsVia, DescribeAccountId32Terminal, DescribeAccountIdTerminal, + DescribeAccountKey20Terminal, DescribeAllTerminal, DescribeBodyTerminal, DescribeFamily, + DescribeLocation, DescribePalletTerminal, DescribeTerminus, DescribeTreasuryVoiceTerminal, + GlobalConsensusConvertsFor, GlobalConsensusParachainConvertsFor, HashedDescription, + LocalTreasuryVoiceConvertsVia, ParentIsPreset, SiblingParachainConvertsVia, }; mod matches_location; @@ -100,9 +85,34 @@ pub use matcher::{CreateMatcher, MatchXcm, Matcher}; mod filter_asset_location; pub use filter_asset_location::{AllAssets, Case, LocationWithAssetFilters, NativeAsset}; +mod nonfungibles_adapter; +pub use nonfungibles_adapter::{ + NonFungiblesAdapter, NonFungiblesMutateAdapter, NonFungiblesTransferAdapter, +}; + +mod origin_aliases; +pub use origin_aliases::AliasForeignAccountId32; + +mod origin_conversion; +pub use origin_conversion::{ + BackingToPlurality, ChildParachainAsNative, ChildSystemParachainAsSuperuser, EnsureXcmOrigin, + OriginToPluralityVoice, ParentAsSuperuser, RelayChainAsNative, SiblingParachainAsNative, + SiblingSystemParachainAsSuperuser, SignedAccountId32AsNative, SignedAccountKey20AsNative, + SignedToAccountId32, SovereignSignedViaLocation, +}; + +mod pay; +pub use pay::{FixedLocation, LocatableAssetId, PayAccountId32OnChainOverXcm, PayOverXcm}; + +mod process_xcm_message; +pub use process_xcm_message::ProcessXcmMessage; + mod routing; pub use routing::{WithTopicSource, WithUniqueTopic}; +mod transactional; +pub use transactional::FrameTransactionalProcessor; + mod universal_exports; pub use universal_exports::{ ensure_is_remote, BridgeBlobDispatcher, BridgeMessage, DispatchBlob, DispatchBlobError, @@ -110,14 +120,7 @@ pub use universal_exports::{ NetworkExportTableItem, SovereignPaidRemoteExporter, UnpaidLocalExporter, UnpaidRemoteExporter, }; -mod origin_aliases; -pub use origin_aliases::AliasForeignAccountId32; - -mod pay; -pub use pay::{FixedLocation, LocatableAssetId, PayAccountId32OnChainOverXcm, PayOverXcm}; - -mod controller; -pub use controller::{ - Controller, ExecuteController, ExecuteControllerWeightInfo, QueryController, - QueryControllerWeightInfo, QueryHandler, SendController, SendControllerWeightInfo, +mod weight; +pub use weight::{ + FixedRateOfFungible, FixedWeightBounds, TakeRevenue, UsingComponents, WeightInfoBounds, }; diff --git a/polkadot/xcm/xcm-builder/src/tests/mock.rs b/polkadot/xcm/xcm-builder/src/tests/mock.rs index 189274eb5f5b..f0c6236f2661 100644 --- a/polkadot/xcm/xcm-builder/src/tests/mock.rs +++ b/polkadot/xcm/xcm-builder/src/tests/mock.rs @@ -744,6 +744,7 @@ impl Config for TestConfig { type CallDispatcher = TestCall; type SafeCallFilter = Everything; type Aliasers = AliasForeignAccountId32; + type TransactionalProcessor = (); } pub fn fungible_multi_asset(location: MultiLocation, amount: u128) -> MultiAsset { diff --git a/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs b/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs index 78b9284c689f..3be6a0aa9b1c 100644 --- a/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs +++ b/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs @@ -178,6 +178,7 @@ type OriginConverter = ( ); type Barrier = AllowUnpaidExecutionFrom; +#[derive(Clone)] pub struct DummyWeightTrader; impl WeightTrader for DummyWeightTrader { fn new() -> Self { @@ -220,6 +221,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = (); } parameter_types! { diff --git a/polkadot/xcm/xcm-builder/src/transactional.rs b/polkadot/xcm/xcm-builder/src/transactional.rs new file mode 100644 index 000000000000..ffe379b0ed41 --- /dev/null +++ b/polkadot/xcm/xcm-builder/src/transactional.rs @@ -0,0 +1,40 @@ +// Copyright 2021 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +use frame_support::storage::{with_transaction, TransactionOutcome}; +use sp_runtime::DispatchError; +use xcm::latest::prelude::*; +use xcm_executor::traits::ProcessTransaction; + +/// Transactional processor implementation using frame transactional layers. +pub struct FrameTransactionalProcessor; +impl ProcessTransaction for FrameTransactionalProcessor { + const IS_TRANSACTIONAL: bool = true; + + fn process(f: F) -> Result<(), XcmError> + where + F: FnOnce() -> Result<(), XcmError>, + { + with_transaction(|| -> TransactionOutcome> { + let output = f(); + match &output { + Ok(()) => TransactionOutcome::Commit(Ok(output)), + _ => TransactionOutcome::Rollback(Ok(output)), + } + }) + .map_err(|_| XcmError::ExceedsStackLimit)? + } +} diff --git a/polkadot/xcm/xcm-builder/src/weight.rs b/polkadot/xcm/xcm-builder/src/weight.rs index c16c52939a38..6b6f5f53ea1b 100644 --- a/polkadot/xcm/xcm-builder/src/weight.rs +++ b/polkadot/xcm/xcm-builder/src/weight.rs @@ -232,12 +232,13 @@ impl< } fn refund_weight(&mut self, weight: Weight, context: &XcmContext) -> Option { - log::trace!(target: "xcm::weight", "UsingComponents::refund_weight weight: {:?}, context: {:?}", weight, context); + log::trace!(target: "xcm::weight", "UsingComponents::refund_weight weight: {:?}, context: {:?}, available weight: {:?}, available amount: {:?}", weight, context, self.0, self.1); let weight = weight.min(self.0); let amount = WeightToFee::weight_to_fee(&weight); self.0 -= weight; self.1 = self.1.saturating_sub(amount); let amount: u128 = amount.saturated_into(); + log::trace!(target: "xcm::weight", "UsingComponents::refund_weight amount to refund: {:?}", amount); if amount > 0 { Some((AssetId::get(), amount).into()) } else { diff --git a/polkadot/xcm/xcm-builder/tests/mock/mod.rs b/polkadot/xcm/xcm-builder/tests/mock/mod.rs index 968b294c6a43..943ae423ea5a 100644 --- a/polkadot/xcm/xcm-builder/tests/mock/mod.rs +++ b/polkadot/xcm/xcm-builder/tests/mock/mod.rs @@ -207,6 +207,7 @@ impl xcm_executor::Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = (); } pub type LocalOriginToLocation = SignedToAccountId32; diff --git a/polkadot/xcm/xcm-executor/src/config.rs b/polkadot/xcm/xcm-executor/src/config.rs index 2ff12cd7a539..8f7e5e2d455c 100644 --- a/polkadot/xcm/xcm-executor/src/config.rs +++ b/polkadot/xcm/xcm-executor/src/config.rs @@ -16,8 +16,8 @@ use crate::traits::{ AssetExchange, AssetLock, CallDispatcher, ClaimAssets, ConvertOrigin, DropAssets, ExportXcm, - FeeManager, OnResponse, ShouldExecute, TransactAsset, VersionChangeNotifier, WeightBounds, - WeightTrader, + FeeManager, OnResponse, ProcessTransaction, ShouldExecute, TransactAsset, + VersionChangeNotifier, WeightBounds, WeightTrader, }; use frame_support::{ dispatch::{GetDispatchInfo, Parameter, PostDispatchInfo}, @@ -111,4 +111,7 @@ pub trait Config { /// Use this type to explicitly whitelist calls that cannot undergo recursion. This is a /// temporary measure until we properly account for proof size weights for XCM instructions. type SafeCallFilter: Contains; + + /// Transactional processor for XCM instructions. + type TransactionalProcessor: ProcessTransaction; } diff --git a/polkadot/xcm/xcm-executor/src/lib.rs b/polkadot/xcm/xcm-executor/src/lib.rs index ac256ea14899..3b418eebbef8 100644 --- a/polkadot/xcm/xcm-executor/src/lib.rs +++ b/polkadot/xcm/xcm-executor/src/lib.rs @@ -19,7 +19,7 @@ use frame_support::{ dispatch::GetDispatchInfo, ensure, - traits::{Contains, ContainsPair, Get, PalletsInfoAccess}, + traits::{Contains, ContainsPair, Defensive, Get, PalletsInfoAccess}, }; use parity_scale_codec::{Decode, Encode}; use sp_core::defer; @@ -31,8 +31,9 @@ use xcm::latest::prelude::*; pub mod traits; use traits::{ validate_export, AssetExchange, AssetLock, CallDispatcher, ClaimAssets, ConvertOrigin, - DropAssets, Enact, ExportXcm, FeeManager, FeeReason, OnResponse, Properties, ShouldExecute, - TransactAsset, VersionChangeNotifier, WeightBounds, WeightTrader, XcmAssetTransfers, + DropAssets, Enact, ExportXcm, FeeManager, FeeReason, OnResponse, ProcessTransaction, + Properties, ShouldExecute, TransactAsset, VersionChangeNotifier, WeightBounds, WeightTrader, + XcmAssetTransfers, }; mod assets; @@ -302,6 +303,56 @@ impl XcmExecutor { } } + fn ensure_can_subsume_assets(&self, assets_length: usize) -> Result<(), XcmError> { + // worst-case, holding.len becomes 2 * holding_limit. + // this guarantees that if holding.len() == holding_limit and you have more than + // `holding_limit` items (which has a best case outcome of holding.len() == holding_limit), + // then the operation is guaranteed to succeed. + let worst_case_holding_len = self.holding.len() + assets_length; + log::trace!(target: "xcm::ensure_can_subsume_assets", "worst_case_holding_len: {:?}, holding_limit: {:?}", worst_case_holding_len, self.holding_limit); + ensure!(worst_case_holding_len <= self.holding_limit * 2, XcmError::HoldingWouldOverflow); + Ok(()) + } + + /// Refund any unused weight. + fn refund_surplus(&mut self) -> Result<(), XcmError> { + let current_surplus = self.total_surplus.saturating_sub(self.total_refunded); + log::trace!( + target: "xcm::refund_surplus", + "total_surplus: {:?}, total_refunded: {:?}, current_surplus: {:?}", + self.total_surplus, + self.total_refunded, + current_surplus, + ); + if current_surplus.any_gt(Weight::zero()) { + if let Some(w) = self.trader.refund_weight(current_surplus, &self.context) { + if !self.holding.contains_asset(&(w.id, 1).into()) && + self.ensure_can_subsume_assets(1).is_err() + { + let _ = self + .trader + .buy_weight(current_surplus, w.into(), &self.context) + .defensive_proof( + "refund_weight returned an asset capable of buying weight; qed", + ); + log::error!( + target: "xcm::refund_surplus", + "error: HoldingWouldOverflow", + ); + return Err(XcmError::HoldingWouldOverflow) + } + self.total_refunded.saturating_accrue(current_surplus); + self.holding.subsume_assets(w.into()); + } + } + log::trace!( + target: "xcm::refund_surplus", + "total_refunded: {:?}", + self.total_refunded, + ); + Ok(()) + } + #[cfg(feature = "runtime-benchmarks")] pub fn bench_process(&mut self, xcm: Xcm) -> Result<(), ExecutorError> { self.process(xcm) @@ -438,36 +489,6 @@ impl XcmExecutor { r } - fn subsume_asset(&mut self, asset: MultiAsset) -> Result<(), XcmError> { - // worst-case, holding.len becomes 2 * holding_limit. - ensure!(self.holding.len() < self.holding_limit * 2, XcmError::HoldingWouldOverflow); - self.holding.subsume(asset); - Ok(()) - } - - fn subsume_assets(&mut self, assets: Assets) -> Result<(), XcmError> { - // worst-case, holding.len becomes 2 * holding_limit. - // this guarantees that if holding.len() == holding_limit and you have holding_limit more - // items (which has a best case outcome of holding.len() == holding_limit), then you'll - // be guaranteed of making the operation. - let worst_case_holding_len = self.holding.len() + assets.len(); - ensure!(worst_case_holding_len <= self.holding_limit * 2, XcmError::HoldingWouldOverflow); - self.holding.subsume_assets(assets); - Ok(()) - } - - /// Refund any unused weight. - fn refund_surplus(&mut self) -> Result<(), XcmError> { - let current_surplus = self.total_surplus.saturating_sub(self.total_refunded); - if current_surplus.any_gt(Weight::zero()) { - self.total_refunded.saturating_accrue(current_surplus); - if let Some(w) = self.trader.refund_weight(current_surplus, &self.context) { - self.subsume_asset(w)?; - } - } - Ok(()) - } - /// Process a single XCM instruction, mutating the state of the XCM virtual machine. fn process_instruction( &mut self, @@ -480,74 +501,101 @@ impl XcmExecutor { ); match instr { WithdrawAsset(assets) => { - // Take `assets` from the origin account (on-chain) and place in holding. - let origin = *self.origin_ref().ok_or(XcmError::BadOrigin)?; - for asset in assets.into_inner().into_iter() { - Config::AssetTransactor::withdraw_asset(&asset, &origin, Some(&self.context))?; - self.subsume_asset(asset)?; - } - Ok(()) + let origin = self.origin_ref().ok_or(XcmError::BadOrigin)?; + self.ensure_can_subsume_assets(assets.len())?; + Config::TransactionalProcessor::process(|| { + // Take `assets` from the origin account (on-chain)... + for asset in assets.inner() { + Config::AssetTransactor::withdraw_asset( + asset, + origin, + Some(&self.context), + )?; + } + Ok(()) + }) + .and_then(|_| { + // ...and place into holding. + self.holding.subsume_assets(assets.into()); + Ok(()) + }) }, ReserveAssetDeposited(assets) => { // check whether we trust origin to be our reserve location for this asset. - let origin = *self.origin_ref().ok_or(XcmError::BadOrigin)?; - for asset in assets.into_inner().into_iter() { + let origin = self.origin_ref().ok_or(XcmError::BadOrigin)?; + self.ensure_can_subsume_assets(assets.len())?; + for asset in assets.inner() { // Must ensure that we recognise the asset as being managed by the origin. ensure!( - Config::IsReserve::contains(&asset, &origin), + Config::IsReserve::contains(asset, origin), XcmError::UntrustedReserveLocation ); - self.subsume_asset(asset)?; } + self.holding.subsume_assets(assets.into()); Ok(()) }, TransferAsset { assets, beneficiary } => { - // Take `assets` from the origin account (on-chain) and place into dest account. - let origin = self.origin_ref().ok_or(XcmError::BadOrigin)?; - for asset in assets.inner() { - Config::AssetTransactor::transfer_asset( - &asset, - origin, - &beneficiary, - &self.context, - )?; - } - Ok(()) + Config::TransactionalProcessor::process(|| { + // Take `assets` from the origin account (on-chain) and place into dest account. + let origin = self.origin_ref().ok_or(XcmError::BadOrigin)?; + for asset in assets.inner() { + Config::AssetTransactor::transfer_asset( + &asset, + origin, + &beneficiary, + &self.context, + )?; + } + Ok(()) + }) }, TransferReserveAsset { mut assets, dest, xcm } => { - let origin = self.origin_ref().ok_or(XcmError::BadOrigin)?; - // Take `assets` from the origin account (on-chain) and place into dest account. - for asset in assets.inner() { - Config::AssetTransactor::transfer_asset(asset, origin, &dest, &self.context)?; - } - let reanchor_context = Config::UniversalLocation::get(); - assets.reanchor(&dest, reanchor_context).map_err(|()| XcmError::LocationFull)?; - let mut message = vec![ReserveAssetDeposited(assets), ClearOrigin]; - message.extend(xcm.0.into_iter()); - self.send(dest, Xcm(message), FeeReason::TransferReserveAsset)?; - Ok(()) + Config::TransactionalProcessor::process(|| { + let origin = self.origin_ref().ok_or(XcmError::BadOrigin)?; + // Take `assets` from the origin account (on-chain) and place into dest account. + for asset in assets.inner() { + Config::AssetTransactor::transfer_asset( + asset, + origin, + &dest, + &self.context, + )?; + } + let reanchor_context = Config::UniversalLocation::get(); + assets + .reanchor(&dest, reanchor_context) + .map_err(|()| XcmError::LocationFull)?; + let mut message = vec![ReserveAssetDeposited(assets), ClearOrigin]; + message.extend(xcm.0.into_iter()); + self.send(dest, Xcm(message), FeeReason::TransferReserveAsset)?; + Ok(()) + }) }, ReceiveTeleportedAsset(assets) => { - let origin = *self.origin_ref().ok_or(XcmError::BadOrigin)?; - // check whether we trust origin to teleport this asset to us via config trait. - for asset in assets.inner() { - // We only trust the origin to send us assets that they identify as their - // sovereign assets. - ensure!( - Config::IsTeleporter::contains(asset, &origin), - XcmError::UntrustedTeleportLocation - ); - // We should check that the asset can actually be teleported in (for this to be - // in error, there would need to be an accounting violation by one of the - // trusted chains, so it's unlikely, but we don't want to punish a possibly - // innocent chain/user). - Config::AssetTransactor::can_check_in(&origin, asset, &self.context)?; - } - for asset in assets.into_inner().into_iter() { - Config::AssetTransactor::check_in(&origin, &asset, &self.context); - self.subsume_asset(asset)?; - } - Ok(()) + let origin = self.origin_ref().ok_or(XcmError::BadOrigin)?; + self.ensure_can_subsume_assets(assets.len())?; + Config::TransactionalProcessor::process(|| { + // check whether we trust origin to teleport this asset to us via config trait. + for asset in assets.inner() { + // We only trust the origin to send us assets that they identify as their + // sovereign assets. + ensure!( + Config::IsTeleporter::contains(asset, origin), + XcmError::UntrustedTeleportLocation + ); + // We should check that the asset can actually be teleported in (for this to + // be in error, there would need to be an accounting violation by one of the + // trusted chains, so it's unlikely, but we don't want to punish a possibly + // innocent chain/user). + Config::AssetTransactor::can_check_in(origin, asset, &self.context)?; + Config::AssetTransactor::check_in(origin, asset, &self.context); + } + Ok(()) + }) + .and_then(|_| { + self.holding.subsume_assets(assets.into()); + Ok(()) + }) }, Transact { origin_kind, require_weight_at_most, mut call } => { // We assume that the Relay-chain is allowed to use transact on this parachain. @@ -619,62 +667,109 @@ impl XcmExecutor { Ok(()) }, DepositAsset { assets, beneficiary } => { - let deposited = self.holding.saturating_take(assets); - for asset in deposited.into_assets_iter() { - Config::AssetTransactor::deposit_asset( - &asset, - &beneficiary, - Some(&self.context), - )?; + let old_holding = self.holding.clone(); + let result = Config::TransactionalProcessor::process(|| { + let deposited = self.holding.saturating_take(assets); + for asset in deposited.into_assets_iter() { + Config::AssetTransactor::deposit_asset( + &asset, + &beneficiary, + Some(&self.context), + )?; + } + Ok(()) + }); + if Config::TransactionalProcessor::IS_TRANSACTIONAL && result.is_err() { + self.holding = old_holding; } - Ok(()) + result }, DepositReserveAsset { assets, dest, xcm } => { - let deposited = self.holding.saturating_take(assets); - for asset in deposited.assets_iter() { - Config::AssetTransactor::deposit_asset(&asset, &dest, Some(&self.context))?; + let old_holding = self.holding.clone(); + let result = Config::TransactionalProcessor::process(|| { + // we need to do this take/put cycle to solve wildcards and get exact assets to + // be weighed + let to_weigh = self.holding.saturating_take(assets.clone()); + self.holding.subsume_assets(to_weigh.clone()); + + let mut message_to_weigh = + vec![ReserveAssetDeposited(to_weigh.into()), ClearOrigin]; + message_to_weigh.extend(xcm.0.clone().into_iter()); + let (_, fee) = + validate_send::(dest, Xcm(message_to_weigh))?; + // set aside fee to be charged by XcmSender + let transport_fee = self.holding.saturating_take(fee.into()); + + // now take assets to deposit (excluding transport_fee) + let deposited = self.holding.saturating_take(assets); + for asset in deposited.assets_iter() { + Config::AssetTransactor::deposit_asset(&asset, &dest, Some(&self.context))?; + } + // Note that we pass `None` as `maybe_failed_bin` and drop any assets which + // cannot be reanchored because we have already called `deposit_asset` on all + // assets. + let assets = Self::reanchored(deposited, &dest, None); + let mut message = vec![ReserveAssetDeposited(assets), ClearOrigin]; + message.extend(xcm.0.into_iter()); + + // put back transport_fee in holding register to be charged by XcmSender + self.holding.subsume_assets(transport_fee); + self.send(dest, Xcm(message), FeeReason::DepositReserveAsset)?; + Ok(()) + }); + if Config::TransactionalProcessor::IS_TRANSACTIONAL && result.is_err() { + self.holding = old_holding; } - // Note that we pass `None` as `maybe_failed_bin` and drop any assets which cannot - // be reanchored because we have already called `deposit_asset` on all assets. - let assets = Self::reanchored(deposited, &dest, None); - let mut message = vec![ReserveAssetDeposited(assets), ClearOrigin]; - message.extend(xcm.0.into_iter()); - self.send(dest, Xcm(message), FeeReason::DepositReserveAsset)?; - Ok(()) + result }, InitiateReserveWithdraw { assets, reserve, xcm } => { - // Note that here we are able to place any assets which could not be reanchored - // back into Holding. - let assets = Self::reanchored( - self.holding.saturating_take(assets), - &reserve, - Some(&mut self.holding), - ); - let mut message = vec![WithdrawAsset(assets), ClearOrigin]; - message.extend(xcm.0.into_iter()); - self.send(reserve, Xcm(message), FeeReason::InitiateReserveWithdraw)?; - Ok(()) + let old_holding = self.holding.clone(); + let result = Config::TransactionalProcessor::process(|| { + // Note that here we are able to place any assets which could not be reanchored + // back into Holding. + let assets = Self::reanchored( + self.holding.saturating_take(assets), + &reserve, + Some(&mut self.holding), + ); + let mut message = vec![WithdrawAsset(assets), ClearOrigin]; + message.extend(xcm.0.into_iter()); + self.send(reserve, Xcm(message), FeeReason::InitiateReserveWithdraw)?; + Ok(()) + }); + if Config::TransactionalProcessor::IS_TRANSACTIONAL && result.is_err() { + self.holding = old_holding; + } + result }, InitiateTeleport { assets, dest, xcm } => { - // We must do this first in order to resolve wildcards. - let assets = self.holding.saturating_take(assets); - for asset in assets.assets_iter() { - // We should check that the asset can actually be teleported out (for this to - // be in error, there would need to be an accounting violation by ourselves, - // so it's unlikely, but we don't want to allow that kind of bug to leak into - // a trusted chain. - Config::AssetTransactor::can_check_out(&dest, &asset, &self.context)?; - } - for asset in assets.assets_iter() { - Config::AssetTransactor::check_out(&dest, &asset, &self.context); + let old_holding = self.holding.clone(); + let result = (|| -> Result<(), XcmError> { + // We must do this first in order to resolve wildcards. + let assets = self.holding.saturating_take(assets); + for asset in assets.assets_iter() { + // We should check that the asset can actually be teleported out (for this + // to be in error, there would need to be an accounting violation by + // ourselves, so it's unlikely, but we don't want to allow that kind of bug + // to leak into a trusted chain. + Config::AssetTransactor::can_check_out(&dest, &asset, &self.context)?; + } + // Note that we pass `None` as `maybe_failed_bin` and drop any assets which + // cannot be reanchored because we have already checked all assets out. + let reanchored_assets = Self::reanchored(assets.clone(), &dest, None); + let mut message = vec![ReceiveTeleportedAsset(reanchored_assets), ClearOrigin]; + message.extend(xcm.0.into_iter()); + self.send(dest, Xcm(message), FeeReason::InitiateTeleport)?; + + for asset in assets.assets_iter() { + Config::AssetTransactor::check_out(&dest, &asset, &self.context); + } + Ok(()) + })(); + if result.is_err() { + self.holding = old_holding; } - // Note that we pass `None` as `maybe_failed_bin` and drop any assets which cannot - // be reanchored because we have already checked all assets out. - let assets = Self::reanchored(assets, &dest, None); - let mut message = vec![ReceiveTeleportedAsset(assets), ClearOrigin]; - message.extend(xcm.0.into_iter()); - self.send(dest, Xcm(message), FeeReason::InitiateTeleport)?; - Ok(()) + result }, ReportHolding { response_info, assets } => { // Note that we pass `None` as `maybe_failed_bin` since no assets were ever removed @@ -690,18 +785,24 @@ impl XcmExecutor { Ok(()) }, BuyExecution { fees, weight_limit } => { - // There is no need to buy any weight is `weight_limit` is `Unlimited` since it + // There is no need to buy any weight if `weight_limit` is `Unlimited` since it // would indicate that `AllowTopLevelPaidExecutionFrom` was unused for execution // and thus there is some other reason why it has been determined that this XCM // should be executed. - if let Some(weight) = Option::::from(weight_limit) { - // pay for `weight` using up to `fees` of the holding register. - let max_fee = - self.holding.try_take(fees.into()).map_err(|_| XcmError::NotHoldingFees)?; + let Some(weight) = Option::::from(weight_limit) else { return Ok(()) }; + let old_holding = self.holding.clone(); + // pay for `weight` using up to `fees` of the holding register. + let max_fee = + self.holding.try_take(fees.into()).map_err(|_| XcmError::NotHoldingFees)?; + let result = || -> Result<(), XcmError> { let unspent = self.trader.buy_weight(weight, max_fee, &self.context)?; - self.subsume_assets(unspent)?; + self.holding.subsume_assets(unspent); + Ok(()) + }(); + if result.is_err() { + self.holding = old_holding; } - Ok(()) + result }, RefundSurplus => self.refund_surplus(), SetErrorHandler(mut handler) => { @@ -726,11 +827,10 @@ impl XcmExecutor { }, ClaimAsset { assets, ticket } => { let origin = self.origin_ref().ok_or(XcmError::BadOrigin)?; + self.ensure_can_subsume_assets(assets.len())?; let ok = Config::AssetClaims::claim_assets(origin, &ticket, &assets, &self.context); ensure!(ok, XcmError::UnknownClaim); - for asset in assets.into_inner().into_iter() { - self.subsume_asset(asset)?; - } + self.holding.subsume_assets(assets.into()); Ok(()) }, Trap(code) => Err(XcmError::Trap(code)), @@ -848,8 +948,8 @@ impl XcmExecutor { let hash = (self.origin_ref(), &destination).using_encoded(blake2_128); let channel = u32::decode(&mut hash.as_ref()).unwrap_or(0); // Hash identifies the lane on the exporter which we use. We use the pairwise - // combination of the origin and destination to ensure origin/destination pairs will - // generally have their own lanes. + // combination of the origin and destination to ensure origin/destination pairs + // will generally have their own lanes. let (ticket, fee) = validate_export::( network, channel, @@ -857,22 +957,41 @@ impl XcmExecutor { destination, xcm, )?; - self.take_fee(fee, FeeReason::Export { network, destination })?; - Config::MessageExporter::deliver(ticket)?; - Ok(()) + let old_holding = self.holding.clone(); + let result = Config::TransactionalProcessor::process(|| { + self.take_fee(fee, FeeReason::Export { network, destination })?; + let _ = Config::MessageExporter::deliver(ticket).defensive_proof( + "`deliver` called immediately after `validate_export`; \ + `take_fee` does not affect the validity of the ticket; qed", + ); + Ok(()) + }); + if Config::TransactionalProcessor::IS_TRANSACTIONAL && result.is_err() { + self.holding = old_holding; + } + result }, LockAsset { asset, unlocker } => { - let origin = *self.origin_ref().ok_or(XcmError::BadOrigin)?; - let (remote_asset, context) = Self::try_reanchor(asset.clone(), &unlocker)?; - let lock_ticket = Config::AssetLocker::prepare_lock(unlocker, asset, origin)?; - let owner = - origin.reanchored(&unlocker, context).map_err(|_| XcmError::ReanchorFailed)?; - let msg = Xcm::<()>(vec![NoteUnlockable { asset: remote_asset, owner }]); - let (ticket, price) = validate_send::(unlocker, msg)?; - self.take_fee(price, FeeReason::LockAsset)?; - lock_ticket.enact()?; - Config::XcmSender::deliver(ticket)?; - Ok(()) + let old_holding = self.holding.clone(); + let result = Config::TransactionalProcessor::process(|| { + let origin = self.cloned_origin().ok_or(XcmError::BadOrigin)?; + let (remote_asset, context) = Self::try_reanchor(asset.clone(), &unlocker)?; + let lock_ticket = + Config::AssetLocker::prepare_lock(unlocker, asset, origin)?; + let owner = origin + .reanchored(&unlocker, context) + .map_err(|_| XcmError::ReanchorFailed)?; + let msg = Xcm::<()>(vec![NoteUnlockable { asset: remote_asset, owner }]); + let (ticket, price) = validate_send::(unlocker, msg)?; + self.take_fee(price, FeeReason::LockAsset)?; + lock_ticket.enact()?; + Config::XcmSender::deliver(ticket)?; + Ok(()) + }); + if Config::TransactionalProcessor::IS_TRANSACTIONAL && result.is_err() { + self.holding = old_holding; + } + result }, UnlockAsset { asset, target } => { let origin = *self.origin_ref().ok_or(XcmError::BadOrigin)?; @@ -893,25 +1012,40 @@ impl XcmExecutor { let msg = Xcm::<()>(vec![UnlockAsset { asset: remote_asset, target: remote_target }]); let (ticket, price) = validate_send::(locker, msg)?; - self.take_fee(price, FeeReason::RequestUnlock)?; - reduce_ticket.enact()?; - Config::XcmSender::deliver(ticket)?; - Ok(()) + let old_holding = self.holding.clone(); + let result = Config::TransactionalProcessor::process(|| { + self.take_fee(price, FeeReason::RequestUnlock)?; + reduce_ticket.enact()?; + Config::XcmSender::deliver(ticket)?; + Ok(()) + }); + if Config::TransactionalProcessor::IS_TRANSACTIONAL && result.is_err() { + self.holding = old_holding; + } + result }, ExchangeAsset { give, want, maximal } => { + let old_holding = self.holding.clone(); let give = self.holding.saturating_take(give); - let r = - Config::AssetExchanger::exchange_asset(self.origin_ref(), give, &want, maximal); - let completed = r.is_ok(); - let received = r.unwrap_or_else(|a| a); - for asset in received.into_assets_iter() { - self.holding.subsume(asset); - } - if completed { - Ok(()) - } else { - Err(XcmError::NoDeal) + let result = (|| -> Result<(), XcmError> { + self.ensure_can_subsume_assets(want.len())?; + let exchange_result = Config::AssetExchanger::exchange_asset( + self.origin_ref(), + give, + &want, + maximal, + ); + if let Ok(received) = exchange_result { + self.holding.subsume_assets(received.into()); + Ok(()) + } else { + Err(XcmError::NoDeal) + } + })(); + if result.is_err() { + self.holding = old_holding; } + result }, SetFeesMode { jit_withdraw } => { self.fees_mode = FeesMode { jit_withdraw }; diff --git a/polkadot/xcm/xcm-executor/src/traits/mod.rs b/polkadot/xcm/xcm-executor/src/traits/mod.rs index 71e75c77e939..b445e84d3912 100644 --- a/polkadot/xcm/xcm-executor/src/traits/mod.rs +++ b/polkadot/xcm/xcm-executor/src/traits/mod.rs @@ -39,6 +39,8 @@ pub use token_matching::{ }; mod on_response; pub use on_response::{OnResponse, QueryHandler, QueryResponseStatus, VersionChangeNotifier}; +mod process_transaction; +pub use process_transaction::ProcessTransaction; mod should_execute; pub use should_execute::{CheckSuspension, Properties, ShouldExecute}; mod transact_asset; @@ -52,8 +54,9 @@ pub mod prelude { pub use super::{ export_xcm, validate_export, AssetExchange, AssetLock, ClaimAssets, ConvertOrigin, DropAssets, Enact, Error, ExportXcm, FeeManager, FeeReason, LockError, MatchesFungible, - MatchesFungibles, MatchesNonFungible, MatchesNonFungibles, OnResponse, ShouldExecute, - TransactAsset, VersionChangeNotifier, WeightBounds, WeightTrader, WithOriginFilter, + MatchesFungibles, MatchesNonFungible, MatchesNonFungibles, OnResponse, ProcessTransaction, + ShouldExecute, TransactAsset, VersionChangeNotifier, WeightBounds, WeightTrader, + WithOriginFilter, }; #[allow(deprecated)] pub use super::{Identity, JustTry}; diff --git a/polkadot/xcm/xcm-executor/src/traits/process_transaction.rs b/polkadot/xcm/xcm-executor/src/traits/process_transaction.rs new file mode 100644 index 000000000000..22ad8755b9c9 --- /dev/null +++ b/polkadot/xcm/xcm-executor/src/traits/process_transaction.rs @@ -0,0 +1,57 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +use xcm::latest::prelude::*; + +/// Provides mechanisms for transactional processing of XCM instructions. +/// +/// This trait defines the behavior required to process XCM instructions in a transactional +/// manner. Implementers of this trait can ensure that XCM instructions are executed +/// atomically, meaning they either fully succeed or fully fail without any partial effects. +/// +/// Implementers of this trait can also choose to not process XCM instructions transactionally. +/// This is useful for cases where the implementer is not able to provide transactional guarantees. +/// In this case the `IS_TRANSACTIONAL` constant should be set to `false`. +/// The `()` type implements this trait in a non-transactional manner. +pub trait ProcessTransaction { + /// Whether or not the implementor of the this trait is actually transactional. + const IS_TRANSACTIONAL: bool; + + /// Processes an XCM instruction encapsulated within the provided closure. Responsible for + /// processing an XCM instruction transactionally. If the closure returns an error, any + /// changes made during its execution should be rolled back. In the case where the + /// implementer is not able to provide transactional guarantees, the closure should be + /// executed as is. + /// # Parameters + /// - `f`: A closure that encapsulates the XCM instruction being processed. It will return a + /// `Result` indicating the success or failure of the instruction. + /// + /// # Returns + /// - A `Result` indicating the overall success or failure of the transactional process. + fn process(f: F) -> Result<(), XcmError> + where + F: FnOnce() -> Result<(), XcmError>; +} + +impl ProcessTransaction for () { + const IS_TRANSACTIONAL: bool = false; + fn process(f: F) -> Result<(), XcmError> + where + F: FnOnce() -> Result<(), XcmError>, + { + f() + } +} diff --git a/polkadot/xcm/xcm-simulator/example/src/parachain.rs b/polkadot/xcm/xcm-simulator/example/src/parachain.rs index 951e946372da..fbc78ed5884f 100644 --- a/polkadot/xcm/xcm-simulator/example/src/parachain.rs +++ b/polkadot/xcm/xcm-simulator/example/src/parachain.rs @@ -41,7 +41,7 @@ use xcm::{latest::prelude::*, VersionedXcm}; use xcm_builder::{ Account32Hash, AccountId32Aliases, AllowUnpaidExecutionFrom, ConvertedConcreteId, CurrencyAdapter as XcmCurrencyAdapter, EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, - IsConcrete, NativeAsset, NoChecking, NonFungiblesAdapter, ParentIsPreset, + FrameTransactionalProcessor, IsConcrete, NativeAsset, NoChecking, NonFungiblesAdapter, ParentIsPreset, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, }; @@ -251,6 +251,7 @@ impl Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } #[frame_support::pallet] diff --git a/polkadot/xcm/xcm-simulator/example/src/relay_chain.rs b/polkadot/xcm/xcm-simulator/example/src/relay_chain.rs index 20070d192b54..50867353d4f1 100644 --- a/polkadot/xcm/xcm-simulator/example/src/relay_chain.rs +++ b/polkadot/xcm/xcm-simulator/example/src/relay_chain.rs @@ -37,7 +37,7 @@ use xcm_builder::{ Account32Hash, AccountId32Aliases, AllowUnpaidExecutionFrom, AsPrefixedGeneralIndex, ChildParachainAsNative, ChildParachainConvertsVia, ChildSystemParachainAsSuperuser, ConvertedConcreteId, CurrencyAdapter as XcmCurrencyAdapter, FixedRateOfFungible, - FixedWeightBounds, IsConcrete, NoChecking, NonFungiblesAdapter, SignedAccountId32AsNative, + FixedWeightBounds, FrameTransactionalProcessor, IsConcrete, NoChecking, NonFungiblesAdapter, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, }; use xcm_executor::{traits::JustTry, Config, XcmExecutor}; @@ -196,6 +196,7 @@ impl Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } pub type LocalOriginToLocation = SignedToAccountId32; diff --git a/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs b/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs index 0aa1b54f5e71..7382d90c7542 100644 --- a/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs +++ b/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs @@ -39,7 +39,7 @@ use polkadot_parachain_primitives::primitives::{ use xcm::{latest::prelude::*, VersionedXcm}; use xcm_builder::{ AccountId32Aliases, AllowUnpaidExecutionFrom, CurrencyAdapter as XcmCurrencyAdapter, - EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, IsConcrete, NativeAsset, + EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, FrameTransactionalProcessor, IsConcrete, NativeAsset, ParentIsPreset, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, }; @@ -164,6 +164,7 @@ impl Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } #[frame_support::pallet] diff --git a/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs b/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs index 085773f30737..1e869fe1fd5d 100644 --- a/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs +++ b/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs @@ -36,8 +36,8 @@ use xcm::latest::prelude::*; use xcm_builder::{ AccountId32Aliases, AllowUnpaidExecutionFrom, ChildParachainAsNative, ChildParachainConvertsVia, ChildSystemParachainAsSuperuser, - CurrencyAdapter as XcmCurrencyAdapter, FixedRateOfFungible, FixedWeightBounds, IsConcrete, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, + CurrencyAdapter as XcmCurrencyAdapter, FixedRateOfFungible, FixedWeightBounds, FrameTransactionalProcessor, + IsConcrete, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, }; use xcm_executor::{Config, XcmExecutor}; @@ -160,6 +160,7 @@ impl Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } pub type LocalOriginToLocation = SignedToAccountId32; diff --git a/prdoc/pr_1222.prdoc b/prdoc/pr_1222.prdoc new file mode 100644 index 000000000000..82eb341649bc --- /dev/null +++ b/prdoc/pr_1222.prdoc @@ -0,0 +1,33 @@ +title: Transactional processing for XCM + +doc: + - audience: Runtime Dev + description: | + Transactional processing was introduced for certain XCM instructions. They are: + - WithdrawAsset + - ReserveAssetDeposited + - TransferAsset + - TransferReserveAsset + - ReceiveTeleportedAsset + - DepositAsset + - DepositReserveAsset + - InitiateReserveWithdraw + - InitiateTeleport + - BuyExecution + - ClaimAsset + - ExportMessage + - LockAsset + - UnlockAsset + - RequestUnlock + Developers must specify a `TransactionalProcessor` when configuring their XCM executor. + FRAME-based runtimes would simply need to configure it with `FrameTransactionalProcessor` to + enable transactional processing. To disable transactional processing of XCMs, `()` may also be + specified as the type for `TransactionalProcessor`. + For runtimes that are not FRAME-based but would like to still harness transactional processing + of XCMs, a type implementing the `ProcessTransaction` trait must be specified as the type for + `TransactionalProcessor`. This trait is for the purpose of connecting the chain's runtime + transactional processor with the XCM executor -- any implementation of `ProcessTransaction` is + possible to be assigned as the `TransactionalProcessor` for the XCM executor. + +crates: + - name: staging-xcm-executor diff --git a/substrate/bin/node/cli/tests/websocket_server.rs b/substrate/bin/node/cli/tests/websocket_server.rs index 432a4871cd37..b34fc82b8be8 100644 --- a/substrate/bin/node/cli/tests/websocket_server.rs +++ b/substrate/bin/node/cli/tests/websocket_server.rs @@ -205,8 +205,7 @@ impl WsServer { Ok(soketto::Data::Text(len)) => String::from_utf8(buf[..len].to_vec()) .map(Message::Text) .map_err(|err| Box::new(err) as Box<_>), - Ok(soketto::Data::Binary(len)) => Ok(buf[..len].to_vec()) - .map(Message::Binary), + Ok(soketto::Data::Binary(len)) => Ok(Message::Binary(buf[..len].to_vec())), Err(err) => Err(Box::new(err) as Box<_>), }; Some((ret, (receiver, buf))) diff --git a/substrate/client/consensus/babe/src/tests.rs b/substrate/client/consensus/babe/src/tests.rs index e7096832eb36..38c9e1ff6ac2 100644 --- a/substrate/client/consensus/babe/src/tests.rs +++ b/substrate/client/consensus/babe/src/tests.rs @@ -411,7 +411,7 @@ async fn run_one_test(mutator: impl Fn(&mut TestHeader, Stage) + Send + Sync + ' let mut net = net.lock(); net.poll(cx); for p in net.peers() { - for (h, e) in p.failed_verifications() { + if let Some((h, e)) = p.failed_verifications().into_iter().next() { panic!("Verification failed for {:?}: {}", h, e); } } diff --git a/substrate/frame/contracts/mock-network/src/parachain.rs b/substrate/frame/contracts/mock-network/src/parachain.rs index 2ef579276aec..b6077e937502 100644 --- a/substrate/frame/contracts/mock-network/src/parachain.rs +++ b/substrate/frame/contracts/mock-network/src/parachain.rs @@ -39,8 +39,8 @@ use sp_std::prelude::*; use xcm::latest::prelude::*; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowTopLevelPaidExecutionFrom, - ConvertedConcreteId, CurrencyAdapter as XcmCurrencyAdapter, EnsureXcmOrigin, - FixedRateOfFungible, FixedWeightBounds, FungiblesAdapter, IsConcrete, NativeAsset, NoChecking, + ConvertedConcreteId, CurrencyAdapter as XcmCurrencyAdapter, EnsureXcmOrigin, FixedRateOfFungible, + FixedWeightBounds, FrameTransactionalProcessor, FungiblesAdapter, IsConcrete, NativeAsset, NoChecking, ParentAsSuperuser, ParentIsPreset, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, WithComputedOrigin, }; @@ -286,6 +286,7 @@ impl Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } impl mock_msg_queue::Config for Runtime { diff --git a/substrate/frame/contracts/mock-network/src/relay_chain.rs b/substrate/frame/contracts/mock-network/src/relay_chain.rs index 17e36eada259..e763e1027bc0 100644 --- a/substrate/frame/contracts/mock-network/src/relay_chain.rs +++ b/substrate/frame/contracts/mock-network/src/relay_chain.rs @@ -33,7 +33,7 @@ use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, ChildParachainAsNative, ChildParachainConvertsVia, ChildSystemParachainAsSuperuser, CurrencyAdapter as XcmCurrencyAdapter, DescribeAllTerminal, - DescribeFamily, FixedRateOfFungible, FixedWeightBounds, HashedDescription, IsConcrete, + DescribeFamily, FixedRateOfFungible, FixedWeightBounds, FrameTransactionalProcessor, HashedDescription, IsConcrete, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, WithComputedOrigin, }; use xcm_executor::{Config, XcmExecutor}; @@ -180,6 +180,7 @@ impl Config for XcmConfig { type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } pub type LocalOriginToLocation = SignedToAccountId32; diff --git a/substrate/frame/sassafras/src/data/tickets-sort.md b/substrate/frame/sassafras/src/data/tickets-sort.md index 4d96a6825c88..64fc45e4fb00 100644 --- a/substrate/frame/sassafras/src/data/tickets-sort.md +++ b/substrate/frame/sassafras/src/data/tickets-sort.md @@ -267,7 +267,7 @@ buffer (i.e. how many tickets we retain from the last processed segment) | 3 | 14 | | 2 | 17 | | 1 | 9 | -| 0 | 13 +| 0 | 13 | # Graph of the same data diff --git a/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr b/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr index a791c313b4a8..b08efb3a8421 100644 --- a/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr +++ b/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr @@ -17,6 +17,7 @@ error: use of deprecated constant `WhereSection::_w`: | |_^ | = note: `-D deprecated` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(deprecated)]` = note: this error originates in the macro `frame_support::match_and_insert` which comes from the expansion of the macro `construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Runtime: Config` is not satisfied diff --git a/substrate/frame/support/test/tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.stderr b/substrate/frame/support/test/tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.stderr index 7ed77e75da4c..a8c1daf88da9 100644 --- a/substrate/frame/support/test/tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.stderr +++ b/substrate/frame/support/test/tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.stderr @@ -31,19 +31,34 @@ error[E0412]: cannot find type `RuntimeOrigin` in this scope --> tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.rs:42:23 | 42 | type RuntimeOrigin = RuntimeOrigin; - | ^^^^^^^^^^^^^ help: you might have meant to use the associated type: `Self::RuntimeOrigin` + | ^^^^^^^^^^^^^ + | +help: you might have meant to use the associated type + | +42 | type RuntimeOrigin = Self::RuntimeOrigin; + | ++++++ error[E0412]: cannot find type `RuntimeCall` in this scope --> tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.rs:44:21 | 44 | type RuntimeCall = RuntimeCall; - | ^^^^^^^^^^^ help: you might have meant to use the associated type: `Self::RuntimeCall` + | ^^^^^^^^^^^ + | +help: you might have meant to use the associated type + | +44 | type RuntimeCall = Self::RuntimeCall; + | ++++++ error[E0412]: cannot find type `RuntimeEvent` in this scope --> tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.rs:50:22 | 50 | type RuntimeEvent = RuntimeEvent; - | ^^^^^^^^^^^^ help: you might have meant to use the associated type: `Self::RuntimeEvent` + | ^^^^^^^^^^^^ + | +help: you might have meant to use the associated type + | +50 | type RuntimeEvent = Self::RuntimeEvent; + | ++++++ error[E0412]: cannot find type `PalletInfo` in this scope --> tests/construct_runtime_ui/number_of_pallets_exceeds_tuple_size.rs:56:20 @@ -54,7 +69,7 @@ error[E0412]: cannot find type `PalletInfo` in this scope help: you might have meant to use the associated type | 56 | type PalletInfo = Self::PalletInfo; - | ~~~~~~~~~~~~~~~~ + | ++++++ help: consider importing one of these items | 18 + use frame_benchmarking::__private::traits::PalletInfo; diff --git a/substrate/frame/support/test/tests/derive_impl_ui/inject_runtime_type_fails_when_type_not_in_scope.stderr b/substrate/frame/support/test/tests/derive_impl_ui/inject_runtime_type_fails_when_type_not_in_scope.stderr index f3ac6b232811..58aae713f752 100644 --- a/substrate/frame/support/test/tests/derive_impl_ui/inject_runtime_type_fails_when_type_not_in_scope.stderr +++ b/substrate/frame/support/test/tests/derive_impl_ui/inject_runtime_type_fails_when_type_not_in_scope.stderr @@ -2,9 +2,13 @@ error[E0412]: cannot find type `RuntimeCall` in this scope --> tests/derive_impl_ui/inject_runtime_type_fails_when_type_not_in_scope.rs:30:10 | 30 | type RuntimeCall = (); - | ^^^^^^^^^^^ help: you might have meant to use the associated type: `Self::RuntimeCall` + | ^^^^^^^^^^^ ... 35 | #[derive_impl(Pallet)] // Injects type RuntimeCall = RuntimeCall; | ---------------------- in this macro invocation | = note: this error originates in the macro `Pallet` which comes from the expansion of the macro `frame_support::macro_magic::forward_tokens_verbatim` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might have meant to use the associated type + | +30 | type Self::RuntimeCall = (); + | ++++++ diff --git a/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound.stderr b/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound.stderr index 08ea7c0bec3a..40f8f1298304 100644 --- a/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound.stderr @@ -10,6 +10,7 @@ error: use of deprecated constant `pallet::warnings::ConstantWeight_0::_w`: | ^ | = note: `-D deprecated` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(deprecated)]` error[E0277]: `::Bar` doesn't implement `std::fmt::Debug` --> tests/pallet_ui/call_argument_invalid_bound.rs:38:36 diff --git a/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr b/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr index 80316fcd2489..5744c6362350 100644 --- a/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_2.stderr @@ -10,6 +10,7 @@ error: use of deprecated constant `pallet::warnings::ConstantWeight_0::_w`: | ^ | = note: `-D deprecated` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(deprecated)]` error[E0277]: `::Bar` doesn't implement `std::fmt::Debug` --> tests/pallet_ui/call_argument_invalid_bound_2.rs:38:36 @@ -45,9 +46,9 @@ error[E0277]: the trait bound `::Bar: WrapperTypeEncode` is = note: required for `::Bar` to implement `Encode` error[E0277]: the trait bound `::Bar: WrapperTypeDecode` is not satisfied - --> tests/pallet_ui/call_argument_invalid_bound_2.rs:34:12 + --> tests/pallet_ui/call_argument_invalid_bound_2.rs:38:42 | -34 | #[pallet::call] - | ^^^^ the trait `WrapperTypeDecode` is not implemented for `::Bar` +38 | pub fn foo(origin: OriginFor, _bar: T::Bar) -> DispatchResultWithPostInfo { + | ^^^^^^ the trait `WrapperTypeDecode` is not implemented for `::Bar` | = note: required for `::Bar` to implement `Decode` diff --git a/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.stderr b/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.stderr index d45b74bad842..b58e4516bceb 100644 --- a/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/call_argument_invalid_bound_3.stderr @@ -10,6 +10,7 @@ error: use of deprecated constant `pallet::warnings::ConstantWeight_0::_w`: | ^ | = note: `-D deprecated` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(deprecated)]` error[E0277]: `Bar` doesn't implement `std::fmt::Debug` --> tests/pallet_ui/call_argument_invalid_bound_3.rs:40:36 diff --git a/substrate/frame/support/test/tests/pallet_ui/call_missing_index.stderr b/substrate/frame/support/test/tests/pallet_ui/call_missing_index.stderr index 4d55ef798569..ba06285bdeea 100644 --- a/substrate/frame/support/test/tests/pallet_ui/call_missing_index.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/call_missing_index.stderr @@ -11,6 +11,7 @@ error: use of deprecated constant `pallet::warnings::ImplicitCallIndex_0::_w`: | ^^^ | = note: `-D deprecated` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(deprecated)]` error: use of deprecated constant `pallet::warnings::ImplicitCallIndex_1::_w`: It is deprecated to use implicit call indices. diff --git a/substrate/frame/support/test/tests/pallet_ui/call_weight_argument_has_suffix.stderr b/substrate/frame/support/test/tests/pallet_ui/call_weight_argument_has_suffix.stderr index cf23a76f8ea0..4b5abdcd0e6d 100644 --- a/substrate/frame/support/test/tests/pallet_ui/call_weight_argument_has_suffix.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/call_weight_argument_has_suffix.stderr @@ -18,3 +18,4 @@ error: use of deprecated constant `pallet::warnings::ConstantWeight_0::_w`: | ^^^^^^^^^^^^^^^ | = note: `-D deprecated` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(deprecated)]` diff --git a/substrate/frame/support/test/tests/pallet_ui/call_weight_const_warning.stderr b/substrate/frame/support/test/tests/pallet_ui/call_weight_const_warning.stderr index ccd5a935773c..d399df4d85bd 100644 --- a/substrate/frame/support/test/tests/pallet_ui/call_weight_const_warning.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/call_weight_const_warning.stderr @@ -10,3 +10,4 @@ error: use of deprecated constant `pallet::warnings::ConstantWeight_0::_w`: | ^^^^^^^ | = note: `-D deprecated` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(deprecated)]` diff --git a/substrate/frame/support/test/tests/pallet_ui/call_weight_const_warning_twice.stderr b/substrate/frame/support/test/tests/pallet_ui/call_weight_const_warning_twice.stderr index aadb939b6454..d7e4951e49fc 100644 --- a/substrate/frame/support/test/tests/pallet_ui/call_weight_const_warning_twice.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/call_weight_const_warning_twice.stderr @@ -18,6 +18,7 @@ error: use of deprecated constant `pallet::warnings::ConstantWeight_0::_w`: | ^^^ | = note: `-D deprecated` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(deprecated)]` error: use of deprecated constant `pallet::warnings::ConstantWeight_1::_w`: It is deprecated to use hard-coded constant as call weight. diff --git a/substrate/frame/support/test/tests/pallet_ui/call_weight_inherited_invalid3.stderr b/substrate/frame/support/test/tests/pallet_ui/call_weight_inherited_invalid3.stderr index e8e6f2fe6df0..339551d9811c 100644 --- a/substrate/frame/support/test/tests/pallet_ui/call_weight_inherited_invalid3.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/call_weight_inherited_invalid3.stderr @@ -17,3 +17,4 @@ error: unused import: `frame_system::pallet_prelude::*` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D unused-imports` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(unused_imports)]` diff --git a/substrate/frame/support/test/tests/pallet_ui/call_weight_unchecked_warning.stderr b/substrate/frame/support/test/tests/pallet_ui/call_weight_unchecked_warning.stderr index 89fc1e0820f5..33302a2a0278 100644 --- a/substrate/frame/support/test/tests/pallet_ui/call_weight_unchecked_warning.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/call_weight_unchecked_warning.stderr @@ -10,3 +10,4 @@ error: use of deprecated constant `pallet::warnings::UncheckedWeightWitness_0::_ | ^^^^^^^ | = note: `-D deprecated` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(deprecated)]` diff --git a/substrate/frame/support/test/tests/pallet_ui/deprecated_store_attr.stderr b/substrate/frame/support/test/tests/pallet_ui/deprecated_store_attr.stderr index 942db0ab4699..e227033d3646 100644 --- a/substrate/frame/support/test/tests/pallet_ui/deprecated_store_attr.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/deprecated_store_attr.stderr @@ -7,3 +7,4 @@ error: use of deprecated struct `pallet::_::Store`: | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D deprecated` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(deprecated)]` diff --git a/substrate/frame/support/test/tests/pallet_ui/dev_mode_without_arg_call_index.stderr b/substrate/frame/support/test/tests/pallet_ui/dev_mode_without_arg_call_index.stderr index bcfe43d008f8..01254584c626 100644 --- a/substrate/frame/support/test/tests/pallet_ui/dev_mode_without_arg_call_index.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/dev_mode_without_arg_call_index.stderr @@ -11,6 +11,7 @@ error: use of deprecated constant `pallet::warnings::ImplicitCallIndex_0::_w`: | ^^^^^^^ | = note: `-D deprecated` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(deprecated)]` error: use of deprecated constant `pallet::warnings::ConstantWeight_0::_w`: It is deprecated to use hard-coded constant as call weight. diff --git a/substrate/frame/support/test/tests/pallet_ui/dev_mode_without_arg_max_encoded_len.stderr b/substrate/frame/support/test/tests/pallet_ui/dev_mode_without_arg_max_encoded_len.stderr index 531e8bdffeb0..02ead305dd81 100644 --- a/substrate/frame/support/test/tests/pallet_ui/dev_mode_without_arg_max_encoded_len.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/dev_mode_without_arg_max_encoded_len.stderr @@ -11,6 +11,7 @@ error: use of deprecated constant `pallet::warnings::ImplicitCallIndex_0::_w`: | ^^^^^^^ | = note: `-D deprecated` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(deprecated)]` error: use of deprecated constant `pallet::warnings::ConstantWeight_0::_w`: It is deprecated to use hard-coded constant as call weight. @@ -26,8 +27,15 @@ error: use of deprecated constant `pallet::warnings::ConstantWeight_0::_w`: error[E0277]: the trait bound `Vec: MaxEncodedLen` is not satisfied --> tests/pallet_ui/dev_mode_without_arg_max_encoded_len.rs:28:12 | -28 | #[pallet::pallet] - | ^^^^^^ the trait `MaxEncodedLen` is not implemented for `Vec` +28 | #[pallet::pallet] + | _______________^ +29 | | pub struct Pallet(_); +30 | | +31 | | // Your Pallet's configuration trait, representing custom external types and interfaces. +... | +35 | | #[pallet::storage] +36 | | type MyStorage = StorageValue<_, Vec>; + | |__________________^ the trait `MaxEncodedLen` is not implemented for `Vec` | = help: the following other types implement trait `MaxEncodedLen`: bool diff --git a/substrate/frame/support/test/tests/pallet_ui/error_does_not_derive_pallet_error.stderr b/substrate/frame/support/test/tests/pallet_ui/error_does_not_derive_pallet_error.stderr index ea1d0ed99cd3..9cefd2f4899a 100644 --- a/substrate/frame/support/test/tests/pallet_ui/error_does_not_derive_pallet_error.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/error_does_not_derive_pallet_error.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `MyError: PalletError` is not satisfied - --> tests/pallet_ui/error_does_not_derive_pallet_error.rs:18:1 + --> tests/pallet_ui/error_does_not_derive_pallet_error.rs:28:15 | -18 | #[frame_support::pallet] - | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `PalletError` is not implemented for `MyError` +28 | CustomError(crate::MyError), + | ^^^^^^^^^^^^^^ the trait `PalletError` is not implemented for `MyError` | = help: the following other types implement trait `PalletError`: bool @@ -14,4 +14,3 @@ error[E0277]: the trait bound `MyError: PalletError` is not satisfied u8 u16 and $N others - = note: this error originates in the derive macro `frame_support::PalletError` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr b/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr index b5d108275249..4229d1e8a545 100644 --- a/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr @@ -1,8 +1,15 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.rs:27:12 | -27 | #[pallet::without_storage_info] - | ^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `Bar` +27 | #[pallet::without_storage_info] + | _______________^ +28 | | pub struct Pallet(core::marker::PhantomData); +29 | | +30 | | #[pallet::hooks] +... | +38 | | #[pallet::storage] +39 | | type Foo = StorageValue; + | |____________^ the trait `WrapperTypeDecode` is not implemented for `Bar` | = help: the following other types implement trait `WrapperTypeDecode`: Box @@ -16,8 +23,15 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.rs:27:12 | -27 | #[pallet::without_storage_info] - | ^^^^^^^^^^^^^^^^^^^^ the trait `EncodeLike` is not implemented for `Bar` +27 | #[pallet::without_storage_info] + | _______________^ +28 | | pub struct Pallet(core::marker::PhantomData); +29 | | +30 | | #[pallet::hooks] +... | +38 | | #[pallet::storage] +39 | | type Foo = StorageValue; + | |____________^ the trait `EncodeLike` is not implemented for `Bar` | = help: the following other types implement trait `EncodeLike`: @@ -36,8 +50,15 @@ error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.rs:27:12 | -27 | #[pallet::without_storage_info] - | ^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `Bar` +27 | #[pallet::without_storage_info] + | _______________^ +28 | | pub struct Pallet(core::marker::PhantomData); +29 | | +30 | | #[pallet::hooks] +... | +38 | | #[pallet::storage] +39 | | type Foo = StorageValue; + | |____________^ the trait `WrapperTypeEncode` is not implemented for `Bar` | = help: the following other types implement trait `WrapperTypeEncode`: Box @@ -57,8 +78,10 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied error[E0277]: the trait bound `Bar: TypeInfo` is not satisfied --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.rs:38:12 | -38 | #[pallet::storage] - | ^^^^^^^ the trait `TypeInfo` is not implemented for `Bar` +38 | #[pallet::storage] + | _______________^ +39 | | type Foo = StorageValue; + | |____________^ the trait `TypeInfo` is not implemented for `Bar` | = help: the following other types implement trait `TypeInfo`: bool @@ -76,8 +99,10 @@ error[E0277]: the trait bound `Bar: TypeInfo` is not satisfied error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.rs:38:12 | -38 | #[pallet::storage] - | ^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `Bar` +38 | #[pallet::storage] + | _______________^ +39 | | type Foo = StorageValue; + | |____________^ the trait `WrapperTypeDecode` is not implemented for `Bar` | = help: the following other types implement trait `WrapperTypeDecode`: Box @@ -91,8 +116,10 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.rs:38:12 | -38 | #[pallet::storage] - | ^^^^^^^ the trait `EncodeLike` is not implemented for `Bar` +38 | #[pallet::storage] + | _______________^ +39 | | type Foo = StorageValue; + | |____________^ the trait `EncodeLike` is not implemented for `Bar` | = help: the following other types implement trait `EncodeLike`: @@ -111,8 +138,10 @@ error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.rs:38:12 | -38 | #[pallet::storage] - | ^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `Bar` +38 | #[pallet::storage] + | _______________^ +39 | | type Foo = StorageValue; + | |____________^ the trait `WrapperTypeEncode` is not implemented for `Bar` | = help: the following other types implement trait `WrapperTypeEncode`: Box @@ -130,10 +159,12 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied = note: required for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` to implement `StorageEntryMetadataBuilder` error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied - --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.rs:18:1 + --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.rs:38:12 | -18 | #[frame_support::pallet] - | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `Bar` +38 | #[pallet::storage] + | _______________^ +39 | | type Foo = StorageValue; + | |____________^ the trait `WrapperTypeDecode` is not implemented for `Bar` | = help: the following other types implement trait `WrapperTypeDecode`: Box @@ -143,13 +174,14 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied = note: required for `Bar` to implement `Decode` = note: required for `Bar` to implement `FullCodec` = note: required for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` to implement `TryDecodeEntireStorage` - = note: this error originates in the attribute macro `frame_support::pallet` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied - --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.rs:18:1 + --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.rs:38:12 | -18 | #[frame_support::pallet] - | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `EncodeLike` is not implemented for `Bar` +38 | #[pallet::storage] + | _______________^ +39 | | type Foo = StorageValue; + | |____________^ the trait `EncodeLike` is not implemented for `Bar` | = help: the following other types implement trait `EncodeLike`: @@ -164,13 +196,14 @@ error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied = note: required for `Bar` to implement `FullEncode` = note: required for `Bar` to implement `FullCodec` = note: required for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` to implement `TryDecodeEntireStorage` - = note: this error originates in the attribute macro `frame_support::pallet` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied - --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.rs:18:1 + --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.rs:38:12 | -18 | #[frame_support::pallet] - | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `Bar` +38 | #[pallet::storage] + | _______________^ +39 | | type Foo = StorageValue; + | |____________^ the trait `WrapperTypeEncode` is not implemented for `Bar` | = help: the following other types implement trait `WrapperTypeEncode`: Box @@ -186,4 +219,3 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied = note: required for `Bar` to implement `FullEncode` = note: required for `Bar` to implement `FullCodec` = note: required for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` to implement `TryDecodeEntireStorage` - = note: this error originates in the attribute macro `frame_support::pallet` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr b/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr index b58902590b85..855d289d0a16 100644 --- a/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr @@ -1,8 +1,15 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:27:12 | -27 | #[pallet::without_storage_info] - | ^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `Bar` +27 | #[pallet::without_storage_info] + | _______________^ +28 | | pub struct Pallet(core::marker::PhantomData); +29 | | +30 | | #[pallet::hooks] +... | +38 | | #[pallet::storage] +39 | | type Foo = StorageValue<_, Bar>; + | |____________^ the trait `WrapperTypeDecode` is not implemented for `Bar` | = help: the following other types implement trait `WrapperTypeDecode`: Box @@ -16,8 +23,15 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:27:12 | -27 | #[pallet::without_storage_info] - | ^^^^^^^^^^^^^^^^^^^^ the trait `EncodeLike` is not implemented for `Bar` +27 | #[pallet::without_storage_info] + | _______________^ +28 | | pub struct Pallet(core::marker::PhantomData); +29 | | +30 | | #[pallet::hooks] +... | +38 | | #[pallet::storage] +39 | | type Foo = StorageValue<_, Bar>; + | |____________^ the trait `EncodeLike` is not implemented for `Bar` | = help: the following other types implement trait `EncodeLike`: @@ -36,8 +50,15 @@ error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:27:12 | -27 | #[pallet::without_storage_info] - | ^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `Bar` +27 | #[pallet::without_storage_info] + | _______________^ +28 | | pub struct Pallet(core::marker::PhantomData); +29 | | +30 | | #[pallet::hooks] +... | +38 | | #[pallet::storage] +39 | | type Foo = StorageValue<_, Bar>; + | |____________^ the trait `WrapperTypeEncode` is not implemented for `Bar` | = help: the following other types implement trait `WrapperTypeEncode`: Box @@ -57,8 +78,10 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied error[E0277]: the trait bound `Bar: TypeInfo` is not satisfied --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:38:12 | -38 | #[pallet::storage] - | ^^^^^^^ the trait `TypeInfo` is not implemented for `Bar` +38 | #[pallet::storage] + | _______________^ +39 | | type Foo = StorageValue<_, Bar>; + | |____________^ the trait `TypeInfo` is not implemented for `Bar` | = help: the following other types implement trait `TypeInfo`: bool @@ -76,8 +99,10 @@ error[E0277]: the trait bound `Bar: TypeInfo` is not satisfied error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:38:12 | -38 | #[pallet::storage] - | ^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `Bar` +38 | #[pallet::storage] + | _______________^ +39 | | type Foo = StorageValue<_, Bar>; + | |____________^ the trait `WrapperTypeDecode` is not implemented for `Bar` | = help: the following other types implement trait `WrapperTypeDecode`: Box @@ -91,8 +116,10 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:38:12 | -38 | #[pallet::storage] - | ^^^^^^^ the trait `EncodeLike` is not implemented for `Bar` +38 | #[pallet::storage] + | _______________^ +39 | | type Foo = StorageValue<_, Bar>; + | |____________^ the trait `EncodeLike` is not implemented for `Bar` | = help: the following other types implement trait `EncodeLike`: @@ -111,8 +138,10 @@ error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:38:12 | -38 | #[pallet::storage] - | ^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `Bar` +38 | #[pallet::storage] + | _______________^ +39 | | type Foo = StorageValue<_, Bar>; + | |____________^ the trait `WrapperTypeEncode` is not implemented for `Bar` | = help: the following other types implement trait `WrapperTypeEncode`: Box @@ -130,10 +159,12 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied = note: required for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` to implement `StorageEntryMetadataBuilder` error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied - --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:18:1 + --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:38:12 | -18 | #[frame_support::pallet] - | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `Bar` +38 | #[pallet::storage] + | _______________^ +39 | | type Foo = StorageValue<_, Bar>; + | |____________^ the trait `WrapperTypeDecode` is not implemented for `Bar` | = help: the following other types implement trait `WrapperTypeDecode`: Box @@ -143,13 +174,14 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied = note: required for `Bar` to implement `Decode` = note: required for `Bar` to implement `FullCodec` = note: required for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` to implement `TryDecodeEntireStorage` - = note: this error originates in the attribute macro `frame_support::pallet` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied - --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:18:1 + --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:38:12 | -18 | #[frame_support::pallet] - | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `EncodeLike` is not implemented for `Bar` +38 | #[pallet::storage] + | _______________^ +39 | | type Foo = StorageValue<_, Bar>; + | |____________^ the trait `EncodeLike` is not implemented for `Bar` | = help: the following other types implement trait `EncodeLike`: @@ -164,13 +196,14 @@ error[E0277]: the trait bound `Bar: EncodeLike` is not satisfied = note: required for `Bar` to implement `FullEncode` = note: required for `Bar` to implement `FullCodec` = note: required for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` to implement `TryDecodeEntireStorage` - = note: this error originates in the attribute macro `frame_support::pallet` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied - --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:18:1 + --> tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.rs:38:12 | -18 | #[frame_support::pallet] - | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `Bar` +38 | #[pallet::storage] + | _______________^ +39 | | type Foo = StorageValue<_, Bar>; + | |____________^ the trait `WrapperTypeEncode` is not implemented for `Bar` | = help: the following other types implement trait `WrapperTypeEncode`: Box @@ -186,4 +219,3 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied = note: required for `Bar` to implement `FullEncode` = note: required for `Bar` to implement `FullCodec` = note: required for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` to implement `TryDecodeEntireStorage` - = note: this error originates in the attribute macro `frame_support::pallet` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.stderr b/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.stderr index e04de98800ec..504db21feeb2 100644 --- a/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied.stderr @@ -1,8 +1,15 @@ error[E0277]: the trait bound `Bar: MaxEncodedLen` is not satisfied --> tests/pallet_ui/storage_info_unsatisfied.rs:26:12 | -26 | #[pallet::pallet] - | ^^^^^^ the trait `MaxEncodedLen` is not implemented for `Bar` +26 | #[pallet::pallet] + | _______________^ +27 | | pub struct Pallet(core::marker::PhantomData); +28 | | +29 | | #[pallet::hooks] +... | +38 | | #[pallet::storage] +39 | | type Foo = StorageValue<_, Bar>; + | |____________^ the trait `MaxEncodedLen` is not implemented for `Bar` | = help: the following other types implement trait `MaxEncodedLen`: bool diff --git a/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr b/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr index 31fe3b573389..6fd0b1959c86 100644 --- a/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/storage_info_unsatisfied_nmap.stderr @@ -1,8 +1,15 @@ error[E0277]: the trait bound `Bar: MaxEncodedLen` is not satisfied --> tests/pallet_ui/storage_info_unsatisfied_nmap.rs:29:12 | -29 | #[pallet::pallet] - | ^^^^^^ the trait `MaxEncodedLen` is not implemented for `Bar` +29 | #[pallet::pallet] + | _______________^ +30 | | pub struct Pallet(core::marker::PhantomData); +31 | | +32 | | #[pallet::hooks] +... | +41 | | #[pallet::storage] +42 | | type Foo = StorageNMap<_, Key, u32>; + | |____________^ the trait `MaxEncodedLen` is not implemented for `Bar` | = help: the following other types implement trait `MaxEncodedLen`: bool diff --git a/substrate/frame/support/test/tests/pallet_ui/store_trait_leak_private.stderr b/substrate/frame/support/test/tests/pallet_ui/store_trait_leak_private.stderr index 20144d825e83..ccb55122e816 100644 --- a/substrate/frame/support/test/tests/pallet_ui/store_trait_leak_private.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/store_trait_leak_private.stderr @@ -7,6 +7,7 @@ error: use of deprecated struct `pallet::_::Store`: | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D deprecated` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(deprecated)]` error[E0446]: private type `_GeneratedPrefixForStorageFoo` in public interface --> tests/pallet_ui/store_trait_leak_private.rs:28:37 diff --git a/substrate/primitives/api/test/tests/ui/impl_incorrect_method_signature.stderr b/substrate/primitives/api/test/tests/ui/impl_incorrect_method_signature.stderr index 4bd64c974f29..788d1807f3ba 100644 --- a/substrate/primitives/api/test/tests/ui/impl_incorrect_method_signature.stderr +++ b/substrate/primitives/api/test/tests/ui/impl_incorrect_method_signature.stderr @@ -1,3 +1,21 @@ +error[E0603]: struct `RuntimeVersion` is private + --> tests/ui/impl_incorrect_method_signature.rs:37:27 + | +37 | fn version() -> sp_api::RuntimeVersion { + | ^^^^^^^^^^^^^^ private struct + | +note: the struct `RuntimeVersion` is defined here + --> $WORKSPACE/substrate/primitives/api/src/lib.rs + | + | use sp_version::RuntimeVersion; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider importing one of these items instead + | +37 | fn version() -> sp_api::__private::RuntimeVersion { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +37 | fn version() -> sp_version::RuntimeVersion { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + error[E0053]: method `test` has an incompatible type for trait --> tests/ui/impl_incorrect_method_signature.rs:33:17 | diff --git a/substrate/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr b/substrate/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr index 4c21a3afb9b6..b4df7c068768 100644 --- a/substrate/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr +++ b/substrate/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr @@ -1,3 +1,21 @@ +error[E0603]: struct `RuntimeVersion` is private + --> tests/ui/type_reference_in_impl_runtime_apis_call.rs:39:27 + | +39 | fn version() -> sp_api::RuntimeVersion { + | ^^^^^^^^^^^^^^ private struct + | +note: the struct `RuntimeVersion` is defined here + --> $WORKSPACE/substrate/primitives/api/src/lib.rs + | + | use sp_version::RuntimeVersion; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider importing one of these items instead + | +39 | fn version() -> sp_api::__private::RuntimeVersion { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +39 | fn version() -> sp_version::RuntimeVersion { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + error[E0053]: method `test` has an incompatible type for trait --> tests/ui/type_reference_in_impl_runtime_apis_call.rs:33:17 |