diff --git a/pallets/admin-utils/src/lib.rs b/pallets/admin-utils/src/lib.rs index 01e9e7b33..f8f9a5683 100644 --- a/pallets/admin-utils/src/lib.rs +++ b/pallets/admin-utils/src/lib.rs @@ -236,6 +236,7 @@ pub mod pallet { netuid, &[Hyperparameter::ServingRateLimit.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; pallet_subtensor::Pallet::::set_serving_rate_limit(netuid, serving_rate_limit); log::debug!("ServingRateLimitSet( serving_rate_limit: {serving_rate_limit:?} ) "); pallet_subtensor::Pallet::::record_owner_rl( @@ -288,6 +289,7 @@ pub mod pallet { netuid, &[Hyperparameter::MaxDifficulty.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), @@ -322,6 +324,7 @@ pub mod pallet { netuid, &[TransactionType::SetWeightsVersionKey], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), @@ -413,6 +416,7 @@ pub mod pallet { netuid, &[Hyperparameter::AdjustmentAlpha.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), @@ -445,6 +449,7 @@ pub mod pallet { netuid, &[Hyperparameter::ImmunityPeriod.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), Error::::SubnetDoesNotExist @@ -479,6 +484,7 @@ pub mod pallet { netuid, &[Hyperparameter::MinAllowedWeights.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), @@ -513,6 +519,7 @@ pub mod pallet { netuid, &[Hyperparameter::MaxAllowedUids.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), Error::::SubnetDoesNotExist @@ -572,6 +579,7 @@ pub mod pallet { netuid, &[Hyperparameter::Rho.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), @@ -604,6 +612,7 @@ pub mod pallet { netuid, &[Hyperparameter::ActivityCutoff.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), @@ -672,6 +681,7 @@ pub mod pallet { netuid, &[Hyperparameter::PowRegistrationAllowed.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; pallet_subtensor::Pallet::::set_network_pow_registration_allowed( netuid, @@ -733,6 +743,7 @@ pub mod pallet { netuid, &[Hyperparameter::MinBurn.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), Error::::SubnetDoesNotExist @@ -773,6 +784,7 @@ pub mod pallet { netuid, &[Hyperparameter::MaxBurn.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), Error::::SubnetDoesNotExist @@ -868,6 +880,7 @@ pub mod pallet { netuid, &[Hyperparameter::BondsMovingAverage.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; if maybe_owner.is_some() { ensure!( bonds_moving_average <= 975000, @@ -908,6 +921,7 @@ pub mod pallet { netuid, &[Hyperparameter::BondsPenalty.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), @@ -1245,6 +1259,7 @@ pub mod pallet { netuid, &[Hyperparameter::CommitRevealEnabled.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), @@ -1288,6 +1303,7 @@ pub mod pallet { netuid, &[Hyperparameter::LiquidAlphaEnabled.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; pallet_subtensor::Pallet::::set_liquid_alpha_enabled(netuid, enabled); log::debug!("LiquidAlphaEnableToggled( netuid: {netuid:?}, Enabled: {enabled:?} ) "); pallet_subtensor::Pallet::::record_owner_rl( @@ -1318,6 +1334,7 @@ pub mod pallet { netuid, &[Hyperparameter::AlphaValues.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; let res = pallet_subtensor::Pallet::::do_set_alpha_values( origin, netuid, alpha_low, alpha_high, ); @@ -1437,6 +1454,7 @@ pub mod pallet { netuid, &[Hyperparameter::WeightCommitInterval.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), @@ -1535,6 +1553,7 @@ pub mod pallet { netuid, &[Hyperparameter::TransferEnabled.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; let res = pallet_subtensor::Pallet::::toggle_transfer(netuid, toggle); if res.is_ok() { pallet_subtensor::Pallet::::record_owner_rl( @@ -1567,6 +1586,7 @@ pub mod pallet { netuid, &[Hyperparameter::RecycleOrBurn.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; pallet_subtensor::Pallet::::set_recycle_or_burn(netuid, recycle_or_burn); pallet_subtensor::Pallet::::record_owner_rl( @@ -1734,6 +1754,7 @@ pub mod pallet { netuid, &[Hyperparameter::AlphaSigmoidSteepness.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), @@ -1784,6 +1805,7 @@ pub mod pallet { netuid, &[Hyperparameter::Yuma3Enabled.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; pallet_subtensor::Pallet::::set_yuma3_enabled(netuid, enabled); Self::deposit_event(Event::Yuma3EnableToggled { netuid, enabled }); @@ -1823,6 +1845,7 @@ pub mod pallet { netuid, &[Hyperparameter::BondsResetEnabled.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; pallet_subtensor::Pallet::::set_bonds_reset(netuid, enabled); Self::deposit_event(Event::BondsResetToggled { netuid, enabled }); @@ -1948,6 +1971,7 @@ pub mod pallet { netuid, &[Hyperparameter::ImmuneNeuronLimit.into()], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; pallet_subtensor::Pallet::::set_owner_immune_neuron_limit(netuid, immune_neurons)?; pallet_subtensor::Pallet::::record_owner_rl( maybe_owner, @@ -2021,6 +2045,7 @@ pub mod pallet { netuid, &[TransactionType::MechanismCountUpdate], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; pallet_subtensor::Pallet::::do_set_mechanism_count(netuid, mechanism_count)?; @@ -2047,6 +2072,7 @@ pub mod pallet { netuid, &[TransactionType::MechanismEmission], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; pallet_subtensor::Pallet::::do_set_emission_split(netuid, maybe_split)?; @@ -2077,6 +2103,7 @@ pub mod pallet { netuid, &[TransactionType::MaxUidsTrimming], )?; + pallet_subtensor::Pallet::::ensure_admin_window_open(netuid)?; pallet_subtensor::Pallet::::trim_to_max_allowed_uids(netuid, max_n)?; diff --git a/pallets/subtensor/src/tests/ensure.rs b/pallets/subtensor/src/tests/ensure.rs index a59bfd748..3b4db87f4 100644 --- a/pallets/subtensor/src/tests/ensure.rs +++ b/pallets/subtensor/src/tests/ensure.rs @@ -111,6 +111,7 @@ fn ensure_owner_or_root_with_limits_checks_rl_and_freeze() { ) .expect("should pass"); assert_eq!(res, Some(owner)); + assert_ok!(crate::Pallet::::ensure_admin_window_open(netuid)); // Simulate previous update at current block -> next call should fail due to rate limit let now = crate::Pallet::::get_current_block_as_u64(); @@ -127,11 +128,14 @@ fn ensure_owner_or_root_with_limits_checks_rl_and_freeze() { // Advance beyond RL and ensure passes again run_to_block(now + 3); + TransactionType::from(Hyperparameter::Kappa) + .set_last_block_on_subnet::(&owner, netuid, 0); assert_ok!(crate::Pallet::::ensure_sn_owner_or_root_with_limits( <::RuntimeOrigin>::signed(owner), netuid, &[Hyperparameter::Kappa.into()] )); + assert_ok!(crate::Pallet::::ensure_admin_window_open(netuid)); // Now advance into the freeze window; ensure blocks // (using loop for clarity, because epoch calculation function uses netuid) @@ -148,12 +152,13 @@ fn ensure_owner_or_root_with_limits_checks_rl_and_freeze() { } run_to_block(cur + 1); } + assert_ok!(crate::Pallet::::ensure_sn_owner_or_root_with_limits( + <::RuntimeOrigin>::signed(owner), + netuid, + &[Hyperparameter::Kappa.into()] + )); assert_noop!( - crate::Pallet::::ensure_sn_owner_or_root_with_limits( - <::RuntimeOrigin>::signed(owner), - netuid, - &[Hyperparameter::Kappa.into()], - ), + crate::Pallet::::ensure_admin_window_open(netuid), crate::Error::::AdminActionProhibitedDuringWeightsWindow ); }); diff --git a/pallets/subtensor/src/utils/misc.rs b/pallets/subtensor/src/utils/misc.rs index 0ba3df110..7a14fafd6 100644 --- a/pallets/subtensor/src/utils/misc.rs +++ b/pallets/subtensor/src/utils/misc.rs @@ -42,23 +42,16 @@ impl Pallet { netuid: NetUid, ) -> Result<(), DispatchError> { ensure_root(o)?; - let now = Self::get_current_block_as_u64(); - Self::ensure_not_in_admin_freeze_window(netuid, now)?; - Ok(()) + Self::ensure_admin_window_open(netuid) } /// Ensure owner-or-root with a set of TransactionType rate checks (owner only). - /// - Root: only freeze window is enforced; no TransactionType checks. - /// - Owner (Signed): freeze window plus all rate checks in `limits` using signer extracted from - /// origin. pub fn ensure_sn_owner_or_root_with_limits( o: T::RuntimeOrigin, netuid: NetUid, limits: &[crate::utils::rate_limiting::TransactionType], ) -> Result, DispatchError> { let maybe_who = Self::ensure_subnet_owner_or_root(o, netuid)?; - let now = Self::get_current_block_as_u64(); - Self::ensure_not_in_admin_freeze_window(netuid, now)?; if let Some(who) = maybe_who.as_ref() { for tx in limits.iter() { ensure!( @@ -70,26 +63,6 @@ impl Pallet { Ok(maybe_who) } - /// Ensure the caller is the subnet owner and passes all provided rate limits. - /// This does NOT allow root; it is strictly owner-only. - /// Returns the signer (owner) on success so callers may record last-blocks. - pub fn ensure_sn_owner_with_limits( - o: T::RuntimeOrigin, - netuid: NetUid, - limits: &[crate::utils::rate_limiting::TransactionType], - ) -> Result { - let who = Self::ensure_subnet_owner(o, netuid)?; - let now = Self::get_current_block_as_u64(); - Self::ensure_not_in_admin_freeze_window(netuid, now)?; - for tx in limits.iter() { - ensure!( - tx.passes_rate_limit_on_subnet::(&who, netuid), - Error::::TxRateLimitExceeded - ); - } - Ok(who) - } - /// Returns true if the current block is within the terminal freeze window of the tempo for the /// given subnet. During this window, admin ops are prohibited to avoid interference with /// validator weight submissions. @@ -103,7 +76,9 @@ impl Pallet { remaining < window } - fn ensure_not_in_admin_freeze_window(netuid: NetUid, now: u64) -> Result<(), DispatchError> { + /// Ensures the admin freeze window is not currently active for the given subnet. + pub fn ensure_admin_window_open(netuid: NetUid) -> Result<(), DispatchError> { + let now = Self::get_current_block_as_u64(); ensure!( !Self::is_in_admin_freeze_window(netuid, now), Error::::AdminActionProhibitedDuringWeightsWindow diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 266a75570..d95eb45ee 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -220,7 +220,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 338, + spec_version: 339, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1,