Skip to content

Commit bb26e74

Browse files
authored
Merge pull request #1306 from opentensor/devnet-ready
devnet deploy 2/15/2025 number 2
2 parents a43217d + fe40cb9 commit bb26e74

File tree

6 files changed

+118
-140
lines changed

6 files changed

+118
-140
lines changed

pallets/subtensor/src/subnets/registration.rs

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use super::*;
22
use sp_core::{H256, U256};
33
use sp_io::hashing::{keccak_256, sha2_256};
44
use sp_runtime::Saturating;
5-
use substrate_fixed::types::I64F64;
65
use system::pallet_prelude::BlockNumberFor;
76

87
const LOG_TARGET: &str = "runtime::subtensor::registration";
@@ -425,29 +424,11 @@ impl<T: Config> Pallet<T> {
425424
return 0; // If there are no neurons in this network.
426425
}
427426

428-
// Get SN owner top stake hotkey
429-
let mut top_stake_sn_owner_hotkey: Option<T::AccountId> = None;
430-
let mut max_stake_weight: I64F64 = I64F64::from_num(-1);
431427
for neuron_uid in 0..neurons_n {
428+
// Do not deregister the owner's hotkey from the `SubnetOwnerHotkey` map
432429
if let Ok(hotkey) = Self::get_hotkey_for_net_and_uid(netuid, neuron_uid) {
433-
let coldkey = Self::get_owning_coldkey_for_hotkey(&hotkey);
434-
if Self::get_subnet_owner(netuid) != coldkey {
435-
continue;
436-
}
437-
438-
let stake_weights = Self::get_stake_weights_for_hotkey_on_subnet(&hotkey, netuid);
439-
if stake_weights.0 > max_stake_weight {
440-
max_stake_weight = stake_weights.0;
441-
top_stake_sn_owner_hotkey = Some(hotkey);
442-
}
443-
}
444-
}
445-
446-
for neuron_uid in 0..neurons_n {
447-
// Do not deregister the owner's top-stake hotkey
448-
if let Ok(hotkey) = Self::get_hotkey_for_net_and_uid(netuid, neuron_uid) {
449-
if let Some(ref top_sn_owner_hotkey) = top_stake_sn_owner_hotkey {
450-
if top_sn_owner_hotkey == &hotkey {
430+
if let Ok(top_sn_owner_hotkey) = SubnetOwnerHotkey::<T>::try_get(netuid) {
431+
if top_sn_owner_hotkey == hotkey {
451432
continue;
452433
}
453434
}

pallets/subtensor/src/subnets/uids.rs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,19 @@ impl<T: Config> Pallet<T> {
4242
// 1. Get the old hotkey under this position.
4343
let old_hotkey: T::AccountId = Keys::<T>::get(netuid, uid_to_replace);
4444

45-
// Do not deregister the owner
46-
let coldkey = Self::get_owning_coldkey_for_hotkey(&old_hotkey);
47-
if Self::get_subnet_owner(netuid) == coldkey {
48-
log::warn!(
49-
"replace_neuron: Skipped replacement because neuron belongs to the subnet owner. \
50-
netuid: {:?}, uid_to_replace: {:?}, new_hotkey: {:?}, owner_coldkey: {:?}",
51-
netuid,
52-
uid_to_replace,
53-
new_hotkey,
54-
coldkey
55-
);
56-
return;
45+
// Do not replace owner hotkey from `SubnetOwnerHotkey`
46+
if let Ok(sn_owner_hotkey) = SubnetOwnerHotkey::<T>::try_get(netuid) {
47+
if sn_owner_hotkey == old_hotkey.clone() {
48+
log::warn!(
49+
"replace_neuron: Skipped replacement because neuron is the subnet owner hotkey. \
50+
netuid: {:?}, uid_to_replace: {:?}, new_hotkey: {:?}, owner_hotkey: {:?}",
51+
netuid,
52+
uid_to_replace,
53+
new_hotkey,
54+
sn_owner_hotkey
55+
);
56+
return;
57+
}
5758
}
5859

5960
// 2. Remove previous set memberships.

pallets/subtensor/src/swap/swap_hotkey.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,18 @@ impl<T: Config> Pallet<T> {
437437
}
438438
}
439439

440+
// 15. Swap SubnetOwnerHotkey
441+
// SubnetOwnerHotkey( netuid ) --> hotkey -- the hotkey that is the owner of the subnet.
442+
for netuid in Self::get_all_subnet_netuids() {
443+
if let Ok(old_subnet_owner_hotkey) = SubnetOwnerHotkey::<T>::try_get(netuid) {
444+
weight.saturating_accrue(T::DbWeight::get().reads(1));
445+
if old_subnet_owner_hotkey == *old_hotkey {
446+
SubnetOwnerHotkey::<T>::insert(netuid, new_hotkey);
447+
weight.saturating_accrue(T::DbWeight::get().writes(1));
448+
}
449+
}
450+
}
451+
440452
// Return successful after swapping all the relevant terms.
441453
Ok(())
442454
}

pallets/subtensor/src/tests/swap_hotkey.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,3 +1359,25 @@ fn test_swap_child_hotkey_childkey_maps() {
13591359
);
13601360
})
13611361
}
1362+
1363+
// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_hotkey_is_sn_owner_hotkey --exact --nocapture
1364+
#[test]
1365+
fn test_swap_hotkey_is_sn_owner_hotkey() {
1366+
new_test_ext(1).execute_with(|| {
1367+
let old_hotkey = U256::from(1);
1368+
let new_hotkey = U256::from(2);
1369+
let coldkey = U256::from(3);
1370+
let mut weight = Weight::zero();
1371+
1372+
// Create dynamic network
1373+
let netuid = add_dynamic_network(&old_hotkey, &coldkey);
1374+
// Check for SubnetOwnerHotkey
1375+
assert_eq!(SubnetOwnerHotkey::<Test>::get(netuid), old_hotkey);
1376+
1377+
// Perform the swap
1378+
SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight);
1379+
1380+
// Check for SubnetOwnerHotkey
1381+
assert_eq!(SubnetOwnerHotkey::<Test>::get(netuid), new_hotkey);
1382+
});
1383+
}

