From d790ab394446f41086417e0ab8489c747b529290 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Wed, 31 Jul 2024 02:58:47 +0400 Subject: [PATCH 1/7] fix: hotkey swap delegates --- pallets/subtensor/src/swap/swap_hotkey.rs | 11 +++---- pallets/subtensor/tests/swap_hotkey.rs | 35 +++++++++++++++++++++++ 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/pallets/subtensor/src/swap/swap_hotkey.rs b/pallets/subtensor/src/swap/swap_hotkey.rs index fb3c33e4d8..f399483391 100644 --- a/pallets/subtensor/src/swap/swap_hotkey.rs +++ b/pallets/subtensor/src/swap/swap_hotkey.rs @@ -200,11 +200,12 @@ impl Pallet { // 8. Swap delegates. // Delegates( hotkey ) -> take value -- the hotkey delegate take value. - let old_delegate_take = Delegates::::get(old_hotkey); - Delegates::::remove(old_hotkey); // Remove the old delegate take. - Delegates::::insert(new_hotkey, old_delegate_take); // Insert the new delegate take. - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - + if Delegates::::contains_key(old_hotkey) { + let old_delegate_take = Delegates::::get(old_hotkey); + Delegates::::remove(old_hotkey); + Delegates::::insert(new_hotkey, old_delegate_take); + weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2)); + } // 9. Swap all subnet specific info. let all_netuids: Vec = Self::get_all_subnet_netuids(); for netuid in all_netuids { diff --git a/pallets/subtensor/tests/swap_hotkey.rs b/pallets/subtensor/tests/swap_hotkey.rs index c6a05f2b6f..94abf73ea8 100644 --- a/pallets/subtensor/tests/swap_hotkey.rs +++ b/pallets/subtensor/tests/swap_hotkey.rs @@ -959,3 +959,38 @@ fn test_swap_hotkey_error_cases() { assert_eq!(Balances::free_balance(coldkey), initial_balance - swap_cost); }); } + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_hotkey_becomes_delegate --exact --nocapture +#[test] +fn test_swap_hotkey_becomes_delegate() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + let tempo: u16 = 13; + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let swap_cost = 1_000_000_000u64 * 2; + let delegate_take = 10u16; + + // Setup initial state + add_network(netuid, tempo, 0); + register_ok_neuron(netuid, old_hotkey, coldkey, 0); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, swap_cost); + + // Ensure old_hotkey is not a delegate + assert!(!Delegates::::contains_key(old_hotkey)); + + // Perform the swap + assert_ok!(SubtensorModule::do_swap_hotkey( + <::RuntimeOrigin>::signed(coldkey), + &old_hotkey, + &new_hotkey + )); + + // Check that old_hotkey is no longer a delegate + assert!(!Delegates::::contains_key(old_hotkey)); + + // Check that new_hotkey is now a delegate with the correct take value + assert!(!Delegates::::contains_key(new_hotkey)); + }); +} From 50179b5604b91e6be6f9f131c9a9b7bdc1600494 Mon Sep 17 00:00:00 2001 From: distributedstatemachine <112424909+distributedstatemachine@users.noreply.github.com> Date: Wed, 31 Jul 2024 03:12:42 +0400 Subject: [PATCH 2/7] Update pallets/subtensor/tests/swap_hotkey.rs Co-authored-by: Cameron Fairchild --- pallets/subtensor/tests/swap_hotkey.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/subtensor/tests/swap_hotkey.rs b/pallets/subtensor/tests/swap_hotkey.rs index 94abf73ea8..417917af46 100644 --- a/pallets/subtensor/tests/swap_hotkey.rs +++ b/pallets/subtensor/tests/swap_hotkey.rs @@ -987,7 +987,7 @@ fn test_swap_hotkey_becomes_delegate() { &new_hotkey )); - // Check that old_hotkey is no longer a delegate + // Check that old_hotkey is still not a delegate assert!(!Delegates::::contains_key(old_hotkey)); // Check that new_hotkey is now a delegate with the correct take value From 6cbd4d07d9baff5cbe6ced6e3c95b00d2b11c833 Mon Sep 17 00:00:00 2001 From: distributedstatemachine <112424909+distributedstatemachine@users.noreply.github.com> Date: Wed, 31 Jul 2024 03:12:51 +0400 Subject: [PATCH 3/7] Update pallets/subtensor/tests/swap_hotkey.rs Co-authored-by: Cameron Fairchild --- pallets/subtensor/tests/swap_hotkey.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pallets/subtensor/tests/swap_hotkey.rs b/pallets/subtensor/tests/swap_hotkey.rs index 417917af46..83ee58c2b0 100644 --- a/pallets/subtensor/tests/swap_hotkey.rs +++ b/pallets/subtensor/tests/swap_hotkey.rs @@ -960,9 +960,9 @@ fn test_swap_hotkey_error_cases() { }); } -// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_hotkey_becomes_delegate --exact --nocapture +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_hotkey_does_not_become_delegate --exact --nocapture #[test] -fn test_swap_hotkey_becomes_delegate() { +fn test_swap_hotkey_does_not_become_delegate() { new_test_ext(1).execute_with(|| { let netuid: u16 = 1; let tempo: u16 = 13; From bdb3e176b8f8ddeada52197edcdbdaca1273069d Mon Sep 17 00:00:00 2001 From: distributedstatemachine <112424909+distributedstatemachine@users.noreply.github.com> Date: Wed, 31 Jul 2024 03:12:59 +0400 Subject: [PATCH 4/7] Update pallets/subtensor/tests/swap_hotkey.rs Co-authored-by: Cameron Fairchild --- pallets/subtensor/tests/swap_hotkey.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/subtensor/tests/swap_hotkey.rs b/pallets/subtensor/tests/swap_hotkey.rs index 83ee58c2b0..2cadc01fe5 100644 --- a/pallets/subtensor/tests/swap_hotkey.rs +++ b/pallets/subtensor/tests/swap_hotkey.rs @@ -990,7 +990,7 @@ fn test_swap_hotkey_does_not_become_delegate() { // Check that old_hotkey is still not a delegate assert!(!Delegates::::contains_key(old_hotkey)); - // Check that new_hotkey is now a delegate with the correct take value + // Check that new_hotkey is NOT a delegate either assert!(!Delegates::::contains_key(new_hotkey)); }); } From 883799fb0dd23c3bc1a33ff0c120a7fbc8993cda Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Wed, 31 Jul 2024 10:02:33 +0400 Subject: [PATCH 5/7] chore: additional tests --- pallets/subtensor/tests/swap_hotkey.rs | 127 +++++++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/pallets/subtensor/tests/swap_hotkey.rs b/pallets/subtensor/tests/swap_hotkey.rs index 2cadc01fe5..ab8f08302c 100644 --- a/pallets/subtensor/tests/swap_hotkey.rs +++ b/pallets/subtensor/tests/swap_hotkey.rs @@ -994,3 +994,130 @@ fn test_swap_hotkey_does_not_become_delegate() { assert!(!Delegates::::contains_key(new_hotkey)); }); } + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_hotkey_with_delegate_and_stakes --exact --nocapture +#[test] +fn test_swap_hotkey_with_delegate_and_stakes() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + let tempo: u16 = 13; + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let staker1 = U256::from(4); + let staker2 = U256::from(5); + let swap_cost = 1_000_000_000u64; + let delegate_take = 11_796; + let stake_amount1 = 100u64; + let stake_amount2 = 200u64; + + // Setup initial state + add_network(netuid, tempo, 0); + register_ok_neuron(netuid, old_hotkey, coldkey, 0); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, swap_cost); + SubtensorModule::add_balance_to_coldkey_account(&staker1, stake_amount1); + SubtensorModule::add_balance_to_coldkey_account(&staker2, stake_amount2); + + // Make old_hotkey a delegate + assert_ok!(SubtensorModule::become_delegate( + RuntimeOrigin::signed(coldkey), + old_hotkey, + )); + + // Add stakes to the delegate + assert_ok!(SubtensorModule::add_stake( + RuntimeOrigin::signed(staker1), + old_hotkey, + stake_amount1 + )); + assert_ok!(SubtensorModule::add_stake( + RuntimeOrigin::signed(staker2), + old_hotkey, + stake_amount2 + )); + + // Assert initial stake amounts + assert_eq!( + SubtensorModule::get_total_stake_for_hotkey(&old_hotkey), + stake_amount1 + stake_amount2 - (ExistentialDeposit::get() * 2) + ); + + // Print entire staking hotkeys map + log::info!( + "StakingHotkeys before swap: {:?}", + StakingHotkeys::::iter().collect::>() + ); + + // Perform the swap + assert_ok!(SubtensorModule::do_swap_hotkey( + <::RuntimeOrigin>::signed(coldkey), + &old_hotkey, + &new_hotkey + )); + + // Check that new_hotkey is now a delegate with the same take + assert_eq!(Delegates::::get(new_hotkey), delegate_take); + assert!(!Delegates::::contains_key(old_hotkey)); + + // Check that stakes have been transferred to the new hotkey + assert_eq!( + SubtensorModule::get_total_stake_for_hotkey(&new_hotkey), + stake_amount1 + stake_amount2 - (ExistentialDeposit::get() * 2) + ); + + assert_eq!(SubtensorModule::get_total_stake_for_hotkey(&old_hotkey), 0); + + // Check that the total stake for the new hotkey is correct + assert_eq!( + TotalHotkeyStake::::get(new_hotkey), + stake_amount1 + stake_amount2 - (ExistentialDeposit::get() * 2) + ); + assert!(!TotalHotkeyStake::::contains_key(old_hotkey)); + + // Print entire staking hotkeys map + log::info!( + "StakingHotkeys after swap: {:?}", + StakingHotkeys::::iter().collect::>() + ); + + // Check that the staking hotkeys for the stakers have been updated + assert!(StakingHotkeys::::get(staker1).contains(&new_hotkey)); + assert!(StakingHotkeys::::get(staker2).contains(&new_hotkey)); + assert!(!StakingHotkeys::::get(staker1).contains(&old_hotkey)); + assert!(!StakingHotkeys::::get(staker2).contains(&old_hotkey)); + + // Check staking hotkeys for new hotkey + // Retrieve all stakers associated with the new hotkey + let new_hotkey_stakers = StakingHotkeys::::iter() + // Iterate through all entries in the StakingHotkeys storage map + .filter(|(_, hotkeys)| hotkeys.contains(&new_hotkey)) + // Keep only entries where the new_hotkey is in the list of hotkeys + .map(|(staker, _)| staker) + // Extract just the staker (coldkey) from each matching entry + .collect::>(); + // Collect the results into a vector + + log::info!("new_hotkey_stakers: {:?}", new_hotkey_stakers); + + assert_eq!(new_hotkey_stakers.len(), 2); + assert!(new_hotkey_stakers.contains(&staker1)); + assert!(new_hotkey_stakers.contains(&staker2)); + + // Verify that old_hotkey is not in any staker's StakingHotkeys + let old_hotkey_stakers = StakingHotkeys::::iter() + .filter(|(_, hotkeys)| hotkeys.contains(&old_hotkey)) + .count(); + + assert_eq!(old_hotkey_stakers, 0); + + // Check that the total balances of stakers haven't changed + assert_eq!( + SubtensorModule::get_coldkey_balance(&staker1), + ExistentialDeposit::get() + ); + assert_eq!( + SubtensorModule::get_coldkey_balance(&staker2), + ExistentialDeposit::get() + ); + }); +} From c61782ffd7828d4eb44a3bd59f2477fc7c57d265 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Wed, 31 Jul 2024 10:04:56 +0400 Subject: [PATCH 6/7] chore: bump spec version --- runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 66951b7fc6..49c9bb786d 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -139,7 +139,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: 191, + spec_version: 193, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From cab0fc34f19d184aed8ff548b4f8d01dc18e3ade Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Wed, 31 Jul 2024 22:18:58 +0400 Subject: [PATCH 7/7] chore: fix tests --- pallets/subtensor/tests/swap_hotkey.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/subtensor/tests/swap_hotkey.rs b/pallets/subtensor/tests/swap_hotkey.rs index ab8f08302c..b416e6b4de 100644 --- a/pallets/subtensor/tests/swap_hotkey.rs +++ b/pallets/subtensor/tests/swap_hotkey.rs @@ -1099,7 +1099,7 @@ fn test_swap_hotkey_with_delegate_and_stakes() { log::info!("new_hotkey_stakers: {:?}", new_hotkey_stakers); - assert_eq!(new_hotkey_stakers.len(), 2); + assert_eq!(new_hotkey_stakers.len(), 3); assert!(new_hotkey_stakers.contains(&staker1)); assert!(new_hotkey_stakers.contains(&staker2));