@@ -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]
15521476fn 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() {
0 commit comments