Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 43 additions & 7 deletions pallets/admin-utils/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2498,6 +2498,28 @@ fn test_trim_to_max_allowed_uids() {
Keys::<Test>::insert(netuid, 14, sn_owner_hotkey2);
Uids::<Test>::insert(netuid, sn_owner_hotkey2, 14);

// Set some evm addresses
AssociatedEvmAddress::<Test>::insert(
netuid,
6,
(sp_core::H160::from_slice(b"12345678901234567891"), now),
);
AssociatedEvmAddress::<Test>::insert(
netuid,
10,
(sp_core::H160::from_slice(b"12345678901234567892"), now),
);
AssociatedEvmAddress::<Test>::insert(
netuid,
12,
(sp_core::H160::from_slice(b"12345678901234567893"), now),
);
AssociatedEvmAddress::<Test>::insert(
netuid,
14,
(sp_core::H160::from_slice(b"12345678901234567894"), now),
);

// Populate Weights and Bonds storage items to test trimming
// Create weights and bonds that span across the range that will be trimmed
for uid in 0..max_n {
Expand Down Expand Up @@ -2574,6 +2596,7 @@ fn test_trim_to_max_allowed_uids() {
for uid in new_max_n..max_n {
assert!(!Keys::<Test>::contains_key(netuid, uid));
assert!(!BlockAtRegistration::<Test>::contains_key(netuid, uid));
assert!(!AssociatedEvmAddress::<Test>::contains_key(netuid, uid));
for mecid in 0..mechanism_count.into() {
let netuid_index =
SubtensorModule::get_mechanism_storage_index(netuid, MechId::from(mecid));
Expand Down Expand Up @@ -2631,6 +2654,23 @@ fn test_trim_to_max_allowed_uids() {
// Actual number of neurons on the network updated after trimming
assert_eq!(SubnetworkN::<Test>::get(netuid), new_max_n);

// Uids match enumeration order
for i in 0..new_max_n.into() {
let hotkey = Keys::<Test>::get(netuid, i);
let uid = Uids::<Test>::get(netuid, hotkey);
assert_eq!(uid, Some(i));
}

// EVM association have been remapped correctly (uids: 7 -> 2, 14 -> 7)
assert_eq!(
AssociatedEvmAddress::<Test>::get(netuid, 2),
Some((sp_core::H160::from_slice(b"12345678901234567891"), now))
);
assert_eq!(
AssociatedEvmAddress::<Test>::get(netuid, 7),
Some((sp_core::H160::from_slice(b"12345678901234567894"), now))
);

// Non existent subnet
assert_err!(
AdminUtils::sudo_trim_to_max_allowed_uids(
Expand Down Expand Up @@ -2673,7 +2713,7 @@ fn test_trim_to_max_allowed_uids_too_many_immune() {
MaxRegistrationsPerBlock::<Test>::insert(netuid, 256);
TargetRegistrationsPerInterval::<Test>::insert(netuid, 256);
ImmuneOwnerUidsLimit::<Test>::insert(netuid, 2);
MinAllowedUids::<Test>::set(netuid, 4);
MinAllowedUids::<Test>::set(netuid, 2);

// Add 5 neurons
let max_n = 5;
Expand Down Expand Up @@ -2711,7 +2751,7 @@ fn test_trim_to_max_allowed_uids_too_many_immune() {
netuid,
4
),
pallet_subtensor::Error::<Test>::InvalidValue
pallet_subtensor::Error::<Test>::TrimmingWouldExceedMaxImmunePercentage
);

// Try to trim to 3 UIDs - this should also fail because 4/3 > 80% immune (>= 80%)
Expand All @@ -2721,7 +2761,7 @@ fn test_trim_to_max_allowed_uids_too_many_immune() {
netuid,
3
),
pallet_subtensor::Error::<Test>::InvalidValue
pallet_subtensor::Error::<Test>::TrimmingWouldExceedMaxImmunePercentage
);

// Now test a scenario where trimming should succeed
Expand All @@ -2733,10 +2773,6 @@ fn test_trim_to_max_allowed_uids_too_many_immune() {
Uids::<Test>::remove(netuid, hotkey_to_remove);
BlockAtRegistration::<Test>::remove(netuid, uid_to_remove);

// Now we have 3 immune out of 4 total UIDs
// Try to trim to 3 UIDs - this should succeed because 3/3 = 100% immune, but that's exactly 80%
// Wait, 100% is > 80%, so this should fail. Let me test with a scenario where we have fewer immune UIDs

// Remove another immune UID to make it 2 immune out of 3 total
let uid_to_remove2 = 2;
let hotkey_to_remove2 = U256::from(uid_to_remove2 * 1000 + 1000);
Expand Down
4 changes: 4 additions & 0 deletions pallets/subtensor/src/macros/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,5 +256,9 @@ mod errors {
CannotAffordLockCost,
/// exceeded the rate limit for associating an EVM key.
EvmKeyAssociateRateLimitExceeded,
/// The UID map for the subnet could not be cleared
UidMapCouldNotBeCleared,
/// Trimming would exceed the max immune neurons percentage
TrimmingWouldExceedMaxImmunePercentage,
}
}
19 changes: 18 additions & 1 deletion pallets/subtensor/src/subnets/uids.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ impl<T: Config> Pallet<T> {
let immune_percentage = Percent::from_rational(immune_count, max_n);
ensure!(
immune_percentage < T::MaxImmuneUidsPercentage::get(),
Error::<T>::InvalidValue
Error::<T>::TrimmingWouldExceedMaxImmunePercentage
);

// Get all emissions with their UIDs and sort by emission (descending)
Expand Down Expand Up @@ -209,6 +209,7 @@ impl<T: Config> Pallet<T> {
#[allow(unknown_lints)]
Keys::<T>::remove(netuid, neuron_uid);
BlockAtRegistration::<T>::remove(netuid, neuron_uid);
AssociatedEvmAddress::<T>::remove(netuid, neuron_uid);
for mecid in 0..mechanisms_count {
let netuid_index = Self::get_mechanism_storage_index(netuid, mecid.into());
Weights::<T>::remove(netuid_index, neuron_uid);
Expand Down Expand Up @@ -315,6 +316,7 @@ impl<T: Config> Pallet<T> {

// Swap uid specific storage items to new compressed positions
Keys::<T>::swap(netuid, old_neuron_uid, netuid, new_neuron_uid);
AssociatedEvmAddress::<T>::swap(netuid, old_neuron_uid, netuid, new_neuron_uid);
BlockAtRegistration::<T>::swap(netuid, old_neuron_uid, netuid, new_neuron_uid);

for mecid in 0..mechanisms_count {
Expand Down Expand Up @@ -352,6 +354,21 @@ impl<T: Config> Pallet<T> {
}
}

// Clear the UID map for the subnet
let clear_result = Uids::<T>::clear_prefix(netuid, u32::MAX, None);
// Shouldn't happen, but possible.
ensure!(
clear_result.maybe_cursor.is_none(),
Error::<T>::UidMapCouldNotBeCleared
);

// Insert the new UIDs
for new_uid in old_to_new_uid.values() {
// Get the hotkey using Keys map and new UID.
let hotkey = Keys::<T>::get(netuid, *new_uid as u16);
Uids::<T>::insert(netuid, hotkey, *new_uid as u16);
}

// Update the subnet's uid count to reflect the new maximum
SubnetworkN::<T>::insert(netuid, max_n);
}
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading