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
6 changes: 3 additions & 3 deletions pallets/subtensor/src/macros/dispatches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1063,9 +1063,9 @@ mod dispatches {
note = "Please use swap_hotkey_v2 instead. This extrinsic will be removed some time after June 2026."
)]
#[pallet::call_index(70)]
#[pallet::weight((Weight::from_parts(275_300_000, 0)
.saturating_add(T::DbWeight::get().reads(57_u64))
.saturating_add(T::DbWeight::get().writes(39_u64)), DispatchClass::Normal, Pays::No))]
#[pallet::weight((Weight::from_parts(263_300_000, 0)
.saturating_add(T::DbWeight::get().reads(45_u64))
.saturating_add(T::DbWeight::get().writes(31_u64)), DispatchClass::Normal, Pays::No))]
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason to keep this Pays::No?

Suggested change
.saturating_add(T::DbWeight::get().writes(31_u64)), DispatchClass::Normal, Pays::No))]
.saturating_add(T::DbWeight::get().writes(31_u64)), DispatchClass::Normal, Pays::Yes))]

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, I don't see any reason, and it's cleaner that way.

pub fn swap_hotkey(
origin: OriginFor<T>,
hotkey: T::AccountId,
Expand Down
125 changes: 39 additions & 86 deletions pallets/subtensor/src/swap/swap_hotkey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use super::*;
use frame_support::weights::Weight;
use share_pool::SafeFloat;
use sp_core::Get;
use sp_std::collections::btree_set::BTreeSet;
use substrate_fixed::types::U64F64;
use subtensor_runtime_common::{MechId, NetUid, Token};

Expand Down Expand Up @@ -360,37 +361,6 @@ impl<T: Config> Pallet<T> {
netuid: NetUid,
keep_stake: bool,
) -> DispatchResult {
if !keep_stake {
// 1. Swap total hotkey alpha for all subnets it exists on.
// TotalHotkeyAlpha( hotkey, netuid ) -> alpha -- the total alpha that the hotkey has on a specific subnet.
let alpha = TotalHotkeyAlpha::<T>::take(old_hotkey, netuid);

TotalHotkeyAlpha::<T>::mutate(new_hotkey, netuid, |value| {
*value = value.saturating_add(alpha)
});
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));

// 2. Swap total hotkey shares on all subnets it exists on.
// TotalHotkeyShares( hotkey, netuid ) -> share pool denominator for this hotkey on this subnet.
// Merge v1 and v2 TotalHotkeyShares because TotalHotkeyShares v1 is deprecated
weight.saturating_accrue(T::DbWeight::get().reads(4));
let old_share_v1 = SafeFloat::from(TotalHotkeyShares::<T>::take(old_hotkey, netuid));
let old_share_v2 = TotalHotkeySharesV2::<T>::take(old_hotkey, netuid);
let total_old_shares = old_share_v1.add(&old_share_v2).unwrap_or_default();

let new_share_v1 = SafeFloat::from(TotalHotkeyShares::<T>::take(new_hotkey, netuid));
let new_share_v2 = TotalHotkeySharesV2::<T>::take(new_hotkey, netuid);
let total_new_shares = new_share_v1.add(&new_share_v2).unwrap_or_default();

TotalHotkeyShares::<T>::remove(old_hotkey, netuid);
TotalHotkeyShares::<T>::remove(new_hotkey, netuid);

let total_old_plus_new_shares =
total_new_shares.add(&total_old_shares).unwrap_or_default();
TotalHotkeySharesV2::<T>::insert(new_hotkey, netuid, total_old_plus_new_shares);
weight.saturating_accrue(T::DbWeight::get().writes(3));
}

// 3. Swap all subnet specific info.

// 3.1 Remove the previous hotkey and insert the new hotkey from membership.
Expand Down Expand Up @@ -549,7 +519,10 @@ impl<T: Config> Pallet<T> {
Self::swap_voting_power_for_hotkey(old_hotkey, new_hotkey, netuid);
weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2));

// 9. Swap Alpha
// Transfer root claimable
Self::transfer_root_claimable_for_new_hotkey(old_hotkey, new_hotkey);

