Skip to content

Commit 5adbbd9

Browse files
Merge pull request #644 from opentensor/hotfix/storage_version_inconsistency
Fix issues with Subtensor storage versions
2 parents 0c2ad41 + 0478596 commit 5adbbd9

File tree

3 files changed

+106
-21
lines changed

3 files changed

+106
-21
lines changed

pallets/subtensor/src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ pub mod pallet {
8484

8585
/// Tracks version for migrations. Should be monotonic with respect to the
8686
/// order of migrations. (i.e. always increasing)
87-
const STORAGE_VERSION: StorageVersion = StorageVersion::new(6);
87+
const STORAGE_VERSION: StorageVersion = StorageVersion::new(7);
8888

8989
/// Minimum balance required to perform a coldkey swap
9090
pub const MIN_BALANCE_TO_PERFORM_COLDKEY_SWAP: u64 = 100_000_000; // 0.1 TAO in RAO
@@ -1140,6 +1140,9 @@ pub mod pallet {
11401140
DefaultBonds<T>,
11411141
>;
11421142

1143+
#[pallet::storage] // --- Storage for migration run status
1144+
pub type HasMigrationRun<T: Config> = StorageMap<_, Identity, Vec<u8>, bool, ValueQuery>;
1145+
11431146
/// ==================
11441147
/// ==== Genesis =====
11451148
/// ==================

pallets/subtensor/src/migration.rs

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use super::*;
2+
use alloc::string::String;
23
use frame_support::traits::DefensiveResult;
34
use frame_support::{
45
pallet_prelude::{Identity, OptionQuery},
@@ -56,30 +57,53 @@ pub fn do_migrate_fix_total_coldkey_stake<T: Config>() -> Weight {
5657
}
5758
weight
5859
}
59-
// Public migrate function to be called by Lib.rs on upgrade.
60+
61+
/// Migrates and fixes the total coldkey stake.
62+
///
63+
/// This function checks if the migration has already run, and if not, it performs the migration
64+
/// to fix the total coldkey stake. It also marks the migration as completed after running.
65+
///
66+
/// # Returns
67+
/// The weight of the migration process.
6068
pub fn migrate_fix_total_coldkey_stake<T: Config>() -> Weight {
61-
let current_storage_version: u16 = 7;
62-
let next_storage_version: u16 = 8;
69+
let migration_name = b"fix_total_coldkey_stake_v7".to_vec();
6370

6471
// Initialize the weight with one read operation.
6572
let mut weight = T::DbWeight::get().reads(1);
6673

67-
// Grab the current on-chain storage version.
68-
// Cant fail on retrieval.
69-
let onchain_version = Pallet::<T>::on_chain_storage_version();
70-
71-
// Only run this migration on storage version 6.
72-
if onchain_version == current_storage_version {
73-
weight = weight.saturating_add(do_migrate_fix_total_coldkey_stake::<T>());
74-
// Cant fail on insert.
75-
StorageVersion::new(next_storage_version).put::<Pallet<T>>();
76-
weight.saturating_accrue(T::DbWeight::get().writes(1));
74+
// Check if the migration has already run
75+
if HasMigrationRun::<T>::get(&migration_name) {
76+
log::info!(
77+
"Migration '{:?}' has already run. Skipping.",
78+
migration_name
79+
);
80+
return Weight::zero();
7781
}
7882

83+
log::info!(
84+
"Running migration '{}'",
85+
String::from_utf8_lossy(&migration_name)
86+
);
87+
88+
// Run the migration
89+
weight = weight.saturating_add(do_migrate_fix_total_coldkey_stake::<T>());
90+
91+
// Mark the migration as completed
92+
HasMigrationRun::<T>::insert(&migration_name, true);
93+
weight = weight.saturating_add(T::DbWeight::get().writes(1));
94+
95+
// Set the storage version to 7
96+
StorageVersion::new(7).put::<Pallet<T>>();
97+
weight = weight.saturating_add(T::DbWeight::get().writes(1));
98+
99+
log::info!(
100+
"Migration '{:?}' completed. Storage version set to 7.",
101+
String::from_utf8_lossy(&migration_name)
102+
);
103+
79104
// Return the migration weight.
80105
weight
81106
}
82-
83107
/// Performs migration to update the total issuance based on the sum of stakes and total balances.
84108
/// This migration is applicable only if the current storage version is 5, after which it updates the storage version to 6.
85109
///

pallets/subtensor/tests/migration.rs

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#![allow(clippy::unwrap_used)]
22

33
mod mock;
4-
use frame_support::assert_ok;
4+
use frame_support::{assert_ok, weights::Weight};
55
use frame_system::Config;
66
use mock::*;
77
use pallet_subtensor::*;
@@ -278,17 +278,25 @@ fn test_migration_delete_subnet_21() {
278278
})
279279
}
280280

281+
// SKIP_WASM_BUILD=1 RUST_LOG=info cargo test --test migration -- test_migrate_fix_total_coldkey_stake --exact --nocapture
281282
// SKIP_WASM_BUILD=1 RUST_LOG=info cargo test --test migration -- test_migrate_fix_total_coldkey_stake --exact --nocapture
282283
#[test]
283284
fn test_migrate_fix_total_coldkey_stake() {
284285
new_test_ext(1).execute_with(|| {
286+
let migration_name = "fix_total_coldkey_stake_v7";
285287
let coldkey = U256::from(0);
286288
TotalColdkeyStake::<Test>::insert(coldkey, 0);
287289
StakingHotkeys::<Test>::insert(coldkey, vec![U256::from(1), U256::from(2), U256::from(3)]);
288290
Stake::<Test>::insert(U256::from(1), U256::from(0), 10000);
289291
Stake::<Test>::insert(U256::from(2), U256::from(0), 10000);
290292
Stake::<Test>::insert(U256::from(3), U256::from(0), 10000);
291-
pallet_subtensor::migration::do_migrate_fix_total_coldkey_stake::<Test>();
293+
294+
let weight = run_migration_and_check(migration_name);
295+
assert!(weight != Weight::zero());
296+
assert_eq!(TotalColdkeyStake::<Test>::get(coldkey), 30000);
297+
298+
let second_weight = run_migration_and_check(migration_name);
299+
assert_eq!(second_weight, Weight::zero());
292300
assert_eq!(TotalColdkeyStake::<Test>::get(coldkey), 30000);
293301
})
294302
}
@@ -297,13 +305,16 @@ fn test_migrate_fix_total_coldkey_stake() {
297305
#[test]
298306
fn test_migrate_fix_total_coldkey_stake_value_already_in_total() {
299307
new_test_ext(1).execute_with(|| {
308+
let migration_name = "fix_total_coldkey_stake_v7";
300309
let coldkey = U256::from(0);
301310
TotalColdkeyStake::<Test>::insert(coldkey, 100000000);
302311
StakingHotkeys::<Test>::insert(coldkey, vec![U256::from(1), U256::from(2), U256::from(3)]);
303312
Stake::<Test>::insert(U256::from(1), U256::from(0), 10000);
304313
Stake::<Test>::insert(U256::from(2), U256::from(0), 10000);
305314
Stake::<Test>::insert(U256::from(3), U256::from(0), 10000);
306-
pallet_subtensor::migration::do_migrate_fix_total_coldkey_stake::<Test>();
315+
316+
let weight = run_migration_and_check(migration_name);
317+
assert!(weight != Weight::zero());
307318
assert_eq!(TotalColdkeyStake::<Test>::get(coldkey), 30000);
308319
})
309320
}
@@ -312,12 +323,15 @@ fn test_migrate_fix_total_coldkey_stake_value_already_in_total() {
312323
#[test]
313324
fn test_migrate_fix_total_coldkey_stake_no_entry() {
314325
new_test_ext(1).execute_with(|| {
326+
let migration_name = "fix_total_coldkey_stake_v7";
315327
let coldkey = U256::from(0);
316328
StakingHotkeys::<Test>::insert(coldkey, vec![U256::from(1), U256::from(2), U256::from(3)]);
317329
Stake::<Test>::insert(U256::from(1), U256::from(0), 10000);
318330
Stake::<Test>::insert(U256::from(2), U256::from(0), 10000);
319331
Stake::<Test>::insert(U256::from(3), U256::from(0), 10000);
320-
pallet_subtensor::migration::do_migrate_fix_total_coldkey_stake::<Test>();
332+
333+
let weight = run_migration_and_check(migration_name);
334+
assert!(weight != Weight::zero());
321335
assert_eq!(TotalColdkeyStake::<Test>::get(coldkey), 30000);
322336
})
323337
}
@@ -326,10 +340,13 @@ fn test_migrate_fix_total_coldkey_stake_no_entry() {
326340
#[test]
327341
fn test_migrate_fix_total_coldkey_stake_no_entry_in_hotkeys() {
328342
new_test_ext(1).execute_with(|| {
343+
let migration_name = "fix_total_coldkey_stake_v7";
329344
let coldkey = U256::from(0);
330345
TotalColdkeyStake::<Test>::insert(coldkey, 100000000);
331346
StakingHotkeys::<Test>::insert(coldkey, vec![U256::from(1), U256::from(2), U256::from(3)]);
332-
pallet_subtensor::migration::do_migrate_fix_total_coldkey_stake::<Test>();
347+
348+
let weight = run_migration_and_check(migration_name);
349+
assert!(weight != Weight::zero());
333350
assert_eq!(TotalColdkeyStake::<Test>::get(coldkey), 0);
334351
})
335352
}
@@ -338,12 +355,53 @@ fn test_migrate_fix_total_coldkey_stake_no_entry_in_hotkeys() {
338355
#[test]
339356
fn test_migrate_fix_total_coldkey_stake_one_hotkey_stake_missing() {
340357
new_test_ext(1).execute_with(|| {
358+
let migration_name = "fix_total_coldkey_stake_v7";
341359
let coldkey = U256::from(0);
342360
TotalColdkeyStake::<Test>::insert(coldkey, 100000000);
343361
StakingHotkeys::<Test>::insert(coldkey, vec![U256::from(1), U256::from(2), U256::from(3)]);
344362
Stake::<Test>::insert(U256::from(1), U256::from(0), 10000);
345363
Stake::<Test>::insert(U256::from(2), U256::from(0), 10000);
346-
pallet_subtensor::migration::do_migrate_fix_total_coldkey_stake::<Test>();
364+
365+
let weight = run_migration_and_check(migration_name);
366+
assert!(weight != Weight::zero());
347367
assert_eq!(TotalColdkeyStake::<Test>::get(coldkey), 20000);
348368
})
349369
}
370+
371+
// New test to check if migration runs only once
372+
#[test]
373+
fn test_migrate_fix_total_coldkey_stake_runs_once() {
374+
new_test_ext(1).execute_with(|| {
375+
let migration_name = "fix_total_coldkey_stake_v7";
376+
let coldkey = U256::from(0);
377+
TotalColdkeyStake::<Test>::insert(coldkey, 0);
378+
StakingHotkeys::<Test>::insert(coldkey, vec![U256::from(1), U256::from(2), U256::from(3)]);
379+
Stake::<Test>::insert(U256::from(1), U256::from(0), 10000);
380+
Stake::<Test>::insert(U256::from(2), U256::from(0), 10000);
381+
Stake::<Test>::insert(U256::from(3), U256::from(0), 10000);
382+
383+
// First run
384+
let first_weight = run_migration_and_check(migration_name);
385+
assert!(first_weight != Weight::zero());
386+
assert_eq!(TotalColdkeyStake::<Test>::get(coldkey), 30000);
387+
388+
// Second run
389+
let second_weight = run_migration_and_check(migration_name);
390+
assert_eq!(second_weight, Weight::zero());
391+
assert_eq!(TotalColdkeyStake::<Test>::get(coldkey), 30000);
392+
})
393+
}
394+
395+
fn run_migration_and_check(migration_name: &'static str) -> frame_support::weights::Weight {
396+
// Execute the migration and store its weight
397+
let weight: frame_support::weights::Weight =
398+
pallet_subtensor::migration::migrate_fix_total_coldkey_stake::<Test>();
399+
400+
// Check if the migration has been marked as completed
401+
assert!(HasMigrationRun::<Test>::get(
402+
migration_name.as_bytes().to_vec()
403+
));
404+
405+
// Return the weight of the executed migration
406+
weight
407+
}

0 commit comments

Comments
 (0)