From 826a44668bac6ea18fea475af596dea8846831cb Mon Sep 17 00:00:00 2001 From: Loris Moulin Date: Mon, 29 Sep 2025 19:11:06 -0300 Subject: [PATCH 1/9] refactor set max allowed uids --- pallets/admin-utils/src/lib.rs | 30 +++++++- pallets/admin-utils/src/tests/mock.rs | 2 +- pallets/admin-utils/src/tests/mod.rs | 80 ++++++++++---------- pallets/subtensor/src/utils/rate_limiting.rs | 1 + 4 files changed, 71 insertions(+), 42 deletions(-) diff --git a/pallets/admin-utils/src/lib.rs b/pallets/admin-utils/src/lib.rs index 61e4b8a49b..a61f31ee25 100644 --- a/pallets/admin-utils/src/lib.rs +++ b/pallets/admin-utils/src/lib.rs @@ -25,7 +25,10 @@ pub mod pallet { use frame_support::{dispatch::DispatchResult, pallet_prelude::StorageMap}; use frame_system::pallet_prelude::*; use pallet_evm_chain_id::{self, ChainId}; - use pallet_subtensor::utils::rate_limiting::{Hyperparameter, TransactionType}; + use pallet_subtensor::{ + DefaultMaxAllowedUids, + utils::rate_limiting::{Hyperparameter, TransactionType}, + }; use sp_runtime::BoundedVec; use substrate_fixed::types::I96F32; use subtensor_runtime_common::{MechId, NetUid, TaoCurrency}; @@ -110,6 +113,10 @@ pub mod pallet { MinAllowedUidsGreaterThanCurrentUids, /// The minimum allowed UIDs must be less than the maximum allowed UIDs. MinAllowedUidsGreaterThanMaxAllowedUids, + /// The maximum allowed UIDs must be greater than the minimum allowed UIDs. + MaxAllowedUidsLessThanMinAllowedUids, + /// The maximum allowed UIDs must be less than the default maximum allowed UIDs. + MaxAllowedUidsGreaterThanDefaultMaxAllowedUids, } /// Enum for specifying the type of precompile operation. #[derive( @@ -517,7 +524,7 @@ pub mod pallet { } /// The extrinsic sets the maximum allowed UIDs for a subnet. - /// It is only callable by the root account. + /// It is only callable by the root account and subnet owner. /// The extrinsic will call the Subtensor pallet to set the maximum allowed UIDs for a subnet. #[pallet::call_index(15)] #[pallet::weight(Weight::from_parts(18_800_000, 0) @@ -528,16 +535,33 @@ pub mod pallet { netuid: NetUid, max_allowed_uids: u16, ) -> DispatchResult { - ensure_root(origin)?; + let maybe_owner = pallet_subtensor::Pallet::::ensure_sn_owner_or_root_with_limits( + origin, + netuid, + &[Hyperparameter::MaxAllowedUids.into()], + )?; ensure!( pallet_subtensor::Pallet::::if_subnet_exist(netuid), Error::::SubnetDoesNotExist ); + ensure!( + max_allowed_uids > pallet_subtensor::Pallet::::get_min_allowed_uids(netuid), + Error::::MaxAllowedUidsLessThanMinAllowedUids + ); ensure!( pallet_subtensor::Pallet::::get_subnetwork_n(netuid) < max_allowed_uids, Error::::MaxAllowedUIdsLessThanCurrentUIds ); + ensure!( + max_allowed_uids <= DefaultMaxAllowedUids::::get(), + Error::::MaxAllowedUidsGreaterThanDefaultMaxAllowedUids + ); pallet_subtensor::Pallet::::set_max_allowed_uids(netuid, max_allowed_uids); + pallet_subtensor::Pallet::::record_owner_rl( + maybe_owner, + netuid, + &[Hyperparameter::MaxAllowedUids.into()], + ); log::debug!( "MaxAllowedUidsSet( netuid: {netuid:?} max_allowed_uids: {max_allowed_uids:?} ) " ); diff --git a/pallets/admin-utils/src/tests/mock.rs b/pallets/admin-utils/src/tests/mock.rs index 8c708adc9e..60ba7cbe09 100644 --- a/pallets/admin-utils/src/tests/mock.rs +++ b/pallets/admin-utils/src/tests/mock.rs @@ -92,7 +92,7 @@ parameter_types! { pub const SelfOwnership: u64 = 2; pub const InitialImmunityPeriod: u16 = 2; pub const InitialMinAllowedUids: u16 = 2; - pub const InitialMaxAllowedUids: u16 = 4; + pub const InitialMaxAllowedUids: u16 = 16; pub const InitialBondsMovingAverage: u64 = 900_000; pub const InitialBondsPenalty: u16 = u16::MAX; pub const InitialBondsResetOn: bool = false; diff --git a/pallets/admin-utils/src/tests/mod.rs b/pallets/admin-utils/src/tests/mod.rs index b6cafb71b7..233cb50aae 100644 --- a/pallets/admin-utils/src/tests/mod.rs +++ b/pallets/admin-utils/src/tests/mod.rs @@ -513,69 +513,73 @@ fn test_sudo_set_min_allowed_weights() { fn test_sudo_set_max_allowed_uids() { new_test_ext().execute_with(|| { let netuid = NetUid::from(1); - let to_be_set: u16 = 10; + let to_be_set: u16 = 12; add_network(netuid, 10); - let init_value: u16 = SubtensorModule::get_max_allowed_uids(netuid); - assert_eq!( + MaxRegistrationsPerBlock::::insert(netuid, 256); + TargetRegistrationsPerInterval::::insert(netuid, 256); + + // Register some neurons + for i in 0..=8 { + register_ok_neuron(netuid, U256::from(i * 1000), U256::from(i * 1000 + i), 0); + } + + // Bad origin that is not root or subnet owner + assert_noop!( AdminUtils::sudo_set_max_allowed_uids( - <::RuntimeOrigin>::signed(U256::from(0)), + <::RuntimeOrigin>::signed(U256::from(42)), netuid, to_be_set ), - Err(DispatchError::BadOrigin) + DispatchError::BadOrigin ); - assert_eq!( + + // Random netuid that doesn't exist + assert_noop!( AdminUtils::sudo_set_max_allowed_uids( <::RuntimeOrigin>::root(), - netuid.next(), + NetUid::from(42), to_be_set ), - Err(Error::::SubnetDoesNotExist.into()) + Error::::SubnetDoesNotExist ); - assert_eq!(SubtensorModule::get_max_allowed_uids(netuid), init_value); - assert_ok!(AdminUtils::sudo_set_max_allowed_uids( - <::RuntimeOrigin>::root(), - netuid, - to_be_set - )); - assert_eq!(SubtensorModule::get_max_allowed_uids(netuid), to_be_set); - }); -} -#[test] -fn test_sudo_set_and_decrease_max_allowed_uids() { - new_test_ext().execute_with(|| { - let netuid = NetUid::from(1); - let to_be_set: u16 = 10; - add_network(netuid, 10); - let init_value: u16 = SubtensorModule::get_max_allowed_uids(netuid); - assert_eq!( + // Trying to set max allowed uids less than min allowed uids + assert_noop!( AdminUtils::sudo_set_max_allowed_uids( - <::RuntimeOrigin>::signed(U256::from(0)), + <::RuntimeOrigin>::root(), netuid, - to_be_set + SubtensorModule::get_min_allowed_uids(netuid) - 1 ), - Err(DispatchError::BadOrigin) + Error::::MaxAllowedUidsLessThanMinAllowedUids ); - assert_eq!( + + // Trying to set max allowed uids less than current uids + assert_noop!( AdminUtils::sudo_set_max_allowed_uids( <::RuntimeOrigin>::root(), - netuid.next(), - to_be_set + netuid, + SubtensorModule::get_subnetwork_n(netuid) - 1 ), - Err(Error::::SubnetDoesNotExist.into()) + Error::::MaxAllowedUIdsLessThanCurrentUIds + ); + + // Trying to set max allowed uids greater than default max allowed uids + assert_noop!( + AdminUtils::sudo_set_max_allowed_uids( + <::RuntimeOrigin>::root(), + netuid, + DefaultMaxAllowedUids::::get() + 1 + ), + Error::::MaxAllowedUidsGreaterThanDefaultMaxAllowedUids ); - assert_eq!(SubtensorModule::get_max_allowed_uids(netuid), init_value); + + // Normal case assert_ok!(AdminUtils::sudo_set_max_allowed_uids( <::RuntimeOrigin>::root(), netuid, to_be_set )); - assert_ok!(AdminUtils::sudo_set_max_allowed_uids( - <::RuntimeOrigin>::root(), - netuid, - to_be_set - 1 - )); + assert_eq!(SubtensorModule::get_max_allowed_uids(netuid), to_be_set); }); } diff --git a/pallets/subtensor/src/utils/rate_limiting.rs b/pallets/subtensor/src/utils/rate_limiting.rs index e7028bc4e3..85f58cfc64 100644 --- a/pallets/subtensor/src/utils/rate_limiting.rs +++ b/pallets/subtensor/src/utils/rate_limiting.rs @@ -197,6 +197,7 @@ pub enum Hyperparameter { BondsResetEnabled = 22, ImmuneNeuronLimit = 23, RecycleOrBurn = 24, + MaxAllowedUids = 25, } impl Pallet { From 0147b633d6b9eeaf3bc11b3b2f15095ecafbfcf9 Mon Sep 17 00:00:00 2001 From: Loris Moulin Date: Mon, 29 Sep 2025 19:41:29 -0300 Subject: [PATCH 2/9] bump spec version --- runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index a1629cdafb..e597728a60 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -223,7 +223,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: 322, + spec_version: 323, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From d07cce92085ef43c6b03dd91d574d97e24e2ae16 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 30 Sep 2025 20:02:19 +0000 Subject: [PATCH 3/9] fix benchmarking --- pallets/admin-utils/src/benchmarking.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/admin-utils/src/benchmarking.rs b/pallets/admin-utils/src/benchmarking.rs index 67fba62b10..d10f36f7fe 100644 --- a/pallets/admin-utils/src/benchmarking.rs +++ b/pallets/admin-utils/src/benchmarking.rs @@ -263,7 +263,7 @@ mod benchmarks { ); #[extrinsic_call] - _(RawOrigin::Root, 1u16.into()/*netuid*/, 4097u16/*max_allowed_uids*/)/*sudo_set_max_allowed_uids*/; + _(RawOrigin::Root, 1u16.into()/*netuid*/, 2048u16/*max_allowed_uids*/)/*sudo_set_max_allowed_uids*/; } #[benchmark] From ce323478127dc0573f72c4521b2abbb416aff119 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 30 Sep 2025 21:11:20 +0000 Subject: [PATCH 4/9] auto-update benchmark weights --- pallets/admin-utils/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pallets/admin-utils/src/lib.rs b/pallets/admin-utils/src/lib.rs index a61f31ee25..0adfec4fe8 100644 --- a/pallets/admin-utils/src/lib.rs +++ b/pallets/admin-utils/src/lib.rs @@ -527,8 +527,8 @@ pub mod pallet { /// It is only callable by the root account and subnet owner. /// The extrinsic will call the Subtensor pallet to set the maximum allowed UIDs for a subnet. #[pallet::call_index(15)] - #[pallet::weight(Weight::from_parts(18_800_000, 0) - .saturating_add(::DbWeight::get().reads(2_u64)) + #[pallet::weight(Weight::from_parts(32_140_000, 0) + .saturating_add(::DbWeight::get().reads(5_u64)) .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_max_allowed_uids( origin: OriginFor, @@ -837,7 +837,7 @@ pub mod pallet { /// It is only callable by the root account or subnet owner. /// The extrinsic will call the Subtensor pallet to set the difficulty. #[pallet::call_index(24)] - #[pallet::weight(Weight::from_parts(26_230_000, 0) + #[pallet::weight(Weight::from_parts(38_500_000, 0) .saturating_add(::DbWeight::get().reads(3_u64)) .saturating_add(::DbWeight::get().writes(1_u64)))] pub fn sudo_set_difficulty( From 05b9ecbdeaf197a51999bce25dfcfe66fc9131fe Mon Sep 17 00:00:00 2001 From: Loris Moulin Date: Tue, 30 Sep 2025 19:29:05 -0300 Subject: [PATCH 5/9] trigger ci From 9e72ab1fa8f5fa27806cff1eecc29453bddef611 Mon Sep 17 00:00:00 2001 From: Loris Moulin Date: Tue, 30 Sep 2025 20:08:34 -0300 Subject: [PATCH 6/9] bump spec version --- runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index e597728a60..aeeb65c7c4 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -223,7 +223,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: 323, + spec_version: 324, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From cc9779df2c10b45153f945a9b56f8b2f12a9ddb3 Mon Sep 17 00:00:00 2001 From: Loris Moulin Date: Tue, 30 Sep 2025 22:12:14 -0300 Subject: [PATCH 7/9] fix evm tests --- evm-tests/src/subtensor.ts | 18 ------------------ .../test/staking.precompile.reward.test.ts | 3 +-- 2 files changed, 1 insertion(+), 20 deletions(-) diff --git a/evm-tests/src/subtensor.ts b/evm-tests/src/subtensor.ts index ab1508e4b4..63a5ef6e8e 100644 --- a/evm-tests/src/subtensor.ts +++ b/evm-tests/src/subtensor.ts @@ -233,24 +233,6 @@ export async function setActivityCutoff(api: TypedApi, netuid: nu assert.equal(activityCutoff, await api.query.SubtensorModule.ActivityCutoff.getValue(netuid)) } -export async function setMaxAllowedUids(api: TypedApi, netuid: number, maxAllowedUids: number) { - const value = await api.query.SubtensorModule.MaxAllowedUids.getValue(netuid) - if (value === maxAllowedUids) { - return; - } - - const alice = getAliceSigner() - - const internalCall = api.tx.AdminUtils.sudo_set_max_allowed_uids({ - netuid: netuid, - max_allowed_uids: maxAllowedUids - }) - const tx = api.tx.Sudo.sudo({ call: internalCall.decodedCall }) - - await waitForTransactionWithRetry(api, tx, alice) - assert.equal(maxAllowedUids, await api.query.SubtensorModule.MaxAllowedUids.getValue(netuid)) -} - export async function setMinDelegateTake(api: TypedApi, minDelegateTake: number) { const value = await api.query.SubtensorModule.MinDelegateTake.getValue() if (value === minDelegateTake) { diff --git a/evm-tests/test/staking.precompile.reward.test.ts b/evm-tests/test/staking.precompile.reward.test.ts index 251fb41ea5..55a1312313 100644 --- a/evm-tests/test/staking.precompile.reward.test.ts +++ b/evm-tests/test/staking.precompile.reward.test.ts @@ -6,7 +6,7 @@ import { convertPublicKeyToSs58 } from "../src/address-utils" import { tao } from "../src/balance-math" import { forceSetBalanceToSs58Address, addNewSubnetwork, burnedRegister, - setTxRateLimit, setTempo, setWeightsSetRateLimit, setSubnetOwnerCut, setMaxAllowedUids, + setTxRateLimit, setTempo, setWeightsSetRateLimit, setSubnetOwnerCut, setMinDelegateTake, setActivityCutoff, addStake, setWeight, rootRegister, startCall, disableAdminFreezeWindowAndOwnerHyperparamRateLimit @@ -52,7 +52,6 @@ describe("Test neuron precompile reward", () => { await burnedRegister(api, netuid, convertPublicKeyToSs58(nominator.publicKey), coldkey) await setSubnetOwnerCut(api, 0) await setActivityCutoff(api, netuid, 65535) - await setMaxAllowedUids(api, netuid, 65535) await setMinDelegateTake(api, 0) }) From 3b062fb9fe7778159f67dc1bd7835c16ef8e26ff Mon Sep 17 00:00:00 2001 From: Loris Moulin Date: Wed, 1 Oct 2025 10:12:29 -0300 Subject: [PATCH 8/9] uniformize to <= --- pallets/admin-utils/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pallets/admin-utils/src/lib.rs b/pallets/admin-utils/src/lib.rs index 0adfec4fe8..7d8a97ba98 100644 --- a/pallets/admin-utils/src/lib.rs +++ b/pallets/admin-utils/src/lib.rs @@ -545,11 +545,11 @@ pub mod pallet { Error::::SubnetDoesNotExist ); ensure!( - max_allowed_uids > pallet_subtensor::Pallet::::get_min_allowed_uids(netuid), + max_allowed_uids >= pallet_subtensor::Pallet::::get_min_allowed_uids(netuid), Error::::MaxAllowedUidsLessThanMinAllowedUids ); ensure!( - pallet_subtensor::Pallet::::get_subnetwork_n(netuid) < max_allowed_uids, + pallet_subtensor::Pallet::::get_subnetwork_n(netuid) <= max_allowed_uids, Error::::MaxAllowedUIdsLessThanCurrentUIds ); ensure!( From 45ecced6adcb4b86eb4567024e49dfb82633f9b9 Mon Sep 17 00:00:00 2001 From: Loris Moulin Date: Wed, 1 Oct 2025 10:33:30 -0300 Subject: [PATCH 9/9] fix test for sudo_set_max_allowed_uids --- pallets/admin-utils/src/tests/mod.rs | 34 ++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/pallets/admin-utils/src/tests/mod.rs b/pallets/admin-utils/src/tests/mod.rs index 80b9cd47cb..4e534c3210 100644 --- a/pallets/admin-utils/src/tests/mod.rs +++ b/pallets/admin-utils/src/tests/mod.rs @@ -580,6 +580,40 @@ fn test_sudo_set_max_allowed_uids() { to_be_set )); assert_eq!(SubtensorModule::get_max_allowed_uids(netuid), to_be_set); + + // Exact current case + assert_ok!(AdminUtils::sudo_set_max_allowed_uids( + <::RuntimeOrigin>::root(), + netuid, + SubtensorModule::get_subnetwork_n(netuid) + )); + assert_eq!( + SubtensorModule::get_max_allowed_uids(netuid), + SubtensorModule::get_subnetwork_n(netuid) + ); + + // Lower bound case + SubtensorModule::set_min_allowed_uids(netuid, SubtensorModule::get_subnetwork_n(netuid)); + assert_ok!(AdminUtils::sudo_set_max_allowed_uids( + <::RuntimeOrigin>::root(), + netuid, + SubtensorModule::get_min_allowed_uids(netuid) + )); + assert_eq!( + SubtensorModule::get_max_allowed_uids(netuid), + SubtensorModule::get_min_allowed_uids(netuid) + ); + + // Upper bound case + assert_ok!(AdminUtils::sudo_set_max_allowed_uids( + <::RuntimeOrigin>::root(), + netuid, + DefaultMaxAllowedUids::::get(), + )); + assert_eq!( + SubtensorModule::get_max_allowed_uids(netuid), + DefaultMaxAllowedUids::::get() + ); }); }