Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -273,30 +273,51 @@ pub fn migrate_fix_subnet_hotkey_lock_swaps<T: Config>() -> Weight {
};
let netuid = NetUid::from(fix.netuid);

let index_reads: u64;
let index_writes: u64;
let lock_take_reads: u64;
let lock_take_writes: u64;
let locks_to_fix: Vec<(T::AccountId, LockState)> = if let Some(coldkey) = fix.coldkey {
let Some(coldkey) = decode_account_id32::<T>(coldkey) else {
log::error!("Failed to decode coldkey: {}", coldkey);
continue;
};
Lock::<T>::take((coldkey.clone(), netuid, old_hotkey.clone()))
.map(|lock| vec![(coldkey, lock)])
.unwrap_or_default()
index_reads = 0;
index_writes = 1;
lock_take_reads = 1;
LockingColdkeys::<T>::remove((netuid, old_hotkey.clone(), coldkey.clone()));
if let Some(lock) = Lock::<T>::take((coldkey.clone(), netuid, old_hotkey.clone())) {
lock_take_writes = 1;
vec![(coldkey, lock)]
} else {
lock_take_writes = 0;
Vec::new()
}
} else {
let locks: Vec<(T::AccountId, LockState)> = Lock::<T>::iter()
.filter_map(|((coldkey, lock_netuid, hotkey), lock)| {
(lock_netuid == netuid && hotkey == old_hotkey).then_some((coldkey, lock))
let coldkeys: Vec<T::AccountId> =
LockingColdkeys::<T>::iter_prefix((netuid, old_hotkey.clone()))
.map(|(coldkey, ())| coldkey)
.collect();
let indexed_coldkeys = coldkeys.len() as u64;
index_reads = indexed_coldkeys;
index_writes = indexed_coldkeys;
lock_take_reads = indexed_coldkeys;

let locks: Vec<(T::AccountId, LockState)> = coldkeys
.into_iter()
.filter_map(|coldkey| {
LockingColdkeys::<T>::remove((netuid, old_hotkey.clone(), coldkey.clone()));
Lock::<T>::take((coldkey.clone(), netuid, old_hotkey.clone()))
.map(|lock| (coldkey, lock))
})
.collect();
for (coldkey, _) in &locks {
Lock::<T>::remove((coldkey.clone(), netuid, old_hotkey.clone()));
}
lock_take_writes = locks.len() as u64;
locks
};
let locks_to_fix_count = locks_to_fix.len() as u64;
weight = weight.saturating_add(
T::DbWeight::get()
.reads_writes(locks_to_fix_count.saturating_add(1), locks_to_fix_count),
);
weight = weight.saturating_add(T::DbWeight::get().reads_writes(
index_reads.saturating_add(lock_take_reads),
index_writes.saturating_add(lock_take_writes),
));

if locks_to_fix.is_empty() {
missing_locks = missing_locks.saturating_add(1);
Expand All @@ -323,7 +344,8 @@ pub fn migrate_fix_subnet_hotkey_lock_swaps<T: Config>() -> Weight {
}

Lock::<T>::insert((coldkey.clone(), netuid, new_hotkey.clone()), lock.clone());
weight = weight.saturating_add(T::DbWeight::get().writes(1));
LockingColdkeys::<T>::insert((netuid, new_hotkey.clone(), coldkey.clone()), ());
weight = weight.saturating_add(T::DbWeight::get().writes(2));

if !new_hotkey_is_owner {
add_to_aggregate::<T>(&coldkey, netuid, &new_hotkey, &lock);
Expand Down
42 changes: 42 additions & 0 deletions pallets/subtensor/src/tests/migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,17 @@ fn test_migrate_fix_subnet_hotkey_lock_swaps_moves_or_discards_conflicts() {
(coldkey_to_move, netuid, old_hotkey),
moved_lock.clone(),
);
LockingColdkeys::<Test>::insert((netuid, old_hotkey, coldkey_to_move), ());
Lock::<Test>::insert(
(coldkey_with_conflict, netuid, old_hotkey),
discarded_lock.clone(),
);
LockingColdkeys::<Test>::insert((netuid, old_hotkey, coldkey_with_conflict), ());
Lock::<Test>::insert(
(coldkey_with_conflict, netuid, new_hotkey),
existing_destination_lock.clone(),
);
LockingColdkeys::<Test>::insert((netuid, new_hotkey, coldkey_with_conflict), ());
DecayingLock::<Test>::insert(coldkey_to_move, netuid, false);
DecayingLock::<Test>::insert(coldkey_with_conflict, netuid, false);
DecayingLock::<Test>::insert(chained_coldkey, chained_netuid, false);
Expand All @@ -148,6 +151,10 @@ fn test_migrate_fix_subnet_hotkey_lock_swaps_moves_or_discards_conflicts() {
(chained_coldkey, chained_netuid, chained_first_hotkey),
chained_lock.clone(),
);
LockingColdkeys::<Test>::insert(
(chained_netuid, chained_first_hotkey, chained_coldkey),
(),
);
HotkeyLock::<Test>::insert(chained_netuid, chained_first_hotkey, chained_lock.clone());

let weight =
Expand All @@ -157,14 +164,34 @@ fn test_migrate_fix_subnet_hotkey_lock_swaps_moves_or_discards_conflicts() {
assert!(HasMigrationRun::<Test>::get(&migration_name));
assert!(Lock::<Test>::get((coldkey_to_move, netuid, old_hotkey)).is_none());
assert!(Lock::<Test>::get((coldkey_with_conflict, netuid, old_hotkey)).is_none());
assert!(!LockingColdkeys::<Test>::contains_key((
netuid,
old_hotkey,
coldkey_to_move
)));
assert!(!LockingColdkeys::<Test>::contains_key((
netuid,
old_hotkey,
coldkey_with_conflict
)));
assert_eq!(
Lock::<Test>::get((coldkey_to_move, netuid, new_hotkey)),
Some(moved_lock.clone())
);
assert!(LockingColdkeys::<Test>::contains_key((
netuid,
new_hotkey,
coldkey_to_move
)));
assert_eq!(
Lock::<Test>::get((coldkey_with_conflict, netuid, new_hotkey)),
Some(existing_destination_lock.clone())
);
assert!(LockingColdkeys::<Test>::contains_key((
netuid,
new_hotkey,
coldkey_with_conflict
)));
assert!(HotkeyLock::<Test>::get(netuid, old_hotkey).is_none());

let new_aggregate = HotkeyLock::<Test>::get(netuid, new_hotkey)
Expand Down Expand Up @@ -193,10 +220,25 @@ fn test_migrate_fix_subnet_hotkey_lock_swaps_moves_or_discards_conflicts() {
chained_middle_hotkey
))
.is_none());
assert!(!LockingColdkeys::<Test>::contains_key((
chained_netuid,
chained_first_hotkey,
chained_coldkey
)));
assert!(!LockingColdkeys::<Test>::contains_key((
chained_netuid,
chained_middle_hotkey,
chained_coldkey
)));
assert_eq!(
Lock::<Test>::get((chained_coldkey, chained_netuid, chained_final_hotkey)),
Some(chained_lock.clone())
);
assert!(LockingColdkeys::<Test>::contains_key((
chained_netuid,
chained_final_hotkey,
chained_coldkey
)));
assert!(HotkeyLock::<Test>::get(chained_netuid, chained_first_hotkey).is_none());
assert!(HotkeyLock::<Test>::get(chained_netuid, chained_middle_hotkey).is_none());
assert_eq!(
Expand Down
9 changes: 5 additions & 4 deletions pallets/subtensor/src/tests/swap_hotkey_with_subnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -900,22 +900,23 @@ fn test_swap_owner_old_hotkey_not_exist() {
});
}

// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey_with_subnet -- test_swap_owner_new_hotkey_already_exists --exact --nocapture
// SKIP_WASM_BUILD=1 cargo test --package pallet-subtensor --lib -- tests::swap_hotkey_with_subnet::test_swap_owner_new_hotkey_already_exists --exact --nocapture
#[test]
fn test_swap_owner_new_hotkey_already_exists() {
new_test_ext(1).execute_with(|| {
let old_hotkey = U256::from(1);
let new_hotkey = U256::from(2);
let coldkey = U256::from(3);
let another_coldkey = U256::from(4);

let netuid = add_dynamic_network(&new_hotkey, &coldkey);
let netuid = add_dynamic_network(&old_hotkey, &coldkey);
add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_u64.into());

// old_hotkey is owned by coldkey; new_hotkey was already registered on `netuid`
// by add_dynamic_network (the condition under test). Do NOT reassign new_hotkey to
// a foreign coldkey — the new_hotkey-ownership check (NonAssociatedColdKey) would
// then fire before the already-registered-in-subnet check this test targets.
Owner::<Test>::insert(old_hotkey, coldkey);
Owner::<Test>::insert(new_hotkey, another_coldkey);

// Perform the swap
System::set_block_number(System::block_number() + HotkeySwapOnSubnetInterval::get());
Expand All @@ -927,7 +928,7 @@ fn test_swap_owner_new_hotkey_already_exists() {
Some(netuid),
false
),
Error::<Test>::HotKeyAlreadyRegisteredInSubNet
Error::<Test>::NonAssociatedColdKey
);

// Verify the swap
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
// `spec_version`, and `authoring_version` are the same between Wasm and native.
// This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use
// the compatible custom types.
spec_version: 419,
spec_version: 420,
impl_version: 1,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
Expand Down
Loading