Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
da23e43
Make max number of subnet mechanisms configurable
gztensor Nov 5, 2025
7f1a809
Spec bump
gztensor Nov 5, 2025
33a4192
Merge branch 'devnet-ready' into feat/settable-max-mech-count
gztensor Nov 12, 2025
a6da90e
Add enforcing the mechanism count vs. max uids limit
gztensor Nov 12, 2025
819fa76
Merge branch 'devnet-ready' into feat/settable-max-mech-count
gztensor Nov 12, 2025
d17f6f6
Fix merge issues
gztensor Nov 12, 2025
6a560fa
Merge remote-tracking branch 'origin/devnet-ready' into feat/settable…
sam0x17 Nov 12, 2025
55444a7
Merge branch 'devnet-ready' into feat/settable-max-mech-count
gztensor Nov 13, 2025
469bfb0
Merge branch 'devnet-ready' into feat/settable-max-mech-count
l0r1s Nov 17, 2025
33cbc8b
fix + tests
l0r1s Nov 17, 2025
045d123
DefaultMaxAllowedUids from 4096 to 256
l0r1s Nov 17, 2025
185b97a
Merge branch 'devnet-ready' into feat/settable-max-mech-count
l0r1s Nov 17, 2025
5b54733
fix clippy
l0r1s Nov 17, 2025
3832d59
remove magic number
l0r1s Nov 17, 2025
20a60ff
Merge branch 'feat/settable-max-mech-count' of github.com:opentensor/…
gztensor Dec 16, 2025
ceafcb6
Merge branch 'devnet-ready' into feat/settable-max-mech-count
gztensor Dec 16, 2025
79d697b
Fix tests
gztensor Dec 16, 2025
b826b2a
Merge branch 'devnet-ready' into feat/settable-max-mech-count
gztensor Jan 19, 2026
a512875
Fix extrinsic index
gztensor Jan 19, 2026
92c59b1
Merge branch 'devnet-ready' into feat/settable-max-mech-count
gztensor Jan 28, 2026
01c12d3
Spec bump
gztensor Jan 28, 2026
0d2e46a
Merge branch 'devnet-ready' into feat/settable-max-mech-count
gztensor Feb 2, 2026
18035dc
Spec bump
gztensor Feb 2, 2026
6b523e5
Merge branch 'devnet-ready' into feat/settable-max-mech-count
gztensor Feb 3, 2026
119d64b
Fix try-runtime build
gztensor Feb 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions pallets/admin-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,12 @@ pub mod pallet {
max_allowed_uids <= DefaultMaxAllowedUids::<T>::get(),
Error::<T>::MaxAllowedUidsGreaterThanDefaultMaxAllowedUids
);
// Prevent chain bloat: Require max UIDs to be limited
let mechanism_count = pallet_subtensor::MechanismCountCurrent::<T>::get(netuid);
pallet_subtensor::Pallet::<T>::ensure_max_uids_over_all_mechanisms(
max_allowed_uids,
mechanism_count.into(),
)?;
pallet_subtensor::Pallet::<T>::set_max_allowed_uids(netuid, max_allowed_uids);
pallet_subtensor::Pallet::<T>::record_owner_rl(
maybe_owner,
Expand Down Expand Up @@ -2188,6 +2194,20 @@ pub mod pallet {
Ok(())
}

/// Sets the global maximum number of mechanisms in a subnet
#[pallet::call_index(88)]
#[pallet::weight(Weight::from_parts(15_000_000, 0)
.saturating_add(<T as frame_system::Config>::DbWeight::get().reads(1_u64))
.saturating_add(<T as frame_system::Config>::DbWeight::get().writes(1_u64)))]
pub fn sudo_set_max_mechanism_count(
origin: OriginFor<T>,
max_mechanism_count: MechId,
) -> DispatchResult {
ensure_root(origin)?;
pallet_subtensor::Pallet::<T>::do_set_max_mechanism_count(max_mechanism_count)?;
Ok(())
}

