Skip to content

Commit d95a7df

Browse files
constconst
authored andcommitted
add migration and tests for total coldkey hotfix
1 parent 4dafd88 commit d95a7df

File tree

6 files changed

+125
-127
lines changed

6 files changed

+125
-127
lines changed

pallets/subtensor/src/lib.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1419,7 +1419,9 @@ pub mod pallet {
14191419
// Populate OwnedHotkeys map for coldkey swap. Doesn't update storage vesion.
14201420
.saturating_add(migration::migrate_populate_owned::<T>())
14211421
// Populate StakingHotkeys map for coldkey swap. Doesn't update storage vesion.
1422-
.saturating_add(migration::migrate_populate_staking_hotkeys::<T>());
1422+
.saturating_add(migration::migrate_populate_staking_hotkeys::<T>())
1423+
// Fix total coldkey stake.
1424+
.saturating_add(migration::migrate_fix_total_coldkey_stake::<T>());
14231425

14241426
weight
14251427
}
@@ -2258,12 +2260,10 @@ pub mod pallet {
22582260
#[pallet::call_index(64)]
22592261
#[pallet::weight((0, DispatchClass::Operational, Pays::No))]
22602262
pub fn sudo_hotfix_swap_coldkey_delegates(
2261-
origin: OriginFor<T>,
2262-
old_coldkey: T::AccountId,
2263-
new_coldkey: T::AccountId,
2263+
_origin: OriginFor<T>,
2264+
_old_coldkey: T::AccountId,
2265+
_new_coldkey: T::AccountId,
22642266
) -> DispatchResult {
2265-
ensure_root(origin)?;
2266-
Self::swap_hotfix(&old_coldkey, &new_coldkey);
22672267
Ok(())
22682268
}
22692269
}

pallets/subtensor/src/migration.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,63 @@ pub mod deprecated_loaded_emission_format {
2424
StorageMap<Pallet<T>, Identity, u16, Vec<(AccountIdOf<T>, u64)>, OptionQuery>;
2525
}
2626

27+
28+
/// Migrates and fixes the total coldkey stake.
29+
///
30+
/// This function iterates through all staking hotkeys, calculates the total stake for each coldkey,
31+
/// and updates the `TotalColdkeyStake` storage accordingly. The migration is only performed if the
32+
/// on-chain storage version is 6.
33+
///
34+
/// # Returns
35+
/// The weight of the migration process.
36+
pub fn do_migrate_fix_total_coldkey_stake<T: Config>() -> Weight{
37+
// Initialize the weight with one read operation.
38+
let mut weight = T::DbWeight::get().reads(1);
39+
40+
// Iterate through all staking hotkeys.
41+
for (coldkey, hotkey_vec) in StakingHotkeys::<T>::iter() {
42+
// Init the zero value.
43+
let mut coldkey_stake_sum: u64 = 0;
44+
weight = weight.saturating_add(T::DbWeight::get().reads(1));
45+
46+
// Calculate the total stake for the current coldkey.
47+
for hotkey in hotkey_vec {
48+
// Cant fail on retrieval.
49+
coldkey_stake_sum = coldkey_stake_sum.saturating_add(Stake::<T>::get(hotkey, coldkey.clone()));
50+
weight = weight.saturating_add(T::DbWeight::get().reads(1));
51+
}
52+
// Update the `TotalColdkeyStake` storage with the calculated stake sum.
53+
// Cant fail on insert.
54+
TotalColdkeyStake::<T>::insert( coldkey.clone(), coldkey_stake_sum );
55+
weight = weight.saturating_add(T::DbWeight::get().writes(1));
56+
}
57+
weight
58+
}
59+
// Public migrate function to be called by Lib.rs on upgrade.
60+
pub fn migrate_fix_total_coldkey_stake<T: Config>() -> Weight {
61+
62+
let current_storage_version: u16 = 6;
63+
let next_storage_version: u16 = 7;
64+
65+
// Initialize the weight with one read operation.
66+
let mut weight = T::DbWeight::get().reads(1);
67+
68+
// Grab the current on-chain storage version.
69+
// Cant fail on retrieval.
70+
let onchain_version = Pallet::<T>::on_chain_storage_version();
71+
72+
// Only run this migration on storage version 6.
73+
if onchain_version == current_storage_version {
74+
weight = weight.saturating_add( do_migrate_fix_total_coldkey_stake::<T>() );
75+
// Cant fail on insert.
76+
StorageVersion::new( next_storage_version ).put::<Pallet<T>>();
77+
weight.saturating_accrue(T::DbWeight::get().writes(1));
78+
}
79+
80+
// Return the migration weight.
81+
weight
82+
}
83+
2784
/// Performs migration to update the total issuance based on the sum of stakes and total balances.
2885
/// This migration is applicable only if the current storage version is 5, after which it updates the storage version to 6.
2986
///

