From 7e93f313a7f7b5e92af7a538671df14f51a4bb4e Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Mon, 24 Nov 2025 16:41:48 +0100 Subject: [PATCH 1/4] Migration to fix StakingHotKeys added --- pallets/subtensor/src/macros/hooks.rs | 4 +- .../migrate_fix_staking_hot_keys.rs | 55 +++++++++++++++++++ pallets/subtensor/src/migrations/mod.rs | 1 + pallets/subtensor/src/tests/migration.rs | 37 +++++++++++++ 4 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 pallets/subtensor/src/migrations/migrate_fix_staking_hot_keys.rs diff --git a/pallets/subtensor/src/macros/hooks.rs b/pallets/subtensor/src/macros/hooks.rs index 1b7d5fd77e..8f6a823a29 100644 --- a/pallets/subtensor/src/macros/hooks.rs +++ b/pallets/subtensor/src/macros/hooks.rs @@ -162,7 +162,9 @@ mod hooks { // Migrate pending emissions .saturating_add(migrations::migrate_pending_emissions::migrate_pending_emissions::()) // Reset unactive subnets - .saturating_add(migrations::migrate_reset_unactive_sn::migrate_reset_unactive_sn::()); + .saturating_add(migrations::migrate_reset_unactive_sn::migrate_reset_unactive_sn::()) + // Fix staking hot keys + .saturating_add(migrations::migrate_fix_staking_hot_keys::migrate_fix_staking_hot_keys::()); weight } diff --git a/pallets/subtensor/src/migrations/migrate_fix_staking_hot_keys.rs b/pallets/subtensor/src/migrations/migrate_fix_staking_hot_keys.rs new file mode 100644 index 0000000000..72fae1fdd7 --- /dev/null +++ b/pallets/subtensor/src/migrations/migrate_fix_staking_hot_keys.rs @@ -0,0 +1,55 @@ +use super::*; +use frame_support::{traits::Get, weights::Weight}; +use log; +use scale_info::prelude::string::String; +use sp_std::collections::btree_map::BTreeMap; + +pub fn migrate_fix_staking_hot_keys() -> Weight { + let migration_name = b"migrate_fix_staking_hot_keys".to_vec(); + let mut weight = T::DbWeight::get().reads(1); + + // Skip if already executed + if HasMigrationRun::::get(&migration_name) { + log::info!( + target: "runtime", + "Migration '{}' already run - skipping.", + String::from_utf8_lossy(&migration_name) + ); + return weight; + } + + let mut cache: BTreeMap> = BTreeMap::new(); + let mut storage_reads: u64 = 0; + let mut storage_writes: u64 = 0; + + for ((hotkey, coldkey, _netuid), alpha) in Alpha::::iter() { + if alpha == 0 { + continue; + } + + let staking_hotkeys = cache.entry(coldkey.clone()) + .or_insert_with(|| { + storage_reads = storage_reads.saturating_add(1); + StakingHotkeys::::get(&coldkey) + }); + + if !staking_hotkeys.contains(&hotkey) { + staking_hotkeys.push(hotkey.clone()); + storage_writes = storage_writes.saturating_add(1); + StakingHotkeys::::insert(&coldkey, staking_hotkeys.clone()); + } + } + weight = weight.saturating_add(T::DbWeight::get().reads_writes(storage_reads, storage_writes)); + + // Mark migration done + HasMigrationRun::::insert(&migration_name, true); + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + + log::info!( + target: "runtime", + "Migration '{}' completed.", + String::from_utf8_lossy(&migration_name) + ); + + weight +} \ No newline at end of file diff --git a/pallets/subtensor/src/migrations/mod.rs b/pallets/subtensor/src/migrations/mod.rs index 41c1333a89..a4473a9dc8 100644 --- a/pallets/subtensor/src/migrations/mod.rs +++ b/pallets/subtensor/src/migrations/mod.rs @@ -58,6 +58,7 @@ pub mod migrate_to_v1_separate_emission; pub mod migrate_to_v2_fixed_total_stake; pub mod migrate_transfer_ownership_to_foundation; pub mod migrate_upgrade_revealed_commitments; +pub mod migrate_fix_staking_hot_keys; pub(crate) fn migrate_storage( migration_name: &'static str, diff --git a/pallets/subtensor/src/tests/migration.rs b/pallets/subtensor/src/tests/migration.rs index b694459eaa..9f5b005ed8 100644 --- a/pallets/subtensor/src/tests/migration.rs +++ b/pallets/subtensor/src/tests/migration.rs @@ -1138,6 +1138,43 @@ fn test_migrate_rate_limit_keys() { }); } +#[test] +fn test_migrate_fix_staking_hot_keys() { + new_test_ext(1).execute_with(|| { + const MIGRATION_NAME: &[u8] = b"migrate_fix_staking_hot_keys"; + + assert!( + !HasMigrationRun::::get(MIGRATION_NAME.to_vec()), + "Migration should not have run yet" + ); + + // Add some data + Alpha::::insert( + (U256::from(1), + U256::from(2), + NetUid::ROOT), + U64F64::from(1_u64) + ); + // Run migration + let weight = migrations::migrate_fix_staking_hot_keys::migrate_fix_staking_hot_keys::(); + + assert!( + HasMigrationRun::::get(MIGRATION_NAME.to_vec()), + "Migration should be marked as completed" + ); + + // Check migration has been marked as run + assert!(HasMigrationRun::::get(MIGRATION_NAME.to_vec())); + + // Verify results + assert_eq!( + StakingHotkeys::::get(U256::from(2)), + vec![U256::from(1)] + ); + }); +} + + #[test] fn test_migrate_fix_root_subnet_tao() { new_test_ext(1).execute_with(|| { From 3b8fcef673eda06738b3a18ae30a922b6cf9548d Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Tue, 16 Dec 2025 17:26:03 +0100 Subject: [PATCH 2/4] Fix the build after the merge --- pallets/subtensor/src/macros/hooks.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/subtensor/src/macros/hooks.rs b/pallets/subtensor/src/macros/hooks.rs index 8af5a9d0cc..ed57d52c8b 100644 --- a/pallets/subtensor/src/macros/hooks.rs +++ b/pallets/subtensor/src/macros/hooks.rs @@ -162,7 +162,7 @@ mod hooks { // Remove old identity map entries(Identities, SubnetIdentities, SubnetIdentitiesV2) .saturating_add(migrations::migrate_remove_old_identity_maps::migrate_remove_old_identity_maps::()) // Remove unknown neuron axon, certificate prom - .saturating_add(migrations::migrate_remove_unknown_neuron_axon_cert_prom::migrate_remove_unknown_neuron_axon_cert_prom::()); + .saturating_add(migrations::migrate_remove_unknown_neuron_axon_cert_prom::migrate_remove_unknown_neuron_axon_cert_prom::()) // Fix staking hot keys .saturating_add(migrations::migrate_fix_staking_hot_keys::migrate_fix_staking_hot_keys::()); weight From 0aa2055d7856bcc38127211f11c42018500b0531 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Tue, 16 Dec 2025 17:38:55 +0100 Subject: [PATCH 3/4] cargo fmt --- .../src/migrations/migrate_fix_staking_hot_keys.rs | 11 +++++------ pallets/subtensor/src/migrations/mod.rs | 2 +- pallets/subtensor/src/tests/migration.rs | 10 ++++------ 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/pallets/subtensor/src/migrations/migrate_fix_staking_hot_keys.rs b/pallets/subtensor/src/migrations/migrate_fix_staking_hot_keys.rs index 72fae1fdd7..7728ff0a6a 100644 --- a/pallets/subtensor/src/migrations/migrate_fix_staking_hot_keys.rs +++ b/pallets/subtensor/src/migrations/migrate_fix_staking_hot_keys.rs @@ -27,11 +27,10 @@ pub fn migrate_fix_staking_hot_keys() -> Weight { continue; } - let staking_hotkeys = cache.entry(coldkey.clone()) - .or_insert_with(|| { - storage_reads = storage_reads.saturating_add(1); - StakingHotkeys::::get(&coldkey) - }); + let staking_hotkeys = cache.entry(coldkey.clone()).or_insert_with(|| { + storage_reads = storage_reads.saturating_add(1); + StakingHotkeys::::get(&coldkey) + }); if !staking_hotkeys.contains(&hotkey) { staking_hotkeys.push(hotkey.clone()); @@ -52,4 +51,4 @@ pub fn migrate_fix_staking_hot_keys() -> Weight { ); weight -} \ No newline at end of file +} diff --git a/pallets/subtensor/src/migrations/mod.rs b/pallets/subtensor/src/migrations/mod.rs index 7eb8a52835..a03da9289e 100644 --- a/pallets/subtensor/src/migrations/mod.rs +++ b/pallets/subtensor/src/migrations/mod.rs @@ -19,6 +19,7 @@ pub mod migrate_fix_childkeys; pub mod migrate_fix_is_network_member; pub mod migrate_fix_root_subnet_tao; pub mod migrate_fix_root_tao_and_alpha_in; +pub mod migrate_fix_staking_hot_keys; pub mod migrate_init_tao_flow; pub mod migrate_init_total_issuance; pub mod migrate_kappa_map_to_default; @@ -58,7 +59,6 @@ pub mod migrate_to_v1_separate_emission; pub mod migrate_to_v2_fixed_total_stake; pub mod migrate_transfer_ownership_to_foundation; pub mod migrate_upgrade_revealed_commitments; -pub mod migrate_fix_staking_hot_keys; pub(crate) fn migrate_storage( migration_name: &'static str, diff --git a/pallets/subtensor/src/tests/migration.rs b/pallets/subtensor/src/tests/migration.rs index 39b00be94a..bed77e797f 100644 --- a/pallets/subtensor/src/tests/migration.rs +++ b/pallets/subtensor/src/tests/migration.rs @@ -1150,13 +1150,12 @@ fn test_migrate_fix_staking_hot_keys() { // Add some data Alpha::::insert( - (U256::from(1), - U256::from(2), - NetUid::ROOT), - U64F64::from(1_u64) + (U256::from(1), U256::from(2), NetUid::ROOT), + U64F64::from(1_u64), ); // Run migration - let weight = migrations::migrate_fix_staking_hot_keys::migrate_fix_staking_hot_keys::(); + let weight = + migrations::migrate_fix_staking_hot_keys::migrate_fix_staking_hot_keys::(); assert!( HasMigrationRun::::get(MIGRATION_NAME.to_vec()), @@ -1174,7 +1173,6 @@ fn test_migrate_fix_staking_hot_keys() { }); } - #[test] fn test_migrate_fix_root_subnet_tao() { new_test_ext(1).execute_with(|| { From 5e6becf900f3e70dbd580e65873999d8985b351a Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Thu, 18 Dec 2025 13:46:09 +0100 Subject: [PATCH 4/4] Consider iteration read --- .../subtensor/src/migrations/migrate_fix_staking_hot_keys.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pallets/subtensor/src/migrations/migrate_fix_staking_hot_keys.rs b/pallets/subtensor/src/migrations/migrate_fix_staking_hot_keys.rs index 7728ff0a6a..8c0358614d 100644 --- a/pallets/subtensor/src/migrations/migrate_fix_staking_hot_keys.rs +++ b/pallets/subtensor/src/migrations/migrate_fix_staking_hot_keys.rs @@ -23,6 +23,8 @@ pub fn migrate_fix_staking_hot_keys() -> Weight { let mut storage_writes: u64 = 0; for ((hotkey, coldkey, _netuid), alpha) in Alpha::::iter() { + storage_reads = storage_reads.saturating_add(1); + if alpha == 0 { continue; }