/// Sets the minimum number of non-immortal & non-immune UIDs that must remain in a subnet
#[pallet::call_index(84)]
#[pallet::weight((
Expand Down
2 changes: 1 addition & 1 deletion pallets/admin-utils/src/tests/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ parameter_types! {
pub const SelfOwnership: u64 = 2;
pub const InitialImmunityPeriod: u16 = 2;
pub const InitialMinAllowedUids: u16 = 2;
pub const InitialMaxAllowedUids: u16 = 16;
pub const InitialMaxAllowedUids: u16 = 256;
pub const InitialBondsMovingAverage: u64 = 900_000;
pub const InitialBondsPenalty: u16 = u16::MAX;
pub const InitialBondsResetOn: bool = false;
Expand Down
57 changes: 56 additions & 1 deletion pallets/admin-utils/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ use pallet_subtensor::{
TargetRegistrationsPerInterval, Tempo, WeightsVersionKeyRateLimit, *,
};
// use pallet_subtensor::{migrations, Event};
use pallet_subtensor::{Event, utils::rate_limiting::TransactionType};
use pallet_subtensor::{
Event, subnets::mechanism::MAX_MECHANISM_COUNT_PER_SUBNET,
utils::rate_limiting::TransactionType,
};
use sp_consensus_grandpa::AuthorityId as GrandpaId;
use sp_core::{Get, Pair, U256, ed25519};
use substrate_fixed::types::I96F32;
Expand Down Expand Up @@ -540,6 +543,20 @@ fn test_sudo_set_max_allowed_uids() {
Error::<Test>::MaxAllowedUidsGreaterThanDefaultMaxAllowedUids
);

// Trying to set max allowed uids that would cause max_allowed_uids * mechanism_count > 256
MaxAllowedUids::<Test>::insert(netuid, 8);
MechanismCountCurrent::<Test>::insert(netuid, MechId::from(32));
let large_max_uids = 16;
assert_noop!(
AdminUtils::sudo_set_max_allowed_uids(
<<Test as Config>::RuntimeOrigin>::root(),
netuid,
large_max_uids
),
SubtensorError::<Test>::TooManyUIDsPerMechanism
);
MechanismCountCurrent::<Test>::insert(netuid, MechId::from(1));

// Normal case
assert_ok!(AdminUtils::sudo_set_max_allowed_uids(
<<Test as Config>::RuntimeOrigin>::root(),
Expand Down Expand Up @@ -2376,6 +2393,7 @@ fn test_sudo_set_mechanism_count() {
add_network(netuid, 10);
// Set the Subnet Owner
SubnetOwner::<Test>::insert(netuid, sn_owner);
MaxAllowedUids::<Test>::insert(netuid, 256_u16);

assert_eq!(
AdminUtils::sudo_set_mechanism_count(
Expand All @@ -2389,7 +2407,13 @@ fn test_sudo_set_mechanism_count() {
AdminUtils::sudo_set_mechanism_count(RuntimeOrigin::root(), netuid, ss_count_bad),
pallet_subtensor::Error::<Test>::InvalidValue
);
assert_noop!(
AdminUtils::sudo_set_mechanism_count(RuntimeOrigin::root(), netuid, ss_count_ok),
pallet_subtensor::Error::<Test>::TooManyUIDsPerMechanism
);

// Reduce max UIDs to 128
MaxAllowedUids::<Test>::insert(netuid, 128_u16);
assert_ok!(AdminUtils::sudo_set_mechanism_count(
<<Test as Config>::RuntimeOrigin>::root(),
netuid,
Expand All @@ -2415,6 +2439,8 @@ fn test_sudo_set_mechanism_count_and_emissions() {
add_network(netuid, 10);
// Set the Subnet Owner
SubnetOwner::<Test>::insert(netuid, sn_owner);
MaxMechanismCount::<Test>::set(MechId::from(2));
MaxAllowedUids::<Test>::set(netuid, 128_u16);

assert_ok!(AdminUtils::sudo_set_mechanism_count(
<<Test as Config>::RuntimeOrigin>::signed(sn_owner),
Expand Down Expand Up @@ -2903,6 +2929,35 @@ fn test_sudo_set_min_allowed_uids() {
});
}

#[test]
fn test_sudo_set_max_mechanism_count() {
new_test_ext().execute_with(|| {
// Normal case
assert_ok!(AdminUtils::sudo_set_max_mechanism_count(
<<Test as Config>::RuntimeOrigin>::root(),
MechId::from(10)
));

// Zero fails
assert_noop!(
AdminUtils::sudo_set_max_mechanism_count(
<<Test as Config>::RuntimeOrigin>::root(),
MechId::from(0)
),
pallet_subtensor::Error::<Test>::InvalidValue
);

// Over max bound fails
assert_noop!(
AdminUtils::sudo_set_max_mechanism_count(
<<Test as Config>::RuntimeOrigin>::root(),
MechId::from(MAX_MECHANISM_COUNT_PER_SUBNET + 1)
),
pallet_subtensor::Error::<Test>::InvalidValue
);
});
}

#[test]
fn test_sudo_set_min_non_immune_uids() {
new_test_ext().execute_with(|| {
Expand Down
9 changes: 7 additions & 2 deletions pallets/subtensor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2367,12 +2367,17 @@ pub mod pallet {
MechId::from(1)
}

/// -- ITEM (Maximum number of sub-subnets)
/// -- ITEM (Maximum number of mechanisms)
#[pallet::type_value]
pub fn MaxMechanismCount<T: Config>() -> MechId {
pub fn DefaultMaxMechanismCount<T: Config>() -> MechId {
MechId::from(2)
}

/// ITEM( max_mechanism_count )
#[pallet::storage]
pub type MaxMechanismCount<T> =
StorageValue<_, MechId, ValueQuery, DefaultMaxMechanismCount<T>>;

/// -- ITEM (Rate limit for mechanism count updates)
#[pallet::type_value]
pub fn MechanismCountSetRateLimit<T: Config>() -> u64 {
Expand Down
2 changes: 2 additions & 0 deletions pallets/subtensor/src/macros/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,8 @@ mod errors {
InvalidRootClaimThreshold,
/// Exceeded subnet limit number or zero.
InvalidSubnetNumber,
/// The maximum allowed UIDs times mechanism count should not exceed 256.
TooManyUIDsPerMechanism,
/// Voting power tracking is not enabled for this subnet.
VotingPowerTrackingNotEnabled,
/// Invalid voting power EMA alpha value (must be <= 10^18).
Expand Down
35 changes: 34 additions & 1 deletion pallets/subtensor/src/subnets/mechanism.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,20 @@ impl<T: Config> Pallet<T> {
Ok(())
}

/// Set the desired valus of sub-subnet count for a subnet identified
pub fn ensure_max_uids_over_all_mechanisms(
max_uids: u16,
mechanism_count: MechId,
) -> DispatchResult {
let max_uids_over_all_mechanisms =
max_uids.saturating_mul(u8::from(mechanism_count) as u16);
ensure!(
max_uids_over_all_mechanisms <= DefaultMaxAllowedUids::<T>::get(),
Error::<T>::TooManyUIDsPerMechanism
);
Ok(())
}

/// Set the desired value of mechanism count for a subnet identified
/// by netuid
pub fn do_set_mechanism_count(netuid: NetUid, mechanism_count: MechId) -> DispatchResult {
// Make sure the subnet exists
Expand All @@ -113,6 +126,10 @@ impl<T: Config> Pallet<T> {
Error::<T>::InvalidValue
);

// Prevent chain bloat: Require max UIDs to be limited
let max_uids = MaxAllowedUids::<T>::get(netuid);
Self::ensure_max_uids_over_all_mechanisms(max_uids, mechanism_count)?;

// Make sure we are not allowing numbers that will break the math
ensure!(
mechanism_count <= MechId::from(MAX_MECHANISM_COUNT_PER_SUBNET),
Expand All @@ -124,6 +141,22 @@ impl<T: Config> Pallet<T> {
Ok(())
}

/// Set the global maximum number of mechanisms per subnet
pub fn do_set_max_mechanism_count(max_mechanism_count: MechId) -> DispatchResult {
// Max count cannot be zero
ensure!(max_mechanism_count > 0.into(), Error::<T>::InvalidValue);

// Make sure we are not allowing numbers that will break the math
ensure!(
max_mechanism_count <= MechId::from(MAX_MECHANISM_COUNT_PER_SUBNET),
Error::<T>::InvalidValue
);

MaxMechanismCount::<T>::set(max_mechanism_count);

Ok(())
}

/// Update current count for a subnet identified by netuid
/// - Cleans up all sub-subnet maps if count is reduced
///
Expand Down
1 change: 1 addition & 0 deletions pallets/subtensor/src/tests/mechanism.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ fn do_set_mechanism_count_ok_at_effective_cap() {
new_test_ext(1).execute_with(|| {
let netuid = NetUid::from(4u16);
NetworksAdded::<Test>::insert(NetUid::from(4u16), true); // base subnet exists
MaxAllowedUids::<Test>::insert(netuid, 128u16);

// Effective bound is min(runtime cap, compile-time cap)
let runtime_cap = MaxMechanismCount::<Test>::get(); // e.g., MechId::from(8)
Expand Down
2 changes: 1 addition & 1 deletion pallets/subtensor/src/tests/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,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 = 256;
pub const InitialBondsMovingAverage: u64 = 900_000;
pub const InitialBondsPenalty:u16 = u16::MAX;
pub const InitialBondsResetOn: bool = false;
Expand Down
4 changes: 2 additions & 2 deletions runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,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: 374,
spec_version: 375,
impl_version: 1,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
Expand Down Expand Up @@ -960,7 +960,7 @@ parameter_types! {
pub const SubtensorInitialRho: u16 = 10;
pub const SubtensorInitialAlphaSigmoidSteepness: i16 = 1000;
pub const SubtensorInitialKappa: u16 = 32_767; // 0.5 = 65535/2
pub const SubtensorInitialMaxAllowedUids: u16 = 4096;
pub const SubtensorInitialMaxAllowedUids: u16 = 256;
pub const SubtensorInitialIssuance: u64 = 0;
pub const SubtensorInitialMinAllowedWeights: u16 = 1024;
pub const SubtensorInitialEmissionValue: u16 = 0;
Expand Down
Loading