// Swap Alpha
// Alpha( hotkey, coldkey, netuid ) -> alpha
let old_alpha_values: Vec<((T::AccountId, NetUid), U64F64)> =
Alpha::<T>::iter_prefix((old_hotkey,)).collect();
Expand All @@ -561,63 +534,43 @@ impl<T: Config> Pallet<T> {
weight.saturating_accrue(T::DbWeight::get().reads(old_alpha_values_v2.len() as u64));
weight.saturating_accrue(T::DbWeight::get().writes(old_alpha_values_v2.len() as u64));

// 9.1. Transfer root claimable
Self::transfer_root_claimable_for_new_hotkey(old_hotkey, new_hotkey);

// 9.2. Insert the new alpha values.
for ((coldkey, netuid_alpha), alpha) in old_alpha_values {
if netuid == netuid_alpha {
Self::transfer_root_claimed_for_new_keys(
netuid, old_hotkey, new_hotkey, &coldkey, &coldkey,
);

let new_alpha = Alpha::<T>::take((new_hotkey, &coldkey, netuid));
Alpha::<T>::remove((old_hotkey, &coldkey, netuid));

// Insert into AlphaV2 because Alpha is deprecated
AlphaV2::<T>::insert(
(new_hotkey, &coldkey, netuid),
SafeFloat::from(alpha.saturating_add(new_alpha)),
);
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2));
// Insert the new alpha values.
// Deduplicate coldkeys staking to old_hotkey from alpha and alpha_v2
let unique_coldkeys: BTreeSet<T::AccountId> = old_alpha_values
.into_iter()
.map(|((coldkey, netuid_alpha), _)| (coldkey, netuid_alpha))
.chain(
old_alpha_values_v2
.into_iter()
.map(|((coldkey, netuid_alpha), _)| (coldkey, netuid_alpha)),
)
.filter(|(_, netuid_alpha)| *netuid_alpha == netuid)
.map(|(coldkey, _)| coldkey)
.collect();

// For each coldkey remove their stake from old_hotkey and add to new_hotkey
for coldkey in unique_coldkeys {
Self::transfer_root_claimed_for_new_keys(
netuid, old_hotkey, new_hotkey, &coldkey, &coldkey,
);

// Swap StakingHotkeys.
// StakingHotkeys( coldkey ) --> Vec<hotkey> -- the hotkeys that the coldkey stakes.
let mut staking_hotkeys = StakingHotkeys::<T>::get(&coldkey);
weight.saturating_accrue(T::DbWeight::get().reads(1));
if staking_hotkeys.contains(old_hotkey) && !staking_hotkeys.contains(new_hotkey)
{
staking_hotkeys.push(new_hotkey.clone());
StakingHotkeys::<T>::insert(&coldkey, staking_hotkeys);
weight.saturating_accrue(T::DbWeight::get().writes(1));
}
}
}
let alpha_old =
Self::get_stake_for_hotkey_and_coldkey_on_subnet(old_hotkey, &coldkey, netuid);
Self::decrease_stake_for_hotkey_and_coldkey_on_subnet(
old_hotkey, &coldkey, netuid, alpha_old,
);
Self::increase_stake_for_hotkey_and_coldkey_on_subnet(
new_hotkey, &coldkey, netuid, alpha_old,
);
weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2));

for ((coldkey, netuid_alpha), alpha) in old_alpha_values_v2 {
if netuid == netuid_alpha {
Self::transfer_root_claimed_for_new_keys(
netuid, old_hotkey, new_hotkey, &coldkey, &coldkey,
);

let new_alpha_v2 = AlphaV2::<T>::take((new_hotkey, &coldkey, netuid));
AlphaV2::<T>::remove((old_hotkey, &coldkey, netuid));
AlphaV2::<T>::insert(
(new_hotkey, &coldkey, netuid),
alpha.add(&new_alpha_v2).unwrap_or_default(),
);
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2));
let mut staking_hotkeys = StakingHotkeys::<T>::get(&coldkey);
weight.saturating_accrue(T::DbWeight::get().reads(1));

// Swap StakingHotkeys.
// StakingHotkeys( coldkey ) --> Vec<hotkey> -- the hotkeys that the coldkey stakes.
let mut staking_hotkeys = StakingHotkeys::<T>::get(&coldkey);
weight.saturating_accrue(T::DbWeight::get().reads(1));
if staking_hotkeys.contains(old_hotkey) && !staking_hotkeys.contains(new_hotkey)
{
staking_hotkeys.push(new_hotkey.clone());
StakingHotkeys::<T>::insert(&coldkey, staking_hotkeys);
weight.saturating_accrue(T::DbWeight::get().writes(1));
}
if staking_hotkeys.contains(old_hotkey) && !staking_hotkeys.contains(new_hotkey) {
staking_hotkeys.push(new_hotkey.clone());
StakingHotkeys::<T>::insert(&coldkey, staking_hotkeys);
weight.saturating_accrue(T::DbWeight::get().writes(1));
}
}
}
Expand Down
9 changes: 6 additions & 3 deletions pallets/subtensor/src/tests/swap_hotkey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -889,7 +889,7 @@ fn test_swap_stake_success() {
let subnet_owner_hotkey = U256::from(1002);
let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey);
let amount = 10_000;
let shares = U64F64::from_num(123456);
let shares = U64F64::from_num(10_000);
let mut weight = Weight::zero();

// Initialize staking variables for old_hotkey
Expand Down Expand Up @@ -974,7 +974,7 @@ fn test_swap_stake_v2_success() {
let subnet_owner_hotkey = U256::from(1002);
let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey);
let amount = 10_000;
let shares = U64F64::from_num(123456);
let shares = U64F64::from_num(10_000);
let mut weight = Weight::zero();

// Initialize staking variables for old_hotkey
Expand Down Expand Up @@ -1045,7 +1045,7 @@ fn test_swap_stake_v2_success() {
});
}

// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_stake_old_hotkey_not_exist --exact --nocapture
// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::swap_hotkey::test_swap_stake_old_hotkey_not_exist --exact --nocapture
#[test]
fn test_swap_stake_old_hotkey_not_exist() {
new_test_ext(1).execute_with(|| {
Expand All @@ -1056,12 +1056,15 @@ fn test_swap_stake_old_hotkey_not_exist() {
let subnet_owner_hotkey = U256::from(1002);
let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey);

let alpha = AlphaBalance::from(1000);
let alpha_share = U64F64::from_num(1234);
let mut weight = Weight::zero();
let netuid = NetUid::from(1);

// Initialize Stake for old_hotkey
Alpha::<Test>::insert((old_hotkey, coldkey, netuid), alpha_share);
TotalHotkeyAlpha::<Test>::insert(old_hotkey, netuid, alpha);
TotalHotkeyShares::<Test>::insert(old_hotkey, netuid, alpha_share);

// Ensure old_hotkey has a stake
assert!(Alpha::<Test>::contains_key((old_hotkey, coldkey, netuid)));
Expand Down
Loading
Loading