Skip to content
Open
18 changes: 18 additions & 0 deletions pallets/admin-utils/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -627,5 +627,23 @@ mod benchmarks {
_(RawOrigin::Root, 1u16.into()/*netuid*/, 256u16/*max_n*/)/*sudo_trim_to_max_allowed_uids()*/;
}

#[benchmark]
fn sudo_set_min_non_immune_uids() {
// disable admin freeze window
pallet_subtensor::Pallet::<T>::set_admin_freeze_window(0);
// create a network for netuid = 1
pallet_subtensor::Pallet::<T>::init_new_network(
1u16.into(), /* netuid */
1u16, /* sudo_tempo */
);

#[extrinsic_call]
_(
RawOrigin::Root,
1u16.into(), /* netuid */
12u16, /* min */
); /* sudo_set_min_non_immune_uids() */
}

//impl_benchmark_test_suite!(AdminUtils, crate::mock::new_test_ext(), crate::mock::Test);
}
19 changes: 19 additions & 0 deletions pallets/admin-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2213,6 +2213,25 @@ pub mod pallet {
log::debug!("set_tao_flow_smoothing_factor( {smoothing_factor:?} ) ");
Ok(())
}

/// Sets the minimum number of non-immortal & non-immune UIDs that must remain in a subnet
#[pallet::call_index(84)]
#[pallet::weight((
Weight::from_parts(7_114_000, 0)
.saturating_add(<T as frame_system::Config>::DbWeight::get().writes(1))
.saturating_add(<T as frame_system::Config>::DbWeight::get().reads(0_u64)),
DispatchClass::Operational,
Pays::Yes
))]
pub fn sudo_set_min_non_immune_uids(
origin: OriginFor<T>,
netuid: NetUid,
min: u16,
) -> DispatchResult {
ensure_root(origin)?;
pallet_subtensor::Pallet::<T>::set_min_non_immune_uids(netuid, min);
Ok(())
}
}
}

Expand Down
36 changes: 29 additions & 7 deletions pallets/admin-utils/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2456,7 +2456,7 @@ fn test_trim_to_max_allowed_uids() {
register_ok_neuron(netuid, U256::from(n), U256::from(n + i), 0);
}

// Run some block to ensure stake weights are set and that we are past the immunity period
// Run some blocks to ensure stake weights are set and that we are past the immunity period
// for all neurons
run_to_block((ImmunityPeriod::<Test>::get(netuid) + 1).into());

