diff --git a/pallets/admin-utils/src/lib.rs b/pallets/admin-utils/src/lib.rs index 921fca9861..4ef196a1b9 100644 --- a/pallets/admin-utils/src/lib.rs +++ b/pallets/admin-utils/src/lib.rs @@ -543,27 +543,17 @@ pub mod pallet { /// It is only callable by the root account or subnet owner. /// The extrinsic will call the Subtensor pallet to set the kappa. #[pallet::call_index(16)] - #[pallet::weight(Weight::from_parts(26_210_000, 0) - .saturating_add(::DbWeight::get().reads(3_u64)) + #[pallet::weight(Weight::from_parts(15_390_000, 0) + .saturating_add(::DbWeight::get().reads(1_u64)) .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_kappa(origin: OriginFor, netuid: NetUid, kappa: u16) -> DispatchResult { - let maybe_owner = pallet_subtensor::Pallet::::ensure_sn_owner_or_root_with_limits( - origin, - netuid, - &[Hyperparameter::Kappa.into()], - )?; - + ensure_root(origin)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), Error::::SubnetDoesNotExist ); pallet_subtensor::Pallet::::set_kappa(netuid, kappa); log::debug!("KappaSet( netuid: {netuid:?} kappa: {kappa:?} ) "); - pallet_subtensor::Pallet::::record_owner_rl( - maybe_owner, - netuid, - &[Hyperparameter::Kappa.into()], - ); Ok(()) } @@ -1218,7 +1208,7 @@ pub mod pallet { /// The extrinsic will call the Subtensor pallet to set the minimum delegate take. #[pallet::call_index(46)] #[pallet::weight(( - Weight::from_parts(7_885_000, 0).saturating_add(T::DbWeight::get().writes(1_u64)), + Weight::from_parts(7_214_000, 0).saturating_add(T::DbWeight::get().writes(1_u64)), DispatchClass::Operational, Pays::Yes ))] diff --git a/pallets/admin-utils/src/tests/mod.rs b/pallets/admin-utils/src/tests/mod.rs index f0ba59e285..f5f53ff60a 100644 --- a/pallets/admin-utils/src/tests/mod.rs +++ b/pallets/admin-utils/src/tests/mod.rs @@ -2025,7 +2025,7 @@ fn test_freeze_window_blocks_root_and_owner() { let owner: U256 = U256::from(9); SubnetOwner::::insert(netuid, owner); assert_noop!( - AdminUtils::sudo_set_kappa( + AdminUtils::sudo_set_commit_reveal_weights_interval( <::RuntimeOrigin>::signed(owner), netuid, 77 @@ -2112,14 +2112,14 @@ fn test_owner_hyperparam_update_rate_limit_enforced() { )); // First update succeeds - assert_ok!(AdminUtils::sudo_set_kappa( + assert_ok!(AdminUtils::sudo_set_commit_reveal_weights_interval( <::RuntimeOrigin>::signed(owner), netuid, 11 )); // Immediate second update fails due to TxRateLimitExceeded assert_noop!( - AdminUtils::sudo_set_kappa( + AdminUtils::sudo_set_commit_reveal_weights_interval( <::RuntimeOrigin>::signed(owner), netuid, 12 @@ -2130,7 +2130,7 @@ fn test_owner_hyperparam_update_rate_limit_enforced() { // Advance less than limit still fails run_to_block(SubtensorModule::get_current_block_as_u64() + 1); assert_noop!( - AdminUtils::sudo_set_kappa( + AdminUtils::sudo_set_commit_reveal_weights_interval( <::RuntimeOrigin>::signed(owner), netuid, 13 @@ -2140,7 +2140,7 @@ fn test_owner_hyperparam_update_rate_limit_enforced() { // Advance one more block to pass the limit; should succeed run_to_block(SubtensorModule::get_current_block_as_u64() + 1); - assert_ok!(AdminUtils::sudo_set_kappa( + assert_ok!(AdminUtils::sudo_set_commit_reveal_weights_interval( <::RuntimeOrigin>::signed(owner), netuid, 14 @@ -2167,7 +2167,7 @@ fn test_hyperparam_rate_limit_enforced_by_tempo() { )); // First owner update should succeed - assert_ok!(AdminUtils::sudo_set_kappa( + assert_ok!(AdminUtils::sudo_set_commit_reveal_weights_interval( <::RuntimeOrigin>::signed(owner), netuid, 1 @@ -2175,13 +2175,17 @@ fn test_hyperparam_rate_limit_enforced_by_tempo() { // Immediate second update should fail due to tempo-based RL assert_noop!( - AdminUtils::sudo_set_kappa(<::RuntimeOrigin>::signed(owner), netuid, 2), + AdminUtils::sudo_set_commit_reveal_weights_interval( + <::RuntimeOrigin>::signed(owner), + netuid, + 2 + ), SubtensorError::::TxRateLimitExceeded ); // Advance 2 blocks (2 tempos with tempo=1) then succeed run_to_block(SubtensorModule::get_current_block_as_u64() + 2); - assert_ok!(AdminUtils::sudo_set_kappa( + assert_ok!(AdminUtils::sudo_set_commit_reveal_weights_interval( <::RuntimeOrigin>::signed(owner), netuid, 3 @@ -2211,7 +2215,7 @@ fn test_owner_hyperparam_rate_limit_independent_per_param() { )); // First update to kappa should succeed - assert_ok!(AdminUtils::sudo_set_kappa( + assert_ok!(AdminUtils::sudo_set_commit_reveal_weights_interval( <::RuntimeOrigin>::signed(owner), netuid, 10 @@ -2219,7 +2223,7 @@ fn test_owner_hyperparam_rate_limit_independent_per_param() { // Immediate second update to the SAME param (kappa) should be blocked by RL assert_noop!( - AdminUtils::sudo_set_kappa( + AdminUtils::sudo_set_commit_reveal_weights_interval( <::RuntimeOrigin>::signed(owner), netuid, 11 @@ -2236,7 +2240,7 @@ fn test_owner_hyperparam_rate_limit_independent_per_param() { // kappa should still be blocked until its own RL window passes assert_noop!( - AdminUtils::sudo_set_kappa( + AdminUtils::sudo_set_commit_reveal_weights_interval( <::RuntimeOrigin>::signed(owner), netuid, 12 @@ -2254,7 +2258,7 @@ fn test_owner_hyperparam_rate_limit_independent_per_param() { run_to_block(SubtensorModule::get_current_block_as_u64() + 2); // Now both hyperparameters can be updated again - assert_ok!(AdminUtils::sudo_set_kappa( + assert_ok!(AdminUtils::sudo_set_commit_reveal_weights_interval( <::RuntimeOrigin>::signed(owner), netuid, 13 diff --git a/pallets/subtensor/src/macros/hooks.rs b/pallets/subtensor/src/macros/hooks.rs index 20651f68fc..3e75035160 100644 --- a/pallets/subtensor/src/macros/hooks.rs +++ b/pallets/subtensor/src/macros/hooks.rs @@ -153,7 +153,9 @@ mod hooks { // Cleanup child/parent keys .saturating_add(migrations::migrate_fix_childkeys::migrate_fix_childkeys::()) // Migrate AutoStakeDestinationColdkeys - .saturating_add(migrations::migrate_auto_stake_destination::migrate_auto_stake_destination::()); + .saturating_add(migrations::migrate_auto_stake_destination::migrate_auto_stake_destination::()) + // Migrate Kappa to default (0.5) + .saturating_add(migrations::migrate_kappa_map_to_default::migrate_kappa_map_to_default::()); weight } diff --git a/pallets/subtensor/src/migrations/migrate_kappa_map_to_default.rs b/pallets/subtensor/src/migrations/migrate_kappa_map_to_default.rs new file mode 100644 index 0000000000..69b82cae0b --- /dev/null +++ b/pallets/subtensor/src/migrations/migrate_kappa_map_to_default.rs @@ -0,0 +1,54 @@ +use super::*; +use frame_support::{traits::Get, weights::Weight}; +use log; +use scale_info::prelude::string::String; + +pub fn migrate_kappa_map_to_default() -> Weight { + let mig_name: Vec = b"kappa_map_to_default".to_vec(); + let mig_name_str = String::from_utf8_lossy(&mig_name); + + // 1 read for the HasMigrationRun flag + let mut total_weight = T::DbWeight::get().reads(1); + + // Run once guard + if HasMigrationRun::::get(&mig_name) { + log::info!("Migration '{mig_name_str}' already executed - skipping"); + return total_weight; + } + + log::info!("Running migration '{mig_name_str}'"); + + let target: u16 = DefaultKappa::::get(); + + let mut reads: u64 = 0; + let mut writes: u64 = 0; + let mut visited: u64 = 0; + let mut updated: u64 = 0; + let mut unchanged: u64 = 0; + + for (netuid, current) in Kappa::::iter() { + visited = visited.saturating_add(1); + reads = reads.saturating_add(1); + + if current != target { + Kappa::::insert(netuid, target); + writes = writes.saturating_add(1); + updated = updated.saturating_add(1); + } else { + unchanged = unchanged.saturating_add(1); + } + } + + total_weight = total_weight.saturating_add(T::DbWeight::get().reads_writes(reads, writes)); + + log::info!( + "Kappa migration summary: visited={visited}, updated={updated}, unchanged={unchanged}, target_default={target}" + ); + + HasMigrationRun::::insert(&mig_name, true); + total_weight = total_weight.saturating_add(T::DbWeight::get().writes(1)); + + log::info!("Migration '{mig_name_str}' completed"); + + total_weight +} diff --git a/pallets/subtensor/src/migrations/mod.rs b/pallets/subtensor/src/migrations/mod.rs index db0b290661..ca21f9bef2 100644 --- a/pallets/subtensor/src/migrations/mod.rs +++ b/pallets/subtensor/src/migrations/mod.rs @@ -21,6 +21,7 @@ pub mod migrate_fix_root_subnet_tao; pub mod migrate_fix_root_tao_and_alpha_in; pub mod migrate_identities_v2; pub mod migrate_init_total_issuance; +pub mod migrate_kappa_map_to_default; pub mod migrate_network_immunity_period; pub mod migrate_network_lock_cost_2500; pub mod migrate_network_lock_reduction_interval; diff --git a/pallets/subtensor/src/tests/migration.rs b/pallets/subtensor/src/tests/migration.rs index ede32aa06c..fbf49f3ae5 100644 --- a/pallets/subtensor/src/tests/migration.rs +++ b/pallets/subtensor/src/tests/migration.rs @@ -2171,3 +2171,83 @@ fn test_migrate_network_lock_cost_2500_sets_price_and_decay() { ); }); } + +#[test] +fn test_migrate_kappa_map_to_default() { + new_test_ext(1).execute_with(|| { + // ------------------------------ + // 0. Constants / helpers + // ------------------------------ + const MIG_NAME: &[u8] = b"kappa_map_to_default"; + let default: u16 = DefaultKappa::::get(); + + let not_default: u16 = if default == u16::MAX { + default.saturating_sub(1) + } else { + default.saturating_add(1) + }; + + // ------------------------------ + // 1. Pre-state: seed using the correct key type (NetUid) + // ------------------------------ + let n0: NetUid = 0u16.into(); + let n1: NetUid = 1u16.into(); + let n2: NetUid = 42u16.into(); + + Kappa::::insert(n0, not_default); + Kappa::::insert(n1, default); + Kappa::::insert(n2, not_default); + + assert_eq!( + Kappa::::get(n0), + not_default, + "precondition failed: Kappa[n0] should be non-default before migration" + ); + assert_eq!( + Kappa::::get(n1), + default, + "precondition failed: Kappa[n1] should be default before migration" + ); + assert_eq!( + Kappa::::get(n2), + not_default, + "precondition failed: Kappa[n2] should be non-default before migration" + ); + + assert!( + !HasMigrationRun::::get(MIG_NAME.to_vec()), + "migration flag should be false before run" + ); + + // ------------------------------ + // 2. Run migration + // ------------------------------ + let w = + crate::migrations::migrate_kappa_map_to_default::migrate_kappa_map_to_default::(); + assert!(!w.is_zero(), "weight must be non-zero"); + + // ------------------------------ + // 3. Verify results + // ------------------------------ + assert!( + HasMigrationRun::::get(MIG_NAME.to_vec()), + "migration flag not set" + ); + + assert_eq!( + Kappa::::get(n0), + default, + "Kappa[n0] should be reset to the configured default" + ); + assert_eq!( + Kappa::::get(n1), + default, + "Kappa[n1] should remain at the configured default" + ); + assert_eq!( + Kappa::::get(n2), + default, + "Kappa[n2] should be reset to the configured default" + ); + }); +}