@@ -426,6 +426,47 @@ impl<T: Config> Pallet<T> {
426426 ( prop_alpha_dividends, tao_dividends)
427427 }
428428
429+ fn get_immune_owner_hotkeys ( netuid : NetUid , coldkey : & T :: AccountId ) -> Vec < T :: AccountId > {
430+ // Gather (block, uid, hotkey) only for hotkeys that have a UID and a registration block.
431+ let mut triples: Vec < ( u64 , u16 , T :: AccountId ) > = OwnedHotkeys :: < T > :: get ( coldkey)
432+ . into_iter ( )
433+ . filter_map ( |hotkey| {
434+ // Uids must exist, filter_map ignores hotkeys without UID
435+ Uids :: < T > :: get ( netuid, & hotkey) . map ( |uid| {
436+ let block = BlockAtRegistration :: < T > :: get ( netuid, uid) ;
437+ ( block, uid, hotkey)
438+ } )
439+ } )
440+ . collect ( ) ;
441+
442+ // Sort by BlockAtRegistration (descending), then by uid (ascending)
443+ // Recent registration is priority so that we can let older keys expire (get non-immune)
444+ triples. sort_by ( |( b1, u1, _) , ( b2, u2, _) | b2. cmp ( b1) . then ( u1. cmp ( u2) ) ) ;
445+
446+ // Keep first ImmuneOwnerUidsLimit
447+ let limit = ImmuneOwnerUidsLimit :: < T > :: get ( netuid) . into ( ) ;
448+ if triples. len ( ) > limit {
449+ triples. truncate ( limit) ;
450+ }
451+
452+ // Project to just hotkeys
453+ let mut immune_hotkeys: Vec < T :: AccountId > =
454+ triples. into_iter ( ) . map ( |( _, _, hk) | hk) . collect ( ) ;
455+
456+ // Insert subnet owner hotkey in the beginning of the list if valid and not
457+ // already present
458+ if let Ok ( owner_hk) = SubnetOwnerHotkey :: < T > :: try_get ( netuid) {
459+ if Uids :: < T > :: get ( netuid, & owner_hk) . is_some ( ) && !immune_hotkeys. contains ( & owner_hk) {
460+ immune_hotkeys. insert ( 0 , owner_hk) ;
461+ if immune_hotkeys. len ( ) > limit {
462+ immune_hotkeys. truncate ( limit) ;
463+ }
464+ }
465+ }
466+
467+ immune_hotkeys
468+ }
469+
429470 pub fn distribute_dividends_and_incentives (
430471 netuid : NetUid ,
431472 owner_cut : AlphaCurrency ,
@@ -454,17 +495,20 @@ impl<T: Config> Pallet<T> {
454495 }
455496
456497 // Distribute mining incentives.
498+ let subnet_owner_coldkey = SubnetOwner :: < T > :: get ( netuid) ;
499+ let owner_hotkeys = Self :: get_immune_owner_hotkeys ( netuid, & subnet_owner_coldkey) ;
500+ log:: debug!( "incentives: owner hotkeys: {owner_hotkeys:?}" ) ;
457501 for ( hotkey, incentive) in incentives {
458502 log:: debug!( "incentives: hotkey: {incentive:?}" ) ;
459503
460- if let Ok ( owner_hotkey) = SubnetOwnerHotkey :: < T > :: try_get ( netuid) {
461- if hotkey == owner_hotkey {
462- log:: debug!(
463- "incentives: hotkey: {hotkey:?} is SN owner hotkey, skipping {incentive:?}"
464- ) ;
465- continue ; // Skip/burn miner-emission for SN owner hotkey.
466- }
504+ // Skip/burn miner-emission for immune keys
505+ if owner_hotkeys. contains ( & hotkey) {
506+ log:: debug!(
507+ "incentives: hotkey: {hotkey:?} is SN owner hotkey or associated hotkey, skipping {incentive:?}"
508+ ) ;
509+ continue ;
467510 }
511+
468512 // Increase stake for miner.
469513 Self :: increase_stake_for_hotkey_and_coldkey_on_subnet (
470514 & hotkey. clone ( ) ,
0 commit comments