Expand All @@ -2479,6 +2479,8 @@ fn test_trim_to_max_allowed_uids() {
let u64_values: Vec<u64> = values.iter().map(|&v| v as u64).collect();

Emission::<Test>::set(netuid, alpha_values);
// NOTE: `Rank`, `Trust`, and `PruningScores` are *not* trimmed anymore,
// but we can still populate them without asserting on them.
Rank::<Test>::insert(netuid, values.clone());
Trust::<Test>::insert(netuid, values.clone());
Consensus::<Test>::insert(netuid, values.clone());
Expand Down Expand Up @@ -2566,7 +2568,7 @@ fn test_trim_to_max_allowed_uids() {
assert_eq!(MaxAllowedUids::<Test>::get(netuid), new_max_n);

// Ensure the emission has been trimmed correctly, keeping the highest emitters
// and immune and compressed to the left
// (after respecting immunity/owner exclusions) and compressed to the left
assert_eq!(
Emission::<Test>::get(netuid),
vec![
Expand All @@ -2580,16 +2582,16 @@ fn test_trim_to_max_allowed_uids() {
74.into()
]
);
// Ensure rest of storage has been trimmed correctly

// Ensure rest of (active) storage has been trimmed correctly
let expected_values = vec![56, 91, 34, 77, 65, 88, 51, 74];
let expected_bools = vec![true, true, true, true, true, true, true, true];
let expected_u64_values = vec![56, 91, 34, 77, 65, 88, 51, 74];
assert_eq!(Rank::<Test>::get(netuid), expected_values);
assert_eq!(Trust::<Test>::get(netuid), expected_values);

// NOTE: Rank/Trust/PruningScores are no longer trimmed; do not assert on them.
assert_eq!(Active::<Test>::get(netuid), expected_bools);
assert_eq!(Consensus::<Test>::get(netuid), expected_values);
assert_eq!(Dividends::<Test>::get(netuid), expected_values);
assert_eq!(PruningScores::<Test>::get(netuid), expected_values);
assert_eq!(ValidatorTrust::<Test>::get(netuid), expected_values);
assert_eq!(ValidatorPermit::<Test>::get(netuid), expected_bools);
assert_eq!(StakeWeight::<Test>::get(netuid), expected_values);
Expand Down Expand Up @@ -2669,7 +2671,7 @@ fn test_trim_to_max_allowed_uids() {
assert_eq!(uid, Some(i));
}

// EVM association have been remapped correctly (uids: 7 -> 2, 14 -> 7)
// EVM association have been remapped correctly (uids: 6 -> 2, 14 -> 7)
assert_eq!(
AssociatedEvmAddress::<Test>::get(netuid, 2),
Some((sp_core::H160::from_slice(b"12345678901234567891"), now))
Expand Down Expand Up @@ -2865,3 +2867,23 @@ fn test_sudo_set_min_allowed_uids() {
);
});
}

#[test]
fn test_sudo_set_min_non_immune_uids() {
new_test_ext().execute_with(|| {
let netuid = NetUid::from(1);
add_network(netuid, 10);

let to_be_set: u16 = 12;
let init_value: u16 = SubtensorModule::get_min_non_immune_uids(netuid);

assert_ok!(AdminUtils::sudo_set_min_non_immune_uids(
<<Test as Config>::RuntimeOrigin>::root(),
netuid,
to_be_set
));

assert!(init_value != to_be_set);
assert_eq!(SubtensorModule::get_min_non_immune_uids(netuid), to_be_set);
});
}
59 changes: 0 additions & 59 deletions pallets/subtensor/src/epoch/run_epoch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,7 @@ pub struct EpochTerms {
pub stake_weight: u16,
pub active: bool,
pub emission: AlphaCurrency,
pub rank: u16,
pub trust: u16,
pub consensus: u16,
pub pruning_score: u16,
pub validator_trust: u16,
pub new_validator_permit: bool,
pub bond: Vec<(u16, u16)>,
Expand Down Expand Up @@ -128,22 +125,16 @@ impl<T: Config> Pallet<T> {

let active = extract_from_sorted_terms!(terms_sorted, active);
let emission = extract_from_sorted_terms!(terms_sorted, emission);
let rank = extract_from_sorted_terms!(terms_sorted, rank);
let trust = extract_from_sorted_terms!(terms_sorted, trust);
let consensus = extract_from_sorted_terms!(terms_sorted, consensus);
let dividend = extract_from_sorted_terms!(terms_sorted, dividend);
let pruning_score = extract_from_sorted_terms!(terms_sorted, pruning_score);
let validator_trust = extract_from_sorted_terms!(terms_sorted, validator_trust);
let new_validator_permit = extract_from_sorted_terms!(terms_sorted, new_validator_permit);
let stake_weight = extract_from_sorted_terms!(terms_sorted, stake_weight);

Active::<T>::insert(netuid, active.clone());
Emission::<T>::insert(netuid, emission);
Rank::<T>::insert(netuid, rank);
Trust::<T>::insert(netuid, trust);
Consensus::<T>::insert(netuid, consensus);
Dividends::<T>::insert(netuid, dividend);
PruningScores::<T>::insert(netuid, pruning_score);
ValidatorTrust::<T>::insert(netuid, validator_trust);
ValidatorPermit::<T>::insert(netuid, new_validator_permit);
StakeWeight::<T>::insert(netuid, stake_weight);
Expand Down Expand Up @@ -325,9 +316,6 @@ impl<T: Config> Pallet<T> {
// == Consensus, Validator Trust ==
// ================================

// Compute preranks: r_j = SUM(i) w_ij * s_i
let preranks: Vec<I32F32> = matmul(&weights, &active_stake);

// Consensus majority ratio, e.g. 51%.
let kappa: I32F32 = Self::get_float_kappa(netuid);
// Calculate consensus as stake-weighted median of weights.
Expand All @@ -345,9 +333,6 @@ impl<T: Config> Pallet<T> {
// Compute ranks: r_j = SUM(i) w_ij * s_i
let mut ranks: Vec<I32F32> = matmul(&clipped_weights, &active_stake);

// Compute server trust: ratio of rank after vs. rank before.
let trust: Vec<I32F32> = vecdiv(&ranks, &preranks);

inplace_normalize(&mut ranks);
let incentive: Vec<I32F32> = ranks.clone();
log::trace!("I: {:?}", &incentive);
Expand Down Expand Up @@ -494,10 +479,6 @@ impl<T: Config> Pallet<T> {
log::trace!("nCE: {:?}", &normalized_combined_emission);
log::trace!("CE: {:?}", &combined_emission);

// Set pruning scores using combined emission scores.
let pruning_scores: Vec<I32F32> = normalized_combined_emission.clone();
log::trace!("P: {:?}", &pruning_scores);

// ===================
// == Value storage ==
// ===================
Expand All @@ -506,14 +487,6 @@ impl<T: Config> Pallet<T> {
.iter()
.map(|xi| fixed_proportion_to_u16(*xi))
.collect::<Vec<u16>>();
let cloned_ranks: Vec<u16> = ranks
.iter()
.map(|xi| fixed_proportion_to_u16(*xi))
.collect::<Vec<u16>>();
let cloned_trust: Vec<u16> = trust
.iter()
.map(|xi| fixed_proportion_to_u16(*xi))
.collect::<Vec<u16>>();
let cloned_consensus: Vec<u16> = consensus
.iter()
.map(|xi| fixed_proportion_to_u16(*xi))
Expand All @@ -526,20 +499,16 @@ impl<T: Config> Pallet<T> {
.iter()
.map(|xi| fixed_proportion_to_u16(*xi))
.collect::<Vec<u16>>();
let cloned_pruning_scores: Vec<u16> = vec_max_upscale_to_u16(&pruning_scores);
let cloned_validator_trust: Vec<u16> = validator_trust
.iter()
.map(|xi| fixed_proportion_to_u16(*xi))
.collect::<Vec<u16>>();
StakeWeight::<T>::insert(netuid, cloned_stake_weight.clone());
Active::<T>::insert(netuid, active.clone());
Emission::<T>::insert(netuid, cloned_emission);
Rank::<T>::insert(netuid, cloned_ranks);
Trust::<T>::insert(netuid, cloned_trust);
Consensus::<T>::insert(netuid, cloned_consensus);
Incentive::<T>::insert(NetUidStorageIndex::from(netuid), cloned_incentive);
Dividends::<T>::insert(netuid, cloned_dividends);
PruningScores::<T>::insert(netuid, cloned_pruning_scores);
ValidatorTrust::<T>::insert(netuid, cloned_validator_trust);
ValidatorPermit::<T>::insert(netuid, new_validator_permits.clone());

Expand Down Expand Up @@ -790,10 +759,6 @@ impl<T: Config> Pallet<T> {
// == Consensus, Validator Trust ==
// ================================

// Compute preranks: r_j = SUM(i) w_ij * s_i
let preranks: Vec<I32F32> = matmul_sparse(&weights, &active_stake, n);
log::trace!("Ranks (before): {:?}", &preranks);

// Consensus majority ratio, e.g. 51%.
let kappa: I32F32 = Self::get_float_kappa(netuid);
// Calculate consensus as stake-weighted median of weights.
Expand All @@ -814,11 +779,6 @@ impl<T: Config> Pallet<T> {

// Compute ranks: r_j = SUM(i) w_ij * s_i.
let mut ranks: Vec<I32F32> = matmul_sparse(&clipped_weights, &active_stake, n);
log::trace!("Ranks (after): {:?}", &ranks);

// Compute server trust: ratio of rank after vs. rank before.
let trust: Vec<I32F32> = vecdiv(&ranks, &preranks); // range: I32F32(0, 1)
log::trace!("Trust: {:?}", &trust);

inplace_normalize(&mut ranks); // range: I32F32(0, 1)
let incentive: Vec<I32F32> = ranks.clone();
Expand Down Expand Up @@ -1004,10 +964,6 @@ impl<T: Config> Pallet<T> {
);
log::trace!("Combined Emission: {:?}", &combined_emission);

// Set pruning scores using combined emission scores.
let pruning_scores: Vec<I32F32> = normalized_combined_emission.clone();
log::trace!("Pruning Scores: {:?}", &pruning_scores);

// ===========================
// == Populate epoch output ==
// ===========================
Expand All @@ -1016,14 +972,6 @@ impl<T: Config> Pallet<T> {
.map(|xi| fixed_proportion_to_u16(*xi))
.collect::<Vec<u16>>();
let cloned_emission = combined_emission.clone();
let cloned_ranks: Vec<u16> = ranks
.iter()
.map(|xi| fixed_proportion_to_u16(*xi))
.collect::<Vec<u16>>();
let cloned_trust: Vec<u16> = trust
.iter()
.map(|xi| fixed_proportion_to_u16(*xi))
.collect::<Vec<u16>>();
let cloned_consensus: Vec<u16> = consensus
.iter()
.map(|xi| fixed_proportion_to_u16(*xi))
Expand All @@ -1036,7 +984,6 @@ impl<T: Config> Pallet<T> {
.iter()
.map(|xi| fixed_proportion_to_u16(*xi))
.collect::<Vec<u16>>();
let cloned_pruning_scores: Vec<u16> = vec_max_upscale_to_u16(&pruning_scores);
let cloned_validator_trust: Vec<u16> = validator_trust
.iter()
.map(|xi| fixed_proportion_to_u16(*xi))
Expand All @@ -1056,13 +1003,7 @@ impl<T: Config> Pallet<T> {
.unwrap_or_default();
terms.active = active.get(terms.uid).copied().unwrap_or_default();
terms.emission = cloned_emission.get(terms.uid).copied().unwrap_or_default();
terms.rank = cloned_ranks.get(terms.uid).copied().unwrap_or_default();
terms.trust = cloned_trust.get(terms.uid).copied().unwrap_or_default();
terms.consensus = cloned_consensus.get(terms.uid).copied().unwrap_or_default();
terms.pruning_score = cloned_pruning_scores
.get(terms.uid)
.copied()
.unwrap_or_default();
terms.validator_trust = cloned_validator_trust
.get(terms.uid)
.copied()
Expand Down
11 changes: 11 additions & 0 deletions pallets/subtensor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -972,6 +972,12 @@ pub mod pallet {
128
}

/// Default value for MinNonImmuneUids.
#[pallet::type_value]
pub fn DefaultMinNonImmuneUids<T: Config>() -> u16 {
10u16
}

#[pallet::storage]
pub type MinActivityCutoff<T: Config> =
StorageValue<_, u16, ValueQuery, DefaultMinActivityCutoff<T>>;
Expand Down Expand Up @@ -2031,6 +2037,11 @@ pub mod pallet {
pub type NetworkRegistrationStartBlock<T> =
StorageValue<_, u64, ValueQuery, DefaultNetworkRegistrationStartBlock<T>>;

#[pallet::storage]
/// --- MAP ( netuid ) --> minimum required number of non-immortal & non-immune UIDs
pub type MinNonImmuneUids<T: Config> =
StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultMinNonImmuneUids<T>>;

/// ============================
/// ==== Subnet Mechanisms =====
/// ============================
Expand Down
20 changes: 10 additions & 10 deletions pallets/subtensor/src/macros/dispatches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1016,8 +1016,8 @@ mod dispatches {
///
#[pallet::call_index(6)]
#[pallet::weight((Weight::from_parts(197_900_000, 0)
.saturating_add(T::DbWeight::get().reads(27_u64))
.saturating_add(T::DbWeight::get().writes(23)), DispatchClass::Normal, Pays::Yes))]
.saturating_add(T::DbWeight::get().reads(24_u64))
.saturating_add(T::DbWeight::get().writes(20_u64)), DispatchClass::Normal, Pays::Yes))]
pub fn register(
origin: OriginFor<T>,
netuid: NetUid,
Expand All @@ -1033,17 +1033,17 @@ mod dispatches {
/// Register the hotkey to root network
#[pallet::call_index(62)]
#[pallet::weight((Weight::from_parts(135_900_000, 0)
.saturating_add(T::DbWeight::get().reads(22_u64))
.saturating_add(T::DbWeight::get().writes(19_u64)), DispatchClass::Normal, Pays::Yes))]
.saturating_add(T::DbWeight::get().reads(19_u64))
.saturating_add(T::DbWeight::get().writes(16_u64)), DispatchClass::Normal, Pays::Yes))]
pub fn root_register(origin: OriginFor<T>, hotkey: T::AccountId) -> DispatchResult {
Self::do_root_register(origin, hotkey)
}

/// User register a new subnetwork via burning token
#[pallet::call_index(7)]
#[pallet::weight((Weight::from_parts(354_200_000, 0)
.saturating_add(T::DbWeight::get().reads(50_u64))
.saturating_add(T::DbWeight::get().writes(43)), DispatchClass::Normal, Pays::Yes))]
.saturating_add(T::DbWeight::get().reads(47_u64))
.saturating_add(T::DbWeight::get().writes(40_u64)), DispatchClass::Normal, Pays::Yes))]
pub fn burned_register(
origin: OriginFor<T>,
netuid: NetUid,
Expand Down Expand Up @@ -1230,8 +1230,8 @@ mod dispatches {
/// User register a new subnetwork
#[pallet::call_index(59)]
#[pallet::weight((Weight::from_parts(235_400_000, 0)
.saturating_add(T::DbWeight::get().reads(39_u64))
.saturating_add(T::DbWeight::get().writes(56_u64)), DispatchClass::Normal, Pays::Yes))]
.saturating_add(T::DbWeight::get().reads(36_u64))
.saturating_add(T::DbWeight::get().writes(53_u64)), DispatchClass::Normal, Pays::Yes))]
pub fn register_network(origin: OriginFor<T>, hotkey: T::AccountId) -> DispatchResult {
Self::do_register_network(origin, &hotkey, 1, None)
}
Expand Down Expand Up @@ -1517,8 +1517,8 @@ mod dispatches {
/// User register a new subnetwork
#[pallet::call_index(79)]
#[pallet::weight((Weight::from_parts(234_200_000, 0)
.saturating_add(T::DbWeight::get().reads(38_u64))
.saturating_add(T::DbWeight::get().writes(55_u64)), DispatchClass::Normal, Pays::Yes))]
.saturating_add(T::DbWeight::get().reads(35_u64))
.saturating_add(T::DbWeight::get().writes(52_u64)), DispatchClass::Normal, Pays::Yes))]
pub fn register_network_with_identity(
origin: OriginFor<T>,
hotkey: T::AccountId,
Expand Down
2 changes: 2 additions & 0 deletions pallets/subtensor/src/macros/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,8 @@ mod events {
hotkey: T::AccountId,
},

/// The minimum allowed non-Immune UIDs has been set.
MinNonImmuneUidsSet(NetUid, u16),
/// Root emissions have been claimed for a coldkey on all subnets and hotkeys.
/// Parameters:
/// (coldkey)
Expand Down
Loading