Skip to content

Commit be221cd

Browse files
committed
add test_registration_pruning
1 parent a8a0546 commit be221cd

File tree

2 files changed

+124
-97
lines changed

2 files changed

+124
-97
lines changed

pallets/subtensor/src/tests/registration.rs

Lines changed: 124 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,82 +1472,6 @@ fn test_registration_get_uid_to_prune_owner_immortality_all_immune() {
14721472
});
14731473
}
14741474

1475-
#[test]
1476-
fn test_registration_pruning() {
1477-
new_test_ext(1).execute_with(|| {
1478-
let netuid = NetUid::from(1);
1479-
let block_number: u64 = 0;
1480-
let tempo: u16 = 13;
1481-
let hotkey_account_id = U256::from(1);
1482-
let coldkey_account_id = U256::from(667);
1483-
let (nonce0, work0): (u64, Vec<u8>) = SubtensorModule::create_work_for_block_number(
1484-
netuid,
1485-
block_number,
1486-
3942084,
1487-
&hotkey_account_id,
1488-
);
1489-
1490-
//add network
1491-
add_network(netuid, tempo, 0);
1492-
1493-
assert_ok!(SubtensorModule::register(
1494-
<<Test as Config>::RuntimeOrigin>::signed(hotkey_account_id),
1495-
netuid,
1496-
block_number,
1497-
nonce0,
1498-
work0,
1499-
hotkey_account_id,
1500-
coldkey_account_id
1501-
));
1502-
//
1503-
let neuron_uid =
1504-
SubtensorModule::get_uid_for_net_and_hotkey(netuid, &hotkey_account_id).unwrap();
1505-
SubtensorModule::set_pruning_score_for_uid(netuid, neuron_uid, 2);
1506-
//
1507-
let hotkey_account_id1 = U256::from(2);
1508-
let coldkey_account_id1 = U256::from(668);
1509-
let (nonce1, work1): (u64, Vec<u8>) = SubtensorModule::create_work_for_block_number(
1510-
netuid,
1511-
block_number,
1512-
11231312312,
1513-
&hotkey_account_id1,
1514-
);
1515-
1516-
assert_ok!(SubtensorModule::register(
1517-
<<Test as Config>::RuntimeOrigin>::signed(hotkey_account_id1),
1518-
netuid,
1519-
block_number,
1520-
nonce1,
1521-
work1,
1522-
hotkey_account_id1,
1523-
coldkey_account_id1
1524-
));
1525-
//
1526-
let neuron_uid1 =
1527-
SubtensorModule::get_uid_for_net_and_hotkey(netuid, &hotkey_account_id1).unwrap();
1528-
SubtensorModule::set_pruning_score_for_uid(netuid, neuron_uid1, 3);
1529-
//
1530-
let hotkey_account_id2 = U256::from(3);
1531-
let coldkey_account_id2 = U256::from(669);
1532-
let (nonce2, work2): (u64, Vec<u8>) = SubtensorModule::create_work_for_block_number(
1533-
netuid,
1534-
block_number,
1535-
212312414,
1536-
&hotkey_account_id2,
1537-
);
1538-
1539-
assert_ok!(SubtensorModule::register(
1540-
<<Test as Config>::RuntimeOrigin>::signed(hotkey_account_id2),
1541-
netuid,
1542-
block_number,
1543-
nonce2,
1544-
work2,
1545-
hotkey_account_id2,
1546-
coldkey_account_id2
1547-
));
1548-
});
1549-
}
1550-
15511475
#[test]
15521476
fn test_registration_get_neuron_metadata() {
15531477
new_test_ext(1).execute_with(|| {
@@ -2238,6 +2162,130 @@ fn test_last_update_correctness() {
22382162
});
22392163
}
22402164

2165+
#[allow(clippy::indexing_slicing)]
2166+
#[test]
2167+
fn test_registration_pruning() {
2168+
new_test_ext(1).execute_with(|| {
2169+
// --- Setup a simple non-root subnet.
2170+
let netuid = NetUid::from(5);
2171+
add_network(netuid, 10_000, 0);
2172+
2173+
// No owner-based immortality: we want to test time-based immunity only.
2174+
ImmuneOwnerUidsLimit::<Test>::insert(netuid, 0);
2175+
2176+
// Allow registrations freely.
2177+
MaxRegistrationsPerBlock::<Test>::insert(netuid, 1024);
2178+
SubtensorModule::set_target_registrations_per_interval(netuid, u16::MAX);
2179+
2180+
// Cap the subnet at 3 UIDs so the 4th registration *must* prune.
2181+
SubtensorModule::set_max_allowed_uids(netuid, 3);
2182+
2183+
// --- Register three neurons (uids 0, 1, 2).
2184+
let coldkeys = [U256::from(20_001), U256::from(20_002), U256::from(20_003)];
2185+
let hotkeys = [U256::from(30_001), U256::from(30_002), U256::from(30_003)];
2186+
2187+
for i in 0..3 {
2188+
register_ok_neuron(netuid, hotkeys[i], coldkeys[i], 0);
2189+
}
2190+
2191+
// Sanity: ensure we got sequential UIDs.
2192+
let uid0 = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &hotkeys[0]).unwrap();
2193+
let uid1 = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &hotkeys[1]).unwrap();
2194+
let uid2 = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &hotkeys[2]).unwrap();
2195+
2196+
assert_eq!(uid0, 0);
2197+
assert_eq!(uid1, 1);
2198+
assert_eq!(uid2, 2);
2199+
assert_eq!(SubtensorModule::get_subnetwork_n(netuid), 3);
2200+
2201+
// --- Craft immunity and tie‑breaking conditions.
2202+
2203+
// Fixed "current" block.
2204+
let now: u64 = 1_000;
2205+
frame_system::Pallet::<Test>::set_block_number(now);
2206+
2207+
// Immunity lasts 100 blocks.
2208+
SubtensorModule::set_immunity_period(netuid, 100);
2209+
2210+
// Registration blocks:
2211+
// - uid0: now - 150 -> non‑immune
2212+
// - uid1: now - 200 -> non‑immune (older than uid0)
2213+
// - uid2: now - 10 -> immune
2214+
BlockAtRegistration::<Test>::insert(netuid, uid0, now - 150);
2215+
BlockAtRegistration::<Test>::insert(netuid, uid1, now - 200);
2216+
BlockAtRegistration::<Test>::insert(netuid, uid2, now - 10);
2217+
2218+
// Check immunity flags: the 3rd neuron is immune, the first two are not.
2219+
assert!(!SubtensorModule::get_neuron_is_immune(netuid, uid0));
2220+
assert!(!SubtensorModule::get_neuron_is_immune(netuid, uid1));
2221+
assert!(SubtensorModule::get_neuron_is_immune(netuid, uid2));
2222+
2223+
// Emissions:
2224+
// - uid0: 10
2225+
// - uid1: 10 (same emission as uid0)
2226+
// - uid2: 1 (better emission, but immune)
2227+
//
2228+
// Among *non‑immune* neurons, emission ties -> break on reg_block:
2229+
// uid1 registered earlier (now-200 < now-150), so uid1 should be pruned.
2230+
// The immune uid2 should **not** be chosen even though it has lower emission.
2231+
Emission::<Test>::mutate(netuid, |v| {
2232+
v[uid0 as usize] = 10u64.into();
2233+
v[uid1 as usize] = 10u64.into();
2234+
v[uid2 as usize] = 1u64.into();
2235+
});
2236+
2237+
// Allow pruning of any non‑immune UID (no safety floor).
2238+
SubtensorModule::set_min_non_immune_uids(netuid, 0);
2239+
2240+
// Check that pruning decision respects:
2241+
// 1. Prefer non‑immune over immune.
2242+
// 2. Then lowest emission.
2243+
// 3. Then earliest registration block.
2244+
// 4. Then uid (not needed here).
2245+
assert_eq!(
2246+
SubtensorModule::get_neuron_to_prune(netuid),
2247+
Some(uid1),
2248+
"Expected pruning to choose the oldest non‑immune neuron \
2249+
when emissions tie, even if an immune neuron has lower emission"
2250+
);
2251+
2252+
// --- Now actually perform a registration that forces pruning.
2253+
2254+
let new_hotkey = U256::from(40_000);
2255+
let new_coldkey = U256::from(50_000);
2256+
2257+
// This should internally call do_burned_registration -> register_neuron,
2258+
// which must reuse the UID returned by get_neuron_to_prune (uid1).
2259+
register_ok_neuron(netuid, new_hotkey, new_coldkey, 0);
2260+
2261+
// Still capped at 3 UIDs.
2262+
assert_eq!(SubtensorModule::get_subnetwork_n(netuid), 3);
2263+
2264+
// Old uid1 hotkey should be gone.
2265+
assert!(
2266+
SubtensorModule::get_uid_for_net_and_hotkey(netuid, &hotkeys[1]).is_err(),
2267+
"Hotkey for pruned UID should no longer be registered"
2268+
);
2269+
2270+
// New hotkey should reuse uid1 (the pruned slot).
2271+
let new_uid = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &new_hotkey).unwrap();
2272+
assert_eq!(
2273+
new_uid, uid1,
2274+
"New registration should reuse the UID selected by get_neuron_to_prune"
2275+
);
2276+
2277+
// The other two original neurons (uid0 and uid2) must remain registered.
2278+
assert_eq!(
2279+
SubtensorModule::get_uid_for_net_and_hotkey(netuid, &hotkeys[0]).unwrap(),
2280+
uid0
2281+
);
2282+
assert_eq!(
2283+
SubtensorModule::get_uid_for_net_and_hotkey(netuid, &hotkeys[2]).unwrap(),
2284+
uid2
2285+
);
2286+
});
2287+
}
2288+
22412289
// #[ignore]
22422290
// #[test]
22432291
// fn test_hotkey_swap_ok() {

