Skip to content

Commit af585b9

Browse files
authored
Merge pull request #809 from opentensor/hotfix/pending-emission-migration-patch
Hotfix/pending emission migration patch and fix set weights check
2 parents 4f3f151 + 4c2629e commit af585b9

File tree

7 files changed

+684
-71
lines changed

7 files changed

+684
-71
lines changed

Diff for: pallets/subtensor/src/macros/hooks.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,7 @@ mod hooks {
7070
// Storage version v8 -> v9
7171
.saturating_add(migrations::migrate_fix_total_coldkey_stake::migrate_fix_total_coldkey_stake::<T>())
7272
// Migrate Delegate Ids on chain
73-
.saturating_add(migrations::migrate_chain_identity::migrate_set_hotkey_identities::<T>())
74-
// Fix pending emissions
75-
.saturating_add(migrations::migrate_fix_pending_emission::migrate_fix_pending_emission::<T>());
73+
.saturating_add(migrations::migrate_chain_identity::migrate_set_hotkey_identities::<T>());
7674
weight
7775
}
7876

Diff for: pallets/subtensor/src/migrations/migrate_fix_pending_emission.rs

+399-49
Large diffs are not rendered by default.

Diff for: pallets/subtensor/src/subnets/weights.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -226,9 +226,9 @@ impl<T: Config> Pallet<T> {
226226
Error::<T>::HotKeyNotRegisteredInSubNet
227227
);
228228

229-
// --- 6. Check to see if the hotkey has enought stake to set weights.
229+
// --- 6. Check to see if the hotkey has enough stake to set weights.
230230
ensure!(
231-
Self::get_total_stake_for_hotkey(&hotkey) >= Self::get_weights_min_stake(),
231+
Self::check_weights_min_stake(&hotkey, netuid),
232232
Error::<T>::NotEnoughStakeToSetWeights
233233
);
234234