pallets/subtensor/src/swap.rs

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -972,35 +972,6 @@ impl<T: Config> Pallet<T> {
972972
);
973973
}
974974

975-
pub fn swap_hotfix(old_coldkey: &T::AccountId, new_coldkey: &T::AccountId) {
976-
let weight = T::DbWeight::get().reads_writes(2, 1);
977-
let staking_hotkeys = StakingHotkeys::<T>::get(old_coldkey);
978-
for staking_hotkey in staking_hotkeys {
979-
if Stake::<T>::contains_key(staking_hotkey.clone(), old_coldkey) {
980-
let hotkey = &staking_hotkey;
981-
// Retrieve and remove the stake associated with the hotkey and old coldkey
982-
let stake: u64 = Stake::<T>::get(hotkey, old_coldkey);
983-
Stake::<T>::remove(hotkey, old_coldkey);
984-
if stake > 0 {
985-
// Insert the stake for the hotkey and new coldkey
986-
let old_stake = Stake::<T>::get(hotkey, new_coldkey);
987-
Stake::<T>::insert(hotkey, new_coldkey, stake.saturating_add(old_stake));
988-
}
989-
}
990-
}
991-
992-
let mut existing_staking_hotkeys = StakingHotkeys::<T>::get(new_coldkey);
993-
994-
let staking_hotkeys = StakingHotkeys::<T>::get(old_coldkey);
995-
for hotkey in staking_hotkeys {
996-
if !existing_staking_hotkeys.contains(&hotkey) {
997-
existing_staking_hotkeys.push(hotkey);
998-
}
999-
}
1000-
StakingHotkeys::<T>::insert(new_coldkey, existing_staking_hotkeys);
1001-
StakingHotkeys::<T>::remove(old_coldkey);
1002-
}
1003-
1004975
/// Swaps the total hotkey-coldkey stakes for the current interval from the old coldkey to the new coldkey.
1005976
///
1006977
/// # Arguments

pallets/subtensor/tests/migration.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
mod mock;
44
use frame_support::assert_ok;
55
use frame_system::Config;
6+
use pallet_subtensor::*;
67
use mock::*;
78
use sp_core::U256;
89