pallets/subtensor/src/tests/uids.rs

Lines changed: 67 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use crate::*;
55
use frame_support::{assert_err, assert_ok};
66
use frame_system::Config;
77
use sp_core::U256;
8-
use substrate_fixed::types::I64F64;
98

109
/********************************************
1110
tests for uids.rs file
@@ -281,10 +280,11 @@ fn test_replace_neuron_subnet_owner_not_replaced() {
281280
}
282281

283282
#[test]
284-
fn test_get_neuron_to_prune_owner_not_pruned() {
283+
fn test_replace_neuron_subnet_owner_not_replaced_if_in_sn_owner_hotkey_map() {
285284
new_test_ext(1).execute_with(|| {
286285
let owner_hotkey = U256::from(123);
287286
let owner_coldkey = U256::from(999);
287+
let other_owner_hotkey = U256::from(456);
288288

289289
let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey);
290290

@@ -295,54 +295,64 @@ fn test_get_neuron_to_prune_owner_not_pruned() {
295295
let owner_uid = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &owner_hotkey)
296296
.expect("Owner neuron should already be registered by add_dynamic_network");
297297

298-
let additional_hotkey_1 = U256::from(1000);
299-
let additional_coldkey_1 = U256::from(2000);
298+
// Register another hotkey for the owner
299+
register_ok_neuron(netuid, other_owner_hotkey, owner_coldkey, 0);
300+
let other_owner_uid =
301+
SubtensorModule::get_uid_for_net_and_hotkey(netuid, &other_owner_hotkey)
302+
.expect("Should be registered");
300303

304+
let additional_hotkey_1 = U256::from(1000);
301305
let additional_hotkey_2 = U256::from(1001);
302-
let additional_coldkey_2 = U256::from(2001);
303-
304-
register_ok_neuron(netuid, additional_hotkey_1, additional_coldkey_1, 0);
305-
let uid_1 = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &additional_hotkey_1)
306-
.expect("Should be registered");
307306

308-
register_ok_neuron(netuid, additional_hotkey_2, additional_coldkey_2, 1);
309-
let uid_2 = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &additional_hotkey_2)
310-
.expect("Should be registered");
311-
312-
SubtensorModule::set_pruning_score_for_uid(netuid, owner_uid, 0);
313-
SubtensorModule::set_pruning_score_for_uid(netuid, uid_1, 1);
314-
SubtensorModule::set_pruning_score_for_uid(netuid, uid_2, 2);
315-
316-
let pruned_uid = SubtensorModule::get_neuron_to_prune(netuid);
307+
let current_block = SubtensorModule::get_current_block_as_u64();
308+
SubtensorModule::replace_neuron(netuid, owner_uid, &additional_hotkey_1, current_block);
317309

318-
// - The pruned UID must be `uid_1` (score=1).
319-
// - The owner's UID remains unpruned.
310+
let still_uid = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &owner_hotkey);
311+
assert_ok!(still_uid);
320312
assert_eq!(
321-
pruned_uid, uid_1,
322-
"Should prune the neuron with pruning score=1, not the owner (score=0)."
313+
still_uid.unwrap(),
314+
owner_uid,
315+
"Owner's first hotkey should remain registered"
323316
);
324317

325-
let pruned_score = SubtensorModule::get_pruning_score_for_uid(netuid, uid_1);
326-
assert_eq!(
327-
pruned_score,
328-
u16::MAX,
329-
"Pruned neuron's score should be set to u16::MAX"
330-
);
318+
let new_key_uid = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &additional_hotkey_1);
319+
assert_err!(new_key_uid, Error::<Test>::HotKeyNotRegisteredInSubNet,);
331320

332-
let owner_score = SubtensorModule::get_pruning_score_for_uid(netuid, owner_uid);
333-
assert_eq!(
334-
owner_score, 0,
335-
"Owner's pruning score remains 0, indicating it was skipped"
321+
// Try to replace the other owner hotkey
322+
SubtensorModule::replace_neuron(
323+
netuid,
324+
other_owner_uid,
325+
&additional_hotkey_1,
326+
current_block,
336327
);
328+
let still_uid = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &other_owner_hotkey);
329+
assert_err!(still_uid, Error::<Test>::HotKeyNotRegisteredInSubNet,); // Was replaced
330+
331+
// Re-register this hotkey
332+
register_ok_neuron(netuid, other_owner_hotkey, owner_coldkey, 0);
333+
let _other_owner_uid =
334+
SubtensorModule::get_uid_for_net_and_hotkey(netuid, &other_owner_hotkey)
335+
.expect("Should be registered");
336+
337+
// Set this hotkey as the SubnetOwnerHotkey
338+
SubnetOwnerHotkey::<Test>::insert(netuid, other_owner_hotkey);
339+
340+
SubtensorModule::replace_neuron(netuid, owner_uid, &additional_hotkey_2, current_block);
341+
342+
// The owner's first hotkey should be replaceable; it's not the top-stake owner hotkey
343+
let still_uid = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &owner_hotkey);
344+
assert_err!(still_uid, Error::<Test>::HotKeyNotRegisteredInSubNet,);
345+
346+
let new_key_uid = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &additional_hotkey_2);
347+
assert_ok!(new_key_uid);
337348
});
338349
}
339350

340351
#[test]
341-
fn test_get_neuron_to_prune_owner_pruned_if_not_top_stake_owner_hotkey() {
352+
fn test_get_neuron_to_prune_owner_not_pruned() {
342353
new_test_ext(1).execute_with(|| {
343354
let owner_hotkey = U256::from(123);
344355
let owner_coldkey = U256::from(999);
345-
let other_owner_hotkey = U256::from(456);
346356

347357
let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey);
348358

@@ -353,68 +363,54 @@ fn test_get_neuron_to_prune_owner_pruned_if_not_top_stake_owner_hotkey() {
353363
let owner_uid = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &owner_hotkey)
354364
.expect("Owner neuron should already be registered by add_dynamic_network");
355365

356-
// Register another hotkey for the owner
357-
register_ok_neuron(netuid, other_owner_hotkey, owner_coldkey, 0);
358-
let other_owner_uid =
359-
SubtensorModule::get_uid_for_net_and_hotkey(netuid, &other_owner_hotkey)
360-
.expect("Should be registered");
361-
362366
let additional_hotkey_1 = U256::from(1000);
363367
let additional_coldkey_1 = U256::from(2000);
364368

365369
let additional_hotkey_2 = U256::from(1001);
366370
let additional_coldkey_2 = U256::from(2001);
367371

368-
register_ok_neuron(netuid, additional_hotkey_1, additional_coldkey_1, 1);
369-
let uid_2 = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &additional_hotkey_1)
372+
register_ok_neuron(netuid, additional_hotkey_1, additional_coldkey_1, 0);
373+
let uid_1 = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &additional_hotkey_1)
370374
.expect("Should be registered");
371375

372-
register_ok_neuron(netuid, additional_hotkey_2, additional_coldkey_2, 2);
373-
let uid_3 = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &additional_hotkey_2)
376+
register_ok_neuron(netuid, additional_hotkey_2, additional_coldkey_2, 1);
377+
let uid_2 = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &additional_hotkey_2)
374378
.expect("Should be registered");
375379

376380
SubtensorModule::set_pruning_score_for_uid(netuid, owner_uid, 0);
377-
// Other owner key has pruning score not worse than the owner's first hotkey, but worse than the additional hotkeys
378-
SubtensorModule::set_pruning_score_for_uid(netuid, other_owner_uid, 1);
381+
SubtensorModule::set_pruning_score_for_uid(netuid, uid_1, 1);
379382
SubtensorModule::set_pruning_score_for_uid(netuid, uid_2, 2);
380-
SubtensorModule::set_pruning_score_for_uid(netuid, uid_3, 3);
381383

382384
let pruned_uid = SubtensorModule::get_neuron_to_prune(netuid);
383-
assert_eq!(pruned_uid, other_owner_uid, "Should prune the owner");
384385

385-
// Give the owner's other hotkey some stake
386-
SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet(
387-
&other_owner_hotkey,
388-
&owner_coldkey,
389-
netuid,
390-
1000,
386+
// - The pruned UID must be `uid_1` (score=1).
387+
// - The owner's UID remains unpruned.
388+
assert_eq!(
389+
pruned_uid, uid_1,
390+
"Should prune the neuron with pruning score=1, not the owner (score=0)."
391391
);
392392

393-
// Reset pruning scores
394-
SubtensorModule::set_pruning_score_for_uid(netuid, owner_uid, 0);
395-
SubtensorModule::set_pruning_score_for_uid(netuid, other_owner_uid, 1);
396-
SubtensorModule::set_pruning_score_for_uid(netuid, uid_2, 2);
397-
SubtensorModule::set_pruning_score_for_uid(netuid, uid_3, 3);
398-
399-
let pruned_uid = SubtensorModule::get_neuron_to_prune(netuid);
393+
let pruned_score = SubtensorModule::get_pruning_score_for_uid(netuid, uid_1);
394+
assert_eq!(
395+
pruned_score,
396+
u16::MAX,
397+
"Pruned neuron's score should be set to u16::MAX"
398+
);
400399

401-
// - The pruned UID must be `uid_1` (score=1).
402-
// - The owner's UID remains unpruned.
400+
let owner_score = SubtensorModule::get_pruning_score_for_uid(netuid, owner_uid);
403401
assert_eq!(
404-
pruned_uid, owner_uid,
405-
"Should prune the owner, not the top-stake owner hotkey and not the additional hotkeys"
402+
owner_score, 0,
403+
"Owner's pruning score remains 0, indicating it was skipped"
406404
);
407405
});
408406
}
409407

410408
#[test]
411-
fn test_get_neuron_to_prune_owner_pruned_if_not_top_stake_owner_hotkey_chk() {
409+
fn test_get_neuron_to_prune_owner_pruned_if_not_in_sn_owner_hotkey_map() {
412410
new_test_ext(1).execute_with(|| {
413411
let owner_hotkey = U256::from(123);
414412
let owner_coldkey = U256::from(999);
415413
let other_owner_hotkey = U256::from(456);
416-
let parent_hotkey = U256::from(4567);
417-
let parent_coldkey = U256::from(4568);
418414

419415
let netuid = add_dynamic_network(&owner_hotkey, &owner_coldkey);
420416

@@ -445,60 +441,26 @@ fn test_get_neuron_to_prune_owner_pruned_if_not_top_stake_owner_hotkey_chk() {
445441
let uid_3 = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &additional_hotkey_2)
446442
.expect("Should be registered");
447443

448-
register_ok_neuron(netuid, parent_hotkey, parent_coldkey, 3);
449-
let uid_4: u16 = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &parent_hotkey)
450-
.expect("Should be registered");
451-
452-
// Give parent key some stake
453-
SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet(
454-
&parent_hotkey,
455-
&parent_coldkey,
456-
netuid,
457-
10_000_000,
458-
);
459-
460444
SubtensorModule::set_pruning_score_for_uid(netuid, owner_uid, 0);
461445
// Other owner key has pruning score not worse than the owner's first hotkey, but worse than the additional hotkeys
462446
SubtensorModule::set_pruning_score_for_uid(netuid, other_owner_uid, 1);
463447
SubtensorModule::set_pruning_score_for_uid(netuid, uid_2, 2);
464448
SubtensorModule::set_pruning_score_for_uid(netuid, uid_3, 3);
465449

466-
// Ensure parent key is not pruned
467-
SubtensorModule::set_pruning_score_for_uid(netuid, uid_4, 10_000);
468-
469450
let pruned_uid = SubtensorModule::get_neuron_to_prune(netuid);
470-
assert_eq!(
471-
pruned_uid, other_owner_uid,
472-
"Should prune the owner's other hotkey"
473-
);
451+
assert_eq!(pruned_uid, other_owner_uid, "Should prune the owner");
474452

475-
// Give the owner's other hotkey some CHK stake; Doesn't need to be much
476-
mock_set_children_no_epochs(
477-
netuid,
478-
&parent_hotkey,
479-
&[(
480-
I64F64::saturating_from_num(0.1)
481-
.saturating_mul(I64F64::saturating_from_num(u64::MAX))
482-
.saturating_to_num::<u64>(),
483-
other_owner_hotkey,
484-
)],
485-
);
486-
// Check stake weight of other_owner_hotkey
487-
let stake_weight =
488-
SubtensorModule::get_stake_weights_for_hotkey_on_subnet(&other_owner_hotkey, netuid);
489-
assert!(stake_weight.0 > 0);
453+
// Set the owner's other hotkey as the SubnetOwnerHotkey
454+
SubnetOwnerHotkey::<Test>::insert(netuid, other_owner_hotkey);
490455

491456
// Reset pruning scores
492457
SubtensorModule::set_pruning_score_for_uid(netuid, owner_uid, 0);
493458
SubtensorModule::set_pruning_score_for_uid(netuid, other_owner_uid, 1);
494459
SubtensorModule::set_pruning_score_for_uid(netuid, uid_2, 2);
495460
SubtensorModule::set_pruning_score_for_uid(netuid, uid_3, 3);
496-
SubtensorModule::set_pruning_score_for_uid(netuid, uid_4, 10_000);
497461

498462
let pruned_uid = SubtensorModule::get_neuron_to_prune(netuid);
499463

500-
// - The pruned UID must be `uid_1` (score=1).
501-
// - The owner's UID remains unpruned.
502464
assert_eq!(
503465
pruned_uid, owner_uid,
504466
"Should prune the owner, not the top-stake owner hotkey and not the additional hotkeys"

runtime/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
229229
// `spec_version`, and `authoring_version` are the same between Wasm and native.
230230
// This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use
231231
// the compatible custom types.
232-
spec_version: 237,
232+
spec_version: 238,
233233
impl_version: 1,
234234
apis: RUNTIME_API_VERSIONS,
235235
transaction_version: 1,

0 commit comments

Comments
 (0)