Diff for: pallets/subtensor/src/utils/try_state.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ impl<T: Config> Pallet<T> {
1717

1818
// Calculate the total staked amount
1919
let mut total_staked: u64 = 0;
20-
for (_account, _netuid, stake) in Stake::<T>::iter() {
20+
for (_hotkey, _coldkey, stake) in Stake::<T>::iter() {
2121
total_staked = total_staked.saturating_add(stake);
2222
}
2323

Diff for: pallets/subtensor/tests/children.rs

+191
Original file line numberDiff line numberDiff line change
@@ -3237,3 +3237,194 @@ fn test_rank_trust_incentive_calculation_with_parent_child() {
32373237

32383238
});
32393239
}
3240+
3241+
// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --test children -- test_childkey_set_weights_single_parent --exact --nocapture
3242+
#[test]
3243+
fn test_childkey_set_weights_single_parent() {
3244+
new_test_ext(1).execute_with(|| {
3245+
let netuid: u16 = 1;
3246+
add_network(netuid, 1, 0);
3247+
3248+
// Define hotkeys
3249+
let parent: U256 = U256::from(1);
3250+
let child: U256 = U256::from(2);
3251+
let weight_setter: U256 = U256::from(3);
3252+
3253+
// Define coldkeys with more readable names
3254+
let coldkey_parent: U256 = U256::from(100);
3255+
let coldkey_child: U256 = U256::from(101);
3256+
let coldkey_weight_setter: U256 = U256::from(102);
3257+
3258+
let stake_to_give_child = 109_999;
3259+
3260+
// Register parent with minimal stake and child with high stake
3261+
SubtensorModule::add_balance_to_coldkey_account(&coldkey_parent, 1);
3262+
SubtensorModule::add_balance_to_coldkey_account(&coldkey_child, stake_to_give_child + 10);
3263+
SubtensorModule::add_balance_to_coldkey_account(&coldkey_weight_setter, 1_000_000);
3264+
3265+
// Add neurons for parent, child and weight_setter
3266+
register_ok_neuron(netuid, parent, coldkey_parent, 1);
3267+
register_ok_neuron(netuid, child, coldkey_child, 1);
3268+
register_ok_neuron(netuid, weight_setter, coldkey_weight_setter, 1);
3269+
3270+
SubtensorModule::increase_stake_on_coldkey_hotkey_account(
3271+
&coldkey_parent,
3272+
&parent,
3273+
stake_to_give_child,
3274+
);
3275+
SubtensorModule::increase_stake_on_coldkey_hotkey_account(
3276+
&coldkey_weight_setter,
3277+
&weight_setter,
3278+
1_000_000,
3279+
);
3280+
3281+
SubtensorModule::set_weights_set_rate_limit(netuid, 0);
3282+
3283+
// Set parent-child relationship
3284+
assert_ok!(SubtensorModule::do_set_children(
3285+
RuntimeOrigin::signed(coldkey_parent),
3286+
parent,
3287+
netuid,
3288+
vec![(u64::MAX, child)]
3289+
));
3290+
step_block(7200 + 1);
3291+
// Set weights on the child using the weight_setter account
3292+
let origin = RuntimeOrigin::signed(weight_setter);
3293+
let uids: Vec<u16> = vec![1]; // Only set weight for the child (UID 1)
3294+
let values: Vec<u16> = vec![u16::MAX]; // Use maximum value for u16
3295+
let version_key = SubtensorModule::get_weights_version_key(netuid);
3296+
assert_ok!(SubtensorModule::set_weights(
3297+
origin,
3298+
netuid,
3299+
uids.clone(),
3300+
values.clone(),
3301+
version_key
3302+
));
3303+
3304+
// Set the min stake very high
3305+
SubtensorModule::set_weights_min_stake(stake_to_give_child * 5);
3306+
3307+
// Check the child has less stake than required
3308+
assert!(
3309+
SubtensorModule::get_stake_for_hotkey_on_subnet(&child, netuid)
3310+
< SubtensorModule::get_weights_min_stake()
3311+
);
3312+
3313+
// Check the child cannot set weights
3314+
assert_noop!(
3315+
SubtensorModule::set_weights(
3316+
RuntimeOrigin::signed(child),
3317+
netuid,
3318+
uids.clone(),
3319+
values.clone(),
3320+
version_key
3321+
),
3322+
Error::<Test>::NotEnoughStakeToSetWeights
3323+
);
3324+
3325+
assert!(!SubtensorModule::check_weights_min_stake(&child, netuid));
3326+
3327+
// Set a minimum stake to set weights
3328+
SubtensorModule::set_weights_min_stake(stake_to_give_child - 5);
3329+
3330+
// Check if the stake for the child is above
3331+
assert!(
3332+
SubtensorModule::get_stake_for_hotkey_on_subnet(&child, netuid)
3333+
>= SubtensorModule::get_weights_min_stake()
3334+
);
3335+
3336+
// Check the child can set weights
3337+
assert_ok!(SubtensorModule::set_weights(
3338+
RuntimeOrigin::signed(child),
3339+
netuid,
3340+
uids,
3341+
values,
3342+
version_key
3343+
));
3344+
3345+
assert!(SubtensorModule::check_weights_min_stake(&child, netuid));
3346+
});
3347+
}
3348+
3349+
// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --test children -- test_set_weights_no_parent --exact --nocapture
3350+
#[test]
3351+
fn test_set_weights_no_parent() {
3352+
// Verify that a regular key without a parent delegation is effected by the minimum stake requirements
3353+
new_test_ext(1).execute_with(|| {
3354+
let netuid: u16 = 1;
3355+
add_network(netuid, 1, 0);
3356+
3357+
let hotkey: U256 = U256::from(2);
3358+
let spare_hk: U256 = U256::from(3);
3359+
3360+
let coldkey: U256 = U256::from(101);
3361+
let spare_ck = U256::from(102);
3362+
3363+
let stake_to_give_child = 109_999;
3364+
3365+
SubtensorModule::add_balance_to_coldkey_account(&coldkey, stake_to_give_child + 10);
3366+
3367+
// Is registered
3368+
register_ok_neuron(netuid, hotkey, coldkey, 1);
3369+
// Register a spare key
3370+
register_ok_neuron(netuid, spare_hk, spare_ck, 1);
3371+
3372+
SubtensorModule::increase_stake_on_coldkey_hotkey_account(
3373+
&coldkey,
3374+
&hotkey,
3375+
stake_to_give_child,
3376+
);
3377+
3378+
SubtensorModule::set_weights_set_rate_limit(netuid, 0);
3379+
3380+
// Has stake and no parent
3381+
step_block(7200 + 1);
3382+
3383+
let uids: Vec<u16> = vec![1]; // Set weights on the other hotkey
3384+
let values: Vec<u16> = vec![u16::MAX]; // Use maximum value for u16
3385+
let version_key = SubtensorModule::get_weights_version_key(netuid);
3386+
3387+
// Set the min stake very high
3388+
SubtensorModule::set_weights_min_stake(stake_to_give_child * 5);
3389+
3390+
// Check the key has less stake than required
3391+
assert!(
3392+
SubtensorModule::get_stake_for_hotkey_on_subnet(&hotkey, netuid)
3393+
< SubtensorModule::get_weights_min_stake()
3394+
);
3395+
3396+
// Check the hotkey cannot set weights
3397+
assert_noop!(
3398+
SubtensorModule::set_weights(
3399+
RuntimeOrigin::signed(hotkey),
3400+
netuid,
3401+
uids.clone(),
3402+
values.clone(),
3403+
version_key
3404+
),
3405+
Error::<Test>::NotEnoughStakeToSetWeights
3406+
);
3407+
3408+
assert!(!SubtensorModule::check_weights_min_stake(&hotkey, netuid));
3409+
3410+
// Set a minimum stake to set weights
3411+
SubtensorModule::set_weights_min_stake(stake_to_give_child - 5);
3412+
3413+
// Check if the stake for the hotkey is above
3414+
assert!(
3415+
SubtensorModule::get_stake_for_hotkey_on_subnet(&hotkey, netuid)
3416+
>= SubtensorModule::get_weights_min_stake()
3417+
);
3418+
3419+
// Check the hotkey can set weights
3420+
assert_ok!(SubtensorModule::set_weights(
3421+
RuntimeOrigin::signed(hotkey),
3422+
netuid,
3423+
uids,
3424+
values,
3425+
version_key
3426+
));
3427+
3428+
assert!(SubtensorModule::check_weights_min_stake(&hotkey, netuid));
3429+
});
3430+
}