pallets/subtensor/src/utils/misc.rs

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -210,27 +210,6 @@ impl<T: Config> Pallet<T> {
210210
*updated_active = active;
211211
Active::<T>::insert(netuid, updated_active_vec);
212212
}
213-
pub fn set_pruning_score_for_uid(netuid: NetUid, uid: u16, pruning_score: u16) {
214-
log::debug!("netuid = {netuid:?}");
215-
log::debug!(
216-
"SubnetworkN::<T>::get( netuid ) = {:?}",
217-
SubnetworkN::<T>::get(netuid)
218-
);
219-
log::debug!("uid = {uid:?}");
220-
if uid < SubnetworkN::<T>::get(netuid) {
221-
PruningScores::<T>::mutate(netuid, |v| {
222-
if let Some(s) = v.get_mut(uid as usize) {
223-
*s = pruning_score;
224-
}
225-
});
226-
} else {
227-
log::error!(
228-
"set_pruning_score_for_uid: uid >= SubnetworkN::<T>::get(netuid): {:?} >= {:?}",
229-
uid,
230-
SubnetworkN::<T>::get(netuid)
231-
);
232-
}
233-
}
234213
pub fn set_validator_permit_for_uid(netuid: NetUid, uid: u16, validator_permit: bool) {
235214
let mut updated_validator_permits = Self::get_validator_permit(netuid);
236215
let Some(updated_validator_permit) = updated_validator_permits.get_mut(uid as usize) else {

0 commit comments

Comments
 (0)