diff --git a/.config/zepter.yaml b/.config/zepter.yaml
index be52cd791d..1a7f36cffe 100644
--- a/.config/zepter.yaml
+++ b/.config/zepter.yaml
@@ -12,7 +12,7 @@ workflows:
# Check that `A` activates the features of `B`.
'propagate-feature',
# These are the features to check:
- '--features=try-runtime,runtime-benchmarks,std,stable2503',
+ '--features=try-runtime,runtime-benchmarks,std,kusama-ahm,polkadot-ahm',
# Do not try to add a new section into `[features]` of `A` only because `B` expose that feature. There are edge-cases where this is still needed, but we can add them manually.
'--left-side-feature-missing=ignore',
# Ignore the case that `A` it outside of the workspace. Otherwise it will report errors in external dependencies that we have no influence on.
diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml
index a9cd147f5f..a546a97d96 100644
--- a/.github/workflows/clippy.yml
+++ b/.github/workflows/clippy.yml
@@ -41,7 +41,9 @@ jobs:
run: |
cargo clippy --version
cargo clippy --all-targets --locked --workspace --quiet
- cargo clippy --all-targets --all-features --locked --workspace --quiet
+ cargo clippy --all-targets --locked --workspace --features try-runtime,runtime-benchmarks,std --quiet
+ cargo clippy --all-targets --locked --quiet --features try-runtime,runtime-benchmarks,std,kusama-ahm -p staging-kusama-runtime -p asset-hub-kusama-runtime
+ cargo clippy --all-targets --locked --quiet --features try-runtime,runtime-benchmarks,std,polkadot-ahm -p polkadot-runtime -p asset-hub-polkadot-runtime
env:
#RUSTFLAGS: "-D warnings" FAIL-CI re-enable after AHM
SKIP_WASM_BUILD: 1
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 73acf66521..da8d5b87af 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -185,21 +185,21 @@ jobs:
shared-key: "fellowship-cache-integration-tests-ahm"
save-if: ${{ github.ref == 'refs/heads/main' }}
- - name: Download Paseo snaps
+ - name: Download Kusama snaps
run: |
python3 -m pip install gdown
- gdown "1AoIyspAe4MzRTlxzQHWqeWNK-kGlWvP6" # 2025-07-29
- gdown "1yjY4fuzJjxSxzfRb8jESqDojfr8Eu2CV" # 2025-07-29
+ gdown 12ndV-id_Z6ZTYx46ULI79XjGVDLiT1pH # 2025-09-02
+ gdown 1ZUMCnf1crYxjLT6WiWAKRas-hQWtLVNE # 2025-09-02
- lz4 -d paseo.snap.lz4 paseo.snap
- lz4 -d ah-paseo.snap.lz4 ah-paseo.snap
+ lz4 -d kusama.snap.lz4 kusama.snap
+ lz4 -d ah-kusama.snap.lz4 ah-kusama.snap
- - name: Test Asset Hub Migration (Paseo)
- run: cargo test --locked -q -p polkadot-integration-tests-ahm -r --features paseo --features try-runtime -- --nocapture --test-threads 1
+ - name: Test Asset Hub Migration (Kusama)
+ run: cargo test --locked -q -p polkadot-integration-tests-ahm -r --features kusama-ahm --features try-runtime -- --nocapture --test-threads 1
env:
RUST_BACKTRACE: 1
- SNAP_RC: "../../paseo.snap"
- SNAP_AH: "../../ah-paseo.snap"
+ SNAP_RC: "../../kusama.snap"
+ SNAP_AH: "../../ah-kusama.snap"
RUST_LOG: "warn"
- name: Download Polkadot snaps
@@ -211,7 +211,7 @@ jobs:
lz4 -d ah-polkadot.snap.lz4 ah-polkadot.snap
- name: Test Asset Hub Migration (Polkadot)
- run: cargo test --locked -q -p polkadot-integration-tests-ahm -r --features try-runtime -- --nocapture --test-threads 1
+ run: cargo test --locked -q -p polkadot-integration-tests-ahm -r --features polkadot-ahm --features try-runtime -- --nocapture --test-threads 1
env:
RUST_BACKTRACE: 1
SNAP_RC: "../../polkadot.snap"
@@ -219,7 +219,13 @@ jobs:
RUST_LOG: "warn"
- name: Test Benchmarks Asset Hub Migration (Polkadot)
- run: cargo test --locked -q -p polkadot-integration-tests-ahm -r --features runtime-benchmarks -- bench_rc bench_ops bench_ah --nocapture
+ run: cargo test --locked -q -p polkadot-integration-tests-ahm -r --features polkadot-ahm --features runtime-benchmarks -- bench_rc bench_ops bench_ah --nocapture
+ env:
+ RUST_BACKTRACE: 1
+ RUST_LOG: "warn"
+
+ - name: Test Benchmarks Asset Hub Migration (Kusama)
+ run: cargo test --locked -q -p polkadot-integration-tests-ahm -r --features kusama-ahm --features runtime-benchmarks -- bench_rc bench_ops bench_ah --nocapture
env:
RUST_BACKTRACE: 1
RUST_LOG: "warn"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2da57d8407..b91547619c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,4 @@
-# Changelog
+t# Changelog
Changelog for the runtimes governed by the Polkadot Fellowship.
diff --git a/Cargo.lock b/Cargo.lock
index 06265ad65b..69df2135e8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -880,6 +880,7 @@ dependencies = [
"cumulus-primitives-core",
"cumulus-primitives-utility",
"frame-benchmarking",
+ "frame-election-provider-support",
"frame-executive",
"frame-metadata-hash-extension",
"frame-support",
@@ -890,30 +891,52 @@ dependencies = [
"hex-literal",
"kusama-runtime-constants",
"log",
+ "pallet-ah-migrator",
+ "pallet-ah-ops",
"pallet-asset-conversion",
"pallet-asset-conversion-tx-payment",
+ "pallet-asset-rate",
"pallet-assets",
"pallet-aura",
"pallet-authorship",
+ "pallet-bags-list",
"pallet-balances",
+ "pallet-bounties",
+ "pallet-child-bounties",
"pallet-collator-selection",
+ "pallet-conviction-voting",
+ "pallet-delegated-staking",
+ "pallet-election-provider-multi-block",
+ "pallet-indices",
"pallet-message-queue",
"pallet-migrations",
"pallet-multisig",
"pallet-nft-fractionalization",
"pallet-nfts",
"pallet-nfts-runtime-api",
+ "pallet-nomination-pools",
+ "pallet-nomination-pools-benchmarking",
+ "pallet-preimage",
"pallet-proxy",
+ "pallet-rc-migrator",
+ "pallet-recovery",
+ "pallet-referenda",
"pallet-remote-proxy",
"pallet-revive",
+ "pallet-scheduler",
"pallet-session",
+ "pallet-staking",
+ "pallet-staking-async",
+ "pallet-staking-async-rc-client",
"pallet-state-trie-migration",
"pallet-timestamp",
"pallet-transaction-payment",
"pallet-transaction-payment-rpc-runtime-api",
+ "pallet-treasury",
"pallet-uniques",
"pallet-utility",
"pallet-vesting",
+ "pallet-whitelist",
"pallet-xcm",
"pallet-xcm-benchmarks",
"pallet-xcm-bridge-hub-router",
@@ -928,15 +951,18 @@ dependencies = [
"serde_json",
"snowbridge-inbound-queue-primitives",
"sp-api",
+ "sp-arithmetic",
"sp-block-builder",
"sp-consensus-aura",
"sp-core 38.0.0",
"sp-genesis-builder",
"sp-inherents",
"sp-io",
+ "sp-npos-elections",
"sp-offchain",
"sp-runtime",
"sp-session",
+ "sp-staking",
"sp-storage",
"sp-transaction-pool",
"sp-version",
@@ -8345,7 +8371,6 @@ name = "pallet-ah-migrator"
version = "0.1.0"
dependencies = [
"assets-common",
- "collectives-polkadot-runtime-constants",
"cumulus-primitives-core",
"frame-benchmarking",
"frame-election-provider-support",
@@ -8370,6 +8395,7 @@ dependencies = [
"pallet-preimage",
"pallet-proxy",
"pallet-rc-migrator",
+ "pallet-recovery",
"pallet-referenda",
"pallet-scheduler",
"pallet-staking",
@@ -8383,7 +8409,6 @@ dependencies = [
"parity-scale-codec",
"polkadot-parachain-primitives",
"polkadot-runtime-common",
- "polkadot-runtime-constants",
"polkadot-runtime-parachains",
"scale-info",
"serde",
@@ -9657,9 +9682,11 @@ dependencies = [
"pallet-indices",
"pallet-message-queue",
"pallet-multisig",
+ "pallet-nis",
"pallet-nomination-pools",
"pallet-preimage",
"pallet-proxy",
+ "pallet-recovery",
"pallet-referenda",
"pallet-scheduler",
"pallet-session",
@@ -9673,7 +9700,6 @@ dependencies = [
"parity-scale-codec",
"polkadot-parachain-primitives",
"polkadot-runtime-common",
- "polkadot-runtime-constants",
"polkadot-runtime-parachains",
"scale-info",
"serde",
@@ -10965,6 +10991,7 @@ dependencies = [
name = "polkadot-integration-tests-ahm"
version = "0.1.0"
dependencies = [
+ "asset-hub-kusama-runtime",
"asset-hub-polkadot-runtime",
"cumulus-pallet-parachain-system",
"cumulus-primitives-core",
@@ -10975,6 +11002,7 @@ dependencies = [
"frame-system",
"hex",
"hex-literal",
+ "kusama-runtime-constants",
"log",
"pallet-ah-migrator",
"pallet-ah-ops",
@@ -11011,6 +11039,7 @@ dependencies = [
"sp-runtime",
"sp-storage",
"sp-tracing 18.0.0",
+ "staging-kusama-runtime",
"staging-xcm",
"staging-xcm-builder",
"tokio",
@@ -15550,6 +15579,7 @@ dependencies = [
"pallet-preimage",
"pallet-proxy",
"pallet-ranked-collective",
+ "pallet-rc-migrator",
"pallet-recovery",
"pallet-referenda",
"pallet-scheduler",
@@ -15557,6 +15587,8 @@ dependencies = [
"pallet-session-benchmarking",
"pallet-society",
"pallet-staking",
+ "pallet-staking-async-ah-client",
+ "pallet-staking-async-rc-client",
"pallet-staking-runtime-api",
"pallet-timestamp",
"pallet-transaction-payment",
diff --git a/Cargo.toml b/Cargo.toml
index a00a603393..97ffc68771 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -276,10 +276,10 @@ ss58-registry = { version = "1.47.0" }
resolver = "2"
members = [
+ "integration-tests/ahm",
"pallets/ah-migrator",
- "pallets/rc-migrator",
"pallets/ah-ops",
- "integration-tests/ahm",
+ "pallets/rc-migrator",
"chain-spec-generator",
"integration-tests/emulated/chains/parachains/assets/asset-hub-kusama",
diff --git a/chain-spec-generator/Cargo.toml b/chain-spec-generator/Cargo.toml
index df2f41d3b8..f8f01e9aa5 100644
--- a/chain-spec-generator/Cargo.toml
+++ b/chain-spec-generator/Cargo.toml
@@ -65,7 +65,11 @@ on-chain-release-build = [
]
polkadot = ["polkadot-runtime"]
-kusama = ["kusama-runtime"]
+kusama = [
+ "asset-hub-kusama-runtime",
+ "kusama-runtime",
+ "kusama-runtime",
+]
asset-hub-polkadot = ["asset-hub-polkadot-runtime"]
asset-hub-kusama = ["asset-hub-kusama-runtime"]
collectives-polkadot = ["collectives-polkadot-runtime"]
diff --git a/integration-tests/ahm/Cargo.toml b/integration-tests/ahm/Cargo.toml
index e284328167..eac7b5b06e 100644
--- a/integration-tests/ahm/Cargo.toml
+++ b/integration-tests/ahm/Cargo.toml
@@ -1,15 +1,14 @@
[package]
name = "polkadot-integration-tests-ahm"
-version = "0.1.0" # Wont work in the SDK otherwise
+version = "0.1.0"
authors.workspace = true
edition.workspace = true
license = "Apache-2.0"
description = "Polkadot integration tests for the Asset Hub Migration"
publish = false
-[dev-dependencies]
+[dependencies]
codec = { workspace = true, default-features = true }
-asset-hub-polkadot-runtime = { workspace = true }
authority-discovery-primitives = { workspace = true, default-features = true }
babe-primitives = { workspace = true, default-features = true }
beefy-primitives = { workspace = true, default-features = true }
@@ -30,9 +29,7 @@ parachains-common = { workspace = true, default-features = true }
pallet-multisig = { workspace = true, default-features = true }
polkadot-parachain-primitives = { workspace = true, default-features = true }
polkadot-primitives = { workspace = true, default-features = true }
-polkadot-runtime = { workspace = true }
polkadot-runtime-common = { workspace = true, default-features = true }
-polkadot-runtime-constants = { workspace = true, default-features = true }
remote-externalities = { workspace = true }
runtime-parachains = { workspace = true, default-features = true }
sp-core = { workspace = true, default-features = true }
@@ -59,21 +56,46 @@ pallet-preimage = { workspace = true, default-features = true }
pallet-staking-async = { workspace = true, default-features = true }
pallet-referenda = { workspace = true, default-features = true }
+polkadot-runtime = { workspace = true, optional = true }
+polkadot-runtime-constants = { workspace = true, default-features = true, optional = true }
+asset-hub-polkadot-runtime = { workspace = true, optional = true }
+
+kusama-runtime = { workspace = true, optional = true }
+kusama-runtime-constants = { workspace = true, default-features = true, optional = true }
+asset-hub-kusama-runtime = { workspace = true, optional = true }
+
[features]
default = ["std"]
+polkadot-ahm = [
+ "asset-hub-polkadot-runtime",
+ "asset-hub-polkadot-runtime?/polkadot-ahm",
+ "polkadot-runtime",
+ "polkadot-runtime-constants",
+ "polkadot-runtime?/polkadot-ahm",
+]
+kusama-ahm = [
+ "asset-hub-kusama-runtime/kusama-ahm",
+ "kusama-runtime-constants",
+ "kusama-runtime/kusama-ahm",
+ "pallet-ah-migrator/kusama-ahm",
+ "pallet-rc-migrator/kusama-ahm",
+]
std = [
"cumulus-pallet-parachain-system/std",
"frame-benchmarking/std",
"hex/std",
+ "kusama-runtime?/std",
"log/std",
- "polkadot-runtime/std",
+ "polkadot-runtime?/std",
"rand/std",
]
try-runtime = [
- "asset-hub-polkadot-runtime/try-runtime",
+ "asset-hub-kusama-runtime?/try-runtime",
+ "asset-hub-polkadot-runtime?/try-runtime",
"cumulus-pallet-parachain-system/try-runtime",
"frame-support/try-runtime",
"frame-system/try-runtime",
+ "kusama-runtime?/try-runtime",
"pallet-ah-migrator/try-runtime",
"pallet-ah-ops/try-runtime",
"pallet-balances/try-runtime",
@@ -89,19 +111,22 @@ try-runtime = [
"pallet-timestamp/try-runtime",
"pallet-whitelist/try-runtime",
"pallet-xcm/try-runtime",
+ "parachains-common/try-runtime",
"polkadot-runtime-common/try-runtime",
- "polkadot-runtime/try-runtime",
+ "polkadot-runtime?/try-runtime",
"runtime-parachains/try-runtime",
"sp-runtime/try-runtime",
- "parachains-common/try-runtime"
]
runtime-benchmarks = [
- "asset-hub-polkadot-runtime/runtime-benchmarks",
+ "asset-hub-kusama-runtime?/runtime-benchmarks",
+ "asset-hub-polkadot-runtime?/runtime-benchmarks",
"cumulus-pallet-parachain-system/runtime-benchmarks",
"cumulus-primitives-core/runtime-benchmarks",
"frame-benchmarking/runtime-benchmarks",
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
+ "kusama-runtime-constants?/runtime-benchmarks",
+ "kusama-runtime?/runtime-benchmarks",
"pallet-ah-migrator/runtime-benchmarks",
"pallet-ah-ops/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
@@ -121,11 +146,10 @@ runtime-benchmarks = [
"polkadot-parachain-primitives/runtime-benchmarks",
"polkadot-primitives/runtime-benchmarks",
"polkadot-runtime-common/runtime-benchmarks",
- "polkadot-runtime-constants/runtime-benchmarks",
- "polkadot-runtime/runtime-benchmarks",
+ "polkadot-runtime-constants?/runtime-benchmarks",
+ "polkadot-runtime?/runtime-benchmarks",
"runtime-parachains/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"xcm-builder/runtime-benchmarks",
"xcm/runtime-benchmarks",
]
-paseo = []
diff --git a/integration-tests/ahm/src/accounts_translation_works.rs b/integration-tests/ahm/src/accounts_translation_works.rs
index 1caee9a163..a59db031d4 100644
--- a/integration-tests/ahm/src/accounts_translation_works.rs
+++ b/integration-tests/ahm/src/accounts_translation_works.rs
@@ -16,6 +16,8 @@
//! Test that account translation works (Para sovereign and derived).
+use crate::porting_prelude::*;
+
use hex_literal::hex;
use pallet_ah_migrator::types::AhMigrationCheck;
use pallet_rc_migrator::{accounts::AccountState, types::RcMigrationCheck};
@@ -27,6 +29,7 @@ type AssetHubRuntime = asset_hub_polkadot_runtime::Runtime;
pub struct AccountTranslationWorks;
+#[cfg(not(feature = "kusama-ahm"))]
pub const TRANSLATIONS: &[(AccountId32, AccountId32)] = &[
// para 2034: 5Ec4AhPbkXX97KXMcf9v9SkRNG4Gyc3VhcMMuQe9QXfAHnrC ->
// 5Eg2fntQqFi3EvFWAf71G66Ecjjah26bmFzoANAeHFgj9Lia
@@ -36,6 +39,9 @@ pub const TRANSLATIONS: &[(AccountId32, AccountId32)] = &[
),
];
+#[cfg(feature = "kusama-ahm")]
+pub const TRANSLATIONS: &[(AccountId32, AccountId32)] = &[];
+
impl RcMigrationCheck for AccountTranslationWorks {
type RcPrePayload = ();
diff --git a/integration-tests/ahm/src/balances_test.rs b/integration-tests/ahm/src/balances_test.rs
index 5ee21e8df3..efcba58c4d 100644
--- a/integration-tests/ahm/src/balances_test.rs
+++ b/integration-tests/ahm/src/balances_test.rs
@@ -26,6 +26,7 @@
//! types directly.
use crate::porting_prelude::*;
+
use frame_support::{defensive_assert, traits::Currency};
use pallet_ah_migrator::types::AhMigrationCheck;
use pallet_rc_migrator::types::RcMigrationCheck;
diff --git a/integration-tests/ahm/src/bench_ah.rs b/integration-tests/ahm/src/bench_ah.rs
index 97a45e9fdf..30b1b40dbc 100644
--- a/integration-tests/ahm/src/bench_ah.rs
+++ b/integration-tests/ahm/src/bench_ah.rs
@@ -18,6 +18,8 @@
#![cfg(feature = "runtime-benchmarks")]
+use crate::porting_prelude::*;
+
use asset_hub_polkadot_runtime::{Runtime as AssetHub, System as AssetHubSystem};
use pallet_ah_migrator::benchmarking::*;
use sp_runtime::BuildStorage;
diff --git a/integration-tests/ahm/src/bench_ops.rs b/integration-tests/ahm/src/bench_ops.rs
index 171cbe87c4..944a3355de 100644
--- a/integration-tests/ahm/src/bench_ops.rs
+++ b/integration-tests/ahm/src/bench_ops.rs
@@ -18,6 +18,8 @@
#![cfg(feature = "runtime-benchmarks")]
+use crate::porting_prelude::*;
+
use asset_hub_polkadot_runtime::{Runtime as AssetHub, System as AssetHubSystem};
use pallet_ah_ops::benchmarking::*;
use sp_runtime::BuildStorage;
diff --git a/integration-tests/ahm/src/bench_rc.rs b/integration-tests/ahm/src/bench_rc.rs
index 876aeac1c9..e65c7837a7 100644
--- a/integration-tests/ahm/src/bench_rc.rs
+++ b/integration-tests/ahm/src/bench_rc.rs
@@ -18,6 +18,8 @@
#![cfg(feature = "runtime-benchmarks")]
+use crate::porting_prelude::*;
+
use pallet_rc_migrator::benchmarking::*;
use polkadot_runtime::{Runtime as RelayChain, System as RcSystem};
use sp_runtime::BuildStorage;
diff --git a/integration-tests/ahm/src/call_filter_asset_hub.rs b/integration-tests/ahm/src/call_filter_asset_hub.rs
index 4b3826022d..ab1f05eccd 100644
--- a/integration-tests/ahm/src/call_filter_asset_hub.rs
+++ b/integration-tests/ahm/src/call_filter_asset_hub.rs
@@ -16,6 +16,8 @@
//! Asset Hub Migration tests.
+use crate::porting_prelude::*;
+
use asset_hub_polkadot_runtime::{BuildStorage, Runtime as T, RuntimeCall, RuntimeOrigin};
use cumulus_primitives_core::AggregateMessageOrigin;
use frame_support::{sp_runtime::traits::Dispatchable, traits::Contains};
diff --git a/integration-tests/ahm/src/call_filter_relay.rs b/integration-tests/ahm/src/call_filter_relay.rs
index 5d3e5a465e..628363f7c7 100644
--- a/integration-tests/ahm/src/call_filter_relay.rs
+++ b/integration-tests/ahm/src/call_filter_relay.rs
@@ -16,6 +16,8 @@
//! Asset Hub Migration tests.
+use crate::porting_prelude::*;
+
use frame_support::{sp_runtime::traits::Dispatchable, traits::Contains};
use pallet_rc_migrator::*;
use polkadot_primitives::Id as ParaId;
diff --git a/integration-tests/ahm/src/checks.rs b/integration-tests/ahm/src/checks.rs
index 450664e1e1..9f1d0f9bbe 100644
--- a/integration-tests/ahm/src/checks.rs
+++ b/integration-tests/ahm/src/checks.rs
@@ -22,7 +22,10 @@ use pallet_ah_migrator::types::AhMigrationCheck;
use pallet_rc_migrator::types::RcMigrationCheck;
#[cfg(feature = "try-runtime")]
-use frame_support::{defensive_assert, traits::{TryDecodeEntireStorage, TryDecodeEntireStorageError, TryState}};
+use frame_support::{
+ defensive_assert,
+ traits::{TryDecodeEntireStorage, TryDecodeEntireStorageError, TryState},
+};
pub struct SanityChecks;
diff --git a/integration-tests/ahm/src/lib.rs b/integration-tests/ahm/src/lib.rs
index ca07425a7a..e2a983504c 100644
--- a/integration-tests/ahm/src/lib.rs
+++ b/integration-tests/ahm/src/lib.rs
@@ -16,7 +16,7 @@
//! Helper imports to make it easy to run the AHM integration tests for different runtimes.
-#![cfg(test)]
+#![cfg(all(test, any(feature = "polkadot-ahm", feature = "kusama-ahm")))]
pub mod accounts_translation_works;
pub mod balances_test;
@@ -36,21 +36,48 @@ pub mod xcm_route;
/// Imports for the AHM tests that can be reused for other chains.
pub mod porting_prelude {
- // For Kusama, we will add a feature here. For now it is just a stub.
+ #[cfg(feature = "polkadot-ahm")]
pub mod import_alias {
pub use polkadot_runtime_constants::DOLLARS as RC_DOLLARS;
}
+ #[cfg(feature = "kusama-ahm")]
+ pub mod import_alias {
+ pub use asset_hub_kusama_runtime as asset_hub_polkadot_runtime;
+ pub use kusama_runtime as polkadot_runtime;
+ pub use kusama_runtime_constants as polkadot_runtime_constants;
+
+ pub use kusama_runtime_constants::currency::UNITS as RC_DOLLARS;
+ }
+ #[cfg(any(feature = "polkadot-ahm", feature = "kusama-ahm"))]
pub use import_alias::*;
// Convenience aliases:
+ #[cfg(feature = "polkadot-ahm")]
pub use asset_hub_polkadot_runtime::{
Runtime as AhRuntime, RuntimeCall as AhRuntimeCall, RuntimeEvent as AhRuntimeEvent,
RuntimeOrigin as AhRuntimeOrigin,
};
+ #[cfg(feature = "polkadot-ahm")]
pub use polkadot_runtime::{
Runtime as RcRuntime, RuntimeCall as RcRuntimeCall, RuntimeEvent as RcRuntimeEvent,
RuntimeOrigin as RcRuntimeOrigin,
};
+ #[cfg(feature = "polkadot-ahm")]
pub use polkadot_runtime_constants::proxy as rc_proxy_definition;
+
+ // Convenience aliases:
+ #[cfg(feature = "kusama-ahm")]
+ pub use asset_hub_kusama_runtime::{
+ Runtime as AhRuntime, RuntimeCall as AhRuntimeCall, RuntimeEvent as AhRuntimeEvent,
+ RuntimeOrigin as AhRuntimeOrigin,
+ };
+ #[cfg(feature = "kusama-ahm")]
+ pub use kusama_runtime::{
+ Runtime as RcRuntime, RuntimeCall as RcRuntimeCall, RuntimeEvent as RcRuntimeEvent,
+ RuntimeOrigin as RcRuntimeOrigin,
+ };
+
+ #[cfg(feature = "kusama-ahm")]
+ pub use kusama_runtime_constants::proxy as rc_proxy_definition;
}
diff --git a/integration-tests/ahm/src/mock.rs b/integration-tests/ahm/src/mock.rs
index 7bd9bcfbd3..6a6903feeb 100644
--- a/integration-tests/ahm/src/mock.rs
+++ b/integration-tests/ahm/src/mock.rs
@@ -14,13 +14,14 @@
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see .
+use crate::porting_prelude::*;
+
use asset_hub_polkadot_runtime::{AhMigrator, Runtime as AssetHub, RuntimeEvent as AhRuntimeEvent};
use codec::Decode;
use cumulus_primitives_core::{
AggregateMessageOrigin as ParachainMessageOrigin, InboundDownwardMessage, ParaId,
};
-use frame_support::traits::QueueFootprintQuery;
-use frame_support::traits::{EnqueueMessage, OnFinalize, OnInitialize};
+use frame_support::traits::{EnqueueMessage, OnFinalize, OnInitialize, QueueFootprintQuery};
use frame_system::pallet_prelude::BlockNumberFor;
use pallet_rc_migrator::{
MigrationStage as RcMigrationStage, MigrationStageOf as RcMigrationStageOf,
diff --git a/integration-tests/ahm/src/multisig_still_work.rs b/integration-tests/ahm/src/multisig_still_work.rs
index 925df77bb6..5c913148e5 100644
--- a/integration-tests/ahm/src/multisig_still_work.rs
+++ b/integration-tests/ahm/src/multisig_still_work.rs
@@ -16,11 +16,12 @@
//! Test that Multisig Account IDs result in the same IDs and they can still dispatch calls.
+use crate::porting_prelude::*;
+
use frame_support::{dispatch::GetDispatchInfo, pallet_prelude::Weight, traits::Currency};
use pallet_ah_migrator::types::AhMigrationCheck;
use pallet_rc_migrator::types::RcMigrationCheck;
-use rand::{Rng};
-use rand::seq::IteratorRandom;
+use rand::{seq::IteratorRandom, Rng};
use sp_core::Get;
use sp_runtime::{traits::StaticLookup, AccountId32};
@@ -75,6 +76,7 @@ impl RcMigrationCheck for MultisigStillWork {
multisigs.push(multisig.clone());
}
+ // TODO: @ggwpez supposed to be error? errors for Kusama
log::error!("multisigs num: {:?}", multisigs.len());
multisigs
}
diff --git a/integration-tests/ahm/src/multisig_test.rs b/integration-tests/ahm/src/multisig_test.rs
index ad823a00e0..7c1232464a 100644
--- a/integration-tests/ahm/src/multisig_test.rs
+++ b/integration-tests/ahm/src/multisig_test.rs
@@ -26,6 +26,7 @@
//! types directly.
use crate::porting_prelude::*;
+
use frame_support::{pallet_prelude::*, traits::Currency};
use pallet_ah_migrator::types::AhMigrationCheck;
use pallet_rc_migrator::types::RcMigrationCheck;
diff --git a/integration-tests/ahm/src/proxy/basic_still_works.rs b/integration-tests/ahm/src/proxy/basic_still_works.rs
index 577094ad99..14b28ae153 100644
--- a/integration-tests/ahm/src/proxy/basic_still_works.rs
+++ b/integration-tests/ahm/src/proxy/basic_still_works.rs
@@ -23,8 +23,9 @@
//! yet, they are here. This test is also very simple, it is not generic and just uses the Runtime
//! types directly.
-use super::Permission;
+use crate::porting_prelude::*;
+use super::Permission;
use frame_support::{
pallet_prelude::*,
traits::{schedule::DispatchTime, Currency, StorePreimage},
@@ -102,7 +103,7 @@ impl RcMigrationCheck for ProxyBasicWorks {
impl AhMigrationCheck for ProxyBasicWorks {
type RcPrePayload = PureProxies;
- type AhPrePayload = ();
+ type AhPrePayload = PureProxies;
fn pre_check(_: Self::RcPrePayload) -> Self::AhPrePayload {
// Not empty in this case
@@ -110,10 +111,40 @@ impl AhMigrationCheck for ProxyBasicWorks {
pallet_proxy::Proxies::::iter().next().is_some(),
"Assert storage 'Proxy::Proxies::ah_pre::empty'"
);
+
+ let mut pre_payload = BTreeMap::new();
+
+ for (delegator, (proxies, _deposit)) in pallet_proxy::Proxies::::iter() {
+ for proxy in proxies.into_iter() {
+ let inner = proxy.proxy_type;
+
+ let permission = match Permission::try_convert(inner) {
+ Ok(permission) => permission,
+ Err(e) => {
+ defensive!("Proxy could not be converted: {:?}", e);
+ continue;
+ },
+ };
+ pre_payload
+ .entry((proxy.delegate, delegator.clone()))
+ .or_insert_with(Vec::new)
+ .push(permission);
+ }
+ }
+
+ pre_payload
}
- fn post_check(rc_pre_payload: Self::RcPrePayload, _: Self::AhPrePayload) {
- for ((delegatee, delegator), permissions) in rc_pre_payload.iter() {
+ fn post_check(rc_pre_payload: Self::RcPrePayload, ah_pre_payload: Self::AhPrePayload) {
+ let mut pre_and_post = rc_pre_payload;
+ for ((delegatee, delegator), permissions) in ah_pre_payload.iter() {
+ pre_and_post
+ .entry((delegatee.clone(), delegator.clone()))
+ .or_insert_with(Vec::new)
+ .extend(permissions.clone());
+ }
+
+ for ((delegatee, delegator), permissions) in pre_and_post.iter() {
// Assert storage "Proxy::Proxies::ah_post::correct"
let (entry, _) = pallet_proxy::Proxies::::get(delegator);
if entry.is_empty() {
@@ -169,9 +200,15 @@ impl ProxyBasicWorks {
let allowed_transfer = permissions.contains(&Permission::Any);
if allowed_transfer {
- assert!(Self::can_transfer(delegatee, delegator, true), "`Any` can transfer");
+ assert!(
+ Self::can_transfer(delegatee, delegator, permissions, true),
+ "`Any` can transfer"
+ );
} else {
- assert!(!Self::can_transfer(delegatee, delegator, false), "Only `Any` can transfer");
+ assert!(
+ !Self::can_transfer(delegatee, delegator, permissions, false),
+ "Only `Any` can transfer"
+ );
}
let allowed_governance = permissions.contains(&Permission::Any) ||
@@ -179,12 +216,12 @@ impl ProxyBasicWorks {
permissions.contains(&Permission::Governance);
if allowed_governance {
assert!(
- Self::can_governance(delegatee, delegator, true),
+ Self::can_governance(delegatee, delegator, permissions, true),
"`Any`, `NonTransfer`, or `Governance` can do governance"
);
} else {
assert!(
- !Self::can_governance(delegatee, delegator, false),
+ !Self::can_governance(delegatee, delegator, permissions, false),
"Only `Any`, `NonTransfer`, or `Governance` can do governance, permissions: {permissions:?}"
);
}
@@ -193,21 +230,54 @@ impl ProxyBasicWorks {
permissions.contains(&Permission::NonTransfer) ||
permissions.contains(&Permission::Staking);
if allowed_staking {
- assert!(Self::can_stake(delegatee, delegator), "`Any` or `Staking` can stake");
+ assert!(
+ Self::can_stake(delegatee, delegator, permissions, true),
+ "`Any` or `Staking` can stake"
+ );
} else {
- assert!(!Self::can_stake(delegatee, delegator), "Only `Any` or `Staking` can stake");
+ assert!(
+ !Self::can_stake(delegatee, delegator, permissions, false),
+ "Only `Any` or `Staking` can stake"
+ );
}
// Alice cannot transfer
- assert!(!Self::can_transfer(&alice, delegator, false), "Alice cannot transfer");
+ assert!(!Self::can_transfer_impl(&alice, delegator, None, false), "Alice cannot transfer");
// Alice cannot do governance
- assert!(!Self::can_governance(&alice, delegator, false), "Alice cannot do governance");
+ assert!(
+ !Self::can_governance_impl(&alice, delegator, None, false),
+ "Alice cannot do governance"
+ );
// Alice cannot stake
- assert!(!Self::can_stake(&alice, delegator), "Alice cannot stake");
+ assert!(!Self::can_stake_impl(&alice, delegator, None, false), "Alice cannot stake");
}
/// Check that the `delegatee` can transfer balances on behalf of the `delegator`.
- fn can_transfer(delegatee: &AccountId32, delegator: &AccountId32, hint: bool) -> bool {
+ fn can_transfer(
+ delegatee: &AccountId32,
+ delegator: &AccountId32,
+ permissions: &Vec,
+ hint: bool,
+ ) -> bool {
+ let mut force_types = permissions
+ .iter()
+ .map(|p| Permission::try_convert(p.clone()).ok())
+ .collect::>();
+ // Also always check without a force type
+ force_types.push(None);
+
+ force_types
+ .into_iter()
+ .map(|p| Self::can_transfer_impl(delegatee, delegator, p, hint))
+ .any(|r| r)
+ }
+
+ fn can_transfer_impl(
+ delegatee: &AccountId32,
+ delegator: &AccountId32,
+ force_proxy_type: Option,
+ hint: bool,
+ ) -> bool {
frame_support::hypothetically!({
let ed = Self::fund_accounts(delegatee, delegator);
@@ -220,7 +290,7 @@ impl ProxyBasicWorks {
let proxy_call: asset_hub_polkadot_runtime::RuntimeCall = pallet_proxy::Call::proxy {
real: delegator.clone().into(),
- force_proxy_type: None,
+ force_proxy_type,
call: Box::new(transfer),
}
.into();
@@ -244,7 +314,31 @@ impl ProxyBasicWorks {
/// Check that the `delegatee` can do governance on behalf of the `delegator`.
///
/// Currently only checks the `bounties::propose_bounty` call.
- fn can_governance(delegatee: &AccountId32, delegator: &AccountId32, hint: bool) -> bool {
+ fn can_governance(
+ delegatee: &AccountId32,
+ delegator: &AccountId32,
+ permissions: &Vec,
+ hint: bool,
+ ) -> bool {
+ let mut force_types = permissions
+ .iter()
+ .map(|p| Permission::try_convert(p.clone()).ok())
+ .collect::>();
+ // Also always check without a force type
+ force_types.push(None);
+
+ force_types
+ .into_iter()
+ .map(|p| Self::can_governance_impl(delegatee, delegator, p, hint))
+ .any(|r| r)
+ }
+
+ fn can_governance_impl(
+ delegatee: &AccountId32,
+ delegator: &AccountId32,
+ force_proxy_type: Option,
+ hint: bool,
+ ) -> bool {
frame_support::hypothetically!({
Self::fund_accounts(delegatee, delegator);
@@ -263,7 +357,7 @@ impl ProxyBasicWorks {
let proxy_call: asset_hub_polkadot_runtime::RuntimeCall = pallet_proxy::Call::proxy {
real: delegator.clone().into(),
- force_proxy_type: None,
+ force_proxy_type,
call: Box::new(call),
}
.into();
@@ -288,7 +382,31 @@ impl ProxyBasicWorks {
/// Check that the `delegatee` can do staking on behalf of the `delegator`.
///
/// Uses the `bond` call
- fn can_stake(delegatee: &AccountId32, delegator: &AccountId32) -> bool {
+ fn can_stake(
+ delegatee: &AccountId32,
+ delegator: &AccountId32,
+ permissions: &Vec,
+ hint: bool,
+ ) -> bool {
+ let mut force_types = permissions
+ .iter()
+ .map(|p| Permission::try_convert(p.clone()).ok())
+ .collect::>();
+ // Also always check without a force type
+ force_types.push(None);
+
+ force_types
+ .into_iter()
+ .map(|p| Self::can_stake_impl(delegatee, delegator, p, hint))
+ .any(|r| r)
+ }
+
+ fn can_stake_impl(
+ delegatee: &AccountId32,
+ delegator: &AccountId32,
+ force_proxy_type: Option,
+ hint: bool,
+ ) -> bool {
frame_support::hypothetically!({
// Migration should have finished
assert!(
@@ -298,29 +416,26 @@ impl ProxyBasicWorks {
);
Self::fund_accounts(delegatee, delegator);
+ let hint = if hint { " (it should)" } else { " (it should not)" };
+ log::debug!(
+ "Checking whether {:?} can stake on behalf of {:?}{}",
+ delegatee.to_polkadot_ss58(),
+ delegator.to_polkadot_ss58(),
+ hint
+ );
+
let call: asset_hub_polkadot_runtime::RuntimeCall =
pallet_staking_async::Call::set_payee { payee: RewardDestination::Staked }.into();
- // The proxy pallet is stupid and does not work when there are multiple delegations for
- // the same account. So we need to force and try which it is...
- frame_system::Pallet::::reset_events();
- for force_proxy_type in [
- None,
- Some(asset_hub_polkadot_runtime::ProxyType::Staking),
- Some(asset_hub_polkadot_runtime::ProxyType::Any),
- Some(asset_hub_polkadot_runtime::ProxyType::NonTransfer),
- ] {
- let proxy_call: asset_hub_polkadot_runtime::RuntimeCall =
- pallet_proxy::Call::proxy {
- real: delegator.clone().into(),
- force_proxy_type,
- call: Box::new(call.clone()),
- }
- .into();
-
- let _ = proxy_call
- .dispatch(asset_hub_polkadot_runtime::RuntimeOrigin::signed(delegatee.clone()));
+ let proxy_call: asset_hub_polkadot_runtime::RuntimeCall = pallet_proxy::Call::proxy {
+ real: delegator.clone().into(),
+ force_proxy_type,
+ call: Box::new(call.clone()),
}
+ .into();
+
+ let _ = proxy_call
+ .dispatch(asset_hub_polkadot_runtime::RuntimeOrigin::signed(delegatee.clone()));
Self::find_proxy_executed_event()
})
diff --git a/integration-tests/ahm/src/proxy/mod.rs b/integration-tests/ahm/src/proxy/mod.rs
index 75b2c3594a..3532b01886 100644
--- a/integration-tests/ahm/src/proxy/mod.rs
+++ b/integration-tests/ahm/src/proxy/mod.rs
@@ -43,6 +43,10 @@ pub enum Permission {
AssetManager,
Collator,
Old,
+ #[cfg(feature = "kusama-ahm")]
+ Society,
+ #[cfg(feature = "kusama-ahm")]
+ Spokesperson,
}
// Relay -> Permission
@@ -61,6 +65,10 @@ impl TryConvert for Permission {
ProxyType::NonTransfer => Permission::NonTransfer,
ProxyType::ParaRegistration => Permission::ParaRegistration,
ProxyType::Staking => Permission::Staking,
+ #[cfg(feature = "kusama-ahm")]
+ ProxyType::Society => Permission::Society,
+ #[cfg(feature = "kusama-ahm")]
+ ProxyType::Spokesperson => Permission::Spokesperson,
})
}
}
@@ -85,6 +93,39 @@ impl TryConvert for Permissio
ProxyType::Auction => Permission::Old,
ProxyType::ParaRegistration => Permission::Old,
ProxyType::Staking => Permission::Staking,
+ #[cfg(feature = "kusama-ahm")]
+ ProxyType::Society => Permission::Society,
+ #[cfg(feature = "kusama-ahm")]
+ ProxyType::Spokesperson => Permission::Spokesperson,
+ })
+ }
+}
+
+// Permission -> Maybe(AH)
+impl TryConvert for Permission {
+ fn try_convert(
+ permission: Permission,
+ ) -> Result {
+ use asset_hub_polkadot_runtime::ProxyType;
+
+ Ok(match permission {
+ Permission::Any => ProxyType::Any,
+ Permission::NonTransfer => ProxyType::NonTransfer,
+ Permission::Governance => ProxyType::Governance,
+ Permission::Staking => ProxyType::Staking,
+ Permission::CancelProxy => ProxyType::CancelProxy,
+ Permission::Auction => ProxyType::Auction,
+ Permission::NominationPools => ProxyType::NominationPools,
+ Permission::ParaRegistration => ProxyType::ParaRegistration,
+ Permission::Assets => ProxyType::Assets,
+ Permission::AssetOwner => ProxyType::AssetOwner,
+ Permission::AssetManager => ProxyType::AssetManager,
+ Permission::Collator => ProxyType::Collator,
+ Permission::Old => return Err(permission),
+ #[cfg(feature = "kusama-ahm")]
+ Permission::Society => ProxyType::Society,
+ #[cfg(feature = "kusama-ahm")]
+ Permission::Spokesperson => ProxyType::Spokesperson,
})
}
}
diff --git a/integration-tests/ahm/src/proxy/whale_watching.rs b/integration-tests/ahm/src/proxy/whale_watching.rs
index ee51dbb262..3cd36c07ab 100644
--- a/integration-tests/ahm/src/proxy/whale_watching.rs
+++ b/integration-tests/ahm/src/proxy/whale_watching.rs
@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see .
+use crate::porting_prelude::*;
+
use crate::proxy::{Permission, ProxyBasicWorks};
use hex_literal::hex;
use pallet_ah_migrator::types::AhMigrationCheck;
diff --git a/integration-tests/ahm/src/queues_priority.rs b/integration-tests/ahm/src/queues_priority.rs
index e949c885ec..e856b25760 100644
--- a/integration-tests/ahm/src/queues_priority.rs
+++ b/integration-tests/ahm/src/queues_priority.rs
@@ -15,6 +15,7 @@
// along with Polkadot. If not, see .
use crate::porting_prelude::*;
+
use asset_hub_polkadot_runtime::{AhMigrator, BuildStorage};
use frame_support::{
traits::{DefensiveTruncateFrom, OnFinalize},
diff --git a/integration-tests/ahm/src/tests.rs b/integration-tests/ahm/src/tests.rs
index 8fffd225f9..0144f38b3b 100644
--- a/integration-tests/ahm/src/tests.rs
+++ b/integration-tests/ahm/src/tests.rs
@@ -34,8 +34,6 @@
use crate::porting_prelude::*;
-#[cfg(not(feature = "paseo"))]
-use super::proxy::ProxyWhaleWatching;
use super::{
accounts_translation_works::AccountTranslationWorks,
balances_test::BalancesCrossChecker,
@@ -43,11 +41,13 @@ use super::{
mock::*,
multisig_still_work::MultisigStillWork,
multisig_test::MultisigsAccountIdStaysTheSame,
- proxy::ProxyBasicWorks,
+ proxy::{ProxyBasicWorks, ProxyWhaleWatching},
};
use asset_hub_polkadot_runtime::Runtime as AssetHub;
use cumulus_pallet_parachain_system::PendingUpwardMessages;
-use cumulus_primitives_core::{InboundDownwardMessage, Junction, Location, ParaId};
+use cumulus_primitives_core::{
+ InboundDownwardMessage, Junction, Location, ParaId, UpwardMessageSender,
+};
use frame_support::{
hypothetically, hypothetically_ok,
traits::{
@@ -73,7 +73,7 @@ use polkadot_runtime::{RcMigrator, Runtime as Polkadot};
use polkadot_runtime_common::slots as pallet_slots;
use rand::Rng;
use runtime_parachains::dmp::DownwardMessageQueues;
-use sp_core::{crypto::Ss58Codec, ByteArray};
+use sp_core::{crypto::Ss58Codec, ByteArray, Get};
use sp_io::TestExternalities;
use sp_runtime::{traits::Dispatchable, AccountId32, BuildStorage, DispatchError, TokenError};
use std::{
@@ -102,6 +102,8 @@ type RcChecks = (
BalancesCrossChecker,
RcRuntimeSpecificChecks,
// other checks go here (if available on Polkadot, Kusama and Westend)
+
+ // TODO: does not work for Kusama; calls are filtered for some reason
ProxyBasicWorks,
MultisigStillWork,
AccountTranslationWorks,
@@ -109,8 +111,8 @@ type RcChecks = (
EntireStateDecodes,
);
-// Checks that are specific to Polkadot, and not available on other chains (like Paseo)
-#[cfg(not(feature = "paseo"))]
+// Checks that are specific to Polkadot, and not available on other chains
+#[cfg(feature = "polkadot-ahm")]
pub type RcRuntimeSpecificChecks = (
MultisigsAccountIdStaysTheSame,
pallet_rc_migrator::multisig::MultisigMigrationChecker,
@@ -123,8 +125,8 @@ pub type RcRuntimeSpecificChecks = (
ChildBountiesMigratedCorrectly,
);
-// Checks that are specific to Paseo.
-#[cfg(feature = "paseo")]
+// Checks that are specific to Kusama.
+#[cfg(feature = "kusama-ahm")]
pub type RcRuntimeSpecificChecks = (
MultisigsAccountIdStaysTheSame,
pallet_rc_migrator::multisig::MultisigMigrationChecker,
@@ -156,6 +158,8 @@ type AhChecks = (
BalancesCrossChecker,
AhRuntimeSpecificChecks,
// other checks go here (if available on Polkadot, Kusama and Westend)
+
+ // TODO: does not work for Kusama; calls are filtered for some reason
ProxyBasicWorks,
MultisigStillWork,
AccountTranslationWorks,
@@ -163,7 +167,7 @@ type AhChecks = (
EntireStateDecodes,
);
-#[cfg(not(feature = "paseo"))]
+#[cfg(feature = "polkadot-ahm")]
pub type AhRuntimeSpecificChecks = (
MultisigsAccountIdStaysTheSame,
pallet_rc_migrator::multisig::MultisigMigrationChecker,
@@ -176,7 +180,7 @@ pub type AhRuntimeSpecificChecks = (
ChildBountiesMigratedCorrectly,
);
-#[cfg(feature = "paseo")]
+#[cfg(feature = "kusama-ahm")]
pub type AhRuntimeSpecificChecks = (
MultisigsAccountIdStaysTheSame,
pallet_rc_migrator::multisig::MultisigMigrationChecker,
@@ -238,6 +242,7 @@ fn run_check(f: impl FnOnce() -> R, ext: &mut TestExternalities) -> Option
}
}
+#[cfg(feature = "polkadot-ahm")] // TODO @ggwpez
#[tokio::test]
async fn num_leases_to_ending_block_works_simple() {
let mut rc = remote_ext_test_setup(Chain::Relay).await.unwrap();
@@ -747,6 +752,7 @@ async fn scheduled_migration_works() {
warm_up_end = start + 3;
// Fellowship Origin
+ #[cfg(not(feature = "kusama-ahm"))]
let origin = pallet_xcm::Origin::Xcm(Location::new(
0,
[
@@ -754,6 +760,9 @@ async fn scheduled_migration_works() {
Junction::Plurality { id: BodyId::Technical, part: BodyPart::Voice },
],
));
+ #[cfg(feature = "kusama-ahm")]
+ let origin = polkadot_runtime::governance::Origin::Fellows;
+
assert_ok!(RcMigrator::schedule_migration(
origin.into(),
DispatchTime::At(start),
@@ -1088,6 +1097,9 @@ fn test_control_flow() {
maybe_xcm_version: Some(xcm::prelude::XCM_VERSION),
})
.dispatch(AhRuntimeOrigin::root());
+
+ asset_hub_polkadot_runtime::ParachainSystem::ensure_successful_delivery();
+
assert!(result.is_ok(), "fails with error: {:?}", result.err());
});
diff --git a/integration-tests/ahm/src/xcm_route.rs b/integration-tests/ahm/src/xcm_route.rs
index b9bca39c3a..98f42a1b80 100644
--- a/integration-tests/ahm/src/xcm_route.rs
+++ b/integration-tests/ahm/src/xcm_route.rs
@@ -15,12 +15,13 @@
// along with Polkadot. If not, see .
use crate::porting_prelude::*;
+
use asset_hub_polkadot_runtime::{
xcm_config::XcmRouter as AhXcmRouter, BuildStorage, ParachainSystem as AhParachainSystem,
};
use codec::Encode;
use cumulus_pallet_parachain_system::PendingUpwardMessages;
-use cumulus_primitives_core::send_xcm;
+use cumulus_primitives_core::{send_xcm, UpwardMessageSender};
use pallet_ah_migrator::{
AhMigrationStage as AhMigrationStageStorage, MigrationStage as AhMigrationStage,
};
@@ -63,6 +64,9 @@ fn test_send_to_rc_from_ah() {
maybe_xcm_version: Some(xcm::prelude::XCM_VERSION),
})
.dispatch(AhRuntimeOrigin::root());
+
+ asset_hub_polkadot_runtime::ParachainSystem::ensure_successful_delivery();
+
assert!(result.is_ok(), "fails with error: {:?}", result.err());
// open the channel between AH and Collectives (1001)
@@ -271,6 +275,8 @@ fn test_send_to_rc_from_ah_via_extrinsic() {
// open the channel between AH and Collectives (1001)
AhParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(1001.into());
+ asset_hub_polkadot_runtime::ParachainSystem::ensure_successful_delivery();
+
let result =
AhRuntimeCall::AhMigrator(pallet_ah_migrator::Call::::set_manager {
new: Some(migration_admin.clone()),
diff --git a/pallets/ah-migrator/Cargo.toml b/pallets/ah-migrator/Cargo.toml
index fc5313f5e4..b8e01139dd 100644
--- a/pallets/ah-migrator/Cargo.toml
+++ b/pallets/ah-migrator/Cargo.toml
@@ -41,10 +41,9 @@ pallet-vesting = { workspace = true }
pallet-treasury = { workspace = true }
pallet-timestamp = { workspace = true }
pallet-xcm = { workspace = true }
+pallet-recovery = { workspace = true, optional = true }
polkadot-parachain-primitives = { workspace = true }
polkadot-runtime-common = { workspace = true }
-polkadot-runtime-constants = { workspace = true }
-collectives-polkadot-runtime-constants = { workspace = true }
runtime-parachains = { workspace = true }
scale-info = { workspace = true, features = ["derive"] }
serde = { features = ["derive"], optional = true, workspace = true }
@@ -66,6 +65,12 @@ pallet-ah-ops = { workspace = true }
[features]
default = ["std"]
+
+kusama-ahm = [
+ "pallet-rc-migrator/kusama-ahm",
+ "pallet-recovery",
+]
+
std = [
"assets-common/std",
"assets-common/std",
@@ -92,6 +97,7 @@ std = [
"pallet-preimage/std",
"pallet-proxy/std",
"pallet-rc-migrator/std",
+ "pallet-recovery?/std",
"pallet-referenda/std",
"pallet-scheduler/std",
"pallet-staking-async/std",
@@ -105,8 +111,6 @@ std = [
"parachains-common/std",
"polkadot-parachain-primitives/std",
"polkadot-runtime-common/std",
- "polkadot-runtime-constants/std",
- "polkadot-runtime-constants/std",
"runtime-parachains/std",
"scale-info/std",
"serde",
@@ -145,6 +149,7 @@ runtime-benchmarks = [
"pallet-preimage/runtime-benchmarks",
"pallet-proxy/runtime-benchmarks",
"pallet-rc-migrator/runtime-benchmarks",
+ "pallet-recovery?/runtime-benchmarks",
"pallet-referenda/runtime-benchmarks",
"pallet-scheduler/runtime-benchmarks",
"pallet-staking-async/runtime-benchmarks",
@@ -158,7 +163,6 @@ runtime-benchmarks = [
"parachains-common/runtime-benchmarks",
"polkadot-parachain-primitives/runtime-benchmarks",
"polkadot-runtime-common/runtime-benchmarks",
- "polkadot-runtime-constants/runtime-benchmarks",
"runtime-parachains/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"sp-staking/runtime-benchmarks",
@@ -187,6 +191,7 @@ try-runtime = [
"pallet-preimage/try-runtime",
"pallet-proxy/try-runtime",
"pallet-rc-migrator/try-runtime",
+ "pallet-recovery?/try-runtime",
"pallet-referenda/try-runtime",
"pallet-scheduler/try-runtime",
"pallet-staking-async/try-runtime",
diff --git a/pallets/ah-migrator/src/account.rs b/pallets/ah-migrator/src/account.rs
index 4fc29f9ba6..84c12ccd03 100644
--- a/pallets/ah-migrator/src/account.rs
+++ b/pallets/ah-migrator/src/account.rs
@@ -331,6 +331,11 @@ pub mod tests {
let mut ah_holds_diff = Vec::new();
for hold in pallet_balances::Holds::::get(&who) {
+ let hold_id_encoded = hold.id.clone().encode();
+ if hold_id_encoded[0] == 60 {
+ // filter out pallet revive holds
+ continue;
+ }
let mut hold_amount = hold.amount;
if let Some(ah_hold_amount_pre) = ah_holds_pre.get(&hold.id.encode()) {
hold_amount -= ah_hold_amount_pre;
diff --git a/pallets/ah-migrator/src/benchmarking.rs b/pallets/ah-migrator/src/benchmarking.rs
index dcb3ecb9f8..2f523e12c1 100644
--- a/pallets/ah-migrator/src/benchmarking.rs
+++ b/pallets/ah-migrator/src/benchmarking.rs
@@ -949,6 +949,7 @@ pub mod benchmarks {
#[benchmark]
fn start_migration() {
+ T::SendXcm::ensure_successful_delivery(Some(xcm::latest::Location::parent()));
#[extrinsic_call]
_(RawOrigin::Root);
diff --git a/pallets/ah-migrator/src/lib.rs b/pallets/ah-migrator/src/lib.rs
index f71029f0c8..60fa891332 100644
--- a/pallets/ah-migrator/src/lib.rs
+++ b/pallets/ah-migrator/src/lib.rs
@@ -46,6 +46,8 @@ pub mod indices;
pub mod multisig;
pub mod preimage;
pub mod proxy;
+#[cfg(feature = "kusama-ahm")]
+pub mod recovery;
pub mod referenda;
pub mod scheduler;
pub mod sovereign_account_translation;
@@ -80,6 +82,8 @@ use frame_support::{
};
use frame_system::pallet_prelude::*;
use pallet_balances::{AccountData, Reasons as LockReasons};
+#[cfg(feature = "kusama-ahm")]
+use pallet_rc_migrator::recovery::{PortableRecoveryMessage, MAX_FRIENDS};
use pallet_rc_migrator::{
bounties::RcBountiesMessageOf, child_bounties::PortableChildBountiesMessage,
claims::RcClaimsMessageOf, crowdloan::RcCrowdloanMessageOf, staking::PortableStakingMessage,
@@ -140,31 +144,32 @@ type RcAccountFor = RcAccount<
MaxEncodedLen,
)]
pub enum PalletEventName {
- Indices,
- Crowdloan,
+ AssetRates,
BagsList,
- Vesting,
+ Balances,
Bounties,
ChildBounties,
- Treasury,
- Balances,
- Multisig,
Claims,
- ProxyProxies,
- ProxyAnnouncements,
+ ConvictionVoting,
+ Crowdloan,
+ DelegatedStaking,
+ Indices,
+ Multisig,
+ NomPools,
PreimageChunk,
- PreimageRequestStatus,
PreimageLegacyStatus,
- NomPools,
- ReferendaValues,
+ PreimageRequestStatus,
+ ProxyAnnouncements,
+ ProxyProxies,
+ Recovery,
ReferendaMetadata,
ReferendaReferendums,
+ ReferendaValues,
Scheduler,
SchedulerAgenda,
- ConvictionVoting,
- AssetRates,
Staking,
- DelegatedStaking,
+ Treasury,
+ Vesting,
}
/// The migration stage on the Asset Hub.
@@ -297,6 +302,18 @@ pub mod pallet {
+ Unbalanced
+ ReservableCurrency
+ LockableCurrency;
+
+ /// Config for pallets that are only on Kusama.
+ #[cfg(feature = "kusama-ahm")]
+ type KusamaConfig: pallet_recovery::Config<
+ Currency = pallet_balances::Pallet,
+ BlockNumberProvider = Self::RecoveryBlockNumberProvider,
+ MaxFriends = ConstU32<{ MAX_FRIENDS }>,
+ > + frame_system::Config, AccountId = AccountId32>;
+
+ #[cfg(feature = "kusama-ahm")]
+ type RecoveryBlockNumberProvider: BlockNumberProvider;
+
/// All supported assets registry.
type Assets: FungiblesMutate;
/// XCM check account.
@@ -332,6 +349,7 @@ pub mod pallet {
Self::RcPalletsOrigin,
<::RuntimeOrigin as OriginTrait>::PalletsOrigin,
>;
+
/// Preimage registry.
type Preimage: QueryPreimage::Hashing> + StorePreimage;
/// Convert a Relay Chain Call to a local AH one.
@@ -941,6 +959,18 @@ pub mod pallet {
Self::do_receive_staking_messages(messages).map_err(Into::into)
}
+ #[cfg(feature = "kusama-ahm")]
+ #[pallet::call_index(26)]
+ #[pallet::weight(T::AhWeightInfo::receive_staking_messages(messages.len() as u32))] // TODO @ggwpez weight
+ pub fn receive_recovery_messages(
+ origin: OriginFor,
+ messages: Vec,
+ ) -> DispatchResult {
+ ensure_root(origin)?;
+
+ Self::do_receive_recovery_messages(messages).map_err(Into::into)
+ }
+
/// Set the migration stage.
///
/// This call is intended for emergency use only and is guarded by the
diff --git a/pallets/ah-migrator/src/recovery.rs b/pallets/ah-migrator/src/recovery.rs
new file mode 100644
index 0000000000..0add1c6ef0
--- /dev/null
+++ b/pallets/ah-migrator/src/recovery.rs
@@ -0,0 +1,60 @@
+// This file is part of Substrate.
+
+// Copyright (C) Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use crate::*;
+use pallet_rc_migrator::types::TranslateAccounts;
+
+impl Pallet {
+ pub fn do_receive_recovery_messages(
+ messages: Vec,
+ ) -> Result<(), Error> {
+ Self::deposit_event(Event::BatchReceived {
+ pallet: PalletEventName::Recovery,
+ count: messages.len() as u32,
+ });
+
+ for message in &messages {
+ Self::do_receive_recovery_message(message.clone());
+ }
+
+ Self::deposit_event(Event::BatchProcessed {
+ pallet: PalletEventName::Recovery,
+ count_good: messages.len() as u32,
+ count_bad: 0,
+ });
+
+ Ok(())
+ }
+
+ pub fn do_receive_recovery_message(message: PortableRecoveryMessage) {
+ let message = message.translate_accounts(Self::translate_account_rc_to_ah);
+
+ match message {
+ PortableRecoveryMessage::Recoverable((who, config)) => {
+ let config: pallet_recovery::RecoveryConfig<_, _, _> = config.into();
+ pallet_recovery::Recoverable::::insert(who, config);
+ },
+ PortableRecoveryMessage::ActiveRecoveries((w1, w2, config)) => {
+ let config: pallet_recovery::ActiveRecovery<_, _, _> = config.into();
+ pallet_recovery::ActiveRecoveries::::insert(w1, w2, config);
+ },
+ PortableRecoveryMessage::Proxy((w1, w2)) => {
+ pallet_recovery::Proxy::::insert(w1, w2);
+ },
+ }
+ }
+}
diff --git a/pallets/ah-migrator/src/sovereign_account_translation.rs b/pallets/ah-migrator/src/sovereign_account_translation.rs
index cd18285dcc..edfed20a56 100644
--- a/pallets/ah-migrator/src/sovereign_account_translation.rs
+++ b/pallets/ah-migrator/src/sovereign_account_translation.rs
@@ -22,6 +22,7 @@ use sp_runtime::AccountId32;
// AUTOGENERATED BELOW
// RC snap path: ../../polkadot.snap
/// List of RC para to AH sibl sovereign account translation sorted by RC account.
+#[cfg(not(feature = "kusama-ahm"))]
pub const SOV_TRANSLATIONS: &[((AccountId32, &'static str), (AccountId32, &'static str))] = &[
// para 0
(
@@ -821,6 +822,7 @@ pub const SOV_TRANSLATIONS: &[((AccountId32, &'static str), (AccountId32, &'stat
];
/// List of RC para to AH sibl derived account translation sorted by RC account.
+#[cfg(not(feature = "kusama-ahm"))]
pub const DERIVED_TRANSLATIONS: &[(
(AccountId32, &'static str),
u16,
@@ -923,3 +925,13 @@ pub const DERIVED_TRANSLATIONS: &[(
),
),
];
+
+#[cfg(feature = "kusama-ahm")]
+pub const SOV_TRANSLATIONS: &[((AccountId32, &'static str), (AccountId32, &'static str))] = &[];
+
+#[cfg(feature = "kusama-ahm")]
+pub const DERIVED_TRANSLATIONS: &[(
+ (AccountId32, &'static str),
+ u16,
+ (AccountId32, &'static str),
+)] = &[];
diff --git a/pallets/ah-migrator/src/xcm_config.rs b/pallets/ah-migrator/src/xcm_config.rs
index db885f024e..f1f333b675 100644
--- a/pallets/ah-migrator/src/xcm_config.rs
+++ b/pallets/ah-migrator/src/xcm_config.rs
@@ -17,223 +17,29 @@
//! XCM configurations for Asset Hub for the AHM migration.
use crate::PhantomData;
-use assets_common::matching::{FromSiblingParachain, IsForeignConcreteAsset, ParentLocation};
-use cumulus_primitives_core::ParaId;
-use frame_support::{
- parameter_types,
- traits::{Contains, ContainsPair, Equals, ProcessMessageError, TypedGet},
-};
+use frame_support::traits::{ContainsPair, TypedGet};
use pallet_rc_migrator::types::MigrationStatus;
-use parachains_common::xcm_config::ConcreteAssetFromSystem;
use sp_runtime::{traits::Get, AccountId32};
use xcm::latest::prelude::*;
-use xcm_builder::{AllowExplicitUnpaidExecutionFrom, IsSiblingSystemParachain};
-use xcm_executor::traits::{Properties, ShouldExecute};
-
-use polkadot_runtime_constants::system_parachain;
-
-pub mod common {
- use super::*;
- parameter_types! {
- pub const AssetHubParaId: ParaId = ParaId::new(system_parachain::ASSET_HUB_ID);
- pub const DotLocation: Location = Location::parent();
- pub const RootLocation: Location = Location::here();
- }
-
- pub struct FellowshipEntities;
- impl Contains for FellowshipEntities {
- fn contains(location: &Location) -> bool {
- matches!(
- location.unpack(),
- (
- 1,
- [
- Parachain(system_parachain::COLLECTIVES_ID),
- Plurality { id: BodyId::Technical, .. }
- ]
- ) | (
- 1,
- [
- Parachain(system_parachain::COLLECTIVES_ID),
- PalletInstance(
- collectives_polkadot_runtime_constants::FELLOWSHIP_SALARY_PALLET_INDEX
- )
- ]
- ) | (
- 1,
- [
- Parachain(system_parachain::COLLECTIVES_ID),
- PalletInstance(
- collectives_polkadot_runtime_constants::FELLOWSHIP_TREASURY_PALLET_INDEX
- )
- ]
- )
- )
- }
- }
-
- pub struct AmbassadorEntities;
- impl Contains for AmbassadorEntities {
- fn contains(location: &Location) -> bool {
- matches!(
- location.unpack(),
- (
- 1,
- [
- Parachain(system_parachain::COLLECTIVES_ID),
- PalletInstance(
- collectives_polkadot_runtime_constants::AMBASSADOR_SALARY_PALLET_INDEX
- )
- ]
- ) | (
- 1,
- [
- Parachain(system_parachain::COLLECTIVES_ID),
- PalletInstance(
- collectives_polkadot_runtime_constants::AMBASSADOR_TREASURY_PALLET_INDEX
- )
- ]
- )
- )
- }
- }
-
- /// Location type to determine the Secretary Collective related
- /// pallets for use in XCM.
- pub struct SecretaryEntities;
- impl Contains for SecretaryEntities {
- fn contains(location: &Location) -> bool {
- matches!(
- location.unpack(),
- (
- 1,
- [
- Parachain(system_parachain::COLLECTIVES_ID),
- PalletInstance(
- collectives_polkadot_runtime_constants::SECRETARY_SALARY_PALLET_INDEX
- )
- ]
- )
- )
- }
- }
-
- // Teleport filters are a special case because we might want to have finer control over which
- // one to use at fine-grained stages of the migration.
-
- /// Cases where a remote origin is accepted as trusted Teleporter for a given asset:
- ///
- /// - DOT with the parent Relay Chain and sibling system parachains; and
- /// - Sibling parachains' assets from where they originate (as `ForeignCreators`).
- pub type TrustedTeleportersBeforeAfter = (
- ConcreteAssetFromSystem,
- IsForeignConcreteAsset>,
- );
-
- /// During migration we only allow teleports of foreign assets (not DOT).
- ///
- /// - Sibling parachains' assets from where they originate (as `ForeignCreators`).
- pub type TrustedTeleportersDuring =
- IsForeignConcreteAsset>;
-}
-
-mod before {
- use super::{
- common::{
- AmbassadorEntities, AssetHubParaId, FellowshipEntities, RootLocation, SecretaryEntities,
- },
- *,
- };
-
- use polkadot_runtime_constants::TREASURY_PALLET_ID;
-
- parameter_types! {
- pub RelayTreasuryLocation: Location =
- (Parent, PalletInstance(TREASURY_PALLET_ID)).into();
- }
-
- pub struct ParentOrParentsPlurality;
- impl Contains for ParentOrParentsPlurality {
- fn contains(location: &Location) -> bool {
- matches!(location.unpack(), (1, []) | (1, [Plurality { .. }]))
- }
- }
-
- /// For use in XCM Barriers: the locations listed below get free execution:
- ///
- /// Parent, its pluralities (i.e. governance bodies), the Fellows plurality, AmbassadorEntities
- /// and sibling system parachains' root get free execution.
- pub type UnpaidExecutionBeforeDuring = AllowExplicitUnpaidExecutionFrom<(
- ParentOrParentsPlurality,
- IsSiblingSystemParachain,
- Equals,
- FellowshipEntities,
- AmbassadorEntities,
- SecretaryEntities,
- )>;
-
- /// Locations that will not be charged fees in the executor, either execution or delivery.
- ///
- /// We only waive fees for system functions, which these locations represent.
- pub type WaivedLocationsBeforeDuring = (
- Equals,
- Equals,
- IsSiblingSystemParachain,
- Equals,
- FellowshipEntities,
- AmbassadorEntities,
- SecretaryEntities,
- );
-}
-
-mod after {
- use super::{
- common::{
- AmbassadorEntities, AssetHubParaId, FellowshipEntities, RootLocation, SecretaryEntities,
- },
- *,
- };
-
- /// For use in XCM Barriers: the locations listed below get free execution:
- ///
- /// Parent, the Fellows plurality, AmbassadorEntities and sibling system parachains' root
- /// get free execution.
- pub type UnpaidExecutionAfter = AllowExplicitUnpaidExecutionFrom<(
- // outside this pallet, when the `Runtime` type is available, the below can be replaced
- // with `RelayOrOtherSystemParachains`
- Equals,
- IsSiblingSystemParachain,
- FellowshipEntities,
- AmbassadorEntities,
- SecretaryEntities,
- )>;
-
- /// Locations that will not be charged fees in the executor, either execution or delivery.
- ///
- /// We only waive fees for system functions, which these locations represent.
- pub type WaivedLocationsAfter = (
- Equals,
- // outside this pallet, when the `Runtime` type is available, the below can be replaced
- // with `RelayOrOtherSystemParachains`
- Equals,
- IsSiblingSystemParachain,
- FellowshipEntities,
- AmbassadorEntities,
- SecretaryEntities,
- );
-}
/// To be used for `IsTeleport` filter. Disallows DOT teleports during the migration.
-pub struct TrustedTeleporters(PhantomData);
-impl ContainsPair for TrustedTeleporters {
+pub struct TrustedTeleporters(
+ PhantomData<(Stage, During, BeforeAfter)>,
+);
+impl<
+ Stage: MigrationStatus,
+ During: ContainsPair,
+ BeforeAfter: ContainsPair,
+ > ContainsPair for TrustedTeleporters
+{
fn contains(asset: &Asset, origin: &Location) -> bool {
let migration_ongoing = Stage::is_ongoing();
log::trace!(target: "xcm::IsTeleport::contains", "migration ongoing: {:?}", migration_ongoing);
let result = if migration_ongoing {
- common::TrustedTeleportersDuring::contains(asset, origin)
+ During::contains(asset, origin)
} else {
// before and after migration use normal filter
- common::TrustedTeleportersBeforeAfter::contains(asset, origin)
+ BeforeAfter::contains(asset, origin)
};
log::trace!(
target: "xcm::IsTeleport::contains",
@@ -244,47 +50,6 @@ impl ContainsPair for TrustedTeleporter
}
}
-pub struct UnpaidExecutionFilter(PhantomData);
-impl ShouldExecute for UnpaidExecutionFilter {
- fn should_execute(
- origin: &Location,
- instructions: &mut [Instruction],
- max_weight: Weight,
- _properties: &mut Properties,
- ) -> Result<(), ProcessMessageError> {
- if Stage::is_finished() {
- log::trace!(target: "xcm::UnpaidExecutionFilter::should_execute", "migration finished");
- after::UnpaidExecutionAfter::should_execute(
- origin,
- instructions,
- max_weight,
- _properties,
- )
- } else {
- log::trace!(target: "xcm::UnpaidExecutionFilter::should_execute", "migration not finished");
- before::UnpaidExecutionBeforeDuring::should_execute(
- origin,
- instructions,
- max_weight,
- _properties,
- )
- }
- }
-}
-
-pub struct WaivedLocations(PhantomData);
-impl Contains for WaivedLocations {
- fn contains(location: &Location) -> bool {
- if Stage::is_finished() {
- log::trace!(target: "xcm::WaivedLocations::contains", "{location:?} (migration finished)");
- after::WaivedLocationsAfter::contains(location)
- } else {
- log::trace!(target: "xcm::WaivedLocations::contains", "{location:?} (migration not finished)");
- before::WaivedLocationsBeforeDuring::contains(location)
- }
- }
-}
-
pub struct TreasuryAccount(
PhantomData<(Stage, PreMigrationAccount, PostMigrationAccount)>,
);
diff --git a/pallets/rc-migrator/Cargo.toml b/pallets/rc-migrator/Cargo.toml
index fc01476e96..84e529d6ba 100644
--- a/pallets/rc-migrator/Cargo.toml
+++ b/pallets/rc-migrator/Cargo.toml
@@ -39,6 +39,8 @@ pallet-treasury = { workspace = true }
pallet-fast-unstake = { workspace = true }
pallet-referenda = { workspace = true }
pallet-vesting = { workspace = true }
+pallet-recovery = { workspace = true, optional = true }
+pallet-nis = { workspace = true, optional = true }
pallet-staking-async-ah-client = { workspace = true }
pallet-session = { workspace = true }
pallet-nomination-pools = { workspace = true }
@@ -47,7 +49,6 @@ pallet-xcm = { workspace = true }
polkadot-runtime-common = { workspace = true }
runtime-parachains = { workspace = true }
polkadot-parachain-primitives = { workspace = true }
-polkadot-runtime-constants = { workspace = true }
hex-literal = { workspace = true }
xcm = { workspace = true }
xcm-builder = { workspace = true }
@@ -58,6 +59,7 @@ frame-election-provider-support = { workspace = true }
[features]
default = ["std"]
+kusama-ahm = ["pallet-nis", "pallet-recovery"]
std = [
"codec/std",
"frame-benchmarking?/std",
@@ -76,9 +78,11 @@ std = [
"pallet-indices/std",
"pallet-message-queue/std",
"pallet-multisig/std",
+ "pallet-nis?/std",
"pallet-nomination-pools/std",
"pallet-preimage/std",
"pallet-proxy/std",
+ "pallet-recovery?/std",
"pallet-referenda/std",
"pallet-scheduler/std",
"pallet-session/std",
@@ -91,8 +95,6 @@ std = [
"pallet-xcm/std",
"polkadot-parachain-primitives/std",
"polkadot-runtime-common/std",
- "polkadot-runtime-constants/std",
- "polkadot-runtime-constants/std",
"runtime-parachains/std",
"scale-info/std",
"serde",
@@ -123,9 +125,11 @@ runtime-benchmarks = [
"pallet-indices/runtime-benchmarks",
"pallet-message-queue/runtime-benchmarks",
"pallet-multisig/runtime-benchmarks",
+ "pallet-nis?/runtime-benchmarks",
"pallet-nomination-pools/runtime-benchmarks",
"pallet-preimage/runtime-benchmarks",
"pallet-proxy/runtime-benchmarks",
+ "pallet-recovery?/runtime-benchmarks",
"pallet-referenda/runtime-benchmarks",
"pallet-scheduler/runtime-benchmarks",
"pallet-staking-async-ah-client/runtime-benchmarks",
@@ -137,7 +141,6 @@ runtime-benchmarks = [
"pallet-xcm/runtime-benchmarks",
"polkadot-parachain-primitives/runtime-benchmarks",
"polkadot-runtime-common/runtime-benchmarks",
- "polkadot-runtime-constants/runtime-benchmarks",
"runtime-parachains/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"sp-staking/runtime-benchmarks",
@@ -160,9 +163,11 @@ try-runtime = [
"pallet-indices/try-runtime",
"pallet-message-queue/try-runtime",
"pallet-multisig/try-runtime",
+ "pallet-nis?/try-runtime",
"pallet-nomination-pools/try-runtime",
"pallet-preimage/try-runtime",
"pallet-proxy/try-runtime",
+ "pallet-recovery?/try-runtime",
"pallet-referenda/try-runtime",
"pallet-scheduler/try-runtime",
"pallet-session/try-runtime",
diff --git a/pallets/rc-migrator/src/accounts.rs b/pallets/rc-migrator/src/accounts.rs
index 0538e2339e..7b7fd28bf7 100644
--- a/pallets/rc-migrator/src/accounts.rs
+++ b/pallets/rc-migrator/src/accounts.rs
@@ -264,13 +264,15 @@ impl PalletMigration for AccountsMigrator {
};
let mut maybe_last_key = last_key;
+ let mut total_items_iterated = 0;
loop {
// account the weight for migrating a single account on Relay Chain.
if weight_counter.try_consume(T::RcWeightInfo::withdraw_account()).is_err() ||
weight_counter.try_consume(batch.consume_weight()).is_err()
{
log::info!("RC weight limit reached at batch length {}, stopping", batch.len());
- if batch.is_empty() {
+ if batch.is_empty() && total_items_iterated == 0 {
+ defensive!("Not enough weight to migrate a single account");
return Err(Error::OutOfWeight);
} else {
break;
@@ -305,6 +307,8 @@ impl PalletMigration for AccountsMigrator {
})
.expect("Always returning Ok; qed");
+ total_items_iterated += 1;
+
match withdraw_res {
// Account does not need to be migrated
Ok(None) => {
@@ -318,11 +322,11 @@ impl PalletMigration for AccountsMigrator {
batch.push(ah_account)
},
// Not enough weight, lets try again in the next block since we made some progress.
- Err(Error::OutOfWeight) if !batch.is_empty() => {
+ Err(Error::OutOfWeight) if total_items_iterated > 1 => {
break;
},
// Not enough weight and was unable to make progress, bad.
- Err(Error::OutOfWeight) if batch.is_empty() => {
+ Err(Error::OutOfWeight) if total_items_iterated <= 1 => {
defensive!("Not enough weight to migrate a single account");
return Err(Error::OutOfWeight);
},
@@ -956,9 +960,9 @@ pub mod tests {
pub struct AccountsMigrationChecker(sp_std::marker::PhantomData);
+ #[cfg(not(feature = "kusama-ahm"))]
impl AccountsMigrationChecker {
// Translate the RC freeze id encoding to the corresponding AH freeze id encoding.
- // TODO: implement mapping for Kusama and Paseo
pub fn rc_freeze_id_encoding_to_ah(freeze_id: Vec) -> Vec {
match freeze_id.as_slice() {
// Nomination pools pallet indexes on Polkadot RC => AH
@@ -968,7 +972,6 @@ pub mod tests {
}
// Translate the RC hold id encoding to the corresponding AH hold id encoding.
- // TODO: implement mapping for Kusama and Paseo
pub fn rc_hold_id_encoding_to_ah(hold_id: Vec) -> Vec {
match hold_id.as_slice() {
// Preimage pallet indexes on Polkadot RC => AH
@@ -994,6 +997,42 @@ pub mod tests {
}
}
+ #[cfg(feature = "kusama-ahm")]
+ impl AccountsMigrationChecker {
+ // Translate the RC freeze id encoding to the corresponding AH freeze id encoding.
+ pub fn rc_freeze_id_encoding_to_ah(freeze_id: Vec) -> Vec {
+ match freeze_id.as_slice() {
+ // Nomination pools pallet indexes on Kusama RC => AH
+ [41, 0] => [80, 0].to_vec(),
+ _ => panic!("Unknown freeze id: {:?}", freeze_id),
+ }
+ }
+ // Translate the RC hold id encoding to the corresponding AH hold id encoding.
+ pub fn rc_hold_id_encoding_to_ah(hold_id: Vec) -> Vec {
+ match hold_id.as_slice() {
+ // Preimage pallet indexes on Kusama RC => AH
+ [32, 0] => [6, 0].to_vec(),
+ // Pallet staking indexes on Kusama RC => AH
+ [6, 0] => [89, 0].to_vec(),
+ // Pallet delegated-staking indexes on Kusama RC => AH
+ [47, 0] => [83, 0].to_vec(),
+ _ => panic!("Unknown hold id: {:?}", hold_id),
+ }
+ }
+
+ // Get the AH expected hold amount for a RC migrated hold.
+ // This is used to check that the hold amount is correct after migration.
+ pub fn ah_hold_amount_from_rc(hold_id: Vec, hold_amount: u128) -> u128 {
+ match hold_id.as_slice() {
+ // Preimage deposits are divided by 100 when migrated to Asset Hub.
+ [32, 0] => hold_amount.saturating_div(100),
+ // TODO: change to correct amounts for Staking if we decide to adjust deposits
+ // during migration.
+ _ => hold_amount,
+ }
+ }
+ }
+
impl crate::types::RcMigrationCheck for AccountsMigrationChecker {
// The first item is a mapping from account to a summary of their balances, including holds,
// reserves, locks, and freezes. The second item is the total issuance on the relay chain
diff --git a/pallets/rc-migrator/src/lib.rs b/pallets/rc-migrator/src/lib.rs
index 1f5a74be3a..b2715fcc6b 100644
--- a/pallets/rc-migrator/src/lib.rs
+++ b/pallets/rc-migrator/src/lib.rs
@@ -51,6 +51,8 @@ pub mod benchmarking;
pub mod bounties;
pub mod child_bounties;
pub mod conviction_voting;
+#[cfg(feature = "kusama-ahm")]
+pub mod recovery;
pub mod scheduler;
pub mod treasury;
pub mod xcm_config;
@@ -344,11 +346,21 @@ pub enum MigrationStage<
},
TreasuryMigrationDone,
+ #[cfg(feature = "kusama-ahm")]
+ RecoveryMigrationInit,
+ #[cfg(feature = "kusama-ahm")]
+ RecoveryMigrationOngoing {
+ last_key: Option,
+ },
+ #[cfg(feature = "kusama-ahm")]
+ RecoveryMigrationDone,
+
StakingMigrationInit,
StakingMigrationOngoing {
next_key: Option>,
},
StakingMigrationDone,
+
CoolOff {
/// The block number at which the post migration cool-off period will end.
///
@@ -476,6 +488,18 @@ pub mod pallet {
+ VariantCount
+ IntoPortable;
+ /// Config for pallets that are only on Kusama.
+ #[cfg(feature = "kusama-ahm")]
+ type KusamaConfig: pallet_recovery::Config<
+ Currency = pallet_balances::Pallet,
+ BlockNumberProvider = Self::RecoveryBlockNumberProvider,
+ MaxFriends = ConstU32<{ recovery::MAX_FRIENDS }>,
+ > + frame_system::Config, AccountId = AccountId32>;
+
+ /// Block number provider of the recovery pallet.
+ #[cfg(feature = "kusama-ahm")]
+ type RecoveryBlockNumberProvider: BlockNumberProvider;
+
/// Block number provider of the treasury pallet.
///
/// This is here to simplify the code of the treasury, bounties and child-bounties migration
@@ -849,8 +873,6 @@ pub mod pallet {
let start = start.evaluate(now);
ensure!(start > now, Error::::PastBlockNumber);
- ensure!(warm_up.evaluate(now) >= start, Error::::PastBlockNumber);
- ensure!(cool_off.evaluate(now) >= start, Error::::PastBlockNumber);
if !unsafe_ignore_staking_lock_check {
let until_start = start.saturating_sub(now);
@@ -1931,6 +1953,22 @@ pub mod pallet {
}
},
MigrationStage::TreasuryMigrationDone => {
+ #[cfg(feature = "kusama-ahm")]
+ Self::transition(MigrationStage::RecoveryMigrationInit);
+ #[cfg(not(feature = "kusama-ahm"))]
+ Self::transition(MigrationStage::StakingMigrationInit);
+ },
+ #[cfg(feature = "kusama-ahm")]
+ MigrationStage::RecoveryMigrationInit => {
+ Self::transition(MigrationStage::RecoveryMigrationOngoing { last_key: None });
+ },
+ #[cfg(feature = "kusama-ahm")]
+ MigrationStage::RecoveryMigrationOngoing { last_key } => {
+ // TODO
+ Self::transition(MigrationStage::RecoveryMigrationDone);
+ },
+ #[cfg(feature = "kusama-ahm")]
+ MigrationStage::RecoveryMigrationDone => {
Self::transition(MigrationStage::StakingMigrationInit);
},
MigrationStage::StakingMigrationInit => {
diff --git a/pallets/rc-migrator/src/multisig.rs b/pallets/rc-migrator/src/multisig.rs
index ae8f0e09c8..898fbec9bb 100644
--- a/pallets/rc-migrator/src/multisig.rs
+++ b/pallets/rc-migrator/src/multisig.rs
@@ -18,7 +18,6 @@
#![doc = include_str!("multisig.md")]
use frame_support::traits::Currency;
-use sp_runtime::traits::Zero;
extern crate alloc;
use crate::{types::*, *};
@@ -184,13 +183,14 @@ impl RcMigrationCheck for MultisigMigrationChecker {
fn pre_check() -> Self::RcPrePayload {
let mut multisig_ids = Vec::new();
+ let ed = <::Currency as Currency<_>>::minimum_balance();
// Collect all multisig account ids with non-zero balance from storage
for (multisig_id, _, _) in aliases::Multisigs::::iter() {
let multisig_balance =
<::Currency as frame_support::traits::Currency<
::AccountId,
>>::total_balance(&multisig_id);
- if !multisig_balance.is_zero() {
+ if multisig_balance >= ed {
multisig_ids.push(multisig_id);
}
}
diff --git a/pallets/rc-migrator/src/recovery.rs b/pallets/rc-migrator/src/recovery.rs
new file mode 100644
index 0000000000..329107f529
--- /dev/null
+++ b/pallets/rc-migrator/src/recovery.rs
@@ -0,0 +1,356 @@
+// Copyright (C) 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 crate::{
+ types::{DefensiveTruncateInto, TranslateAccounts},
+ *,
+};
+
+/// Hard-code the number of max friends in Kusama for simplicity.
+pub const MAX_FRIENDS: u32 = 9;
+
+#[derive(
+ Encode,
+ DecodeWithMemTracking,
+ Decode,
+ Clone,
+ RuntimeDebug,
+ TypeInfo,
+ MaxEncodedLen,
+ PartialEq,
+ Eq,
+)]
+pub enum RecoveryStage {
+ Recoverable(Option),
+ ActiveRecoveries(Option<(AccountId32, AccountId32)>),
+ Proxy(Option),
+ Finished,
+}
+
+#[derive(
+ Encode,
+ DecodeWithMemTracking,
+ Decode,
+ Clone,
+ RuntimeDebug,
+ TypeInfo,
+ MaxEncodedLen,
+ PartialEq,
+ Eq,
+)]
+pub enum PortableRecoveryMessage {
+ Recoverable((AccountId32, PortableRecoveryConfig)),
+ ActiveRecoveries((AccountId32, AccountId32, PortableActiveRecovery)),
+ Proxy((AccountId32, AccountId32)),
+}
+
+#[derive(
+ Encode,
+ DecodeWithMemTracking,
+ Decode,
+ Clone,
+ RuntimeDebug,
+ TypeInfo,
+ MaxEncodedLen,
+ PartialEq,
+ Eq,
+)]
+pub struct PortableRecoveryConfig {
+ pub delay_period: u32,
+ pub deposit: u128,
+ pub friends: PortableRecoveryFriends,
+ pub threshold: u16,
+}
+
+#[derive(
+ Encode,
+ DecodeWithMemTracking,
+ Decode,
+ Clone,
+ RuntimeDebug,
+ TypeInfo,
+ MaxEncodedLen,
+ PartialEq,
+ Eq,
+)]
+pub struct PortableActiveRecovery {
+ pub created: u32,
+ pub deposit: u128,
+ pub friends: PortableRecoveryFriends,
+}
+
+#[derive(
+ Encode,
+ DecodeWithMemTracking,
+ Decode,
+ Clone,
+ RuntimeDebug,
+ TypeInfo,
+ MaxEncodedLen,
+ PartialEq,
+ Eq,
+)]
+pub struct PortableRecoveryFriends {
+ pub friends: BoundedVec>,
+}
+
+// Acc Translation
+impl TranslateAccounts for PortableRecoveryMessage {
+ fn translate_accounts(self, f: impl Fn(AccountId32) -> AccountId32) -> Self {
+ match self {
+ PortableRecoveryMessage::Recoverable((who, config)) =>
+ PortableRecoveryMessage::Recoverable((f(who), config.translate_accounts(f))),
+ PortableRecoveryMessage::ActiveRecoveries((w1, w2, config)) =>
+ PortableRecoveryMessage::ActiveRecoveries((
+ f(w1),
+ f(w2),
+ config.translate_accounts(f),
+ )),
+ PortableRecoveryMessage::Proxy((w1, w2)) =>
+ PortableRecoveryMessage::Proxy((f(w1), f(w2))),
+ }
+ }
+}
+
+// RC -> Portable
+impl IntoPortable
+ for pallet_recovery::RecoveryConfig>>
+{
+ type Portable = PortableRecoveryConfig;
+
+ fn into_portable(self) -> Self::Portable {
+ PortableRecoveryConfig {
+ delay_period: self.delay_period,
+ deposit: self.deposit,
+ friends: self.friends.into_portable(),
+ threshold: self.threshold,
+ }
+ }
+}
+
+// Acc Translation
+impl TranslateAccounts for PortableRecoveryConfig {
+ fn translate_accounts(self, f: impl Fn(AccountId32) -> AccountId32) -> Self {
+ Self { friends: self.friends.translate_accounts(f), ..self }
+ }
+}
+
+// Portable -> AH
+impl
+ Into>>>
+ for PortableRecoveryConfig
+{
+ fn into(
+ self,
+ ) -> pallet_recovery::RecoveryConfig>>
+ {
+ pallet_recovery::RecoveryConfig {
+ delay_period: self.delay_period,
+ deposit: self.deposit,
+ friends: self.friends.into(),
+ threshold: self.threshold,
+ }
+ }
+}
+
+// Acc Translation
+impl TranslateAccounts for PortableActiveRecovery {
+ fn translate_accounts(self, f: impl Fn(AccountId32) -> AccountId32) -> Self {
+ Self { friends: self.friends.translate_accounts(f), ..self }
+ }
+}
+
+// RC -> Portable
+impl IntoPortable
+ for pallet_recovery::ActiveRecovery>>
+{
+ type Portable = PortableActiveRecovery;
+
+ fn into_portable(self) -> Self::Portable {
+ PortableActiveRecovery {
+ created: self.created,
+ deposit: self.deposit,
+ friends: self.friends.into_portable(),
+ }
+ }
+}
+
+// Portable -> AH
+impl
+ Into>>>
+ for PortableActiveRecovery
+{
+ fn into(
+ self,
+ ) -> pallet_recovery::ActiveRecovery>>
+ {
+ pallet_recovery::ActiveRecovery {
+ created: self.created,
+ deposit: self.deposit,
+ friends: self.friends.into(),
+ }
+ }
+}
+
+// RC -> Portable
+impl IntoPortable for BoundedVec> {
+ type Portable = PortableRecoveryFriends;
+
+ fn into_portable(self) -> Self::Portable {
+ PortableRecoveryFriends { friends: self }
+ }
+}
+
+// Acc Translation
+impl TranslateAccounts for PortableRecoveryFriends {
+ fn translate_accounts(self, f: impl Fn(AccountId32) -> AccountId32) -> Self {
+ Self {
+ friends: self.friends.into_iter().map(f).collect::>().defensive_truncate_into(),
+ } // TODO @ggwpez iter_mut?
+ }
+}
+
+// Portable -> AH
+impl Into>> for PortableRecoveryFriends {
+ fn into(self) -> BoundedVec> {
+ self.friends
+ }
+}
+
+pub struct RecoveryMigrator {
+ _phantom: sp_std::marker::PhantomData,
+}
+
+impl PalletMigration for RecoveryMigrator {
+ type Key = RecoveryStage;
+ type Error = Error;
+
+ fn migrate_many(
+ last_key: Option,
+ weight_counter: &mut WeightMeter,
+ ) -> Result