diff --git a/pallets/subtensor/src/coinbase/run_coinbase.rs b/pallets/subtensor/src/coinbase/run_coinbase.rs index 723edc423..66617fd88 100644 --- a/pallets/subtensor/src/coinbase/run_coinbase.rs +++ b/pallets/subtensor/src/coinbase/run_coinbase.rs @@ -145,7 +145,7 @@ impl Pallet { // We keep track of the last stake increase event for accounting purposes. // hotkeys --> nominators. let emission_tempo: u64 = Self::get_hotkey_emission_tempo(); - for (hotkey, hotkey_emission) in PendingdHotkeyEmission::::iter() { + for (hotkey, hotkey_emission) in PendingHotkeyEmission::::iter() { // Check for zeros. // remove zero values. if hotkey_emission == 0 { @@ -227,7 +227,7 @@ impl Pallet { .to_num::(); // --- 5.5. Accumulate emissions for the parent hotkey. - PendingdHotkeyEmission::::mutate(parent, |parent_accumulated| { + PendingHotkeyEmission::::mutate(parent, |parent_accumulated| { *parent_accumulated = parent_accumulated.saturating_add(parent_emission_take) }); @@ -237,7 +237,7 @@ impl Pallet { } // --- 6. Add the remaining emission plus the hotkey's initial take to the pending emission for this hotkey. - PendingdHotkeyEmission::::mutate(hotkey, |hotkey_pending| { + PendingHotkeyEmission::::mutate(hotkey, |hotkey_pending| { *hotkey_pending = hotkey_pending.saturating_add( remaining_emission .saturating_add(hotkey_take) @@ -263,7 +263,7 @@ impl Pallet { let mut total_new_tao: u64 = 0; // --- 1.0 Drain the hotkey emission. - PendingdHotkeyEmission::::insert(hotkey, 0); + PendingHotkeyEmission::::insert(hotkey, 0); // --- 2 Retrieve the last time this hotkey's emissions were drained. let last_emission_drain: u64 = LastHotkeyEmissionDrain::::get(hotkey); diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index cc3d7d025..0a57e50d9 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -780,7 +780,7 @@ pub mod pallet { pub type HotkeyEmissionTempo = StorageValue<_, u64, ValueQuery, DefaultHotkeyEmissionTempo>; #[pallet::storage] - /// Map ( hot ) --> emission | Accumulated hotkey emission. + /// Name corrected: PendingdHotkeyEmission => PendingHotkeyEmission pub type PendingdHotkeyEmission = StorageMap< _, Blake2_128Concat, @@ -790,6 +790,16 @@ pub mod pallet { DefaultAccumulatedEmission, >; #[pallet::storage] + /// Map ( hot ) --> emission | Accumulated hotkey emission. + pub type PendingHotkeyEmission = StorageMap< + _, + Blake2_128Concat, + T::AccountId, + u64, + ValueQuery, + DefaultAccumulatedEmission, + >; + #[pallet::storage] /// Map ( hot, cold ) --> block_number | Last add stake increase. pub type LastAddStakeIncrease = StorageDoubleMap< _, @@ -939,10 +949,14 @@ pub mod pallet { pub type BlocksSinceLastStep = StorageMap<_, Identity, u16, u64, ValueQuery, DefaultBlocksSinceLastStep>; #[pallet::storage] - /// --- MAP ( netuid ) --> last_mechanism_step_block + /// Name corrected: LastMechansimStepBlock => LastMechanismStepBlock pub type LastMechansimStepBlock = StorageMap<_, Identity, u16, u64, ValueQuery, DefaultLastMechanismStepBlock>; #[pallet::storage] + /// --- MAP ( netuid ) --> last_mechanism_step_block + pub type LastMechanismStepBlock = + StorageMap<_, Identity, u16, u64, ValueQuery, DefaultLastMechanismStepBlock>; + #[pallet::storage] /// --- MAP ( netuid ) --> subnet_owner pub type SubnetOwner = StorageMap<_, Identity, u16, T::AccountId, ValueQuery, DefaultSubnetOwner>; diff --git a/pallets/subtensor/src/macros/hooks.rs b/pallets/subtensor/src/macros/hooks.rs index 76f140002..bfb9ef31b 100644 --- a/pallets/subtensor/src/macros/hooks.rs +++ b/pallets/subtensor/src/macros/hooks.rs @@ -70,7 +70,9 @@ mod hooks { // Storage version v8 -> v9 .saturating_add(migrations::migrate_fix_total_coldkey_stake::migrate_fix_total_coldkey_stake::()) // Migrate Delegate Ids on chain - .saturating_add(migrations::migrate_chain_identity::migrate_set_hotkey_identities::()); + .saturating_add(migrations::migrate_chain_identity::migrate_set_hotkey_identities::()) + // Migration to fix typos in storage items + .saturating_add(migrations::migrate_fix_storage_typos::migrate_rename_storage_items::()); weight } diff --git a/pallets/subtensor/src/migrations/migrate_fix_storage_typos.rs b/pallets/subtensor/src/migrations/migrate_fix_storage_typos.rs new file mode 100644 index 000000000..5596f3234 --- /dev/null +++ b/pallets/subtensor/src/migrations/migrate_fix_storage_typos.rs @@ -0,0 +1,59 @@ +use super::*; +use frame_support::{traits::Get, weights::Weight}; +use scale_info::prelude::string::String; + +/// Migrates storage items with typos to their correctly named counterparts. +/// +/// - `PendingdHotkeyEmission` is migrated to `PendingHotkeyEmission`. +/// - `LastMechansimStepBlock` is migrated to `LastMechanismStepBlock`. +/// +/// # Returns +/// The cumulative weight of the migration process. +pub fn migrate_rename_storage_items() -> Weight { + let migration_name = b"migrate_rename_storage_items_v1".to_vec(); + + let mut weight = T::DbWeight::get().reads(1); + + // Check if the migration has already been run. + if HasMigrationRun::::get(&migration_name) { + log::info!( + "Migration '{:?}' has already run. Skipping.", + migration_name + ); + return weight; + } + + log::info!( + "Running migration '{}'", + String::from_utf8_lossy(&migration_name) + ); + + // === Migrate `PendingdHotkeyEmission` to `PendingHotkeyEmission` and wipe old storage === + for (account_id, emission) in PendingdHotkeyEmission::::drain() { + // Insert the value into the new storage + PendingHotkeyEmission::::insert(account_id, emission); + + // Add weight for the write operation (the `drain` method takes care of the removal) + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + } + + // === Migrate `LastMechansimStepBlock` to `LastMechanismStepBlock` and wipe old storage === + for (netuid, block) in LastMechansimStepBlock::::drain() { + // Insert the value into the new storage + LastMechanismStepBlock::::insert(netuid, block); + + // Add weight for the write operation (the `drain` method takes care of the removal) + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + } + + // === Mark Migration as Completed === + HasMigrationRun::::insert(&migration_name, true); + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + + log::info!( + "Migration '{:?}' completed.", + String::from_utf8_lossy(&migration_name) + ); + + weight +} diff --git a/pallets/subtensor/src/migrations/mod.rs b/pallets/subtensor/src/migrations/mod.rs index 6036b23e0..d2254aa37 100644 --- a/pallets/subtensor/src/migrations/mod.rs +++ b/pallets/subtensor/src/migrations/mod.rs @@ -3,6 +3,7 @@ pub mod migrate_chain_identity; pub mod migrate_create_root_network; pub mod migrate_delete_subnet_21; pub mod migrate_delete_subnet_3; +pub mod migrate_fix_storage_typos; pub mod migrate_fix_total_coldkey_stake; pub mod migrate_init_total_issuance; pub mod migrate_populate_owned_hotkeys; diff --git a/pallets/subtensor/src/utils/misc.rs b/pallets/subtensor/src/utils/misc.rs index 76546a1a2..2e6dd1a27 100644 --- a/pallets/subtensor/src/utils/misc.rs +++ b/pallets/subtensor/src/utils/misc.rs @@ -39,7 +39,7 @@ impl Pallet { RegistrationsThisBlock::::insert(netuid, registrations_this_block); } pub fn set_last_mechanism_step_block(netuid: u16, last_mechanism_step_block: u64) { - LastMechansimStepBlock::::insert(netuid, last_mechanism_step_block); + LastMechanismStepBlock::::insert(netuid, last_mechanism_step_block); } pub fn set_registrations_this_interval(netuid: u16, registrations_this_interval: u16) { RegistrationsThisInterval::::insert(netuid, registrations_this_interval); @@ -242,7 +242,7 @@ impl Pallet { RegistrationsThisBlock::::get(netuid) } pub fn get_last_mechanism_step_block(netuid: u16) -> u64 { - LastMechansimStepBlock::::get(netuid) + LastMechanismStepBlock::::get(netuid) } pub fn get_registrations_this_interval(netuid: u16) -> u16 { RegistrationsThisInterval::::get(netuid) @@ -716,7 +716,7 @@ impl Pallet { } pub fn get_pending_hotkey_emission(hotkey: &T::AccountId) -> u64 { - PendingdHotkeyEmission::::get(hotkey) + PendingHotkeyEmission::::get(hotkey) } /// Retrieves the maximum stake allowed for a given network. diff --git a/pallets/subtensor/tests/migration.rs b/pallets/subtensor/tests/migration.rs index 6c40d7d78..79ecc609b 100644 --- a/pallets/subtensor/tests/migration.rs +++ b/pallets/subtensor/tests/migration.rs @@ -1,6 +1,6 @@ #![allow(unused, clippy::indexing_slicing, clippy::panic, clippy::unwrap_used)] mod mock; -use frame_support::{assert_ok, weights::Weight}; +use frame_support::{assert_ok, traits::StorageVersion, weights::Weight}; use frame_system::Config; use mock::*; use pallet_subtensor::*; @@ -430,3 +430,63 @@ fn run_migration_and_check(migration_name: &'static str) -> frame_support::weigh // Return the weight of the executed migration weight } + +#[test] +fn test_migrate_rename_storage_items() { + new_test_ext(1).execute_with(|| { + let migration_name = b"migrate_rename_storage_items_v1"; + + let account_ids: [U256; 3] = [ + AccountId::from([1u8; 32]), + AccountId::from([2u8; 32]), + AccountId::from([3u8; 32]), + ]; + + let netuids: Vec = vec![42, 43, 44]; + let emission_values: Vec = vec![4, 1000, 0, u64::MAX]; + let block_values: Vec = vec![11, 5000, 1, u64::MAX]; + + // Insert multiple entries into old storage items with typos + for (i, account_id) in account_ids.iter().enumerate() { + PendingdHotkeyEmission::::insert(account_id, emission_values[i]); + } + for (i, netuid) in netuids.iter().enumerate() { + LastMechansimStepBlock::::insert(*netuid, block_values[i]); + } + + assert!(!HasMigrationRun::::get(migration_name.to_vec())); + + let weight: frame_support::weights::Weight = + pallet_subtensor::migrations::migrate_fix_storage_typos::migrate_rename_storage_items::< + Test, + >(); + + assert!( + weight != Weight::zero(), + "Migration weight should be non-zero" + ); + + assert!(HasMigrationRun::::get(migration_name.to_vec())); + + // Verify data has been migrated to the new storage items + for (i, account_id) in account_ids.iter().enumerate() { + let expected_emission = emission_values[i]; + assert_eq!( + PendingHotkeyEmission::::get(account_id), + expected_emission + ); + } + for (i, netuid) in netuids.iter().enumerate() { + let expected_block = block_values[i]; + assert_eq!(LastMechanismStepBlock::::get(*netuid), expected_block); + } + + // Verify all items are removed from the old storage + for account_id in account_ids.iter() { + assert!(!PendingdHotkeyEmission::::contains_key(account_id)); + } + for netuid in netuids.iter() { + assert!(!LastMechansimStepBlock::::contains_key(*netuid)); + } + }); +}