From a814f55716fb53318bd0ba41706c2bc756369c06 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Wed, 5 Mar 2025 15:35:48 +0100 Subject: [PATCH 1/4] [AHM] Make more stuff public (#7802) Make some more stuff public that will be useful for AHM to reduce code duplication. --------- Signed-off-by: Oliver Tale-Yazdi Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- prdoc/pr_7802.prdoc | 11 +++++++++++ substrate/frame/child-bounties/src/lib.rs | 20 ++++++++++---------- substrate/frame/recovery/src/lib.rs | 23 ++++++++++++----------- 3 files changed, 33 insertions(+), 21 deletions(-) create mode 100644 prdoc/pr_7802.prdoc diff --git a/prdoc/pr_7802.prdoc b/prdoc/pr_7802.prdoc new file mode 100644 index 0000000000000..71c1256e75c74 --- /dev/null +++ b/prdoc/pr_7802.prdoc @@ -0,0 +1,11 @@ +title: '[AHM] child bounties and recovery: make more stuff public' +doc: +- audience: Runtime Dev + description: | + Make some items in the child-bounties and recovery pallet public to reduce code-duplication for + the Asset Hub migration. +crates: +- name: pallet-child-bounties + bump: minor +- name: pallet-recovery + bump: minor diff --git a/substrate/frame/child-bounties/src/lib.rs b/substrate/frame/child-bounties/src/lib.rs index 9fca26510989a..b20ef72fda4b1 100644 --- a/substrate/frame/child-bounties/src/lib.rs +++ b/substrate/frame/child-bounties/src/lib.rs @@ -88,26 +88,26 @@ pub use weights::WeightInfo; pub use pallet::*; -type BalanceOf = pallet_treasury::BalanceOf; -type BountiesError = pallet_bounties::Error; -type BountyIndex = pallet_bounties::BountyIndex; -type AccountIdLookupOf = <::Lookup as StaticLookup>::Source; -type BlockNumberFor = +pub type BalanceOf = pallet_treasury::BalanceOf; +pub type BountiesError = pallet_bounties::Error; +pub type BountyIndex = pallet_bounties::BountyIndex; +pub type AccountIdLookupOf = <::Lookup as StaticLookup>::Source; +pub type BlockNumberFor = <::BlockNumberProvider as BlockNumberProvider>::BlockNumber; /// A child bounty proposal. #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] pub struct ChildBounty { /// The parent of this child-bounty. - parent_bounty: BountyIndex, + pub parent_bounty: BountyIndex, /// The (total) amount that should be paid if this child-bounty is rewarded. - value: Balance, + pub value: Balance, /// The child bounty curator fee. - fee: Balance, + pub fee: Balance, /// The deposit of child-bounty curator. - curator_deposit: Balance, + pub curator_deposit: Balance, /// The status of this child-bounty. - status: ChildBountyStatus, + pub status: ChildBountyStatus, } /// The status of a child-bounty. diff --git a/substrate/frame/recovery/src/lib.rs b/substrate/frame/recovery/src/lib.rs index 8159bbefa76b1..80c897dfef700 100644 --- a/substrate/frame/recovery/src/lib.rs +++ b/substrate/frame/recovery/src/lib.rs @@ -181,23 +181,24 @@ mod mock; mod tests; pub mod weights; -type AccountIdLookupOf = <::Lookup as StaticLookup>::Source; -type BalanceOf = +pub type AccountIdLookupOf = <::Lookup as StaticLookup>::Source; +pub type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; -type BlockNumberFromProviderOf = +pub type BlockNumberFromProviderOf = <::BlockNumberProvider as BlockNumberProvider>::BlockNumber; -type FriendsOf = BoundedVec<::AccountId, ::MaxFriends>; +pub type FriendsOf = + BoundedVec<::AccountId, ::MaxFriends>; /// An active recovery process. #[derive(Clone, Eq, PartialEq, Encode, Decode, Default, RuntimeDebug, TypeInfo, MaxEncodedLen)] pub struct ActiveRecovery { /// The block number when the recovery process started. - created: BlockNumber, + pub created: BlockNumber, /// The amount held in reserve of the `depositor`, /// to be returned once this recovery process is closed. - deposit: Balance, + pub deposit: Balance, /// The friends which have vouched so far. Always sorted. - friends: Friends, + pub friends: Friends, } /// Configuration for recovering an account. @@ -205,14 +206,14 @@ pub struct ActiveRecovery { pub struct RecoveryConfig { /// The minimum number of blocks since the start of the recovery process before the account /// can be recovered. - delay_period: BlockNumber, + pub delay_period: BlockNumber, /// The amount held in reserve of the `depositor`, /// to be returned once this configuration is removed. - deposit: Balance, + pub deposit: Balance, /// The list of friends which can help recover an account. Always sorted. - friends: Friends, + pub friends: Friends, /// The number of approving friends needed to recover an account. - threshold: u16, + pub threshold: u16, } #[frame_support::pallet] From 1dbaeba9044ef491847a8204da98cd9e74534cdb Mon Sep 17 00:00:00 2001 From: Nathaniel Bajo <73991674+Nathy-bajo@users.noreply.github.com> Date: Wed, 5 Mar 2025 16:53:44 +0100 Subject: [PATCH 2/4] [XCM] add generic location to account converter that also works with external ecosystems (#7313) I added a new `ExternalConsensusLocationsConverterFor` struct to handle external global consensus locations and their child locations. This struct extends the functionality of existing converters (`GlobalConsensusParachainConvertsFor` and `EthereumLocationsConverterFor`) while maintaining backward compatibility. Fixes https://github.com/paritytech/polkadot-sdk/issues/7129 Polkadot address: 121HJWZtD13GJQPD82oEj3gSeHqsRYm1mFgRALu4L96kfPD1 --------- Co-authored-by: Adrian Catangiu Co-authored-by: ndk --- Cargo.lock | 5 + .../snowbridge/primitives/router/Cargo.toml | 3 + .../primitives/router/src/inbound/mod.rs | 1 + .../primitives/router/src/inbound/tests.rs | 21 ++- .../bridges/bridge-hub-rococo/Cargo.toml | 1 + .../bridges/bridge-hub-rococo/src/lib.rs | 1 + .../bridge-hub-rococo/src/tests/snowbridge.rs | 23 ++- .../bridges/bridge-hub-westend/Cargo.toml | 1 + .../bridges/bridge-hub-westend/src/lib.rs | 1 + .../src/tests/snowbridge.rs | 58 +++++-- .../assets/asset-hub-rococo/Cargo.toml | 1 + .../assets/asset-hub-rococo/src/xcm_config.rs | 28 ++-- .../assets/asset-hub-rococo/tests/tests.rs | 147 ++++++++++++++++-- .../assets/asset-hub-westend/Cargo.toml | 1 + .../asset-hub-westend/src/xcm_config.rs | 28 ++-- .../assets/asset-hub-westend/tests/tests.rs | 141 ++++++++++++++++- .../runtimes/testing/penpal/src/xcm_config.rs | 13 +- polkadot/xcm/xcm-builder/src/lib.rs | 5 +- .../xcm-builder/src/location_conversion.rs | 118 ++++++++++++-- prdoc/pr_7313.prdoc | 21 +++ 20 files changed, 515 insertions(+), 103 deletions(-) create mode 100644 prdoc/pr_7313.prdoc diff --git a/Cargo.lock b/Cargo.lock index 2b0448a3baeed..1fee693385ecb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1009,6 +1009,7 @@ dependencies = [ "sp-core 28.0.0", "sp-genesis-builder", "sp-inherents", + "sp-io 30.0.0", "sp-keyring", "sp-offchain", "sp-runtime 31.0.1", @@ -1149,6 +1150,7 @@ dependencies = [ "sp-core 28.0.0", "sp-genesis-builder", "sp-inherents", + "sp-io 30.0.0", "sp-keyring", "sp-offchain", "sp-runtime 31.0.1", @@ -2374,6 +2376,7 @@ dependencies = [ "sp-core 28.0.0", "sp-runtime 31.0.1", "staging-xcm", + "staging-xcm-builder", "staging-xcm-executor", "testnet-parachains-constants", "xcm-runtime-apis", @@ -2569,6 +2572,7 @@ dependencies = [ "sp-core 28.0.0", "sp-runtime 31.0.1", "staging-xcm", + "staging-xcm-builder", "staging-xcm-executor", "testnet-parachains-constants", "xcm-runtime-apis", @@ -21752,6 +21756,7 @@ dependencies = [ "sp-runtime 31.0.1", "sp-std 14.0.0", "staging-xcm", + "staging-xcm-builder", "staging-xcm-executor", ] diff --git a/bridges/snowbridge/primitives/router/Cargo.toml b/bridges/snowbridge/primitives/router/Cargo.toml index e44cca077ef32..44e8cbdfc30c2 100644 --- a/bridges/snowbridge/primitives/router/Cargo.toml +++ b/bridges/snowbridge/primitives/router/Cargo.toml @@ -23,6 +23,7 @@ sp-runtime = { workspace = true } sp-std = { workspace = true } xcm = { workspace = true } +xcm-builder = { workspace = true } xcm-executor = { workspace = true } snowbridge-core = { workspace = true } @@ -43,6 +44,7 @@ std = [ "sp-io/std", "sp-runtime/std", "sp-std/std", + "xcm-builder/std", "xcm-executor/std", "xcm/std", ] @@ -50,6 +52,7 @@ runtime-benchmarks = [ "frame-support/runtime-benchmarks", "snowbridge-core/runtime-benchmarks", "sp-runtime/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", "xcm-executor/runtime-benchmarks", "xcm/runtime-benchmarks", ] diff --git a/bridges/snowbridge/primitives/router/src/inbound/mod.rs b/bridges/snowbridge/primitives/router/src/inbound/mod.rs index f2d5b02e8bbdf..98a563f1894ee 100644 --- a/bridges/snowbridge/primitives/router/src/inbound/mod.rs +++ b/bridges/snowbridge/primitives/router/src/inbound/mod.rs @@ -466,6 +466,7 @@ where } } +/// DEPRECATED in favor of [xcm_builder::ExternalConsensusLocationsConverterFor] pub struct EthereumLocationsConverterFor(PhantomData); impl ConvertLocation for EthereumLocationsConverterFor where diff --git a/bridges/snowbridge/primitives/router/src/inbound/tests.rs b/bridges/snowbridge/primitives/router/src/inbound/tests.rs index 11d7928602c6e..1d8ac7393cdd9 100644 --- a/bridges/snowbridge/primitives/router/src/inbound/tests.rs +++ b/bridges/snowbridge/primitives/router/src/inbound/tests.rs @@ -2,11 +2,16 @@ use super::EthereumLocationsConverterFor; use crate::inbound::{ mock::*, Command, ConvertMessage, Destination, MessageV1, VersionedMessage, H160, }; -use frame_support::assert_ok; +use frame_support::{assert_ok, parameter_types}; use hex_literal::hex; use xcm::prelude::*; +use xcm_builder::ExternalConsensusLocationsConverterFor; use xcm_executor::traits::ConvertLocation; +parameter_types! { + pub UniversalLocation: InteriorLocation = [GlobalConsensus(ByGenesis([9; 32])), Parachain(1234)].into(); +} + #[test] fn test_ethereum_network_converts_successfully() { let expected_account: [u8; 32] = @@ -15,7 +20,12 @@ fn test_ethereum_network_converts_successfully() { let account = EthereumLocationsConverterFor::<[u8; 32]>::convert_location(&contract_location).unwrap(); - + assert_eq!(account, expected_account); + let account = + ExternalConsensusLocationsConverterFor::::convert_location( + &contract_location, + ) + .unwrap(); assert_eq!(account, expected_account); } @@ -30,7 +40,12 @@ fn test_contract_location_with_network_converts_successfully() { let account = EthereumLocationsConverterFor::<[u8; 32]>::convert_location(&contract_location).unwrap(); - + assert_eq!(account, expected_account); + let account = + ExternalConsensusLocationsConverterFor::::convert_location( + &contract_location, + ) + .unwrap(); assert_eq!(account, expected_account); } diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml index 35ceffe4c6953..4b229fd311b4a 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml @@ -27,6 +27,7 @@ sp-runtime = { workspace = true } # Polkadot pallet-xcm = { workspace = true } xcm = { workspace = true } +xcm-builder = { workspace = true } xcm-executor = { workspace = true } xcm-runtime-apis = { workspace = true } diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/lib.rs index f84d42cb29f8e..f89880b284bcc 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/lib.rs @@ -25,6 +25,7 @@ mod imports { latest::{ParentThen, ROCOCO_GENESIS_HASH, WESTEND_GENESIS_HASH}, prelude::{AccountId32 as AccountId32Junction, *}, }; + pub use xcm_builder::ExternalConsensusLocationsConverterFor; pub use xcm_executor::traits::TransferType; // Cumulus diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs index 7f242bab5a9da..9acdf20e2a955 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs @@ -13,6 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. use crate::imports::*; +use ahr_xcm_config::UniversalLocation as AssetHubRococoUniversalLocation; use codec::{Decode, Encode}; use emulated_integration_tests_common::xcm_emulator::ConvertLocation; use frame_support::pallet_prelude::TypeInfo; @@ -24,9 +25,7 @@ use snowbridge_pallet_inbound_queue_fixtures::{ send_token::make_send_token_message, send_token_to_penpal::make_send_token_to_penpal_message, }; use snowbridge_pallet_system; -use snowbridge_router_primitives::inbound::{ - Command, Destination, EthereumLocationsConverterFor, MessageV1, VersionedMessage, -}; +use snowbridge_router_primitives::inbound::{Command, Destination, MessageV1, VersionedMessage}; use sp_core::H256; use sp_runtime::{DispatchError::Token, TokenError::FundsUnavailable}; use testnet_parachains_constants::rococo::snowbridge::EthereumNetwork; @@ -319,8 +318,13 @@ fn send_weth_from_ethereum_to_penpal() { let origin_location = (Parent, Parent, ethereum_network_v5).into(); // Fund ethereum sovereign on AssetHub - let ethereum_sovereign: AccountId = - EthereumLocationsConverterFor::::convert_location(&origin_location).unwrap(); + let ethereum_sovereign: AccountId = AssetHubRococo::execute_with(|| { + ExternalConsensusLocationsConverterFor::< + AssetHubRococoUniversalLocation, + AccountId, + >::convert_location(&origin_location) + .unwrap() + }); AssetHubRococo::fund_accounts(vec![(ethereum_sovereign.clone(), INITIAL_FUND)]); // Create asset on the Penpal parachain. @@ -526,8 +530,13 @@ fn send_eth_asset_from_asset_hub_to_ethereum_and_back() { use ahr_xcm_config::bridging::to_ethereum::DefaultBridgeHubEthereumBaseFee; let assethub_location = BridgeHubRococo::sibling_location_of(AssetHubRococo::para_id()); let assethub_sovereign = BridgeHubRococo::sovereign_account_id_of(assethub_location); - let ethereum_sovereign: AccountId = - EthereumLocationsConverterFor::::convert_location(&origin_location).unwrap(); + let ethereum_sovereign: AccountId = AssetHubRococo::execute_with(|| { + ExternalConsensusLocationsConverterFor::< + AssetHubRococoUniversalLocation, + AccountId, + >::convert_location(&origin_location) + .unwrap() + }); AssetHubRococo::force_default_xcm_version(Some(XCM_VERSION)); BridgeHubRococo::force_default_xcm_version(Some(XCM_VERSION)); diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml index 05c7021d380ae..facd837cbc080 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml @@ -28,6 +28,7 @@ sp-runtime = { workspace = true } # Polkadot pallet-xcm = { workspace = true } xcm = { workspace = true } +xcm-builder = { workspace = true } xcm-executor = { workspace = true } xcm-runtime-apis = { workspace = true } diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/lib.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/lib.rs index cd5e22372f0e6..a61bc0d5adc6e 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/lib.rs @@ -26,6 +26,7 @@ mod imports { prelude::{AccountId32 as AccountId32Junction, *}, v5, }; + pub use xcm_builder::ExternalConsensusLocationsConverterFor; pub use xcm_executor::traits::TransferType; // Cumulus diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge.rs index 6789aae83ffe4..ea3ede20590c8 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge.rs @@ -13,7 +13,10 @@ // See the License for the specific language governing permissions and // limitations under the License. use crate::{imports::*, tests::penpal_emulated_chain::penpal_runtime}; -use asset_hub_westend_runtime::xcm_config::bridging::to_ethereum::DefaultBridgeHubEthereumBaseFee; +use asset_hub_westend_runtime::xcm_config::{ + bridging::to_ethereum::DefaultBridgeHubEthereumBaseFee, + UniversalLocation as AssetHubWestendUniversalLocation, +}; use bridge_hub_westend_runtime::{ bridge_to_ethereum_config::EthereumGatewayAddress, EthereumBeaconClient, EthereumInboundQueue, }; @@ -24,9 +27,7 @@ use hex_literal::hex; use rococo_westend_system_emulated_network::asset_hub_westend_emulated_chain::genesis::AssetHubWestendAssetOwner; use snowbridge_core::{inbound::InboundQueueFixture, AssetMetadata, TokenIdOf}; use snowbridge_pallet_inbound_queue_fixtures::send_native_eth::make_send_native_eth_message; -use snowbridge_router_primitives::inbound::{ - Command, Destination, EthereumLocationsConverterFor, MessageV1, VersionedMessage, -}; +use snowbridge_router_primitives::inbound::{Command, Destination, MessageV1, VersionedMessage}; use sp_core::H256; use testnet_parachains_constants::westend::snowbridge::EthereumNetwork; use xcm_executor::traits::ConvertLocation; @@ -161,8 +162,13 @@ fn register_weth_token_from_ethereum_to_asset_hub() { fn send_weth_token_from_ethereum_to_asset_hub() { let ethereum_network: NetworkId = EthereumNetwork::get().into(); let origin_location = Location::new(2, ethereum_network); - let ethereum_sovereign: AccountId = - EthereumLocationsConverterFor::::convert_location(&origin_location).unwrap(); + let ethereum_sovereign: AccountId = AssetHubWestend::execute_with(|| { + ExternalConsensusLocationsConverterFor::< + AssetHubWestendUniversalLocation, + AccountId, + >::convert_location(&origin_location) + .unwrap() + }); BridgeHubWestend::fund_para_sovereign(AssetHubWestend::para_id().into(), INITIAL_FUND); @@ -280,8 +286,13 @@ fn send_weth_from_ethereum_to_penpal() { let origin_location = (Parent, Parent, ethereum_network_v5).into(); // Fund ethereum sovereign on AssetHub - let ethereum_sovereign: AccountId = - EthereumLocationsConverterFor::::convert_location(&origin_location).unwrap(); + let ethereum_sovereign: AccountId = AssetHubWestend::execute_with(|| { + ExternalConsensusLocationsConverterFor::< + AssetHubWestendUniversalLocation, + AccountId, + >::convert_location(&origin_location) + .unwrap() + }); AssetHubWestend::fund_accounts(vec![(ethereum_sovereign.clone(), INITIAL_FUND)]); // Create asset on the Penpal parachain. @@ -387,8 +398,13 @@ fn send_eth_asset_from_asset_hub_to_ethereum_and_back() { use asset_hub_westend_runtime::xcm_config::bridging::to_ethereum::DefaultBridgeHubEthereumBaseFee; let assethub_location = BridgeHubWestend::sibling_location_of(AssetHubWestend::para_id()); let assethub_sovereign = BridgeHubWestend::sovereign_account_id_of(assethub_location); - let ethereum_sovereign: AccountId = - EthereumLocationsConverterFor::::convert_location(&origin_location).unwrap(); + let ethereum_sovereign: AccountId = AssetHubWestend::execute_with(|| { + ExternalConsensusLocationsConverterFor::< + AssetHubWestendUniversalLocation, + AccountId, + >::convert_location(&origin_location) + .unwrap() + }); AssetHubWestend::force_default_xcm_version(Some(XCM_VERSION)); BridgeHubWestend::force_default_xcm_version(Some(XCM_VERSION)); @@ -934,13 +950,17 @@ fn transfer_relay_token() { let expected_token_id = TokenIdOf::convert_location(&expected_asset_id).unwrap(); - let ethereum_sovereign: AccountId = - EthereumLocationsConverterFor::<[u8; 32]>::convert_location(&Location::new( + let ethereum_sovereign: AccountId = AssetHubWestend::execute_with(|| { + ExternalConsensusLocationsConverterFor::< + AssetHubWestendUniversalLocation, + [u8; 32], + >::convert_location(&Location::new( 2, [GlobalConsensus(EthereumNetwork::get())], )) .unwrap() - .into(); + .into() + }); // Register token BridgeHubWestend::execute_with(|| { @@ -1082,10 +1102,14 @@ fn transfer_ah_token() { let ethereum_destination = Location::new(2, [GlobalConsensus(Ethereum { chain_id: CHAIN_ID })]); - let ethereum_sovereign: AccountId = - EthereumLocationsConverterFor::<[u8; 32]>::convert_location(ðereum_destination) - .unwrap() - .into(); + let ethereum_sovereign: AccountId = AssetHubWestend::execute_with(|| { + ExternalConsensusLocationsConverterFor::< + AssetHubWestendUniversalLocation, + [u8; 32], + >::convert_location(ðereum_destination) + .unwrap() + .into() + }); AssetHubWestend::fund_accounts(vec![(ethereum_sovereign.clone(), INITIAL_FUND)]); let asset_id: Location = diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml index 3da8aa9b6cfea..f931706e4fc71 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml @@ -103,6 +103,7 @@ snowbridge-router-primitives = { workspace = true } [dev-dependencies] asset-test-utils = { workspace = true, default-features = true } parachains-runtimes-test-utils = { workspace = true, default-features = true } +sp-io = { workspace = true, default-features = true } [build-dependencies] substrate-wasm-builder = { optional = true, workspace = true, default-features = true } 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 84526b2e4f2ee..bf44d2408d030 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 @@ -42,7 +42,6 @@ use parachains_common::{ }; use polkadot_parachain_primitives::primitives::Sibling; use polkadot_runtime_common::xcm_sender::ExponentialPrice; -use snowbridge_router_primitives::inbound::EthereumLocationsConverterFor; use sp_runtime::traits::{AccountIdConversion, ConvertInto, TryConvertInto}; use testnet_parachains_constants::rococo::snowbridge::{ EthereumNetwork, INBOUND_QUEUE_PALLET_INDEX, @@ -52,16 +51,15 @@ use xcm_builder::{ AccountId32Aliases, AliasChildLocation, AllowExplicitUnpaidExecutionFrom, AllowHrmpNotificationsFromRelayChain, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, DenyRecursively, DenyReserveTransferToRelayChain, DenyThenTry, - DescribeAllTerminal, DescribeFamily, EnsureXcmOrigin, FrameTransactionalProcessor, - FungibleAdapter, FungiblesAdapter, GlobalConsensusParachainConvertsFor, HashedDescription, - IsConcrete, LocalMint, MatchedConvertedConcreteId, NetworkExportTableItem, NoChecking, - NonFungiblesAdapter, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, - SendXcmFeeToAccount, SiblingParachainAsNative, SiblingParachainConvertsVia, - SignedAccountId32AsNative, SignedToAccountId32, SingleAssetExchangeAdapter, - SovereignPaidRemoteExporter, SovereignSignedViaLocation, StartsWith, - StartsWithExplicitGlobalConsensus, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, - WeightInfoBounds, WithComputedOrigin, WithLatestLocationConverter, WithUniqueTopic, - XcmFeeManagerFromComponents, + DescribeAllTerminal, DescribeFamily, EnsureXcmOrigin, ExternalConsensusLocationsConverterFor, + FrameTransactionalProcessor, FungibleAdapter, FungiblesAdapter, HashedDescription, IsConcrete, + LocalMint, MatchedConvertedConcreteId, NetworkExportTableItem, NoChecking, NonFungiblesAdapter, + ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SendXcmFeeToAccount, + SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, + SignedToAccountId32, SingleAssetExchangeAdapter, SovereignPaidRemoteExporter, + SovereignSignedViaLocation, StartsWith, StartsWithExplicitGlobalConsensus, TakeWeightCredit, + TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, + WithLatestLocationConverter, WithUniqueTopic, XcmFeeManagerFromComponents, }; use xcm_executor::XcmExecutor; @@ -105,12 +103,8 @@ pub type LocationToAccountId = ( AccountId32Aliases, // Foreign locations alias into accounts according to a hash of their standard description. HashedDescription>, - // Different global consensus parachain sovereign account. - // (Used for over-bridge transfers and reserve processing) - GlobalConsensusParachainConvertsFor, - // Ethereum contract sovereign account. - // (Used to get convert ethereum contract locations to sovereign account) - EthereumLocationsConverterFor, + // Different global consensus locations sovereign accounts. + ExternalConsensusLocationsConverterFor, ); /// Means for transacting the native currency on this chain. diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs index 0057459fc93c6..22e43ec7b3ed2 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs @@ -47,13 +47,17 @@ use frame_support::{ }, weights::{Weight, WeightToFee as WeightToFeeT}, }; +use hex_literal::hex; use parachains_common::{AccountId, AssetIdForTrustBackedAssets, AuraId, Balance}; use sp_consensus_aura::SlotDuration; use sp_core::crypto::Ss58Codec; -use sp_runtime::traits::MaybeEquivalence; +use sp_runtime::{traits::MaybeEquivalence, BuildStorage}; use std::convert::Into; use testnet_parachains_constants::rococo::{consensus::*, currency::UNITS, fee::WeightToFee}; -use xcm::latest::prelude::{Assets as XcmAssets, *}; +use xcm::latest::{ + prelude::{Assets as XcmAssets, *}, + WESTEND_GENESIS_HASH, +}; use xcm_builder::WithLatestLocationConverter; use xcm_executor::traits::{JustTry, WeightTrader}; use xcm_runtime_apis::conversions::LocationToAccountHelper; @@ -1514,18 +1518,143 @@ fn location_conversion_works() { ), expected_account_id_str: "5DBoExvojy8tYnHgLL97phNH975CyT45PWTZEeGoBZfAyRMH", }, + // ExternalConsensusLocationsConverterFor + TestCase { + description: "Describe Ethereum Location", + location: Location::new(2, [GlobalConsensus(Ethereum { chain_id: 11155111 })]), + expected_account_id_str: "5GjRnmh5o3usSYzVmsxBWzHEpvJyHK4tKNPhjpUR3ASrruBy", + }, + TestCase { + description: "Describe Ethereum AccountKey", + location: Location::new( + 2, + [ + GlobalConsensus(Ethereum { chain_id: 11155111 }), + AccountKey20 { + network: None, + key: hex!("87d1f7fdfEe7f651FaBc8bFCB6E086C278b77A7d"), + }, + ], + ), + expected_account_id_str: "5HV4j4AsqT349oLRZmTjhGKDofPBWmWaPUfWGaRkuvzkjW9i", + }, + TestCase { + description: "Describe Westend Location", + location: Location::new(2, [GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH))]), + expected_account_id_str: "5Fb4pyqFuYLZ43USEAcVUBhFTfTckG9zv9kUaVnmR79YgBCe", + }, + TestCase { + description: "Describe Westend AccountID", + location: Location::new( + 2, + [ + GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)), + AccountId32 { network: None, id: AccountId::from(ALICE).into() }, + ], + ), + expected_account_id_str: "5CpcvNFY6jkMJrd7XQt3yTweRD1WxUeHXvHnbWuVM1MHKHPe", + }, + TestCase { + description: "Describe Westend AccountKey", + location: Location::new( + 2, + [ + GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)), + AccountKey20 { network: None, key: [0u8; 20] }, + ], + ), + expected_account_id_str: "5FzaTcFwUMyX5Sfe7wRGuc3zw1cbpGAGZpmAsxS4tBX6x6U3", + }, + TestCase { + description: "Describe Westend Treasury Plurality", + location: Location::new( + 2, + [ + GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)), + Plurality { id: BodyId::Treasury, part: BodyPart::Voice }, + ], + ), + expected_account_id_str: "5CpdRCmCYwnxS1mifwEddYHDJR8ydDfTpi1gwAQKQvfAjjzu", + }, + TestCase { + description: "Describe Westend Parachain Location", + location: Location::new( + 2, + [GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)), Parachain(1000)], + ), + expected_account_id_str: "5CkWf1L181BiSbvoofnzfSg8ZLiBK3i1U4sknzETHk8QS2mA", + }, + TestCase { + description: "Describe Westend Parachain AccountID", + location: Location::new( + 2, + [ + GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)), + Parachain(1000), + AccountId32 { network: None, id: AccountId::from(ALICE).into() }, + ], + ), + expected_account_id_str: "5G6JJUm6tgsxJhRn76VGme8WGukdUNiBBK6ABUtH9YXEjEk9", + }, + TestCase { + description: "Describe Westend Parachain AccountKey", + location: Location::new( + 2, + [ + GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)), + Parachain(1000), + AccountKey20 { network: None, key: [0u8; 20] }, + ], + ), + expected_account_id_str: "5EFpSvq8BUAjdjY4tuGhGXZ66P16iQnX7nxsNoHy7TM6NhMa", + }, + TestCase { + description: "Describe Westend Parachain Treasury Plurality", + location: Location::new( + 2, + [ + GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)), + Parachain(1000), + Plurality { id: BodyId::Treasury, part: BodyPart::Voice }, + ], + ), + expected_account_id_str: "5GfwA4qaz9wpQPPHmf5MSKqvsPyrfx1yYeeZB1SUkqDuRuZ1", + }, + TestCase { + description: "Describe Westend USDT Location", + location: Location::new( + 2, + [ + GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)), + Parachain(1000), + PalletInstance(50), + GeneralIndex(1984), + ], + ), + expected_account_id_str: "5Hd77ZjbVRrYiRXER8qo9DRDB8ZzaKtRswZoypMnMLdixzMs", + }, ]; for tc in test_cases { - let expected = - AccountId::from_string(tc.expected_account_id_str).expect("Invalid AccountId string"); - - let got = LocationToAccountHelper::::convert_location( - tc.location.into(), - ) + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + parachain_info::GenesisConfig:: { + parachain_id: 1000.into(), + ..Default::default() + } + .assimilate_storage(&mut t) .unwrap(); + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| { + let expected = AccountId::from_string(tc.expected_account_id_str) + .expect("Invalid AccountId string"); - assert_eq!(got, expected, "{}", tc.description); + let got = LocationToAccountHelper::::convert_location( + tc.location.into(), + ) + .unwrap(); + + assert_eq!(got, expected, "{}", tc.description); + }); } } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml index f7fb858de62e8..1c2b0c1fa4408 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml @@ -107,6 +107,7 @@ snowbridge-router-primitives = { workspace = true } [dev-dependencies] asset-test-utils = { workspace = true, default-features = true } parachains-runtimes-test-utils = { workspace = true, default-features = true } +sp-io = { workspace = true, default-features = true } [build-dependencies] substrate-wasm-builder = { optional = true, workspace = true, default-features = true } 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 46c4e4d0b28e4..cc093d6fa5752 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 @@ -42,7 +42,6 @@ use parachains_common::{ }; use polkadot_parachain_primitives::primitives::Sibling; use polkadot_runtime_common::xcm_sender::ExponentialPrice; -use snowbridge_router_primitives::inbound::EthereumLocationsConverterFor; use sp_runtime::traits::{AccountIdConversion, ConvertInto, TryConvertInto}; use westend_runtime_constants::system_parachain::COLLECTIVES_ID; use xcm::latest::{prelude::*, ROCOCO_GENESIS_HASH, WESTEND_GENESIS_HASH}; @@ -50,16 +49,15 @@ use xcm_builder::{ AccountId32Aliases, AliasChildLocation, AllowExplicitUnpaidExecutionFrom, AllowHrmpNotificationsFromRelayChain, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, DenyRecursively, DenyReserveTransferToRelayChain, DenyThenTry, - DescribeAllTerminal, DescribeFamily, EnsureXcmOrigin, FrameTransactionalProcessor, - FungibleAdapter, FungiblesAdapter, GlobalConsensusParachainConvertsFor, HashedDescription, - IsConcrete, LocalMint, MatchedConvertedConcreteId, NetworkExportTableItem, NoChecking, - NonFungiblesAdapter, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, - SendXcmFeeToAccount, SiblingParachainAsNative, SiblingParachainConvertsVia, - SignedAccountId32AsNative, SignedToAccountId32, SingleAssetExchangeAdapter, - SovereignPaidRemoteExporter, SovereignSignedViaLocation, StartsWith, - StartsWithExplicitGlobalConsensus, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, - WeightInfoBounds, WithComputedOrigin, WithLatestLocationConverter, WithUniqueTopic, - XcmFeeManagerFromComponents, + DescribeAllTerminal, DescribeFamily, EnsureXcmOrigin, ExternalConsensusLocationsConverterFor, + FrameTransactionalProcessor, FungibleAdapter, FungiblesAdapter, HashedDescription, IsConcrete, + LocalMint, MatchedConvertedConcreteId, NetworkExportTableItem, NoChecking, NonFungiblesAdapter, + ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SendXcmFeeToAccount, + SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, + SignedToAccountId32, SingleAssetExchangeAdapter, SovereignPaidRemoteExporter, + SovereignSignedViaLocation, StartsWith, StartsWithExplicitGlobalConsensus, TakeWeightCredit, + TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, + WithLatestLocationConverter, WithUniqueTopic, XcmFeeManagerFromComponents, }; use xcm_executor::XcmExecutor; @@ -99,12 +97,8 @@ pub type LocationToAccountId = ( AccountId32Aliases, // Foreign locations alias into accounts according to a hash of their standard description. HashedDescription>, - // Different global consensus parachain sovereign account. - // (Used for over-bridge transfers and reserve processing) - GlobalConsensusParachainConvertsFor, - // Ethereum contract sovereign account. - // (Used to get convert ethereum contract locations to sovereign account) - EthereumLocationsConverterFor, + // Different global consensus locations sovereign accounts. + ExternalConsensusLocationsConverterFor, ); /// Means for transacting the native currency on this chain. diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs index 38673606541b0..0c195332897c1 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs @@ -47,10 +47,11 @@ use frame_support::{ }, weights::{Weight, WeightToFee as WeightToFeeT}, }; +use hex_literal::hex; use parachains_common::{AccountId, AssetIdForTrustBackedAssets, AuraId, Balance}; use sp_consensus_aura::SlotDuration; use sp_core::crypto::Ss58Codec; -use sp_runtime::{traits::MaybeEquivalence, Either}; +use sp_runtime::{traits::MaybeEquivalence, BuildStorage, Either}; use std::{convert::Into, ops::Mul}; use testnet_parachains_constants::westend::{consensus::*, currency::UNITS, fee::WeightToFee}; use xcm::latest::{ @@ -1487,18 +1488,142 @@ fn location_conversion_works() { ), expected_account_id_str: "5DBoExvojy8tYnHgLL97phNH975CyT45PWTZEeGoBZfAyRMH", }, + // ExternalConsensusLocationsConverterFor + TestCase { + description: "Describe Ethereum Location", + location: Location::new(2, [GlobalConsensus(Ethereum { chain_id: 11155111 })]), + expected_account_id_str: "5GjRnmh5o3usSYzVmsxBWzHEpvJyHK4tKNPhjpUR3ASrruBy", + }, + TestCase { + description: "Describe Ethereum AccountKey", + location: Location::new( + 2, + [ + GlobalConsensus(Ethereum { chain_id: 11155111 }), + AccountKey20 { + network: None, + key: hex!("87d1f7fdfEe7f651FaBc8bFCB6E086C278b77A7d"), + }, + ], + ), + expected_account_id_str: "5HV4j4AsqT349oLRZmTjhGKDofPBWmWaPUfWGaRkuvzkjW9i", + }, + TestCase { + description: "Describe Rococo Location", + location: Location::new(2, [GlobalConsensus(ByGenesis(ROCOCO_GENESIS_HASH))]), + expected_account_id_str: "5FfpYGrFybJXFsQk7dabr1vEbQ5ycBBu85vrDjPJsF3q4A8P", + }, + TestCase { + description: "Describe Rococo AccountID", + location: Location::new( + 2, + [ + GlobalConsensus(ByGenesis(ROCOCO_GENESIS_HASH)), + AccountId32 { network: None, id: AccountId::from(ALICE).into() }, + ], + ), + expected_account_id_str: "5CXVYinTeQKQGWAP9RqaPhitk7ybrqBZf66kCJmtAjV4Xwbg", + }, + TestCase { + description: "Describe Rococo AccountKey", + location: Location::new( + 2, + [ + GlobalConsensus(ByGenesis(ROCOCO_GENESIS_HASH)), + AccountKey20 { network: None, key: [0u8; 20] }, + ], + ), + expected_account_id_str: "5GbRhbJWb2hZY7TCeNvTqZXaP3x3UY5xt4ccxpV1ZtJS1gFL", + }, + TestCase { + description: "Describe Rococo Treasury Plurality", + location: Location::new( + 2, + [ + GlobalConsensus(ByGenesis(ROCOCO_GENESIS_HASH)), + Plurality { id: BodyId::Treasury, part: BodyPart::Voice }, + ], + ), + expected_account_id_str: "5EGi9NgJNGoMawY8ubnCDLmbdEW6nt2W2U2G3j9E3jXmspT7", + }, + TestCase { + description: "Describe Rococo Parachain Location", + location: Location::new( + 2, + [GlobalConsensus(ByGenesis(ROCOCO_GENESIS_HASH)), Parachain(1000)], + ), + expected_account_id_str: "5CQeLKM7XC1xNBiQLp26Wa948cudjYRD5VzvaTG3BjnmUvLL", + }, + TestCase { + description: "Describe Rococo Parachain AccountID", + location: Location::new( + 2, + [ + GlobalConsensus(ByGenesis(ROCOCO_GENESIS_HASH)), + Parachain(1000), + AccountId32 { network: None, id: AccountId::from(ALICE).into() }, + ], + ), + expected_account_id_str: "5H8HsK17dV7i7J8fZBNd438rvwd7rHviZxJqyZpLEGJn6vb6", + }, + TestCase { + description: "Describe Rococo Parachain AccountKey", + location: Location::new( + 2, + [ + GlobalConsensus(ByGenesis(ROCOCO_GENESIS_HASH)), + Parachain(1000), + AccountKey20 { network: None, key: [0u8; 20] }, + ], + ), + expected_account_id_str: "5G121Rtddxn6zwMD2rZZGXxFHZ2xAgzFUgM9ki4A8wMGo4e2", + }, + TestCase { + description: "Describe Rococo Parachain Treasury Plurality", + location: Location::new( + 2, + [ + GlobalConsensus(ByGenesis(ROCOCO_GENESIS_HASH)), + Parachain(1000), + Plurality { id: BodyId::Treasury, part: BodyPart::Voice }, + ], + ), + expected_account_id_str: "5FNk7za2pQ71NHnN1jA63hJxJwdQywiVGnK6RL3nYjCdkWDF", + }, + TestCase { + description: "Describe Rococo USDT Location", + location: Location::new( + 2, + [ + GlobalConsensus(ByGenesis(ROCOCO_GENESIS_HASH)), + Parachain(1000), + PalletInstance(50), + GeneralIndex(1984), + ], + ), + expected_account_id_str: "5HNfT779KHeAL7PaVBTQDVxrT6dfJZJoQMTScxLSahBc9kxF", + }, ]; for tc in test_cases { - let expected = - AccountId::from_string(tc.expected_account_id_str).expect("Invalid AccountId string"); - - let got = LocationToAccountHelper::::convert_location( - tc.location.into(), - ) + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + parachain_info::GenesisConfig:: { + parachain_id: 1000.into(), + ..Default::default() + } + .assimilate_storage(&mut t) .unwrap(); + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| { + let expected = AccountId::from_string(tc.expected_account_id_str) + .expect("Invalid AccountId string"); + let got = LocationToAccountHelper::::convert_location( + tc.location.into(), + ) + .unwrap(); - assert_eq!(got, expected, "{}", tc.description); + assert_eq!(got, expected, "{}", tc.description); + }); } } diff --git a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs index 82db8829e516a..65e2c7e738d30 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs @@ -56,15 +56,14 @@ use pallet_xcm::XcmPassthrough; use parachains_common::{xcm_config::AssetFeeAsExistentialDepositMultiplier, TREASURY_PALLET_ID}; use polkadot_parachain_primitives::primitives::Sibling; use polkadot_runtime_common::{impls::ToAuthor, xcm_sender::ExponentialPrice}; -use snowbridge_router_primitives::inbound::EthereumLocationsConverterFor; use sp_runtime::traits::{AccountIdConversion, ConvertInto, Identity, TryConvertInto}; use xcm::latest::{prelude::*, WESTEND_GENESIS_HASH}; use xcm_builder::{ AccountId32Aliases, AliasOriginRootUsingFilter, AllowHrmpNotificationsFromRelayChain, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, ConvertedConcreteId, DescribeAllTerminal, DescribeFamily, - EnsureXcmOrigin, FixedWeightBounds, FrameTransactionalProcessor, FungibleAdapter, - FungiblesAdapter, GlobalConsensusParachainConvertsFor, HashedDescription, IsConcrete, + EnsureXcmOrigin, ExternalConsensusLocationsConverterFor, FixedWeightBounds, + FrameTransactionalProcessor, FungibleAdapter, FungiblesAdapter, HashedDescription, IsConcrete, LocalMint, NativeAsset, NoChecking, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SendXcmFeeToAccount, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SingleAssetExchangeAdapter, @@ -106,12 +105,8 @@ pub type LocationToAccountId = ( AccountId32Aliases, // Foreign locations alias into accounts according to a hash of their standard description. HashedDescription>, - // Different global consensus parachain sovereign account. - // (Used for over-bridge transfers and reserve processing) - GlobalConsensusParachainConvertsFor, - // Ethereum contract sovereign account. - // (Used to get convert ethereum contract locations to sovereign account) - EthereumLocationsConverterFor, + // Different global consensus locations sovereign accounts. + ExternalConsensusLocationsConverterFor, ); /// Means for transacting assets on this chain. diff --git a/polkadot/xcm/xcm-builder/src/lib.rs b/polkadot/xcm/xcm-builder/src/lib.rs index 1c08c875eb21c..8f6eb9d642962 100644 --- a/polkadot/xcm/xcm-builder/src/lib.rs +++ b/polkadot/xcm/xcm-builder/src/lib.rs @@ -83,8 +83,9 @@ pub use location_conversion::{ ChildParachainConvertsVia, DescribeAccountId32Terminal, DescribeAccountIdTerminal, DescribeAccountKey20Terminal, DescribeAllTerminal, DescribeBodyTerminal, DescribeFamily, DescribeLocation, DescribePalletTerminal, DescribeTerminus, DescribeTreasuryVoiceTerminal, - GlobalConsensusConvertsFor, GlobalConsensusParachainConvertsFor, HashedDescription, - LocalTreasuryVoiceConvertsVia, ParentIsPreset, SiblingParachainConvertsVia, + ExternalConsensusLocationsConverterFor, GlobalConsensusConvertsFor, + GlobalConsensusParachainConvertsFor, HashedDescription, LocalTreasuryVoiceConvertsVia, + ParentIsPreset, SiblingParachainConvertsVia, }; mod matches_location; diff --git a/polkadot/xcm/xcm-builder/src/location_conversion.rs b/polkadot/xcm/xcm-builder/src/location_conversion.rs index c7aa0c8b5041d..0f4703dca89ca 100644 --- a/polkadot/xcm/xcm-builder/src/location_conversion.rs +++ b/polkadot/xcm/xcm-builder/src/location_conversion.rs @@ -427,6 +427,8 @@ impl GlobalConsensusConvertsFor( PhantomData<(UniversalLocation, AccountId)>, ); @@ -458,6 +460,55 @@ impl } } +/// Converts locations from external global consensus systems (e.g., Ethereum, other parachains) +/// into `AccountId`. +/// +/// Replaces `GlobalConsensusParachainConvertsFor` and `EthereumLocationsConverterFor` in a +/// backwards-compatible way, and extends them for also handling child locations (e.g., +/// `AccountId(Alice)`). +pub struct ExternalConsensusLocationsConverterFor( + PhantomData<(UniversalLocation, AccountId)>, +); + +impl, AccountId: From<[u8; 32]> + Clone> + ConvertLocation + for ExternalConsensusLocationsConverterFor +{ + fn convert_location(location: &Location) -> Option { + let universal_source = UniversalLocation::get(); + tracing::trace!( + target: "xcm::location_conversion", + "ExternalConsensusLocationsConverterFor universal_source: {:?}, location: {:?}", + universal_source, location, + ); + let (remote_network, remote_location) = + ensure_is_remote(universal_source, location.clone()).ok()?; + + // replaces and extends `EthereumLocationsConverterFor` and + // `GlobalConsensusParachainConvertsFor` + let acc_id: AccountId = if let Ethereum { chain_id } = &remote_network { + match remote_location.as_slice() { + // equivalent to `EthereumLocationsConverterFor` + [] => (b"ethereum-chain", chain_id).using_encoded(blake2_256).into(), + // equivalent to `EthereumLocationsConverterFor` + [AccountKey20 { network: _, key }] => + (b"ethereum-chain", chain_id, *key).using_encoded(blake2_256).into(), + // extends `EthereumLocationsConverterFor` + tail => (b"ethereum-chain", chain_id, tail).using_encoded(blake2_256).into(), + } + } else { + match remote_location.as_slice() { + // equivalent to `GlobalConsensusParachainConvertsFor` + [Parachain(para_id)] => + (b"glblcnsnss/prchn_", remote_network, para_id).using_encoded(blake2_256).into(), + // converts everything else based on hash of encoded location tail + tail => (b"glblcnsnss", remote_network, tail).using_encoded(blake2_256).into(), + } + }; + Some(acc_id) + } +} + #[cfg(test)] mod tests { use super::*; @@ -608,32 +659,32 @@ mod tests { GlobalConsensusConvertsFor::::convert_location( &Location::new(2, [GlobalConsensus(network_3)]), ) - .expect("conversion is ok"); + .unwrap(); let res_2_gc_network_3 = GlobalConsensusConvertsFor::::convert_location( &Location::new(2, [GlobalConsensus(network_3)]), ) - .expect("conversion is ok"); + .unwrap(); let res_1_gc_network_4 = GlobalConsensusConvertsFor::::convert_location( &Location::new(2, [GlobalConsensus(network_4)]), ) - .expect("conversion is ok"); + .unwrap(); let res_2_gc_network_4 = GlobalConsensusConvertsFor::::convert_location( &Location::new(2, [GlobalConsensus(network_4)]), ) - .expect("conversion is ok"); + .unwrap(); let res_1_gc_network_5 = GlobalConsensusConvertsFor::::convert_location( &Location::new(2, [GlobalConsensus(network_5)]), ) - .expect("conversion is ok"); + .unwrap(); let res_2_gc_network_5 = GlobalConsensusConvertsFor::::convert_location( &Location::new(2, [GlobalConsensus(network_5)]), ) - .expect("conversion is ok"); + .unwrap(); assert_ne!(res_1_gc_network_3, res_1_gc_network_4); assert_ne!(res_1_gc_network_4, res_1_gc_network_5); @@ -678,6 +729,10 @@ mod tests { GlobalConsensusParachainConvertsFor::::convert_location( &location, ); + let result2 = + ExternalConsensusLocationsConverterFor::::convert_location( + &location, + ); match result { Some(account) => { assert_eq!( @@ -707,29 +762,64 @@ mod tests { ); }, } + if expected_result { + assert_eq!(result, result2); + } } // all success + let location = Location::new(2, [GlobalConsensus(ByGenesis([3; 32])), Parachain(1000)]); let res_gc_a_p1000 = GlobalConsensusParachainConvertsFor::::convert_location( - &Location::new(2, [GlobalConsensus(ByGenesis([3; 32])), Parachain(1000)]), + &location, ) - .expect("conversion is ok"); + .unwrap(); + assert_eq!( + res_gc_a_p1000, + ExternalConsensusLocationsConverterFor::::convert_location( + &location, + ).unwrap() + ); + + let location = Location::new(2, [GlobalConsensus(ByGenesis([3; 32])), Parachain(1001)]); let res_gc_a_p1001 = GlobalConsensusParachainConvertsFor::::convert_location( - &Location::new(2, [GlobalConsensus(ByGenesis([3; 32])), Parachain(1001)]), + &location, ) - .expect("conversion is ok"); + .unwrap(); + assert_eq!( + res_gc_a_p1001, + ExternalConsensusLocationsConverterFor::::convert_location( + &location, + ).unwrap() + ); + + let location = Location::new(2, [GlobalConsensus(ByGenesis([4; 32])), Parachain(1000)]); let res_gc_b_p1000 = GlobalConsensusParachainConvertsFor::::convert_location( - &Location::new(2, [GlobalConsensus(ByGenesis([4; 32])), Parachain(1000)]), + &location, ) - .expect("conversion is ok"); + .unwrap(); + assert_eq!( + res_gc_b_p1000, + ExternalConsensusLocationsConverterFor::::convert_location( + &location, + ).unwrap() + ); + + let location = Location::new(2, [GlobalConsensus(ByGenesis([4; 32])), Parachain(1001)]); let res_gc_b_p1001 = GlobalConsensusParachainConvertsFor::::convert_location( - &Location::new(2, [GlobalConsensus(ByGenesis([4; 32])), Parachain(1001)]), + &location, ) - .expect("conversion is ok"); + .unwrap(); + assert_eq!( + res_gc_b_p1001, + ExternalConsensusLocationsConverterFor::::convert_location( + &location, + ).unwrap() + ); + assert_ne!(res_gc_a_p1000, res_gc_a_p1001); assert_ne!(res_gc_a_p1000, res_gc_b_p1000); assert_ne!(res_gc_a_p1000, res_gc_b_p1001); diff --git a/prdoc/pr_7313.prdoc b/prdoc/pr_7313.prdoc new file mode 100644 index 0000000000000..d1114534cc239 --- /dev/null +++ b/prdoc/pr_7313.prdoc @@ -0,0 +1,21 @@ +title: "[XCM] add generic location to account converter that also works with external ecosystems" + +doc: +- audience: Runtime Dev + description: | + Adds a new `ExternalConsensusLocationsConverterFor` struct to handle external global + consensus locations and their child locations. + This struct extends the functionality of existing converters (`GlobalConsensusParachainConvertsFor` + and `EthereumLocationsConverterFor`) while maintaining backward compatibility. + +crates: + - name: snowbridge-router-primitives + bump: minor + - name: staging-xcm-builder + bump: minor + - name: asset-hub-rococo-runtime + bump: minor + - name: asset-hub-westend-runtime + bump: minor + - name: penpal-runtime + bump: minor From 945e5fe8874eb8b9abdbd54de7441d75bb1ad4b5 Mon Sep 17 00:00:00 2001 From: Alexander Samusev <41779041+alvicsam@users.noreply.github.com> Date: Wed, 5 Mar 2025 21:15:15 +0100 Subject: [PATCH 3/4] ci: update credentials for command-backport (#7798) close https://github.com/paritytech/ci_cd/issues/1114 --- .github/workflows/command-backport.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/command-backport.yml b/.github/workflows/command-backport.yml index d7b01000855ad..67de5418434f9 100644 --- a/.github/workflows/command-backport.yml +++ b/.github/workflows/command-backport.yml @@ -31,10 +31,10 @@ jobs: - name: Generate token id: generate_token - uses: tibdex/github-app-token@v2.1.0 + uses: actions/create-github-app-token@v1 with: - app_id: ${{ secrets.CMD_BOT_APP_ID }} - private_key: ${{ secrets.CMD_BOT_APP_KEY }} + app_id: ${{ secrets.RELEASE_BACKPORT_AUTOMATION_APP_ID }} + private_key: ${{ secrets.RELEASE_BACKPORT_AUTOMATION_APP_PRIVATE_KEY }} - name: Create backport pull requests uses: korthout/backport-action@v3 From 00d8eea8d2f6fccbc709ae759192684472cf92e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Thu, 6 Mar 2025 00:10:19 +0100 Subject: [PATCH 4/4] pallet-scheduler: Put back postponed tasks into the agenda (#7790) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Right now `pallet-scheduler` is not putting back postponed tasks into the agenda when the early weight check is failing. This pull request ensures that these tasks are put back into the agenda and are not just "lost". --------- Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Guillaume Thiolliere Co-authored-by: Alexandre R. Baldé --- prdoc/pr_7790.prdoc | 9 ++++ substrate/frame/scheduler/src/lib.rs | 10 +++-- substrate/frame/scheduler/src/mock.rs | 2 +- substrate/frame/scheduler/src/tests.rs | 57 +++++++++++++++++++++----- 4 files changed, 63 insertions(+), 15 deletions(-) create mode 100644 prdoc/pr_7790.prdoc diff --git a/prdoc/pr_7790.prdoc b/prdoc/pr_7790.prdoc new file mode 100644 index 0000000000000..09a8ff52c8d13 --- /dev/null +++ b/prdoc/pr_7790.prdoc @@ -0,0 +1,9 @@ +title: 'pallet-scheduler: Put back postponed tasks into the agenda' +doc: +- audience: Runtime Dev + description: "Right now `pallet-scheduler` is not putting back postponed tasks into\ + \ the agenda when the early weight check is failing. This pull request ensures\ + \ that these tasks are put back into the agenda and are not just \"lost\".\r\n" +crates: +- name: pallet-scheduler + bump: patch diff --git a/substrate/frame/scheduler/src/lib.rs b/substrate/frame/scheduler/src/lib.rs index 2ad94ec04df47..65099dfd690cf 100644 --- a/substrate/frame/scheduler/src/lib.rs +++ b/substrate/frame/scheduler/src/lib.rs @@ -323,6 +323,7 @@ pub mod pallet { type BlockNumberProvider: BlockNumberProvider; } + /// Block number at which the agenda began incomplete execution. #[pallet::storage] pub type IncompleteSince = StorageValue<_, BlockNumberFor>; @@ -386,6 +387,8 @@ pub mod pallet { RetryFailed { task: TaskAddress>, id: Option }, /// The given task can never be executed since it is overweight. PermanentlyOverweight { task: TaskAddress>, id: Option }, + /// Agenda is incomplete from `when`. + AgendaIncomplete { when: BlockNumberFor }, } #[pallet::error] @@ -1202,6 +1205,7 @@ impl Pallet { } incomplete_since = incomplete_since.min(when); if incomplete_since <= now { + Self::deposit_event(Event::AgendaIncomplete { when: incomplete_since }); IncompleteSince::::put(incomplete_since); } } @@ -1235,10 +1239,7 @@ impl Pallet { let mut dropped = 0; for (agenda_index, _) in ordered.into_iter().take(max as usize) { - let task = match agenda[agenda_index as usize].take() { - None => continue, - Some(t) => t, - }; + let Some(task) = agenda[agenda_index as usize].take() else { continue }; let base_weight = T::WeightInfo::service_task( task.call.lookup_len().map(|x| x as usize), task.maybe_id.is_some(), @@ -1246,6 +1247,7 @@ impl Pallet { ); if !weight.can_consume(base_weight) { postponed += 1; + agenda[agenda_index as usize] = Some(task); break } let result = Self::service_task(weight, now, when, agenda_index, *executed == 0, task); diff --git a/substrate/frame/scheduler/src/mock.rs b/substrate/frame/scheduler/src/mock.rs index a9aea97542acd..28b5ee6d6083c 100644 --- a/substrate/frame/scheduler/src/mock.rs +++ b/substrate/frame/scheduler/src/mock.rs @@ -212,7 +212,7 @@ impl WeightInfo for TestWeightInfo { } } parameter_types! { - pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * + pub storage MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * BlockWeights::get().max_block; } diff --git a/substrate/frame/scheduler/src/tests.rs b/substrate/frame/scheduler/src/tests.rs index d0a3acc05ac7e..1b7739e855ea7 100644 --- a/substrate/frame/scheduler/src/tests.rs +++ b/substrate/frame/scheduler/src/tests.rs @@ -1264,8 +1264,8 @@ fn cancel_named_periodic_scheduling_works() { #[test] fn scheduler_respects_weight_limits() { - let max_weight: Weight = ::MaximumWeight::get(); new_test_ext().execute_with(|| { + let max_weight: Weight = ::MaximumWeight::get(); let call = RuntimeCall::Logger(LoggerCall::log { i: 42, weight: max_weight / 3 * 2 }); assert_ok!(Scheduler::do_schedule( DispatchTime::At(4), @@ -1292,8 +1292,8 @@ fn scheduler_respects_weight_limits() { #[test] fn retry_respects_weight_limits() { - let max_weight: Weight = ::MaximumWeight::get(); new_test_ext().execute_with(|| { + let max_weight: Weight = ::MaximumWeight::get(); // schedule 42 let call = RuntimeCall::Logger(LoggerCall::log { i: 42, weight: max_weight / 3 * 2 }); assert_ok!(Scheduler::do_schedule( @@ -1344,8 +1344,8 @@ fn retry_respects_weight_limits() { #[test] fn try_schedule_retry_respects_weight_limits() { - let max_weight: Weight = ::MaximumWeight::get(); new_test_ext().execute_with(|| { + let max_weight: Weight = ::MaximumWeight::get(); let service_agendas_weight = ::WeightInfo::service_agendas_base(); let service_agenda_weight = ::WeightInfo::service_agenda_base( ::MaxScheduledPerBlock::get(), @@ -1404,8 +1404,8 @@ fn try_schedule_retry_respects_weight_limits() { /// Permanently overweight calls are not deleted but also not executed. #[test] fn scheduler_does_not_delete_permanently_overweight_call() { - let max_weight: Weight = ::MaximumWeight::get(); new_test_ext().execute_with(|| { + let max_weight: Weight = ::MaximumWeight::get(); let call = RuntimeCall::Logger(LoggerCall::log { i: 42, weight: max_weight }); assert_ok!(Scheduler::do_schedule( DispatchTime::At(4), @@ -1430,10 +1430,10 @@ fn scheduler_does_not_delete_permanently_overweight_call() { #[test] fn scheduler_handles_periodic_failure() { - let max_weight: Weight = ::MaximumWeight::get(); - let max_per_block = ::MaxScheduledPerBlock::get(); - new_test_ext().execute_with(|| { + let max_weight: Weight = ::MaximumWeight::get(); + let max_per_block = ::MaxScheduledPerBlock::get(); + let call = RuntimeCall::Logger(LoggerCall::log { i: 42, weight: (max_weight / 3) * 2 }); let bound = Preimage::bound(call).unwrap(); @@ -1472,9 +1472,9 @@ fn scheduler_handles_periodic_failure() { #[test] fn scheduler_handles_periodic_unavailable_preimage() { - let max_weight: Weight = ::MaximumWeight::get(); - new_test_ext().execute_with(|| { + let max_weight: Weight = ::MaximumWeight::get(); + let call = RuntimeCall::Logger(LoggerCall::log { i: 42, weight: (max_weight / 3) * 2 }); let hash = ::Hashing::hash_of(&call); let len = call.using_encoded(|x| x.len()) as u32; @@ -1518,8 +1518,8 @@ fn scheduler_handles_periodic_unavailable_preimage() { #[test] fn scheduler_respects_priority_ordering() { - let max_weight: Weight = ::MaximumWeight::get(); new_test_ext().execute_with(|| { + let max_weight: Weight = ::MaximumWeight::get(); let call = RuntimeCall::Logger(LoggerCall::log { i: 42, weight: max_weight / 3 }); assert_ok!(Scheduler::do_schedule( DispatchTime::At(4), @@ -3039,3 +3039,40 @@ fn unavailable_call_is_detected() { assert!(!Preimage::is_requested(&hash)); }); } + +#[test] +fn postponed_task_is_still_available() { + new_test_ext().execute_with(|| { + let service_agendas_weight = ::WeightInfo::service_agendas_base(); + let service_agenda_weight = ::WeightInfo::service_agenda_base( + ::MaxScheduledPerBlock::get(), + ); + + assert_ok!(Scheduler::schedule( + RuntimeOrigin::root(), + 4, + None, + 128, + Box::new(RuntimeCall::from(frame_system::Call::remark { + remark: vec![0u8; 3 * 1024 * 1024], + })) + )); + System::run_to_block::(3); + // Scheduled calls are in the agenda. + assert_eq!(Agenda::::get(4).len(), 1); + + let old_weight = MaximumSchedulerWeight::get(); + MaximumSchedulerWeight::set(&service_agenda_weight.saturating_add(service_agendas_weight)); + + System::run_to_block::(4); + + // The task should still be there. + assert_eq!(Agenda::::get(4).iter().filter(|a| a.is_some()).count(), 1); + System::assert_last_event(crate::Event::AgendaIncomplete { when: 4 }.into()); + + // Now it should get executed + MaximumSchedulerWeight::set(&old_weight); + System::run_to_block::(5); + assert!(Agenda::::get(4).is_empty()); + }); +}