Diff for: pallets/subtensor/tests/migration.rs

+86-14
Original file line numberDiff line numberDiff line change
@@ -436,11 +436,11 @@ fn run_migration_and_check(migration_name: &'static str) -> frame_support::weigh
436436
fn run_pending_emissions_migration_and_check(
437437
migration_name: &'static str,
438438
) -> frame_support::weights::Weight {
439+
use frame_support::traits::OnRuntimeUpgrade;
440+
439441
// Execute the migration and store its weight
440442
let weight: frame_support::weights::Weight =
441-
pallet_subtensor::migrations::migrate_fix_pending_emission::migrate_fix_pending_emission::<
442-
Test,
443-
>();
443+
pallet_subtensor::migrations::migrate_fix_pending_emission::migration::Migration::<Test>::on_runtime_upgrade();
444444

445445
// Check if the migration has been marked as completed
446446
assert!(HasMigrationRun::<Test>::get(
@@ -463,34 +463,49 @@ fn test_migrate_fix_pending_emissions() {
463463
new_test_ext(1).execute_with(|| {
464464
let migration_name = "fix_pending_emission";
465465

466-
let null_account = U256::from(0); // The null account
467-
let rand_coldkeys = [U256::from(1), U256::from(2), U256::from(3), U256::from(4)];
466+
let null_account = &U256::from(0); // The null account
468467

469468
let taostats_old_hotkey = "5Hddm3iBFD2GLT5ik7LZnT3XJUnRnN8PoeCFgGQgawUVKNm8";
470469
let taostats_new_hotkey = "5GKH9FPPnWSUoeeTJp19wVtd84XqFW4pyK2ijV2GsFbhTrP1";
471470

472-
let taostats_old_hk_account: AccountId = get_account_id_from_ss58(taostats_old_hotkey);
473-
let taostats_new_hk_account: AccountId = get_account_id_from_ss58(taostats_new_hotkey);
471+
let taostats_old_hk_account: &AccountId = &get_account_id_from_ss58(taostats_old_hotkey);
472+
let taostats_new_hk_account: &AccountId = &get_account_id_from_ss58(taostats_new_hotkey);
474473

475474
let datura_old_hotkey = "5FKstHjZkh4v3qAMSBa1oJcHCLjxYZ8SNTSz1opTv4hR7gVB";
476475
let datura_new_hotkey = "5GP7c3fFazW9GXK8Up3qgu2DJBk8inu4aK9TZy3RuoSWVCMi";
477476

478-
let datura_old_hk_account: AccountId = get_account_id_from_ss58(datura_old_hotkey);
479-
let datura_new_hk_account: AccountId = get_account_id_from_ss58(datura_new_hotkey);
477+
let datura_old_hk_account: &AccountId = &get_account_id_from_ss58(datura_old_hotkey);
478+
let datura_new_hk_account: &AccountId = &get_account_id_from_ss58(datura_new_hotkey);
479+
480+
let migration_coldkey = "5GeRjQYsobRWFnrbBmGe5ugme3rfnDVF69N45YtdBpUFsJG8";
481+
let migration_account: &AccountId = &get_account_id_from_ss58(migration_coldkey);
482+
483+
// "Issue" the TAO we're going to insert to stake
484+
let null_stake_datura = 123_456_789;
485+
let null_stake_tao_stats = 123_456_789;
486+
let null_stake_total = null_stake_datura + null_stake_tao_stats;
487+
SubtensorModule::set_total_issuance(null_stake_total);
488+
TotalStake::<Test>::put(null_stake_total);
489+
TotalColdkeyStake::<Test>::insert(null_account, null_stake_total);
490+
TotalHotkeyStake::<Test>::insert(datura_old_hk_account, null_stake_datura);
491+
TotalHotkeyStake::<Test>::insert(taostats_old_hk_account, null_stake_tao_stats);
480492

481493
// Setup the old Datura hotkey with a pending emission
482494
PendingdHotkeyEmission::<Test>::insert(datura_old_hk_account, 10_000);
483495
// Setup the NEW Datura hotkey with a pending emission
484496
PendingdHotkeyEmission::<Test>::insert(datura_new_hk_account, 123_456_789);
497+
Stake::<Test>::insert(datura_old_hk_account, null_account, null_stake_datura);
485498
let expected_datura_new_hk_pending_emission: u64 = 123_456_789 + 10_000;
486499

487500
// Setup the old TaoStats hotkey with a pending emission
488501
PendingdHotkeyEmission::<Test>::insert(taostats_old_hk_account, 987_654);
489502
// Setup the new TaoStats hotkey with a pending emission
490503
PendingdHotkeyEmission::<Test>::insert(taostats_new_hk_account, 100_000);
491504
// Setup the old TaoStats hotkey with a null-key stake entry
492-
Stake::<Test>::insert(taostats_old_hk_account, null_account, 123_456_789);
493-
let expected_taostats_new_hk_pending_emission: u64 = 987_654 + 100_000 + 123_456_789;
505+
Stake::<Test>::insert(taostats_old_hk_account, null_account, null_stake_tao_stats);
506+
let expected_taostats_new_hk_pending_emission: u64 = 987_654 + 100_000;
507+
508+
let total_issuance_before = SubtensorModule::get_total_issuance();
494509

495510
// Run migration
496511
let first_weight = run_pending_emissions_migration_and_check(migration_name);
@@ -508,10 +523,67 @@ fn test_migrate_fix_pending_emissions() {
508523
expected_taostats_new_hk_pending_emission
509524
);
510525

511-
// Check the pending emission is added to new the Datura hotkey
526+
// Check the pending emission is removed from old ones
512527
assert_eq!(
513-
PendingdHotkeyEmission::<Test>::get(datura_new_hk_account),
514-
expected_datura_new_hk_pending_emission
528+
PendingdHotkeyEmission::<Test>::get(datura_old_hk_account),
529+
0
530+
);
531+
532+
assert_eq!(
533+
PendingdHotkeyEmission::<Test>::get(taostats_old_hk_account),
534+
0
535+
);
536+
537+
// Check the stake entry is removed
538+
assert_eq!(Stake::<Test>::get(datura_old_hk_account, null_account), 0);
539+
assert_eq!(Stake::<Test>::get(taostats_old_hk_account, null_account), 0);
540+
541+
// Check the total issuance is the SAME following migration (no TAO issued)
542+
let expected_total_issuance = total_issuance_before;
543+
assert_eq!(
544+
SubtensorModule::get_total_issuance(),
545+
expected_total_issuance
546+
);
547+
548+
// Check total stake is the SAME following the migration (no new TAO staked)
549+
assert_eq!(TotalStake::<Test>::get(), expected_total_issuance);
550+
// Check the total stake maps are updated following the migration (removal of old null_account stake entries)
551+
assert_eq!(TotalColdkeyStake::<Test>::get(null_account), 0);
552+
assert_eq!(
553+
SubtensorModule::get_stake_for_coldkey_and_hotkey(null_account, datura_old_hk_account),
554+
0
555+
);
556+
assert_eq!(
557+
SubtensorModule::get_stake_for_coldkey_and_hotkey(
558+
null_account,
559+
taostats_old_hk_account
560+
),
561+
0
562+
);
563+
564+
// Check staking hotkeys is updated
565+
assert_eq!(StakingHotkeys::<Test>::get(null_account), vec![]);
566+
567+
// Check the migration key has stake with both *old* hotkeys
568+
assert_eq!(
569+
SubtensorModule::get_stake_for_coldkey_and_hotkey(
570+
migration_account,
571+
datura_old_hk_account
572+
),
573+
null_stake_datura
574+
);
575+
assert_eq!(
576+
SubtensorModule::get_stake_for_coldkey_and_hotkey(
577+
migration_account,
578+
taostats_old_hk_account
579+
),
580+
null_stake_tao_stats
581+
);
582+
assert_eq!(
583+
TotalColdkeyStake::<Test>::get(migration_account),
584+
null_stake_total
515585
);
586+
assert!(StakingHotkeys::<Test>::get(migration_account).contains(datura_old_hk_account));
587+
assert!(StakingHotkeys::<Test>::get(migration_account).contains(taostats_old_hk_account));
516588
})
517589
}

Diff for: runtime/src/lib.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1075,10 +1075,12 @@ pub type SignedExtra = (
10751075
frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
10761076
);
10771077

1078-
type Migrations =
1078+
type Migrations = (
10791079
pallet_subtensor::migrations::migrate_init_total_issuance::initialise_total_issuance::Migration<
10801080
Runtime,
1081-
>;
1081+
>,
1082+
pallet_subtensor::migrations::migrate_fix_pending_emission::migration::Migration<Runtime>,
1083+
);
10821084

10831085
// Unchecked extrinsic type as expected by this runtime.
10841086
pub type UncheckedExtrinsic =

0 commit comments

Comments
 (0)