@@ -276,3 +277,62 @@ fn test_migration_delete_subnet_21() {
276277
assert!(!SubtensorModule::if_subnet_exist(21));
277278
})
278279
}
280+
281+
282+
// SKIP_WASM_BUILD=1 RUST_LOG=info cargo test --test migration -- test_migrate_fix_total_coldkey_stake --exact --nocapture
283+
#[test]
284+
fn test_migrate_fix_total_coldkey_stake() {
285+
new_test_ext(1).execute_with(|| {
286+
let coldkey = U256::from(0);
287+
TotalColdkeyStake::<Test>::insert(coldkey, 0);
288+
StakingHotkeys::<Test>::insert(coldkey, vec![U256::from(1), U256::from(2), U256::from(3)]);
289+
Stake::<Test>::insert(U256::from(1), U256::from(0), 10000);
290+
Stake::<Test>::insert(U256::from(2), U256::from(0), 10000);
291+
Stake::<Test>::insert(U256::from(3), U256::from(0), 10000);
292+
pallet_subtensor::migration::do_migrate_fix_total_coldkey_stake::<Test>();
293+
assert_eq!(TotalColdkeyStake::<Test>::get(coldkey), 30000);
294+
})
295+
}
296+
297+
// SKIP_WASM_BUILD=1 RUST_LOG=info cargo test --test migration -- test_migrate_fix_total_coldkey_stake_value_already_in_total --exact --nocapture
298+
#[test]
299+
fn test_migrate_fix_total_coldkey_stake_value_already_in_total() {
300+
new_test_ext(1).execute_with(|| {
301+
let coldkey = U256::from(0);
302+
TotalColdkeyStake::<Test>::insert(coldkey, 100000000);
303+
StakingHotkeys::<Test>::insert(coldkey, vec![U256::from(1), U256::from(2), U256::from(3)]);
304+
Stake::<Test>::insert(U256::from(1), U256::from(0), 10000);
305+
Stake::<Test>::insert(U256::from(2), U256::from(0), 10000);
306+
Stake::<Test>::insert(U256::from(3), U256::from(0), 10000);
307+
pallet_subtensor::migration::do_migrate_fix_total_coldkey_stake::<Test>();
308+
assert_eq!(TotalColdkeyStake::<Test>::get(coldkey), 30000);
309+
})
310+
}
311+
312+
// SKIP_WASM_BUILD=1 RUST_LOG=info cargo test --test migration -- test_migrate_fix_total_coldkey_stake_no_entry --exact --nocapture
313+
#[test]
314+
fn test_migrate_fix_total_coldkey_stake_no_entry() {
315+
new_test_ext(1).execute_with(|| {
316+
let coldkey = U256::from(0);
317+
StakingHotkeys::<Test>::insert(coldkey, vec![U256::from(1), U256::from(2), U256::from(3)]);
318+
Stake::<Test>::insert(U256::from(1), U256::from(0), 10000);
319+
Stake::<Test>::insert(U256::from(2), U256::from(0), 10000);
320+
Stake::<Test>::insert(U256::from(3), U256::from(0), 10000);
321+
pallet_subtensor::migration::do_migrate_fix_total_coldkey_stake::<Test>();
322+
assert_eq!(TotalColdkeyStake::<Test>::get(coldkey), 30000);
323+
})
324+
}
325+
326+
// SKIP_WASM_BUILD=1 RUST_LOG=info cargo test --test migration -- test_migrate_fix_total_coldkey_stake_no_entry_in_hotkeys --exact --nocapture
327+
#[test]
328+
fn test_migrate_fix_total_coldkey_stake_no_entry_in_hotkeys() {
329+
new_test_ext(1).execute_with(|| {
330+
let coldkey = U256::from(0);
331+
TotalColdkeyStake::<Test>::insert(coldkey, 100000000);
332+
StakingHotkeys::<Test>::insert(coldkey, vec![U256::from(1), U256::from(2), U256::from(3)]);
333+
pallet_subtensor::migration::do_migrate_fix_total_coldkey_stake::<Test>();
334+
assert_eq!(TotalColdkeyStake::<Test>::get(coldkey), 0);
335+
})
336+
}
337+
338+

pallets/subtensor/tests/swap.rs

