diff --git a/Cargo.lock b/Cargo.lock index 969120b3..48533ebc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8104,7 +8104,7 @@ dependencies = [ [[package]] name = "pallet-shielded-pool" -version = "0.12.0" +version = "0.13.0" dependencies = [ "ark-bn254", "ark-ff 0.5.0", @@ -8329,7 +8329,7 @@ dependencies = [ [[package]] name = "pallet-zk-verifier" -version = "0.10.0" +version = "0.11.0" dependencies = [ "ark-bn254", "ark-ec 0.5.0", diff --git a/frame/shielded-pool/CHANGELOG.md b/frame/shielded-pool/CHANGELOG.md index 1b6de227..42f9eeed 100644 --- a/frame/shielded-pool/CHANGELOG.md +++ b/frame/shielded-pool/CHANGELOG.md @@ -2,6 +2,23 @@ All notable changes to `pallet-shielded-pool` will be documented in this file. +## [0.13.0] - 2026-08-04 + +### Removed +- **`migrations` module.** Every live chain is at storage version v2 (verified + on-chain against testnet at block 283941), and a fresh chain starts there via + genesis, so `MigrateToV1`/`MigrateToV2` were no-ops guarded by their version + checks. Keeping `MigrateToV1` was a liability rather than a safety net: it + rebuilds the entire Merkle tree inside a single `on_runtime_upgrade`, which + cannot be split across blocks. At the testnet's 134201 leaves that is already + a ~4 MB `Vec` and ~270k writes in one block; at the 2^20 tree cap it would + exhaust the Wasm heap and produce a block no validator can import. Storage + version history stays documented on `STORAGE_VERSION`; see git history if an + old chain ever needs the code. The runtime's `Migrations` tuple is now empty. + `try-runtime` features are unaffected — they back `try_state`, not migrations. + `STORAGE_VERSION` itself is unchanged (still v2) — this removes the upgrade + path, not the on-chain layout. + ## [0.12.0] - 2026-07-30 ### Added diff --git a/frame/shielded-pool/Cargo.toml b/frame/shielded-pool/Cargo.toml index a09cd33a..b4e5a80b 100644 --- a/frame/shielded-pool/Cargo.toml +++ b/frame/shielded-pool/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-shielded-pool" -version = "0.12.0" +version = "0.13.0" description = "Shielded pool pallet for private transactions using ZK proofs" authors = ["Orbinum Team"] license = "GPL-3.0-or-later" diff --git a/frame/shielded-pool/src/lib.rs b/frame/shielded-pool/src/lib.rs index a346b3b6..76f6e07e 100644 --- a/frame/shielded-pool/src/lib.rs +++ b/frame/shielded-pool/src/lib.rs @@ -65,7 +65,6 @@ mod benchmarking; pub mod genesis; pub mod helpers; pub mod merkle; -pub mod migrations; pub mod operations; pub mod storage; pub mod types; @@ -103,10 +102,11 @@ pub mod pallet { <::Currency as Currency<::AccountId>>::Balance; /// Storage version history: - /// - v1: `MerkleNodes` (internal Merkle tree nodes), backfilled by - /// `migrations::v1::MigrateToV1`. - /// - v2: multi-tree forest — `SealedTreeRoots` / `SealedRootIndex` - /// (start empty; version-only bump in `migrations::v2::MigrateToV2`). + /// - v1: `MerkleNodes` (internal Merkle tree nodes), backfilled from `MerkleLeaves`. + /// - v2: multi-tree forest — `SealedTreeRoots` / `SealedRootIndex` (start empty). + /// + /// The v1/v2 migration code was removed once every live chain reached v2; a new + /// chain starts here via genesis. See git history if an old chain ever needs it. pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(2); #[pallet::pallet] diff --git a/frame/shielded-pool/src/migrations.rs b/frame/shielded-pool/src/migrations.rs deleted file mode 100644 index 2fad8665..00000000 --- a/frame/shielded-pool/src/migrations.rs +++ /dev/null @@ -1,193 +0,0 @@ -//! Storage migrations for pallet-shielded-pool. - -use crate::{ - merkle::{get_zero_hash_cached, hash_pair_poseidon}, - pallet::{Config, Pallet}, - storage::MerkleRepository, -}; -use frame_support::{ - pallet_prelude::*, - traits::{GetStorageVersion, OnRuntimeUpgrade}, - weights::Weight, -}; -use sp_std::vec::Vec; - -pub mod v1 { - use super::*; - - /// Backfill `MerkleNodes` from `MerkleLeaves` (storage v0 -> v1). - /// - /// Rebuilds every internal node (levels 1..=19) that `insert_leaf` would - /// have written had `MerkleNodes` existed from genesis. One-shot cost: - /// O(n) Poseidon hashes plus O(n) storage writes for n existing leaves — - /// sized for the runtime-upgrade block, which tolerates overweight. - pub struct MigrateToV1(core::marker::PhantomData); - - impl OnRuntimeUpgrade for MigrateToV1 { - fn on_runtime_upgrade() -> Weight { - let onchain = Pallet::::on_chain_storage_version(); - if onchain >= 1 { - return T::DbWeight::get().reads(1); - } - - let size = MerkleRepository::get_tree_size::(); - let mut reads: u64 = 2; // storage version + tree size - let mut writes: u64 = 1; // storage version bump - - let mut level_nodes: Vec<[u8; 32]> = (0..size) - .filter_map(|i| MerkleRepository::get_leaf::(i).map(|c| c.0)) - .collect(); - reads = reads.saturating_add(size as u64); - - // Pair-hash upward, mirroring the frontier walk: a missing right - // sibling is the zero hash of the child level. Every level up to 19 - // gets written, matching what per-insert writes would have produced. - for level in 0..(crate::types::DEFAULT_TREE_DEPTH - 1) { - let mut next: Vec<[u8; 32]> = Vec::with_capacity(level_nodes.len().div_ceil(2)); - for pair in level_nodes.chunks(2) { - let left = pair[0]; - let right = pair - .get(1) - .copied() - .unwrap_or_else(|| get_zero_hash_cached(level)); - next.push(hash_pair_poseidon(&left, &right)); - } - for (i, node) in next.iter().enumerate() { - MerkleRepository::set_node::(0, (level + 1) as u8, i as u32, *node); - } - writes = writes.saturating_add(next.len() as u64); - level_nodes = next; - if level_nodes.is_empty() { - break; - } - } - - StorageVersion::new(1).put::>(); - T::DbWeight::get().reads_writes(reads, writes) - } - - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, sp_runtime::TryRuntimeError> { - Ok(MerkleRepository::get_tree_size::().encode()) - } - - #[cfg(feature = "try-runtime")] - fn post_upgrade(state: Vec) -> Result<(), sp_runtime::TryRuntimeError> { - let size = u32::decode(&mut &state[..]) - .map_err(|_| sp_runtime::TryRuntimeError::Other("pre_upgrade state must decode"))?; - frame_support::ensure!( - Pallet::::on_chain_storage_version() >= 1, - sp_runtime::TryRuntimeError::Other("storage version not bumped") - ); - if size > 0 { - let top = (crate::types::DEFAULT_TREE_DEPTH - 1) as u8; // 19 - let left = MerkleRepository::get_node::(0, top, 0).ok_or( - sp_runtime::TryRuntimeError::Other("top-left node missing after backfill"), - )?; - let right = MerkleRepository::get_node::(0, top, 1) - .unwrap_or_else(|| get_zero_hash_cached(top as usize)); - frame_support::ensure!( - hash_pair_poseidon(&left, &right) == MerkleRepository::get_poseidon_root::(), - sp_runtime::TryRuntimeError::Other( - "backfilled nodes do not derive PoseidonRoot" - ) - ); - } - Ok(()) - } - } -} - -pub mod v2 { - use super::*; - - /// Storage v1 -> v2: multi-tree forest. `SealedTreeRoots` and - /// `SealedRootIndex` start empty (tree 0 has never filled), so this is a - /// version-only bump — the rollover logic activates with the runtime code. - pub struct MigrateToV2(core::marker::PhantomData); - - impl OnRuntimeUpgrade for MigrateToV2 { - fn on_runtime_upgrade() -> Weight { - if Pallet::::on_chain_storage_version() >= 2 { - return T::DbWeight::get().reads(1); - } - StorageVersion::new(2).put::>(); - T::DbWeight::get().reads_writes(1, 1) - } - - #[cfg(feature = "try-runtime")] - fn post_upgrade(_state: Vec) -> Result<(), sp_runtime::TryRuntimeError> { - frame_support::ensure!( - Pallet::::on_chain_storage_version() >= 2, - sp_runtime::TryRuntimeError::Other("storage version not bumped to 2") - ); - Ok(()) - } - } -} - -#[cfg(test)] -mod tests { - use super::v1::MigrateToV1; - use crate::{ - merkle::MerkleTreeService, - mock::{Test, new_test_ext}, - pallet::{MerkleNodes, Pallet}, - storage::MerkleRepository, - types::Commitment, - }; - use frame_support::traits::{GetStorageVersion, OnRuntimeUpgrade, StorageVersion}; - - fn insert_leaves(n: u8) { - for i in 0..n { - MerkleTreeService::insert_leaf::(Commitment::new([i + 1; 32])).unwrap(); - } - } - - #[test] - fn backfill_rebuilds_nodes_and_proofs_verify() { - new_test_ext().execute_with(|| { - // A v0-era chain only ever had a single tree; stay below the mock - // per-tree cap so the backfill precondition holds. - insert_leaves(7); - let root = MerkleRepository::get_poseidon_root::(); - - // Simulate a v0 chain: leaves exist but internal nodes were never stored. - let _ = MerkleNodes::::clear(u32::MAX, None); - StorageVersion::new(0).put::>(); - - MigrateToV1::::on_runtime_upgrade(); - - assert_eq!(Pallet::::on_chain_storage_version(), 1); - for i in 0..7u32 { - let leaf = MerkleRepository::get_leaf::(i).unwrap(); - let path = MerkleTreeService::get_merkle_path::(i).unwrap(); - assert!( - MerkleTreeService::verify_merkle_proof(&root, &leaf.0, &path), - "leaf {i} proof must verify after backfill" - ); - } - }); - } - - #[test] - fn migration_is_idempotent_once_versioned() { - new_test_ext().execute_with(|| { - insert_leaves(4); - StorageVersion::new(1).put::>(); - let node_before = MerkleRepository::get_node::(0, 1, 0); - MigrateToV1::::on_runtime_upgrade(); - assert_eq!(MerkleRepository::get_node::(0, 1, 0), node_before); - }); - } - - #[test] - fn empty_tree_migration_only_bumps_version() { - new_test_ext().execute_with(|| { - StorageVersion::new(0).put::>(); - MigrateToV1::::on_runtime_upgrade(); - assert_eq!(Pallet::::on_chain_storage_version(), 1); - assert_eq!(MerkleNodes::::iter().count(), 0); - }); - } -} diff --git a/frame/zk-verifier/CHANGELOG.md b/frame/zk-verifier/CHANGELOG.md index 81dcb6f8..af059a6e 100644 --- a/frame/zk-verifier/CHANGELOG.md +++ b/frame/zk-verifier/CHANGELOG.md @@ -4,7 +4,16 @@ All notable changes to this pallet are documented here. --- -## [Unreleased] +## [0.11.0] - 2026-08-04 + +### Removed +- **`migrations` module.** Every live chain is at storage version v1 (verified + on-chain against testnet at block 283941) and a fresh chain starts there via + genesis, so `MigrateToV1` was a no-op guarded by its version check. Removed + alongside the shielded-pool migrations. Storage version history stays + documented on `STORAGE_VERSION`; see git history if an old chain ever needs + the code. `STORAGE_VERSION` itself is unchanged (still v1) — this removes the + upgrade path, not the on-chain layout. --- diff --git a/frame/zk-verifier/Cargo.toml b/frame/zk-verifier/Cargo.toml index 449f0637..fa24eb90 100644 --- a/frame/zk-verifier/Cargo.toml +++ b/frame/zk-verifier/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-zk-verifier" -version = "0.10.0" +version = "0.11.0" description = "Zero-Knowledge proof verification pallet for Orbinum" authors = ["Orbinum Team"] license = "GPL-3.0-or-later" diff --git a/frame/zk-verifier/src/lib.rs b/frame/zk-verifier/src/lib.rs index ed5dc8a1..6ed1c3d2 100644 --- a/frame/zk-verifier/src/lib.rs +++ b/frame/zk-verifier/src/lib.rs @@ -22,7 +22,6 @@ extern crate alloc; pub use pallet::*; mod encoding; -pub mod migrations; mod port; mod runtime_api; mod types; @@ -52,8 +51,10 @@ pub mod pallet { use frame_system::pallet_prelude::*; /// Storage version history: - /// - v1: drop the retired `private_link` circuit (id 5), cleared by - /// `migrations::v1::MigrateToV1`. + /// - v1: drop the retired `private_link` circuit (id 5). + /// + /// The v1 migration code was removed once every live chain reached v1; a new chain + /// starts here via genesis. See git history if an old chain ever needs it. pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); #[pallet::pallet] diff --git a/frame/zk-verifier/src/migrations.rs b/frame/zk-verifier/src/migrations.rs deleted file mode 100644 index 7018623b..00000000 --- a/frame/zk-verifier/src/migrations.rs +++ /dev/null @@ -1,327 +0,0 @@ -//! Storage migrations for pallet-zk-verifier. - -use crate::pallet::{ - ActiveCircuitVersion, Config, Pallet, RetiredVersions, VerificationKeys, VerificationStats, - VkHashes, -}; -use crate::types::CircuitId; -use crate::weights::WeightInfo as _; -use frame_support::{ - pallet_prelude::*, - traits::{GetStorageVersion, OnRuntimeUpgrade}, - weights::Weight, -}; -#[cfg(feature = "try-runtime")] -use sp_std::vec::Vec; - -pub mod v1 { - use super::*; - - /// Circuit id of the retired `private_link` proof. - /// - /// Hardcoded rather than derived from `expected_public_inputs`: this runs - /// once, only on chains still at storage v0, where 5 can only ever mean - /// `private_link`. A chain that reassigns the id is already past v1 and never - /// executes this. - const RETIRED_PRIVATE_LINK: CircuitId = CircuitId(5); - - /// Storage v0 -> v1: drop the `private_link` circuit (id 5). - /// - /// The circuit was removed from the runtime along with - /// `pallet-account-mapping`, its only consumer, but chains that ran the - /// previous runtime still carry its verification key on-chain. Nothing can - /// route to it — `ZkVerifierPort` no longer exposes - /// `verify_private_link_proof` — yet it stays visible: the - /// `get_all_circuit_versions` runtime API iterates storage keys with no - /// allowlist, so explorers keep listing a circuit the runtime cannot serve. - /// - /// Runs unconditionally rather than leaving the cleanup to `purge_circuit`: - /// the migration lands with the runtime that retires the circuit, so chains - /// are clean the moment they upgrade instead of waiting on a governance call. - /// - /// One-shot, and in practice the circuit only ever had one version registered. - pub struct MigrateToV1(core::marker::PhantomData); - - impl OnRuntimeUpgrade for MigrateToV1 { - fn on_runtime_upgrade() -> Weight { - if Pallet::::on_chain_storage_version() >= 1 { - return T::DbWeight::get().reads(1); - } - - // Cleared by prefix, not by iterating one map's versions: an earlier - // `remove_verification_key` dropped keys without their hash or stats, so - // the satellite maps can hold entries no `VerificationKeys` row lists. - // - // Counted separately because `clear_prefix`'s own counters only report - // keys committed to the backend, and writes from the same block are - // still in the overlay. - // - // The widest map, not the sum: this feeds `purge_circuit`'s benchmark, - // whose linear component is already the per-version cost of clearing all - // four maps. - let versions = [ - VerificationKeys::::iter_key_prefix(RETIRED_PRIVATE_LINK).count(), - VkHashes::::iter_key_prefix(RETIRED_PRIVATE_LINK).count(), - VerificationStats::::iter_key_prefix(RETIRED_PRIVATE_LINK).count(), - RetiredVersions::::iter_key_prefix(RETIRED_PRIVATE_LINK).count(), - ] - .into_iter() - .max() - .unwrap_or(0) as u32; - - let _ = VerificationKeys::::clear_prefix(RETIRED_PRIVATE_LINK, u32::MAX, None); - let _ = VkHashes::::clear_prefix(RETIRED_PRIVATE_LINK, u32::MAX, None); - let _ = VerificationStats::::clear_prefix(RETIRED_PRIVATE_LINK, u32::MAX, None); - let _ = RetiredVersions::::clear_prefix(RETIRED_PRIVATE_LINK, u32::MAX, None); - ActiveCircuitVersion::::remove(RETIRED_PRIVATE_LINK); - - StorageVersion::new(1).put::>(); - - // Reuse the extrinsic's benchmark: it measures exactly this work, so the - // migration cannot drift from the cost the runner actually recorded. - T::WeightInfo::purge_circuit(versions) - .saturating_add(T::DbWeight::get().reads_writes(1, 2)) - } - - /// Records how many circuits are registered, so `post_upgrade` can assert - /// the migration removed at most the retired one. - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, sp_runtime::TryRuntimeError> { - let others = VerificationKeys::::iter_keys() - .filter(|(cid, _)| *cid != RETIRED_PRIVATE_LINK) - .count() as u32; - Ok(others.encode()) - } - - #[cfg(feature = "try-runtime")] - fn post_upgrade(state: Vec) -> Result<(), sp_runtime::TryRuntimeError> { - let others_before = u32::decode(&mut state.as_slice()) - .map_err(|_| sp_runtime::TryRuntimeError::Other("pre_upgrade state decode"))?; - - frame_support::ensure!( - Pallet::::on_chain_storage_version() >= 1, - sp_runtime::TryRuntimeError::Other("storage version not bumped to 1") - ); - frame_support::ensure!( - VerificationKeys::::iter_key_prefix(RETIRED_PRIVATE_LINK) - .next() - .is_none(), - sp_runtime::TryRuntimeError::Other("circuit 5 keys still present") - ); - // The satellite maps are the ones an earlier `remove_verification_key` - // could strand, so check them explicitly rather than trusting that - // clearing `VerificationKeys` implied clearing these. - frame_support::ensure!( - VkHashes::::iter_key_prefix(RETIRED_PRIVATE_LINK) - .next() - .is_none(), - sp_runtime::TryRuntimeError::Other("circuit 5 vk hashes still present") - ); - frame_support::ensure!( - VerificationStats::::iter_key_prefix(RETIRED_PRIVATE_LINK) - .next() - .is_none(), - sp_runtime::TryRuntimeError::Other("circuit 5 stats still present") - ); - frame_support::ensure!( - RetiredVersions::::iter_key_prefix(RETIRED_PRIVATE_LINK) - .next() - .is_none(), - sp_runtime::TryRuntimeError::Other("circuit 5 retired versions still present") - ); - frame_support::ensure!( - ActiveCircuitVersion::::get(RETIRED_PRIVATE_LINK).is_none(), - sp_runtime::TryRuntimeError::Other("circuit 5 still has an active version") - ); - - // Every other circuit must be untouched: this migration only ever - // clears the retired id. - let others_after = VerificationKeys::::iter_keys() - .filter(|(cid, _)| *cid != RETIRED_PRIVATE_LINK) - .count() as u32; - frame_support::ensure!( - others_after == others_before, - sp_runtime::TryRuntimeError::Other("migration touched a live circuit") - ); - Ok(()) - } - } -} - -#[cfg(test)] -mod tests { - use super::v1::MigrateToV1; - use crate::mock::Test; - use crate::pallet::{ - ActiveCircuitVersion, Pallet, RetiredVersions, VerificationKeys, VerificationStats, - VkHashes, - }; - use crate::types::{CircuitId, ProofSystem, VerificationKeyInfo}; - use frame_support::{ - BoundedVec, - traits::{GetStorageVersion, OnRuntimeUpgrade, StorageVersion}, - }; - use sp_io::TestExternalities; - use sp_runtime::BuildStorage; - - const PRIVATE_LINK: CircuitId = CircuitId(5); - - fn new_test_ext() -> TestExternalities { - let storage = frame_system::GenesisConfig::::default() - .build_storage() - .expect("mock storage ok"); - TestExternalities::new(storage) - } - - fn seed(circuit_id: CircuitId, version: u32) { - let key_data: BoundedVec> = - vec![0xABu8; 300].try_into().unwrap(); - VerificationKeys::::insert( - circuit_id, - version, - VerificationKeyInfo { - key_data, - system: ProofSystem::Groth16, - registered_at: 0u64, - }, - ); - VkHashes::::insert(circuit_id, version, [0x11u8; 32]); - ActiveCircuitVersion::::insert(circuit_id, version); - } - - #[test] - fn clears_every_map_for_the_retired_circuit() { - new_test_ext().execute_with(|| { - StorageVersion::new(0).put::>(); - seed(PRIVATE_LINK, 1); - RetiredVersions::::insert(PRIVATE_LINK, 1, ()); - - MigrateToV1::::on_runtime_upgrade(); - - assert!(VerificationKeys::::get(PRIVATE_LINK, 1).is_none()); - assert!(VkHashes::::get(PRIVATE_LINK, 1).is_none()); - assert!(!VerificationStats::::contains_key(PRIVATE_LINK, 1)); - assert!(!RetiredVersions::::contains_key(PRIVATE_LINK, 1)); - assert!(ActiveCircuitVersion::::get(PRIVATE_LINK).is_none()); - assert_eq!(Pallet::::on_chain_storage_version(), 1); - }); - } - - /// The migration must not disturb circuits the runtime still implements. - #[test] - fn leaves_live_circuits_untouched() { - new_test_ext().execute_with(|| { - StorageVersion::new(0).put::>(); - seed(CircuitId::TRANSFER, 1); - seed(CircuitId::UNSHIELD, 1); - seed(CircuitId::VALUE_PROOF, 1); - seed(PRIVATE_LINK, 1); - - MigrateToV1::::on_runtime_upgrade(); - - for cid in [ - CircuitId::TRANSFER, - CircuitId::UNSHIELD, - CircuitId::VALUE_PROOF, - ] { - assert!(VerificationKeys::::get(cid, 1).is_some()); - assert_eq!(ActiveCircuitVersion::::get(cid), Some(1)); - } - assert!(VerificationKeys::::get(PRIVATE_LINK, 1).is_none()); - }); - } - - /// The case the prefix-clear exists for: an earlier `remove_verification_key` - /// dropped the key but left its hash and stats, so there is no - /// `VerificationKeys` row to enumerate them from. - #[test] - fn clears_satellite_maps_with_no_verification_key() { - new_test_ext().execute_with(|| { - StorageVersion::new(0).put::>(); - VkHashes::::insert(PRIVATE_LINK, 1, [0x11u8; 32]); - RetiredVersions::::insert(PRIVATE_LINK, 1, ()); - // Deliberately no VerificationKeys entry. - - MigrateToV1::::on_runtime_upgrade(); - - assert!(VkHashes::::get(PRIVATE_LINK, 1).is_none()); - assert!(!RetiredVersions::::contains_key(PRIVATE_LINK, 1)); - }); - } - - /// Running twice must be a no-op, not a double-charge. - #[test] - fn is_idempotent() { - new_test_ext().execute_with(|| { - StorageVersion::new(0).put::>(); - seed(PRIVATE_LINK, 1); - - let first = MigrateToV1::::on_runtime_upgrade(); - let second = MigrateToV1::::on_runtime_upgrade(); - - // Second run hits the version guard and returns before doing any work, - // so it must be strictly cheaper than the run that cleared storage. - assert!(second.ref_time() < first.ref_time() || second.all_lte(first)); - assert!(VerificationKeys::::get(PRIVATE_LINK, 1).is_none()); - }); - } - - /// A chain that never registered the circuit still lands on version 1. - #[test] - fn bumps_version_when_nothing_to_clear() { - new_test_ext().execute_with(|| { - StorageVersion::new(0).put::>(); - - MigrateToV1::::on_runtime_upgrade(); - - assert_eq!(Pallet::::on_chain_storage_version(), 1); - }); - } - - /// The `try-runtime` hooks are what an upgrade dry-run relies on, but nothing - /// else in the suite executes them: the tests above call `on_runtime_upgrade` - /// directly, and the CLI cannot get this far on a real snapshot because an - /// earlier migration in the tuple needs a host function it does not register. - /// Without this the checks are unrun code. - #[cfg(feature = "try-runtime")] - #[test] - fn try_runtime_hooks_pass_over_a_realistic_state() { - new_test_ext().execute_with(|| { - StorageVersion::new(0).put::>(); - // The retired circuit alongside live ones, plus satellite entries the - // post-upgrade checks look at individually. - seed(PRIVATE_LINK, 1); - seed(PRIVATE_LINK, 2); - RetiredVersions::::insert(PRIVATE_LINK, 2, ()); - VerificationStats::::insert( - PRIVATE_LINK, - 1, - crate::types::VerificationStatistics::default(), - ); - seed(CircuitId::TRANSFER, 1); - seed(CircuitId::UNSHIELD, 1); - - let state = MigrateToV1::::pre_upgrade().expect("pre_upgrade"); - MigrateToV1::::on_runtime_upgrade(); - MigrateToV1::::post_upgrade(state).expect("post_upgrade"); - }); - } - - /// `post_upgrade` must fail, not pass silently, when the migration left the - /// circuit behind — otherwise a dry-run would green-light a broken upgrade. - #[cfg(feature = "try-runtime")] - #[test] - fn try_runtime_post_upgrade_catches_leftovers() { - new_test_ext().execute_with(|| { - StorageVersion::new(0).put::>(); - seed(PRIVATE_LINK, 1); - - let state = MigrateToV1::::pre_upgrade().expect("pre_upgrade"); - MigrateToV1::::on_runtime_upgrade(); - // Simulate a migration that missed one of the satellite maps. - VkHashes::::insert(PRIVATE_LINK, 1, [0x11u8; 32]); - - assert!(MigrateToV1::::post_upgrade(state).is_err()); - }); - } -} diff --git a/template/runtime/src/lib.rs b/template/runtime/src/lib.rs index 75f96e49..b59dfc57 100644 --- a/template/runtime/src/lib.rs +++ b/template/runtime/src/lib.rs @@ -150,11 +150,7 @@ pub type CheckedExtrinsic = pub type SignedPayload = generic::SignedPayload; /// Storage migrations run on runtime upgrade, oldest first. -pub type Migrations = ( - pallet_shielded_pool::migrations::v1::MigrateToV1, - pallet_shielded_pool::migrations::v2::MigrateToV2, - pallet_zk_verifier::migrations::v1::MigrateToV1, -); +pub type Migrations = (); /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive<