Skip to content

Commit dbef23b

Browse files
Merge pull request #464 from opentensor/hotfix/reapply-before-testnet-merge
Hotfix/reapply before testnet merge
2 parents 8153831 + 970e3ec commit dbef23b

File tree

8 files changed

+144
-299
lines changed

8 files changed

+144
-299
lines changed

pallets/subtensor/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1988,7 +1988,7 @@ where
19881988
Pallet::<T>::get_registrations_this_interval(*netuid);
19891989
let max_registrations_per_interval =
19901990
Pallet::<T>::get_target_registrations_per_interval(*netuid);
1991-
if registrations_this_interval >= max_registrations_per_interval {
1991+
if registrations_this_interval >= (max_registrations_per_interval * 3) {
19921992
// If the registration limit for the interval is exceeded, reject the transaction
19931993
return InvalidTransaction::ExhaustsResources.into();
19941994
}

pallets/subtensor/src/staking.rs

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -436,26 +436,18 @@ impl<T: Config> Pallet<T> {
436436
Error::<T>::UnstakeRateLimitExceeded
437437
);
438438

439-
// If this is a nomination stake, check if total stake after removing will be above
440-
// the minimum required stake.
441-
442-
// If coldkey is not owner of the hotkey, it's a nomination stake.
443-
if !Self::coldkey_owns_hotkey(&coldkey, &hotkey) {
444-
let total_stake_after_remove =
445-
Stake::<T>::get(&hotkey, &coldkey).saturating_sub(stake_to_be_removed);
446-
447-
ensure!(
448-
total_stake_after_remove >= NominatorMinRequiredStake::<T>::get(),
449-
Error::<T>::NomStakeBelowMinimumThreshold
450-
);
451-
}
452-
453439
// We remove the balance from the hotkey.
454440
Self::decrease_stake_on_coldkey_hotkey_account(&coldkey, &hotkey, stake_to_be_removed);
455441

456-
// We add the balancer to the coldkey. If the above fails we will not credit this coldkey.
442+
// We add the balance to the coldkey. If the above fails we will not credit this coldkey.
457443
Self::add_balance_to_coldkey_account(&coldkey, stake_to_be_removed);
458444

445+
// If the stake is below the minimum, we clear the nomination from storage.
446+
// This only applies to nominator stakes.
447+
// If the coldkey does not own the hotkey, it's a nominator stake.
448+
let new_stake = Self::get_stake_for_coldkey_and_hotkey(&coldkey, &hotkey);
449+
Self::clear_small_nomination_if_required(&hotkey, &coldkey, new_stake);
450+
459451
// Set last block for rate limiting
460452
let block: u64 = Self::get_current_block_as_u64();
461453
Self::set_last_tx_block(&coldkey, block);
@@ -679,17 +671,24 @@ impl<T: Config> Pallet<T> {
679671
/// It also removes the stake entry for the hotkey-coldkey pairing and adjusts the TotalStake
680672
/// and TotalIssuance by subtracting the removed stake amount.
681673
///
674+
/// Returns the amount of stake that was removed.
675+
///
682676
/// # Arguments
683677
///
684678
/// * `coldkey` - A reference to the AccountId of the coldkey involved in the staking.
685679
/// * `hotkey` - A reference to the AccountId of the hotkey associated with the coldkey.
686-
pub fn empty_stake_on_coldkey_hotkey_account(coldkey: &T::AccountId, hotkey: &T::AccountId) {
680+
pub fn empty_stake_on_coldkey_hotkey_account(
681+
coldkey: &T::AccountId,
682+
hotkey: &T::AccountId,
683+
) -> u64 {
687684
let current_stake: u64 = Stake::<T>::get(hotkey, coldkey);
688685
TotalColdkeyStake::<T>::mutate(coldkey, |old| *old = old.saturating_sub(current_stake));
689686
TotalHotkeyStake::<T>::mutate(hotkey, |stake| *stake = stake.saturating_sub(current_stake));
690687
Stake::<T>::remove(hotkey, coldkey);
691688
TotalStake::<T>::mutate(|stake| *stake = stake.saturating_sub(current_stake));
692689
TotalIssuance::<T>::mutate(|issuance| *issuance = issuance.saturating_sub(current_stake));
690+
691+
current_stake
693692
}
694693

695694
/// Clears the nomination for an account, if it is a nominator account and the stake is below the minimum required threshold.
@@ -704,9 +703,9 @@ impl<T: Config> Pallet<T> {
704703
if stake < Self::get_nominator_min_required_stake() {
705704
// Remove the stake from the nominator account. (this is a more forceful unstake operation which )
706705
// Actually deletes the staking account.
707-
Self::empty_stake_on_coldkey_hotkey_account(coldkey, hotkey);
706+
let cleared_stake = Self::empty_stake_on_coldkey_hotkey_account(coldkey, hotkey);
708707
// Add the stake to the coldkey account.
709-
Self::add_balance_to_coldkey_account(coldkey, stake);
708+
Self::add_balance_to_coldkey_account(coldkey, cleared_stake);
710709
}
711710
}
712711
}

pallets/subtensor/tests/registration.rs

Lines changed: 74 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -249,9 +249,10 @@ fn test_registration_rate_limit_exceeded() {
249249
let coldkey_account_id = U256::from(667);
250250
let who: <Test as frame_system::Config>::AccountId = hotkey_account_id;
251251

252-
let max_registrants = 1;
253-
SubtensorModule::set_target_registrations_per_interval(netuid, max_registrants);
254-
SubtensorModule::set_registrations_this_interval(netuid, 1);
252+
let target_registrants = 1;
253+
let max_registrants = target_registrants * 3;
254+
SubtensorModule::set_target_registrations_per_interval(netuid, target_registrants);
255+
SubtensorModule::set_registrations_this_interval(netuid, max_registrants);
255256

256257
let (nonce, work) = SubtensorModule::create_work_for_block_number(
257258
netuid,
@@ -290,18 +291,18 @@ fn test_burned_registration_under_limit() {
290291
let netuid: u16 = 1;
291292
let hotkey_account_id: U256 = U256::from(1);
292293
let coldkey_account_id = U256::from(667);
293-
let who: <Test as frame_system::Config>::AccountId = hotkey_account_id;
294-
let block_number: u64 = 0;
294+
let who: <Test as frame_system::Config>::AccountId = coldkey_account_id;
295+
let burn_cost = 1000;
296+
// Set the burn cost
297+
SubtensorModule::set_burn(netuid, burn_cost);
295298

296-
let (nonce, work) = SubtensorModule::create_work_for_block_number(
297-
netuid,
298-
block_number,
299-
129123813,
300-
&hotkey_account_id,
301-
);
299+
add_network(netuid, 13, 0); // Add the network
300+
// Give it some TAO to the coldkey balance; more than the burn cost
301+
SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, burn_cost + 10_000);
302302

303-
let max_registrants = 2;
304-
SubtensorModule::set_target_registrations_per_interval(netuid, max_registrants);
303+
let target_registrants = 2;
304+
let max_registrants = target_registrants * 3; // Maximum is 3 times the target
305+
SubtensorModule::set_target_registrations_per_interval(netuid, target_registrants);
305306

306307
let call_burned_register: pallet_subtensor::Call<Test> =
307308
pallet_subtensor::Call::burned_register {
@@ -317,21 +318,15 @@ fn test_burned_registration_under_limit() {
317318
extension.validate(&who, &call_burned_register.into(), &info, 10);
318319
assert_ok!(burned_register_result);
319320

320-
add_network(netuid, 13, 0);
321321
//actually call register
322-
assert_ok!(SubtensorModule::register(
323-
<<Test as Config>::RuntimeOrigin>::signed(hotkey_account_id),
322+
assert_ok!(SubtensorModule::burned_register(
323+
<<Test as Config>::RuntimeOrigin>::signed(coldkey_account_id),
324324
netuid,
325-
block_number,
326-
nonce,
327-
work,
328325
hotkey_account_id,
329-
coldkey_account_id
330326
));
331327

332328
let current_registrants = SubtensorModule::get_registrations_this_interval(netuid);
333-
let target_registrants = SubtensorModule::get_target_registrations_per_interval(netuid);
334-
assert!(current_registrants <= target_registrants);
329+
assert!(current_registrants <= max_registrants);
335330
});
336331
}
337332

@@ -340,11 +335,15 @@ fn test_burned_registration_rate_limit_exceeded() {
340335
new_test_ext(1).execute_with(|| {
341336
let netuid: u16 = 1;
342337
let hotkey_account_id: U256 = U256::from(1);
343-
let who: <Test as frame_system::Config>::AccountId = hotkey_account_id;
344-
let max_registrants = 1;
338+
let coldkey_account_id = U256::from(667);
339+
let who: <Test as frame_system::Config>::AccountId = coldkey_account_id;
345340

346-
SubtensorModule::set_target_registrations_per_interval(netuid, max_registrants);
347-
SubtensorModule::set_registrations_this_interval(netuid, 1);
341+
let target_registrants = 1;
342+
let max_registrants = target_registrants * 3; // Maximum is 3 times the target
343+
344+
SubtensorModule::set_target_registrations_per_interval(netuid, target_registrants);
345+
// Set the current registrations to the maximum; should not be able to register more
346+
SubtensorModule::set_registrations_this_interval(netuid, max_registrants);
348347

349348
let call_burned_register: pallet_subtensor::Call<Test> =
350349
pallet_subtensor::Call::burned_register {
@@ -369,6 +368,55 @@ fn test_burned_registration_rate_limit_exceeded() {
369368
});
370369
}
371370

371+
#[test]
372+
fn test_burned_registration_rate_allows_burn_adjustment() {
373+
// We need to be able to register more than the *target* registrations per interval
374+
new_test_ext(1).execute_with(|| {
375+
let netuid: u16 = 1;
376+
let hotkey_account_id: U256 = U256::from(1);
377+
let coldkey_account_id = U256::from(667);
378+
let who: <Test as frame_system::Config>::AccountId = coldkey_account_id;
379+
380+
let burn_cost = 1000;
381+
// Set the burn cost
382+
SubtensorModule::set_burn(netuid, burn_cost);
383+
384+
add_network(netuid, 13, 0); // Add the network
385+
// Give it some TAO to the coldkey balance; more than the burn cost
386+
SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, burn_cost + 10_000);
387+
388+
let target_registrants = 1; // Target is 1, but we can register more than that, up to some maximum.
389+
SubtensorModule::set_target_registrations_per_interval(netuid, target_registrants);
390+
// Set the current registrations to above the target; we should be able to register at least 1 more
391+
SubtensorModule::set_registrations_this_interval(netuid, target_registrants);
392+
393+
// Register one more, so the current registrations are above the target
394+
let call_burned_register: pallet_subtensor::Call<Test> =
395+
pallet_subtensor::Call::burned_register {
396+
netuid,
397+
hotkey: hotkey_account_id,
398+
};
399+
400+
let info: DispatchInfo =
401+
DispatchInfoOf::<<Test as frame_system::Config>::RuntimeCall>::default();
402+
let extension = SubtensorSignedExtension::<Test>::new();
403+
//does not actually call register
404+
let burned_register_result =
405+
extension.validate(&who, &call_burned_register.into(), &info, 10);
406+
assert_ok!(burned_register_result);
407+
408+
//actually call register
409+
assert_ok!(SubtensorModule::burned_register(
410+
<<Test as Config>::RuntimeOrigin>::signed(coldkey_account_id),
411+
netuid,
412+
hotkey_account_id
413+
));
414+
415+
let current_registrants = SubtensorModule::get_registrations_this_interval(netuid);
416+
assert!(current_registrants > target_registrants); // Should be able to register more than the target
417+
});
418+
}
419+
372420
#[test]
373421
fn test_burned_registration_ok() {
374422
new_test_ext(1).execute_with(|| {

pallets/subtensor/tests/staking.rs

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2698,16 +2698,55 @@ fn test_remove_stake_below_minimum_threshold() {
26982698
stake_amount_to_remove
26992699
));
27002700

2701-
// Nomination stake cannot stake below min threshold.
2702-
assert_noop!(
2703-
SubtensorModule::remove_stake(
2704-
<<Test as Config>::RuntimeOrigin>::signed(coldkey2),
2705-
hotkey1,
2706-
stake_amount_to_remove
2707-
),
2708-
Error::<Test>::NomStakeBelowMinimumThreshold
2701+
// Nomination stake cannot unstake below min threshold,
2702+
// without unstaking all and removing the nomination.
2703+
let total_hotkey_stake_before = SubtensorModule::get_total_stake_for_hotkey(&hotkey1);
2704+
let bal_before = Balances::free_balance(coldkey2);
2705+
let staked_before = SubtensorModule::get_stake_for_coldkey_and_hotkey(&coldkey2, &hotkey1);
2706+
let total_network_stake_before = SubtensorModule::get_total_stake();
2707+
let total_issuance_before = SubtensorModule::get_total_issuance();
2708+
// check the premise of the test is correct
2709+
assert!(initial_stake - stake_amount_to_remove < minimum_threshold);
2710+
assert_ok!(SubtensorModule::remove_stake(
2711+
<<Test as Config>::RuntimeOrigin>::signed(coldkey2),
2712+
hotkey1,
2713+
stake_amount_to_remove
2714+
));
2715+
2716+
// Has no stake now
2717+
assert_eq!(
2718+
SubtensorModule::get_stake_for_coldkey_and_hotkey(&coldkey2, &hotkey1),
2719+
0
27092720
);
2710-
})
2721+
let stake_removed = staked_before; // All stake was removed
2722+
// Has the full balance
2723+
assert_eq!(Balances::free_balance(coldkey2), bal_before + stake_removed);
2724+
2725+
// Stake map entry is removed
2726+
assert_eq!(
2727+
Stake::<Test>::try_get(hotkey1, coldkey2).is_err(),
2728+
true // Entry was removed
2729+
);
2730+
// Stake tracking is updated
2731+
assert_eq!(
2732+
TotalColdkeyStake::<Test>::try_get(coldkey2).unwrap(),
2733+
0 // Did not have any stake before; Entry is NOT removed
2734+
);
2735+
assert_eq!(
2736+
TotalHotkeyStake::<Test>::try_get(hotkey1).unwrap(),
2737+
total_hotkey_stake_before - stake_removed // Stake was removed from hotkey1 tracker
2738+
);
2739+
assert_eq!(
2740+
TotalStake::<Test>::try_get().unwrap(),
2741+
total_network_stake_before - stake_removed
2742+
);
2743+
2744+
// Total issuance is the same
2745+
assert_eq!(
2746+
SubtensorModule::get_total_issuance(),
2747+
total_issuance_before // Nothing was issued
2748+
);
2749+
});
27112750
}
27122751

27132752
// Verify delegate take can be decreased

runtime/src/lib.rs

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,12 @@ mod migrations;
1010

1111
use codec::{Decode, Encode, MaxEncodedLen};
1212

13-
use migrations::{account_data_migration, init_storage_versions};
1413
use pallet_commitments::CanCommit;
1514
use pallet_grandpa::{
1615
fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList,
1716
};
1817

19-
use frame_support::{
20-
pallet_prelude::{DispatchError, DispatchResult, Get},
21-
traits::OnRuntimeUpgrade,
22-
};
18+
use frame_support::pallet_prelude::{DispatchError, DispatchResult, Get};
2319
use frame_system::{EnsureNever, EnsureRoot, RawOrigin};
2420

2521
use pallet_registry::CanRegisterIdentity;
@@ -137,7 +133,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
137133
// `spec_version`, and `authoring_version` are the same between Wasm and native.
138134
// This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use
139135
// the compatible custom types.
140-
spec_version: 149,
136+
spec_version: 150,
141137
impl_version: 1,
142138
apis: RUNTIME_API_VERSIONS,
143139
transaction_version: 1,
@@ -1171,12 +1167,7 @@ pub type SignedExtra = (
11711167
pallet_commitments::CommitmentsSignedExtension<Runtime>,
11721168
);
11731169

1174-
type Migrations = (
1175-
init_storage_versions::Migration,
1176-
account_data_migration::Migration,
1177-
pallet_multisig::migrations::v1::MigrateToV1<Runtime>,
1178-
pallet_preimage::migration::v1::Migration<Runtime>,
1179-
);
1170+
type Migrations = ();
11801171

11811172
// Unchecked extrinsic type as expected by this runtime.
11821173
pub type UncheckedExtrinsic =

0 commit comments

Comments
 (0)