Lines changed: 1 addition & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1886,94 +1886,4 @@ fn test_coldkey_delegations() {
18861886
assert_eq!(Stake::<Test>::get(delegate, new_coldkey), 100);
18871887
assert_eq!(Stake::<Test>::get(delegate, coldkey), 0);
18881888
});
1889-
}
1890-
1891-
// SKIP_WASM_BUILD=1 RUST_LOG=info cargo test --test swap -- test_sudo_hotfix_swap_coldkey_delegates --exact --nocapture
1892-
// #[test]
1893-
// fn test_sudo_hotfix_swap_coldkey_delegates() {
1894-
// new_test_ext(1).execute_with(|| {
1895-
// let new_coldkey = U256::from(0);
1896-
// let owner = U256::from(1);
1897-
// let coldkey = U256::from(4);
1898-
// let delegate = U256::from(2);
1899-
// let netuid = 1u16;
1900-
// add_network(netuid, 13, 0);
1901-
// register_ok_neuron(netuid, delegate, owner, 0);
1902-
// SubtensorModule::add_balance_to_coldkey_account(&coldkey, 1000);
1903-
// assert_ok!(SubtensorModule::do_become_delegate(
1904-
// <<Test as Config>::RuntimeOrigin>::signed(owner),
1905-
// delegate,
1906-
// u16::MAX / 10
1907-
// ));
1908-
// assert_ok!(SubtensorModule::add_stake(
1909-
// <<Test as Config>::RuntimeOrigin>::signed(coldkey),
1910-
// delegate,
1911-
// 100
1912-
// ));
1913-
1914-
// assert_ok!(SubtensorModule::perform_swap_coldkey(
1915-
// &coldkey,
1916-
// &new_coldkey
1917-
// ));
1918-
1919-
// assert_ok!(AdminUtils::sudo_hotfix_swap_coldkey_delegates(
1920-
// <<Test as Config>::RuntimeOrigin>::root(),
1921-
// to_be_set
1922-
// ));
1923-
1924-
// assert_eq!( SubtensorModule::get_total_stake_for_hotkey( &delegate), 100 );
1925-
// assert_eq!( SubtensorModule::get_total_stake_for_coldkey( &coldkey), 0 );
1926-
// assert_eq!( SubtensorModule::get_total_stake_for_coldkey( &new_coldkey), 100 );
1927-
// assert_eq!( Stake::<Test>::get( delegate, new_coldkey ), 100 );
1928-
// assert_eq!( Stake::<Test>::get( delegate, coldkey ), 0 );
1929-
1930-
// });
1931-
// }
1932-
1933-
// SKIP_WASM_BUILD=1 RUST_LOG=info cargo test --test swap -- test_sudo_hotfix_swap_coldkey_delegates --exact --nocapture
1934-
#[test]
1935-
fn test_sudo_hotfix_swap_coldkey_delegates() {
1936-
new_test_ext(1).execute_with(|| {
1937-
let new_coldkey = U256::from(0);
1938-
let coldkey = U256::from(4);
1939-
assert_ok!(SubtensorModule::sudo_hotfix_swap_coldkey_delegates(
1940-
<<Test as Config>::RuntimeOrigin>::root(),
1941-
coldkey,
1942-
new_coldkey
1943-
));
1944-
});
1945-
}
1946-
1947-
// SKIP_WASM_BUILD=1 RUST_LOG=info cargo test --test swap -- test_sudo_hotfix_swap_coldkey_delegates_with_broken_stake --exact --nocapture
1948-
#[test]
1949-
fn test_sudo_hotfix_swap_coldkey_delegates_with_broken_stake() {
1950-
new_test_ext(1).execute_with(|| {
1951-
let new_coldkey = U256::from(0);
1952-
let old_coldkey = U256::from(4);
1953-
let h1 = U256::from(5);
1954-
let h2 = U256::from(6);
1955-
let h3 = U256::from(7);
1956-
Stake::<Test>::insert(h3, old_coldkey, 100);
1957-
Stake::<Test>::insert(h2, old_coldkey, 100);
1958-
assert_eq!(Stake::<Test>::get(h3, old_coldkey), 100);
1959-
assert_eq!(Stake::<Test>::get(h2, old_coldkey), 100);
1960-
StakingHotkeys::<Test>::insert(new_coldkey, vec![h1, h2]);
1961-
StakingHotkeys::<Test>::insert(old_coldkey, vec![h3, h2]);
1962-
assert_ok!(SubtensorModule::sudo_hotfix_swap_coldkey_delegates(
1963-
<<Test as Config>::RuntimeOrigin>::root(),
1964-
old_coldkey,
1965-
new_coldkey
1966-
));
1967-
let hotkeys = StakingHotkeys::<Test>::get(new_coldkey);
1968-
assert_eq!(hotkeys.len(), 3);
1969-
assert_eq!(hotkeys[0], h1);
1970-
assert_eq!(hotkeys[1], h2);
1971-
assert_eq!(hotkeys[2], h3);
1972-
let hotkeys_old = StakingHotkeys::<Test>::get(old_coldkey);
1973-
assert_eq!(hotkeys_old.len(), 0);
1974-
assert_eq!(Stake::<Test>::get(h3, old_coldkey), 0);
1975-
assert_eq!(Stake::<Test>::get(h2, old_coldkey), 0);
1976-
assert_eq!(Stake::<Test>::get(h3, new_coldkey), 100);
1977-
assert_eq!(Stake::<Test>::get(h2, new_coldkey), 100);
1978-
});
1979-
}
1889+
}

runtime/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
139139
// `spec_version`, and `authoring_version` are the same between Wasm and native.
140140
// This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use
141141
// the compatible custom types.
142-
spec_version: 164,
142+
spec_version: 165,
143143
impl_version: 1,
144144
apis: RUNTIME_API_VERSIONS,
145145
transaction_version: 1,

0 commit comments

Comments
 (0)