From 07e46e312b56dd129d5a9b73cb9f5080db1d0e45 Mon Sep 17 00:00:00 2001 From: const Date: Mon, 22 Jul 2024 12:28:42 -0500 Subject: [PATCH 1/6] initial --- pallets/subtensor/src/lib.rs | 2 +- pallets/subtensor/src/swap_hotkey.rs | 280 +++++++++++++++++++++++++++ 2 files changed, 281 insertions(+), 1 deletion(-) create mode 100644 pallets/subtensor/src/swap_hotkey.rs diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index f7824e2a3..cfb3a5828 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -367,7 +367,7 @@ pub mod pallet { pub type TotalColdkeyStake = StorageMap<_, Identity, T::AccountId, u64, ValueQuery, DefaultAccountTake>; #[pallet::storage] - /// MAP (hot, cold) --> stake | Returns a tuple (u64: stakes, u64: block_number) + /// MAP (hot, cold) --> u64, u64) | Returns a tuple (u64: stakes, u64: block_number) pub type TotalHotkeyColdkeyStakesThisInterval = StorageDoubleMap< _, Identity, diff --git a/pallets/subtensor/src/swap_hotkey.rs b/pallets/subtensor/src/swap_hotkey.rs new file mode 100644 index 000000000..068b24b78 --- /dev/null +++ b/pallets/subtensor/src/swap_hotkey.rs @@ -0,0 +1,280 @@ +use super::*; +use crate::MIN_BALANCE_TO_PERFORM_COLDKEY_SWAP; +use frame_support::traits::fungible::Mutate; +use frame_support::traits::tokens::Preservation; +use frame_support::{storage::IterableStorageDoubleMap, weights::Weight}; +use sp_core::{Get, U256}; + +impl Pallet { + /// Swaps the hotkey of a coldkey account. + /// + /// # Arguments + /// + /// * `origin` - The origin of the transaction, and also the coldkey account. + /// * `old_hotkey` - The old hotkey to be swapped. + /// * `new_hotkey` - The new hotkey to replace the old one. + /// + /// # Returns + /// + /// * `DispatchResultWithPostInfo` - The result of the dispatch. + /// + /// # Errors + /// + /// * `NonAssociatedColdKey` - If the coldkey does not own the old hotkey. + /// * `HotKeySetTxRateLimitExceeded` - If the transaction rate limit is exceeded. + /// * `NewHotKeyIsSameWithOld` - If the new hotkey is the same as the old hotkey. + /// * `HotKeyAlreadyRegisteredInSubNet` - If the new hotkey is already registered in the subnet. + /// * `NotEnoughBalanceToPaySwapHotKey` - If there is not enough balance to pay for the swap. + pub fn do_swap_hotkey( + origin: T::RuntimeOrigin, + old_hotkey: &T::AccountId, + new_hotkey: &T::AccountId, + ) -> DispatchResultWithPostInfo { + // Ensure the origin is signed and get the coldkey + let coldkey = ensure_signed(origin)?; + + // Check if the coldkey is in arbitration + ensure!( + !Self::coldkey_in_arbitration(&coldkey), + Error::::ColdkeyIsInArbitration + ); + + // Initialize the weight for this operation + let mut weight = T::DbWeight::get().reads(2); + + // Ensure the new hotkey is different from the old one + ensure!(old_hotkey != new_hotkey, Error::::NewHotKeyIsSameWithOld); + // Ensure the new hotkey is not already registered on any network + ensure!( + !Self::is_hotkey_registered_on_any_network(new_hotkey), + Error::::HotKeyAlreadyRegisteredInSubNet + ); + + // Update the weight for the checks above + weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 0)); + // Ensure the coldkey owns the old hotkey + ensure!( + Self::coldkey_owns_hotkey(&coldkey, old_hotkey), + Error::::NonAssociatedColdKey + ); + + // Get the current block number + let block: u64 = Self::get_current_block_as_u64(); + // Ensure the transaction rate limit is not exceeded + ensure!( + !Self::exceeds_tx_rate_limit(Self::get_last_tx_block(&coldkey), block), + Error::::HotKeySetTxRateLimitExceeded + ); + + // Update the weight for reading the total networks + weight.saturating_accrue( + T::DbWeight::get().reads((TotalNetworks::::get().saturating_add(1u16)) as u64), + ); + + // Get the cost for swapping the key + let swap_cost = Self::get_key_swap_cost(); + log::debug!("Swap cost: {:?}", swap_cost); + + // Ensure the coldkey has enough balance to pay for the swap + ensure!( + Self::can_remove_balance_from_coldkey_account(&coldkey, swap_cost), + Error::::NotEnoughBalanceToPaySwapHotKey + ); + // Remove the swap cost from the coldkey's account + let actual_burn_amount = Self::remove_balance_from_coldkey_account(&coldkey, swap_cost)?; + // Burn the tokens + Self::burn_tokens(actual_burn_amount); + + // Perform the hotkey swap + Self::perform_hotkey_swap(old_hotkey, new_hotkey, &coldkey, &mut weight); + + // Update the last transaction block for the coldkey + Self::set_last_tx_block(&coldkey, block); + weight.saturating_accrue(T::DbWeight::get().writes(1)); + + // Emit an event for the hotkey swap + Self::deposit_event(Event::HotkeySwapped { + coldkey, + old_hotkey: old_hotkey.clone(), + new_hotkey: new_hotkey.clone(), + }); + + // Return the weight of the operation + Ok(Some(weight).into()) + } + + pub fn perform_hotkey_swap( old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, coldkey: &T::AccountId, weight: &mut Weight ) { + + // 1. Swap owner. + // Owner( hotkey ) -> coldkey -- the coldkey that owns the hotkey. + Owner::::remove(old_hotkey); + Owner::::insert(new_hotkey, coldkey.clone()); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); + + // 2. Swap OwnedHotkeys. + // OwnedHotkeys( coldkey ) -> Vec -- the hotkeys that the coldkey owns. + let mut hotkeys = OwnedHotkeys::::get(coldkey); + // Add the new key if needed. + if !hotkeys.contains(new_hotkey) { + hotkeys.push(new_hotkey.clone()); + } + // Remove the old key. + hotkeys.retain(|hk| *hk != *old_hotkey); + OwnedHotkeys::::insert(coldkey, hotkeys); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); + + // 3. Swap total hotkey stake. + // TotalHotkeyStake( hotkey ) -> stake -- the total stake that the hotkey has across all delegates. + let old_total_hotkey_stake = TotalHotkeyStake::::get( old_hotkey ); // Get the old total hotkey stake. + let new_total_hotkey_stake = TotalHotkeyStake::::get( new_hotkey ); // Get the new total hotkey stake. + TotalHotkeyStake::::remove( old_hotkey ); // Remove the old total hotkey stake. + TotalHotkeyStake::::insert( new_hotkey, old_total_hotkey_stake.saturating_add( new_total_hotkey_stake ) ); // Insert the new total hotkey stake via the addition. + weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2)); + + // Swap total hotkey stakes. + // TotalHotkeyColdkeyStakesThisInterval( hotkey ) --> (u64: stakes, u64: block_number) + let stake_tuples: Vec<(T::AccountId, (u64, u64))> = TotalHotkeyColdkeyStakesThisInterval::::iter_prefix(old_hotkey).collect(); + for (coldkey, stake_tup) in stake_tuples { + // NOTE: You could use this to increase your allowed stake operations but this would cost. + TotalHotkeyColdkeyStakesThisInterval::::insert(new_hotkey, &coldkey, stake_tup); + TotalHotkeyColdkeyStakesThisInterval::::remove(old_hotkey, &coldkey); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + } + + // Swap LastTxBlock + // LastTxBlock( hotkey ) --> u64 -- the last transaction block for the hotkey. + let old_last_tx_block: u64 = LastTxBlock::::get( old_hotkey ); + LastTxBlock::::remove( old_hotkey ); + LastTxBlock::::insert( new_hotkey, Self::get_current_block_as_u64() ); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + + // Swap LastTxBlockDelegateTake + // LastTxBlockDelegateTake( hotkey ) --> u64 -- the last transaction block for the hotkey delegate take. + LastTxBlockDelegateTake::::remove( old_hotkey ); + LastTxBlockDelegateTake::::insert( new_hotkey, Self::get_current_block_as_u64() ); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + + // Swap Senate members. + // Senate( hotkey ) --> ? + if T::SenateMembers::is_member(old_hotkey) { + T::SenateMembers::swap_member(old_hotkey, new_hotkey).map_err(|e| e.error)?; + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + } + + // 4. 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)); + + // Swap all subnet specific info. + let all_netuid: Vec = Self::get_all_subnet_netuids(); + for netuid in all_netuids { + // 7.1 Remove the previous hotkey and insert the new hotkey from membership. + // IsNetworkMember( hotkey, netuid ) -> bool -- is the hotkey a subnet member. + let is_network_member: bool = IsNetworkMember::::get( old_hotkey, netuid ); + IsNetworkMember::::remove( old_hotkey, netuid ); + IsNetworkMember::::insert( new_hotkey, netuid, is_network_member ); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + + // 7.2 Swap Uids + Keys. + // Keys( netuid, hotkey ) -> uid -- the uid the hotkey has in the network if it is a member. + // Uids( netuid, hotkey ) -> uid -- the uids that the hotkey has. + if is_network_member { + // 7.2.1 Swap the UIDS + let old_uid: u16 = Uids::::get(netuid, old_hotkey); + Uids::::remove(netuid, old_hotkey); + Uids::::insert(netuid, new_hotkey, old_uid); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + + // 7.2.2 Swap the keys. + Keys::::insert(netuid, old_uid, new_hotkey.clone()); + weight.saturating_accrue(T::DbWeight::get().reads_writes(0, 1)); + } + + // 7.3 Swap Prometheus. + // Prometheus( netuid, hotkey ) -> prometheus -- the prometheus data that a hotkey has in the network. + if is_network_member { + let old_prometheus_info: PrometheusInfo = Prometheus::::get(netuid, old_hotkey); + Prometheus::::remove(netuid, old_hotkey); + Prometheus::::insert(netuid, new_hotkey, old_prometheus_info); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + } + + // 7.4. Swap axons. + // Axons( netuid, hotkey ) -> axon -- the axon that the hotkey has. + if is_network_member { + let old_axon_info: AxonInfo = Axons::::get(netuid, old_hotkey); + Axons::::remove(netuid, old_hotkey); + Axons::::insert(netuid, new_hotkey, old_axon_info); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + } + + // 7.5 Swap WeightCommits + // WeightCommits( hotkey ) --> Vec -- the weight commits for the hotkey. + if is_network_member { + if let Ok(old_weight_commits) = WeightCommits::::try_get(old_hotkey) { + WeightCommits::::remove(old_hotkey); + WeightCommits::::insert(new_hotkey, old_weight_commits); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + } + } + + // 7.5. Swap the subnet loaded emission. + // LoadedEmission( netuid ) --> Vec<(hotkey, u64)> -- the loaded emission for the subnet. + if is_network_member { + if let Some(mut old_loaded_emission) = LoadedEmission::::get(netuid) { + for emission in old_loaded_emission.iter_mut() { + if emission.0 == *old_hotkey { + emission.0 = new_hotkey.clone(); + } + } + LoadedEmission::::remove(netuid); + LoadedEmission::::insert(netuid, old_loaded_emission); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + } + } + + } + + // Swap Stake. + // Stake( hotkey, coldkey ) -> stake -- the stake that the hotkey controls on behalf of the coldkey. + let stakes: Vec<(T::AccountId, u64)> = Stake::::iter_prefix(old_hotkey).collect(); + // Clear the entire old prefix here. + let _ = Stake::::clear_prefix( old_hotkey, stakes.len() as u32, None ); + // Iterate over all the staking rows and insert them into the new hotkey. + for (coldkey, old_stake_amount) in stakes { + weight.saturating_accrue(T::DbWeight::get().reads(1)); + + // Swap Stake value + // Stake( hotkey, coldkey ) -> stake -- the stake that the hotkey controls on behalf of the coldkey. + // Get the new stake value. + let new_stake_value: u64 = Stake::::get(new_hotkey, &coldkey); + // Insert the new stake value. + Stake::::insert(new_hotkey, &coldkey, new_stake_value.saturating_add(old_stake_amount)); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); + + // Swap StakingHotkeys. + // StakingHotkeys( coldkey ) --> Vec -- the hotkeys that the coldkey stakes. + let mut staking_hotkeys = StakingHotkeys::::get(&coldkey); + staking_hotkeys.retain(|hk| *hk != *old_hotkey && *hk != *new_hotkey); + staking_hotkeys.push(new_hotkey.clone()); + StakingHotkeys::::insert(coldkey.clone(), staking_hotkeys); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); + } + } + + pub fn swap_senate_member( + old_hotkey: &T::AccountId, + new_hotkey: &T::AccountId, + weight: &mut Weight, + ) -> DispatchResult { + weight.saturating_accrue(T::DbWeight::get().reads(1)); + if T::SenateMembers::is_member(old_hotkey) { + T::SenateMembers::swap_member(old_hotkey, new_hotkey).map_err(|e| e.error)?; + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + } + Ok(()) + } +} From 0432b53d428e1f7f5d2b449bbcb0a649e0e6a01d Mon Sep 17 00:00:00 2001 From: const Date: Mon, 22 Jul 2024 13:26:28 -0500 Subject: [PATCH 2/6] add tests --- pallets/subtensor/src/lib.rs | 35 +- pallets/subtensor/src/swap.rs | 417 +------------- pallets/subtensor/src/swap_hotkey.rs | 47 +- pallets/subtensor/tests/swap.rs | 719 +------------------------ pallets/subtensor/tests/swap_hotkey.rs | 542 +++++++++++++++++++ 5 files changed, 604 insertions(+), 1156 deletions(-) create mode 100644 pallets/subtensor/tests/swap_hotkey.rs diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index cfb3a5828..d492b5477 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -45,6 +45,7 @@ mod root; mod serving; mod staking; mod swap; +mod swap_hotkey; mod uids; mod utils; mod weights; @@ -272,7 +273,7 @@ pub mod pallet { } #[pallet::storage] - pub(super) type SenateRequiredStakePercentage = + pub type SenateRequiredStakePercentage = StorageValue<_, u64, ValueQuery, DefaultSenateRequiredStakePercentage>; /// ============================ @@ -796,15 +797,15 @@ pub mod pallet { } #[pallet::storage] // --- ITEM ( tx_rate_limit ) - pub(super) type TxRateLimit = StorageValue<_, u64, ValueQuery, DefaultTxRateLimit>; + pub type TxRateLimit = StorageValue<_, u64, ValueQuery, DefaultTxRateLimit>; #[pallet::storage] // --- ITEM ( tx_rate_limit ) - pub(super) type TxDelegateTakeRateLimit = + pub type TxDelegateTakeRateLimit = StorageValue<_, u64, ValueQuery, DefaultTxDelegateTakeRateLimit>; #[pallet::storage] // --- MAP ( key ) --> last_block pub type LastTxBlock = StorageMap<_, Identity, T::AccountId, u64, ValueQuery, DefaultLastTxBlock>; #[pallet::storage] // --- MAP ( key ) --> last_block - pub(super) type LastTxBlockDelegateTake = + pub type LastTxBlockDelegateTake = StorageMap<_, Identity, T::AccountId, u64, ValueQuery, DefaultLastTxBlock>; /// Default value for serving rate limit. @@ -1084,41 +1085,41 @@ pub mod pallet { StorageMap<_, Identity, u16, Vec<(T::AccountId, u64, u64)>, OptionQuery>; #[pallet::storage] // --- DMAP ( netuid ) --> active - pub(super) type Active = + pub type Active = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyBoolVec>; #[pallet::storage] // --- DMAP ( netuid ) --> rank - pub(super) type Rank = + pub type Rank = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] // --- DMAP ( netuid ) --> trust - pub(super) type Trust = + pub type Trust = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] // --- DMAP ( netuid ) --> consensus - pub(super) type Consensus = + pub type Consensus = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] // --- DMAP ( netuid ) --> incentive - pub(super) type Incentive = + pub type Incentive = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] // --- DMAP ( netuid ) --> dividends - pub(super) type Dividends = + pub type Dividends = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] // --- DMAP ( netuid ) --> emission - pub(super) type Emission = + pub type Emission = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU64Vec>; #[pallet::storage] // --- DMAP ( netuid ) --> last_update - pub(super) type LastUpdate = + pub type LastUpdate = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU64Vec>; #[pallet::storage] // --- DMAP ( netuid ) --> validator_trust - pub(super) type ValidatorTrust = + pub type ValidatorTrust = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] // --- DMAP ( netuid ) --> pruning_scores - pub(super) type PruningScores = + pub type PruningScores = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] // --- DMAP ( netuid ) --> validator_permit - pub(super) type ValidatorPermit = + pub type ValidatorPermit = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyBoolVec>; #[pallet::storage] // --- DMAP ( netuid, uid ) --> weights - pub(super) type Weights = StorageDoubleMap< + pub type Weights = StorageDoubleMap< _, Identity, u16, @@ -1129,7 +1130,7 @@ pub mod pallet { DefaultWeights, >; #[pallet::storage] // --- DMAP ( netuid, uid ) --> bonds - pub(super) type Bonds = StorageDoubleMap< + pub type Bonds = StorageDoubleMap< _, Identity, u16, diff --git a/pallets/subtensor/src/swap.rs b/pallets/subtensor/src/swap.rs index 8e4ca5cc9..5d8f66c68 100644 --- a/pallets/subtensor/src/swap.rs +++ b/pallets/subtensor/src/swap.rs @@ -6,100 +6,6 @@ use frame_support::{storage::IterableStorageDoubleMap, weights::Weight}; use sp_core::{Get, U256}; impl Pallet { - /// Swaps the hotkey of a coldkey account. - /// - /// # Arguments - /// - /// * `origin` - The origin of the transaction, and also the coldkey account. - /// * `old_hotkey` - The old hotkey to be swapped. - /// * `new_hotkey` - The new hotkey to replace the old one. - /// - /// # Returns - /// - /// * `DispatchResultWithPostInfo` - The result of the dispatch. - /// - /// # Errors - /// - /// * `NonAssociatedColdKey` - If the coldkey does not own the old hotkey. - /// * `HotKeySetTxRateLimitExceeded` - If the transaction rate limit is exceeded. - /// * `NewHotKeyIsSameWithOld` - If the new hotkey is the same as the old hotkey. - /// * `HotKeyAlreadyRegisteredInSubNet` - If the new hotkey is already registered in the subnet. - /// * `NotEnoughBalanceToPaySwapHotKey` - If there is not enough balance to pay for the swap. - pub fn do_swap_hotkey( - origin: T::RuntimeOrigin, - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - ) -> DispatchResultWithPostInfo { - let coldkey = ensure_signed(origin)?; - - ensure!( - !Self::coldkey_in_arbitration(&coldkey), - Error::::ColdkeyIsInArbitration - ); - - let mut weight = T::DbWeight::get().reads(2); - - ensure!(old_hotkey != new_hotkey, Error::::NewHotKeyIsSameWithOld); - ensure!( - !Self::is_hotkey_registered_on_any_network(new_hotkey), - Error::::HotKeyAlreadyRegisteredInSubNet - ); - - weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 0)); - ensure!( - Self::coldkey_owns_hotkey(&coldkey, old_hotkey), - Error::::NonAssociatedColdKey - ); - - let block: u64 = Self::get_current_block_as_u64(); - ensure!( - !Self::exceeds_tx_rate_limit(Self::get_last_tx_block(&coldkey), block), - Error::::HotKeySetTxRateLimitExceeded - ); - - weight.saturating_accrue( - T::DbWeight::get().reads((TotalNetworks::::get().saturating_add(1u16)) as u64), - ); - - let swap_cost = Self::get_key_swap_cost(); - log::debug!("Swap cost: {:?}", swap_cost); - - ensure!( - Self::can_remove_balance_from_coldkey_account(&coldkey, swap_cost), - Error::::NotEnoughBalanceToPaySwapHotKey - ); - let actual_burn_amount = Self::remove_balance_from_coldkey_account(&coldkey, swap_cost)?; - Self::burn_tokens(actual_burn_amount); - - Self::swap_owner(old_hotkey, new_hotkey, &coldkey, &mut weight); - Self::swap_total_hotkey_stake(old_hotkey, new_hotkey, &mut weight); - Self::swap_delegates(old_hotkey, new_hotkey, &mut weight); - Self::swap_stake(old_hotkey, new_hotkey, &mut weight); - - // Store the value of is_network_member for the old key - let netuid_is_member: Vec = Self::get_netuid_is_member(old_hotkey, &mut weight); - - Self::swap_is_network_member(old_hotkey, new_hotkey, &netuid_is_member, &mut weight); - Self::swap_axons(old_hotkey, new_hotkey, &netuid_is_member, &mut weight); - Self::swap_keys(old_hotkey, new_hotkey, &netuid_is_member, &mut weight); - Self::swap_loaded_emission(old_hotkey, new_hotkey, &netuid_is_member, &mut weight); - Self::swap_uids(old_hotkey, new_hotkey, &netuid_is_member, &mut weight); - Self::swap_prometheus(old_hotkey, new_hotkey, &netuid_is_member, &mut weight); - Self::swap_senate_member(old_hotkey, new_hotkey, &mut weight)?; - - Self::swap_total_hotkey_coldkey_stakes_this_interval(old_hotkey, new_hotkey, &mut weight); - - Self::set_last_tx_block(&coldkey, block); - weight.saturating_accrue(T::DbWeight::get().writes(1)); - - Self::deposit_event(Event::HotkeySwapped { - coldkey, - old_hotkey: old_hotkey.clone(), - new_hotkey: new_hotkey.clone(), - }); - - Ok(Some(weight).into()) - } /// Swaps the coldkey associated with a set of hotkeys from an old coldkey to a new coldkey. /// @@ -472,316 +378,6 @@ impl Pallet { netuid_is_member } - /// Swaps the owner of the hotkey. - /// - /// # Arguments - /// - /// * `old_hotkey` - The old hotkey. - /// * `new_hotkey` - The new hotkey. - /// * `coldkey` - The coldkey owning the hotkey. - /// * `weight` - The weight of the transaction. - /// - pub fn swap_owner( - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - coldkey: &T::AccountId, - weight: &mut Weight, - ) { - Owner::::remove(old_hotkey); - Owner::::insert(new_hotkey, coldkey.clone()); - - // Update OwnedHotkeys map - let mut hotkeys = OwnedHotkeys::::get(coldkey); - if !hotkeys.contains(new_hotkey) { - hotkeys.push(new_hotkey.clone()); - } - hotkeys.retain(|hk| *hk != *old_hotkey); - OwnedHotkeys::::insert(coldkey, hotkeys); - - weight.saturating_accrue(T::DbWeight::get().writes(2)); - } - - /// Swaps the total stake of the hotkey. - /// - /// # Arguments - /// - /// * `old_hotkey` - The old hotkey. - /// * `new_hotkey` - The new hotkey. - /// * `weight` - The weight of the transaction. - /// - /// # Weight Calculation - /// - /// * Reads: 1 if the old hotkey exists, otherwise 1 for the failed read. - /// * Writes: 2 if the old hotkey exists (one for removal and one for insertion). - pub fn swap_total_hotkey_stake( - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - weight: &mut Weight, - ) { - if let Ok(total_hotkey_stake) = TotalHotkeyStake::::try_get(old_hotkey) { - TotalHotkeyStake::::remove(old_hotkey); - TotalHotkeyStake::::insert(new_hotkey, total_hotkey_stake); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - } else { - weight.saturating_accrue(T::DbWeight::get().reads(1)); - } - } - - /// Swaps the delegates of the hotkey. - /// - /// # Arguments - /// - /// * `old_hotkey` - The old hotkey. - /// * `new_hotkey` - The new hotkey. - /// * `weight` - The weight of the transaction. - /// - /// # Weight Calculation - /// - /// * Reads: 1 if the old hotkey exists, otherwise 1 for the failed read. - /// * Writes: 2 if the old hotkey exists (one for removal and one for insertion). - pub fn swap_delegates( - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - weight: &mut Weight, - ) { - if let Ok(delegate_take) = Delegates::::try_get(old_hotkey) { - Delegates::::remove(old_hotkey); - Delegates::::insert(new_hotkey, delegate_take); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - } else { - weight.saturating_accrue(T::DbWeight::get().reads(1)); - } - } - - /// Swaps the stake of the hotkey. - /// - /// # Arguments - /// - /// * `old_hotkey` - The old hotkey. - /// * `new_hotkey` - The new hotkey. - /// * `weight` - The weight of the transaction. - pub fn swap_stake(old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, weight: &mut Weight) { - let mut writes: u64 = 0; - let stakes: Vec<(T::AccountId, u64)> = Stake::::iter_prefix(old_hotkey).collect(); - let stake_count = stakes.len() as u32; - - for (coldkey, stake_amount) in stakes { - Stake::::insert(new_hotkey, &coldkey, stake_amount); - writes = writes.saturating_add(1u64); // One write for insert - - // Update StakingHotkeys map - let mut staking_hotkeys = StakingHotkeys::::get(&coldkey); - if !staking_hotkeys.contains(new_hotkey) { - staking_hotkeys.push(new_hotkey.clone()); - writes = writes.saturating_add(1u64); // One write for insert - } - if let Some(pos) = staking_hotkeys.iter().position(|x| x == old_hotkey) { - staking_hotkeys.remove(pos); - writes = writes.saturating_add(1u64); // One write for remove - } - StakingHotkeys::::insert(coldkey.clone(), staking_hotkeys); - writes = writes.saturating_add(1u64); // One write for insert - } - - // Clear the prefix for the old hotkey after transferring all stakes - let _ = Stake::::clear_prefix(old_hotkey, stake_count, None); - writes = writes.saturating_add(1); // One write for insert; // One write for clear_prefix - - // TODO: Remove all entries for old hotkey from StakingHotkeys map - - weight.saturating_accrue(T::DbWeight::get().writes(writes)); - } - - /// Swaps the network membership status of the hotkey. - /// - /// # Arguments - /// - /// * `old_hotkey` - The old hotkey. - /// * `new_hotkey` - The new hotkey. - /// * `netuid_is_member` - A vector of network IDs where the hotkey is a member. - /// * `weight` - The weight of the transaction. - pub fn swap_is_network_member( - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - netuid_is_member: &[u16], - weight: &mut Weight, - ) { - let _ = IsNetworkMember::::clear_prefix(old_hotkey, netuid_is_member.len() as u32, None); - weight.saturating_accrue(T::DbWeight::get().writes(netuid_is_member.len() as u64)); - for netuid in netuid_is_member.iter() { - IsNetworkMember::::insert(new_hotkey, netuid, true); - weight.saturating_accrue(T::DbWeight::get().writes(1)); - } - } - - /// Swaps the axons of the hotkey. - /// - /// # Arguments - /// - /// * `old_hotkey` - The old hotkey. - /// * `new_hotkey` - The new hotkey. - /// * `netuid_is_member` - A vector of network IDs where the hotkey is a member. - /// * `weight` - The weight of the transaction. - /// - /// # Weight Calculation - /// - /// * Reads: 1 for each network ID if the old hotkey exists in that network. - /// * Writes: 2 for each network ID if the old hotkey exists in that network (one for removal and one for insertion). - pub fn swap_axons( - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - netuid_is_member: &[u16], - weight: &mut Weight, - ) { - for netuid in netuid_is_member.iter() { - if let Ok(axon_info) = Axons::::try_get(netuid, old_hotkey) { - Axons::::remove(netuid, old_hotkey); - Axons::::insert(netuid, new_hotkey, axon_info); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - } else { - weight.saturating_accrue(T::DbWeight::get().reads(1)); - } - } - } - - /// Swaps the references in the keys storage map of the hotkey. - /// - /// # Arguments - /// - /// * `old_hotkey` - The old hotkey. - /// * `new_hotkey` - The new hotkey. - /// * `netuid_is_member` - A vector of network IDs where the hotkey is a member. - /// * `weight` - The weight of the transaction. - pub fn swap_keys( - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - netuid_is_member: &[u16], - weight: &mut Weight, - ) { - let mut writes: u64 = 0; - for netuid in netuid_is_member { - let keys: Vec<(u16, T::AccountId)> = Keys::::iter_prefix(netuid).collect(); - for (uid, key) in keys { - if key == *old_hotkey { - log::info!("old hotkey found: {:?}", old_hotkey); - Keys::::insert(netuid, uid, new_hotkey.clone()); - } - writes = writes.saturating_add(2u64); - } - } - log::info!("writes: {:?}", writes); - weight.saturating_accrue(T::DbWeight::get().writes(writes)); - } - - /// Swaps the loaded emission of the hotkey. - /// - /// # Arguments - /// - /// * `old_hotkey` - The old hotkey. - /// * `new_hotkey` - The new hotkey. - /// * `netuid_is_member` - A vector of network IDs where the hotkey is a member. - /// * `weight` - The weight of the transaction. - /// - pub fn swap_loaded_emission( - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - netuid_is_member: &[u16], - weight: &mut Weight, - ) { - for netuid in netuid_is_member { - if let Some(mut emissions) = LoadedEmission::::get(netuid) { - for emission in emissions.iter_mut() { - if emission.0 == *old_hotkey { - emission.0 = new_hotkey.clone(); - } - } - LoadedEmission::::insert(netuid, emissions); - } - } - weight.saturating_accrue(T::DbWeight::get().writes(netuid_is_member.len() as u64)); - } - - /// Swaps the UIDs of the hotkey. - /// - /// # Arguments - /// - /// * `old_hotkey` - The old hotkey. - /// * `new_hotkey` - The new hotkey. - /// * `netuid_is_member` - A vector of network IDs where the hotkey is a member. - /// * `weight` - The weight of the transaction. - /// - pub fn swap_uids( - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - netuid_is_member: &[u16], - weight: &mut Weight, - ) { - for netuid in netuid_is_member.iter() { - if let Ok(uid) = Uids::::try_get(netuid, old_hotkey) { - Uids::::remove(netuid, old_hotkey); - Uids::::insert(netuid, new_hotkey, uid); - weight.saturating_accrue(T::DbWeight::get().writes(2)); - } - } - } - - /// Swaps the Prometheus data of the hotkey. - /// - /// # Arguments - /// - /// * `old_hotkey` - The old hotkey. - /// * `new_hotkey` - The new hotkey. - /// * `netuid_is_member` - A vector of network IDs where the hotkey is a member. - /// * `weight` - The weight of the transaction. - /// - /// # Weight Calculation - /// - /// * Reads: 1 for each network ID if the old hotkey exists in that network. - /// * Writes: 2 for each network ID if the old hotkey exists in that network (one for removal and one for insertion). - pub fn swap_prometheus( - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - netuid_is_member: &[u16], - weight: &mut Weight, - ) { - for netuid in netuid_is_member.iter() { - if let Ok(prometheus_info) = Prometheus::::try_get(netuid, old_hotkey) { - Prometheus::::remove(netuid, old_hotkey); - Prometheus::::insert(netuid, new_hotkey, prometheus_info); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - } else { - weight.saturating_accrue(T::DbWeight::get().reads(1)); - } - } - } - - /// Swaps the total hotkey-coldkey stakes for the current interval. - /// - /// # Arguments - /// - /// * `old_hotkey` - The old hotkey. - /// * `new_hotkey` - The new hotkey. - /// * `weight` - The weight of the transaction. - /// - pub fn swap_total_hotkey_coldkey_stakes_this_interval( - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - weight: &mut Weight, - ) { - let stakes: Vec<(T::AccountId, (u64, u64))> = - TotalHotkeyColdkeyStakesThisInterval::::iter_prefix(old_hotkey).collect(); - log::info!("Stakes to swap: {:?}", stakes); - for (coldkey, stake) in stakes { - log::info!( - "Swapping stake for coldkey: {:?}, stake: {:?}", - coldkey, - stake - ); - TotalHotkeyColdkeyStakesThisInterval::::insert(new_hotkey, &coldkey, stake); - TotalHotkeyColdkeyStakesThisInterval::::remove(old_hotkey, &coldkey); - weight.saturating_accrue(T::DbWeight::get().writes(2)); // One write for insert and one for remove - } - } /// Swaps the total stake associated with a coldkey from the old coldkey to the new coldkey. /// @@ -1040,16 +636,5 @@ impl Pallet { weight.saturating_accrue(T::DbWeight::get().reads(TotalNetworks::::get() as u64)); } - pub fn swap_senate_member( - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - weight: &mut Weight, - ) -> DispatchResult { - weight.saturating_accrue(T::DbWeight::get().reads(1)); - if T::SenateMembers::is_member(old_hotkey) { - T::SenateMembers::swap_member(old_hotkey, new_hotkey).map_err(|e| e.error)?; - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - } - Ok(()) - } + } diff --git a/pallets/subtensor/src/swap_hotkey.rs b/pallets/subtensor/src/swap_hotkey.rs index 068b24b78..222a4ff37 100644 --- a/pallets/subtensor/src/swap_hotkey.rs +++ b/pallets/subtensor/src/swap_hotkey.rs @@ -103,7 +103,7 @@ impl Pallet { Ok(Some(weight).into()) } - pub fn perform_hotkey_swap( old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, coldkey: &T::AccountId, weight: &mut Weight ) { + pub fn perform_hotkey_swap( old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, coldkey: &T::AccountId, weight: &mut Weight ) -> DispatchResult { // 1. Swap owner. // Owner( hotkey ) -> coldkey -- the coldkey that owns the hotkey. @@ -169,7 +169,7 @@ impl Pallet { weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); // Swap all subnet specific info. - let all_netuid: Vec = Self::get_all_subnet_netuids(); + let all_netuids: Vec = Self::get_all_subnet_netuids(); for netuid in all_netuids { // 7.1 Remove the previous hotkey and insert the new hotkey from membership. // IsNetworkMember( hotkey, netuid ) -> bool -- is the hotkey a subnet member. @@ -183,40 +183,43 @@ impl Pallet { // Uids( netuid, hotkey ) -> uid -- the uids that the hotkey has. if is_network_member { // 7.2.1 Swap the UIDS - let old_uid: u16 = Uids::::get(netuid, old_hotkey); - Uids::::remove(netuid, old_hotkey); - Uids::::insert(netuid, new_hotkey, old_uid); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - - // 7.2.2 Swap the keys. - Keys::::insert(netuid, old_uid, new_hotkey.clone()); - weight.saturating_accrue(T::DbWeight::get().reads_writes(0, 1)); + if let Ok(old_uid) = Uids::::try_get(netuid, old_hotkey) { + Uids::::remove(netuid, old_hotkey); + Uids::::insert(netuid, new_hotkey, old_uid); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + + // 7.2.2 Swap the keys. + Keys::::insert(netuid, old_uid, new_hotkey.clone()); + weight.saturating_accrue(T::DbWeight::get().reads_writes(0, 1)); + } } // 7.3 Swap Prometheus. // Prometheus( netuid, hotkey ) -> prometheus -- the prometheus data that a hotkey has in the network. if is_network_member { - let old_prometheus_info: PrometheusInfo = Prometheus::::get(netuid, old_hotkey); - Prometheus::::remove(netuid, old_hotkey); - Prometheus::::insert(netuid, new_hotkey, old_prometheus_info); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + if let Ok(old_prometheus_info) = Prometheus::::try_get(netuid, old_hotkey) { + Prometheus::::remove(netuid, old_hotkey); + Prometheus::::insert(netuid, new_hotkey, old_prometheus_info); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + } } // 7.4. Swap axons. // Axons( netuid, hotkey ) -> axon -- the axon that the hotkey has. if is_network_member { - let old_axon_info: AxonInfo = Axons::::get(netuid, old_hotkey); - Axons::::remove(netuid, old_hotkey); - Axons::::insert(netuid, new_hotkey, old_axon_info); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + if let Ok(old_axon_info) = Axons::::try_get(netuid, old_hotkey) { + Axons::::remove(netuid, old_hotkey); + Axons::::insert(netuid, new_hotkey, old_axon_info); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + } } // 7.5 Swap WeightCommits // WeightCommits( hotkey ) --> Vec -- the weight commits for the hotkey. if is_network_member { - if let Ok(old_weight_commits) = WeightCommits::::try_get(old_hotkey) { - WeightCommits::::remove(old_hotkey); - WeightCommits::::insert(new_hotkey, old_weight_commits); + if let Ok(old_weight_commits) = WeightCommits::::try_get(netuid, old_hotkey) { + WeightCommits::::remove(netuid, old_hotkey); + WeightCommits::::insert(netuid, new_hotkey, old_weight_commits); weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); } } @@ -263,6 +266,8 @@ impl Pallet { StakingHotkeys::::insert(coldkey.clone(), staking_hotkeys); weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); } + + Ok(()) } pub fn swap_senate_member( diff --git a/pallets/subtensor/tests/swap.rs b/pallets/subtensor/tests/swap.rs index 21c3a983a..86fe109be 100644 --- a/pallets/subtensor/tests/swap.rs +++ b/pallets/subtensor/tests/swap.rs @@ -9,6 +9,7 @@ use mock::*; use pallet_subtensor::*; use sp_core::U256; +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap -- test_do_swap_hotkey_ok --exact --nocapture #[test] fn test_do_swap_hotkey_ok() { new_test_ext(1).execute_with(|| { @@ -42,15 +43,11 @@ fn test_do_swap_hotkey_ok() { ); // Verify other storage changes - assert_eq!( - SubtensorModule::get_total_stake_for_hotkey(&new_hotkey), - SubtensorModule::get_total_stake_for_hotkey(&old_hotkey) - ); - assert_eq!( + assert_ne!( SubtensorModule::get_delegate(new_hotkey.encode()), SubtensorModule::get_delegate(old_hotkey.encode()) ); - assert_eq!( + assert_ne!( SubtensorModule::get_last_tx_block(&new_hotkey), SubtensorModule::get_last_tx_block(&old_hotkey) ); @@ -62,29 +59,6 @@ fn test_do_swap_hotkey_ok() { } let mut weight = Weight::zero(); - // UIDs - for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight) { - assert_eq!( - Uids::::get(netuid, new_hotkey), - Uids::::get(netuid, old_hotkey) - ); - } - - // Prometheus - for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight) { - assert_eq!( - Prometheus::::get(netuid, new_hotkey), - Prometheus::::get(netuid, old_hotkey) - ); - } - - // LoadedEmission - for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight) { - assert_eq!( - LoadedEmission::::get(netuid).unwrap(), - LoadedEmission::::get(netuid).unwrap() - ); - } // IsNetworkMember for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight) { @@ -96,7 +70,7 @@ fn test_do_swap_hotkey_ok() { assert_eq!(Owner::::get(new_hotkey), coldkey); // TotalHotkeyStake - assert_eq!( + assert_ne!( TotalHotkeyStake::::get(new_hotkey), TotalHotkeyStake::::get(old_hotkey) ); @@ -129,185 +103,6 @@ fn test_do_swap_hotkey_ok() { }); } -#[test] -fn test_do_swap_hotkey_ok_robust() { - new_test_ext(1).execute_with(|| { - let num_subnets: u16 = 10; - let tempo: u16 = 13; - let swap_cost = 1_000_000_000u64; - - // Create 10 sets of keys - let mut old_hotkeys = vec![]; - let mut new_hotkeys = vec![]; - let mut coldkeys = vec![]; - - for i in 0..10 { - old_hotkeys.push(U256::from(i * 2 + 1)); - new_hotkeys.push(U256::from(i * 2 + 2)); - coldkeys.push(U256::from(i * 2 + 11)); - } - - // Setup initial state - for netuid in 1..=num_subnets { - add_network(netuid, tempo, 0); - SubtensorModule::set_max_registrations_per_block(netuid, 20); - SubtensorModule::set_target_registrations_per_interval(netuid, 1000); - log::info!( - "Registrations this interval for netuid {:?} is {:?}", - netuid, - SubtensorModule::get_target_registrations_per_interval(netuid) - ); - for i in 0..10 { - register_ok_neuron(netuid, old_hotkeys[i], coldkeys[i], 0); - } - } - - // Add balance to coldkeys for swap cost - for coldkey in coldkeys.iter().take(10) { - SubtensorModule::add_balance_to_coldkey_account(coldkey, swap_cost); - } - - // Add old_hotkeys[0] and old_hotkeys[1] to Senate - assert_ok!(SenateMembers::add_member( - RawOrigin::Root.into(), - old_hotkeys[0] - )); - assert_ok!(SenateMembers::add_member( - RawOrigin::Root.into(), - old_hotkeys[1] - )); - - // Verify initial Senate membership - assert!(Senate::is_member(&old_hotkeys[0])); - assert!(Senate::is_member(&old_hotkeys[1])); - assert!(!Senate::is_member(&new_hotkeys[0])); - assert!(!Senate::is_member(&new_hotkeys[1])); - - // Perform the swaps for only two hotkeys - assert_ok!(SubtensorModule::do_swap_hotkey( - <::RuntimeOrigin>::signed(coldkeys[0]), - &old_hotkeys[0], - &new_hotkeys[0] - )); - assert_ok!(SubtensorModule::do_swap_hotkey( - <::RuntimeOrigin>::signed(coldkeys[1]), - &old_hotkeys[1], - &new_hotkeys[1] - )); - - // Verify the swaps - for netuid in 1..=num_subnets { - for i in 0..10 { - if i == 0 || i == 1 { - assert_eq!( - SubtensorModule::get_owning_coldkey_for_hotkey(&new_hotkeys[i]), - coldkeys[i] - ); - assert_ne!( - SubtensorModule::get_owning_coldkey_for_hotkey(&old_hotkeys[i]), - coldkeys[i] - ); - - // Verify other storage changes - assert_eq!( - SubtensorModule::get_total_stake_for_hotkey(&new_hotkeys[i]), - SubtensorModule::get_total_stake_for_hotkey(&old_hotkeys[i]) - ); - - assert_eq!( - SubtensorModule::get_delegate(new_hotkeys[i].encode()), - SubtensorModule::get_delegate(old_hotkeys[i].encode()) - ); - - assert_eq!( - SubtensorModule::get_last_tx_block(&new_hotkeys[i]), - SubtensorModule::get_last_tx_block(&old_hotkeys[i]) - ); - - // Verify raw storage maps - // Stake - for (coldkey, stake_amount) in Stake::::iter_prefix(old_hotkeys[i]) { - assert_eq!(Stake::::get(new_hotkeys[i], coldkey), stake_amount); - } - - let mut weight = Weight::zero(); - // UIDs - for netuid in - SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight) - { - assert_eq!( - Uids::::get(netuid, new_hotkeys[i]), - Uids::::get(netuid, old_hotkeys[i]) - ); - } - - // Prometheus - for netuid in - SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight) - { - assert_eq!( - Prometheus::::get(netuid, new_hotkeys[i]), - Prometheus::::get(netuid, old_hotkeys[i]) - ); - } - - // LoadedEmission - for netuid in - SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight) - { - assert_eq!( - LoadedEmission::::get(netuid).unwrap(), - LoadedEmission::::get(netuid).unwrap() - ); - } - - // IsNetworkMember - for netuid in - SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight) - { - assert!(IsNetworkMember::::contains_key( - new_hotkeys[i], - netuid - )); - assert!(!IsNetworkMember::::contains_key( - old_hotkeys[i], - netuid - )); - } - - // Owner - assert_eq!(Owner::::get(new_hotkeys[i]), coldkeys[i]); - - // Keys - for (uid, hotkey) in Keys::::iter_prefix(netuid) { - if hotkey == old_hotkeys[i] { - assert_eq!(Keys::::get(netuid, uid), new_hotkeys[i]); - } - } - - // Verify Senate membership swap - assert!(!Senate::is_member(&old_hotkeys[i])); - assert!(Senate::is_member(&new_hotkeys[i])); - } else { - // Ensure other hotkeys remain unchanged - assert_eq!( - SubtensorModule::get_owning_coldkey_for_hotkey(&old_hotkeys[i]), - coldkeys[i] - ); - assert_ne!( - SubtensorModule::get_owning_coldkey_for_hotkey(&new_hotkeys[i]), - coldkeys[i] - ); - - // Verify Senate membership remains unchanged for other hotkeys - assert!(!Senate::is_member(&old_hotkeys[i])); - assert!(!Senate::is_member(&new_hotkeys[i])); - } - } - } - }); -} - #[test] fn test_swap_hotkey_tx_rate_limit_exceeded() { new_test_ext(1).execute_with(|| { @@ -402,7 +197,7 @@ fn test_swap_owner_success() { Owner::::insert(old_hotkey, coldkey); // Perform the swap - SubtensorModule::swap_owner(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); // Verify the swap assert_eq!(Owner::::get(new_hotkey), coldkey); @@ -422,7 +217,7 @@ fn test_swap_owner_old_hotkey_not_exist() { assert!(!Owner::::contains_key(old_hotkey)); // Perform the swap - SubtensorModule::swap_owner(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); // Verify the swap assert_eq!(Owner::::get(new_hotkey), coldkey); @@ -444,7 +239,7 @@ fn test_swap_owner_new_hotkey_already_exists() { Owner::::insert(new_hotkey, another_coldkey); // Perform the swap - SubtensorModule::swap_owner(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); // Verify the swap assert_eq!(Owner::::get(new_hotkey), coldkey); @@ -452,31 +247,12 @@ fn test_swap_owner_new_hotkey_already_exists() { }); } -#[test] -fn test_swap_owner_weight_update() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let mut weight = Weight::zero(); - - // Initialize Owner for old_hotkey - Owner::::insert(old_hotkey, coldkey); - - // Perform the swap - SubtensorModule::swap_owner(&old_hotkey, &new_hotkey, &coldkey, &mut weight); - - // Verify the weight update - let expected_weight = ::DbWeight::get().writes(2); - assert_eq!(weight, expected_weight); - }); -} - #[test] fn test_swap_total_hotkey_stake_success() { new_test_ext(1).execute_with(|| { let old_hotkey = U256::from(1); let new_hotkey = U256::from(2); + let coldkey = U256::from(3); let total_stake = 1000u64; let mut weight = Weight::zero(); @@ -484,7 +260,7 @@ fn test_swap_total_hotkey_stake_success() { TotalHotkeyStake::::insert(old_hotkey, total_stake); // Perform the swap - SubtensorModule::swap_total_hotkey_stake(&old_hotkey, &new_hotkey, &mut weight); + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); // Verify the swap assert_eq!(TotalHotkeyStake::::get(new_hotkey), total_stake); @@ -492,49 +268,14 @@ fn test_swap_total_hotkey_stake_success() { }); } -#[test] -fn test_swap_total_hotkey_stake_old_hotkey_not_exist() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let mut weight = Weight::zero(); - - // Ensure old_hotkey does not exist - assert!(!TotalHotkeyStake::::contains_key(old_hotkey)); - - // Perform the swap - SubtensorModule::swap_total_hotkey_stake(&old_hotkey, &new_hotkey, &mut weight); - // Verify that new_hotkey does not have a stake - assert!(!TotalHotkeyStake::::contains_key(new_hotkey)); - }); -} - -#[test] -fn test_swap_total_hotkey_stake_weight_update() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let total_stake = 1000u64; - let mut weight = Weight::zero(); - - // Initialize TotalHotkeyStake for old_hotkey - TotalHotkeyStake::::insert(old_hotkey, total_stake); - - // Perform the swap - SubtensorModule::swap_total_hotkey_stake(&old_hotkey, &new_hotkey, &mut weight); - - // Verify the weight update - let expected_weight = ::DbWeight::get().reads_writes(1, 2); - assert_eq!(weight, expected_weight); - }); -} #[test] fn test_swap_delegates_success() { new_test_ext(1).execute_with(|| { let old_hotkey = U256::from(1); let new_hotkey = U256::from(2); + let coldkey = U256::from(3); let delegate_take = 10u16; let mut weight = Weight::zero(); @@ -542,7 +283,7 @@ fn test_swap_delegates_success() { Delegates::::insert(old_hotkey, delegate_take); // Perform the swap - SubtensorModule::swap_delegates(&old_hotkey, &new_hotkey, &mut weight); + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); // Verify the swap assert_eq!(Delegates::::get(new_hotkey), delegate_take); @@ -550,29 +291,12 @@ fn test_swap_delegates_success() { }); } -#[test] -fn test_swap_delegates_old_hotkey_not_exist() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let mut weight = Weight::zero(); - - // Ensure old_hotkey does not exist - assert!(!Delegates::::contains_key(old_hotkey)); - - // Perform the swap - SubtensorModule::swap_delegates(&old_hotkey, &new_hotkey, &mut weight); - - // Verify that new_hotkey does not have a delegate - assert!(!Delegates::::contains_key(new_hotkey)); - }); -} - #[test] fn test_swap_delegates_weight_update() { new_test_ext(1).execute_with(|| { let old_hotkey = U256::from(1); let new_hotkey = U256::from(2); + let coldkey = U256::from(3); let delegate_take = 10u16; let mut weight = Weight::zero(); @@ -580,7 +304,7 @@ fn test_swap_delegates_weight_update() { Delegates::::insert(old_hotkey, delegate_take); // Perform the swap - SubtensorModule::swap_delegates(&old_hotkey, &new_hotkey, &mut weight); + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); // Verify the weight update let expected_weight = ::DbWeight::get().reads_writes(1, 2); @@ -601,7 +325,7 @@ fn test_swap_stake_success() { Stake::::insert(old_hotkey, coldkey, stake_amount); // Perform the swap - SubtensorModule::swap_stake(&old_hotkey, &new_hotkey, &mut weight); + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); // Verify the swap assert_eq!(Stake::::get(new_hotkey, coldkey), stake_amount); @@ -625,7 +349,7 @@ fn test_swap_stake_old_hotkey_not_exist() { assert!(Stake::::contains_key(old_hotkey, coldkey)); // Perform the swap - SubtensorModule::swap_stake(&old_hotkey, &new_hotkey, &mut weight); + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); // Verify that new_hotkey has the stake and old_hotkey does not assert!(Stake::::contains_key(new_hotkey, coldkey)); @@ -633,390 +357,6 @@ fn test_swap_stake_old_hotkey_not_exist() { }); } -#[test] -fn test_swap_stake_weight_update() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let stake_amount = 1000u64; - let mut weight = Weight::zero(); - - // Initialize Stake for old_hotkey - Stake::::insert(old_hotkey, coldkey, stake_amount); - - // Perform the swap - SubtensorModule::swap_stake(&old_hotkey, &new_hotkey, &mut weight); - - // Verify the weight update - let expected_weight = ::DbWeight::get().writes(4); - assert_eq!(weight, expected_weight); - }); -} - -#[test] -fn test_swap_is_network_member_success() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let netuid_is_member = vec![1u16, 2u16]; - let mut weight = Weight::zero(); - - // Initialize IsNetworkMember for old_hotkey - for netuid in &netuid_is_member { - IsNetworkMember::::insert(old_hotkey, netuid, true); - } - - // Perform the swap - SubtensorModule::swap_is_network_member( - &old_hotkey, - &new_hotkey, - &netuid_is_member, - &mut weight, - ); - - // Verify the swap - for netuid in &netuid_is_member { - assert!(IsNetworkMember::::contains_key(new_hotkey, netuid)); - assert!(!IsNetworkMember::::contains_key(old_hotkey, netuid)); - } - }); -} - -#[test] -fn test_swap_is_network_member_weight_update() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let netuid_is_member = vec![1u16, 2u16]; - let mut weight = Weight::zero(); - - // Initialize IsNetworkMember for old_hotkey - for netuid in &netuid_is_member { - IsNetworkMember::::insert(old_hotkey, netuid, true); - } - - // Perform the swap - SubtensorModule::swap_is_network_member( - &old_hotkey, - &new_hotkey, - &netuid_is_member, - &mut weight, - ); - - // Verify the weight update - let expected_weight = ::DbWeight::get().writes(4); - assert_eq!(weight, expected_weight); - }); -} - -#[test] -fn test_swap_axons_success() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let netuid_is_member = vec![1u16, 2u16]; - let axon_info = AxonInfo { - block: 100, - version: 1, - ip: 0x1234567890abcdef, - port: 8080, - ip_type: 4, - protocol: 1, - placeholder1: 0, - placeholder2: 0, - }; - let mut weight = Weight::zero(); - - // Initialize Axons for old_hotkey - for netuid in &netuid_is_member { - Axons::::insert(netuid, old_hotkey, axon_info.clone()); - } - - // Perform the swap - SubtensorModule::swap_axons(&old_hotkey, &new_hotkey, &netuid_is_member, &mut weight); - - // Verify the swap - for netuid in &netuid_is_member { - assert_eq!(Axons::::get(netuid, new_hotkey).unwrap(), axon_info); - assert!(!Axons::::contains_key(netuid, old_hotkey)); - } - }); -} - -#[test] -fn test_swap_axons_weight_update() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let netuid_is_member = vec![1u16, 2u16]; - let axon_info = AxonInfo { - block: 100, - version: 1, - ip: 0x1234567890abcdef, - port: 8080, - ip_type: 4, - protocol: 1, - placeholder1: 0, - placeholder2: 0, - }; - let mut weight = Weight::zero(); - - // Initialize Axons for old_hotkey - for netuid in &netuid_is_member { - Axons::::insert(netuid, old_hotkey, axon_info.clone()); - } - - // Perform the swap - SubtensorModule::swap_axons(&old_hotkey, &new_hotkey, &netuid_is_member, &mut weight); - - // Verify the weight update - let expected_weight = netuid_is_member.len() as u64 - * ::DbWeight::get().reads_writes(1, 2); - assert_eq!(weight, expected_weight); - }); -} - -#[test] -fn test_swap_keys_success() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let netuid_is_member = vec![1u16, 2u16]; - let uid = 42u16; - let mut weight = Weight::zero(); - - // Initialize Keys for old_hotkey - for netuid in &netuid_is_member { - log::info!("Inserting old_hotkey:{:?} netuid:{:?}", old_hotkey, netuid); - Keys::::insert(*netuid, uid, old_hotkey); - } - - // Perform the swap - SubtensorModule::swap_keys(&old_hotkey, &new_hotkey, &netuid_is_member, &mut weight); - - // Verify the swap - for netuid in &netuid_is_member { - log::info!( - "neutuid, uid, hotkey: {:?}, {:?}, {:?}", - netuid, - uid, - new_hotkey - ); - assert_eq!(Keys::::get(netuid, uid), new_hotkey); - } - }); -} - -#[test] -fn test_swap_keys_weight_update() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let netuid_is_member = vec![1u16, 2u16]; - let uid = 42u16; - let mut weight = Weight::zero(); - - // Initialize Keys for old_hotkey - for netuid in &netuid_is_member { - Keys::::insert(*netuid, uid, old_hotkey); - } - - // Perform the swap - SubtensorModule::swap_keys(&old_hotkey, &new_hotkey, &netuid_is_member, &mut weight); - - // Verify the weight update - let expected_weight = ::DbWeight::get().writes(4); - assert_eq!(weight, expected_weight); - }); -} - -#[test] -fn test_swap_loaded_emission_success() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let netuid_is_member = vec![1u16, 2u16]; - let se = 100u64; - let ve = 200u64; - let mut weight = Weight::zero(); - - // Initialize LoadedEmission for old_hotkey - for netuid in &netuid_is_member { - LoadedEmission::::mutate(netuid, |emission_exists| { - if let Some(emissions) = emission_exists { - emissions.push((old_hotkey, se, ve)); - } else { - *emission_exists = Some(vec![(old_hotkey, se, ve)]); - } - }); - } - - // Perform the swap - SubtensorModule::swap_loaded_emission( - &old_hotkey, - &new_hotkey, - &netuid_is_member, - &mut weight, - ); - - // Verify the swap - for netuid in &netuid_is_member { - let emissions = LoadedEmission::::get(netuid).unwrap(); - assert!(emissions.iter().any(|(hk, _, _)| hk == &new_hotkey)); - assert!(!emissions.iter().any(|(hk, _, _)| hk == &old_hotkey)); - } - }); -} - -#[test] -fn test_swap_loaded_emission_weight_update() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let netuid_is_member = vec![1u16, 2u16]; - // let uid = 42u64; - let se = 100u64; - let ve = 200u64; - let mut weight = Weight::zero(); - - // Initialize LoadedEmission for old_hotkey - for netuid in &netuid_is_member { - LoadedEmission::::mutate(netuid, |emission_exists| { - if let Some(emissions) = emission_exists { - emissions.push((old_hotkey, se, ve)); - } else { - *emission_exists = Some(vec![(old_hotkey, se, ve)]); - } - }); - } - - // Perform the swap - SubtensorModule::swap_loaded_emission( - &old_hotkey, - &new_hotkey, - &netuid_is_member, - &mut weight, - ); - - // Verify the weight update - let expected_weight = ::DbWeight::get().writes(2); - assert_eq!(weight, expected_weight); - }); -} - -#[test] -fn test_swap_uids_success() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let netuid_is_member = vec![1u16, 2u16]; - let uid = 42u16; - let mut weight = Weight::zero(); - - // Initialize Uids for old_hotkey - for netuid in &netuid_is_member { - Uids::::insert(netuid, old_hotkey, uid); - } - - // Perform the swap - SubtensorModule::swap_uids(&old_hotkey, &new_hotkey, &netuid_is_member, &mut weight); - - // Verify the swap - for netuid in &netuid_is_member { - assert_eq!(Uids::::get(netuid, new_hotkey).unwrap(), uid); - assert!(!Uids::::contains_key(netuid, old_hotkey)); - } - }); -} - -#[test] -fn test_swap_uids_weight_update() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let netuid_is_member = vec![1u16, 2u16]; - let uid = 42u16; - let mut weight = Weight::zero(); - - // Initialize Uids for old_hotkey - for netuid in &netuid_is_member { - Uids::::insert(netuid, old_hotkey, uid); - } - - // Perform the swap - SubtensorModule::swap_uids(&old_hotkey, &new_hotkey, &netuid_is_member, &mut weight); - - // Verify the weight update - let expected_weight = ::DbWeight::get().writes(4); - assert_eq!(weight, expected_weight); - }); -} - -#[test] -fn test_swap_prometheus_success() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let netuid_is_member = vec![1u16, 2u16]; - let prometheus_info = PrometheusInfo { - block: 100, - version: 1, - ip: 0x1234567890abcdef, - port: 8080, - ip_type: 4, - }; - let mut weight = Weight::zero(); - - // Initialize Prometheus for old_hotkey - for netuid in &netuid_is_member { - Prometheus::::insert(netuid, old_hotkey, prometheus_info.clone()); - } - - // Perform the swap - SubtensorModule::swap_prometheus(&old_hotkey, &new_hotkey, &netuid_is_member, &mut weight); - - // Verify the swap - for netuid in &netuid_is_member { - assert_eq!( - Prometheus::::get(netuid, new_hotkey).unwrap(), - prometheus_info - ); - assert!(!Prometheus::::contains_key(netuid, old_hotkey)); - } - }); -} - -#[test] -fn test_swap_prometheus_weight_update() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let netuid_is_member = vec![1u16, 2u16]; - let prometheus_info = PrometheusInfo { - block: 100, - version: 1, - ip: 0x1234567890abcdef, - port: 8080, - ip_type: 4, - }; - let mut weight = Weight::zero(); - - // Initialize Prometheus for old_hotkey - for netuid in &netuid_is_member { - Prometheus::::insert(netuid, old_hotkey, prometheus_info.clone()); - } - - // Perform the swap - SubtensorModule::swap_prometheus(&old_hotkey, &new_hotkey, &netuid_is_member, &mut weight); - - // Verify the weight update - let expected_weight = netuid_is_member.len() as u64 - * ::DbWeight::get().reads_writes(1, 2); - assert_eq!(weight, expected_weight); - }); -} - #[test] fn test_swap_total_hotkey_coldkey_stakes_this_interval_success() { new_test_ext(1).execute_with(|| { @@ -1030,9 +370,10 @@ fn test_swap_total_hotkey_coldkey_stakes_this_interval_success() { TotalHotkeyColdkeyStakesThisInterval::::insert(old_hotkey, coldkey, stake); // Perform the swap - SubtensorModule::swap_total_hotkey_coldkey_stakes_this_interval( + SubtensorModule::perform_hotkey_swap( &old_hotkey, &new_hotkey, + &coldkey, &mut weight, ); @@ -1047,32 +388,6 @@ fn test_swap_total_hotkey_coldkey_stakes_this_interval_success() { }); } -#[test] -fn test_swap_total_hotkey_coldkey_stakes_this_interval_weight_update() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let stake = (1000u64, 42u64); - let mut weight = Weight::zero(); - - // Initialize TotalHotkeyColdkeyStakesThisInterval for old_hotkey - TotalHotkeyColdkeyStakesThisInterval::::insert(old_hotkey, coldkey, stake); - - // Perform the swap - - SubtensorModule::swap_total_hotkey_coldkey_stakes_this_interval( - &old_hotkey, - &new_hotkey, - &mut weight, - ); - - // Verify the weight update - let expected_weight = ::DbWeight::get().writes(2); - assert_eq!(weight, expected_weight); - }); -} - #[test] fn test_do_swap_coldkey_success() { new_test_ext(1).execute_with(|| { diff --git a/pallets/subtensor/tests/swap_hotkey.rs b/pallets/subtensor/tests/swap_hotkey.rs new file mode 100644 index 000000000..22e266efa --- /dev/null +++ b/pallets/subtensor/tests/swap_hotkey.rs @@ -0,0 +1,542 @@ +#![allow(unused, clippy::indexing_slicing, clippy::panic, clippy::unwrap_used)] + +use codec::Encode; +use frame_support::weights::Weight; +use frame_support::{assert_err, assert_noop, assert_ok}; +use frame_system::{Config, RawOrigin}; +mod mock; +use mock::*; +use pallet_subtensor::*; +use sp_core::U256; +use sp_core::H256; + + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_owner --exact --nocapture +#[test] +fn test_swap_owner() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let mut weight = Weight::zero(); + + Owner::::insert(&old_hotkey, &coldkey); + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert!(!Owner::::contains_key(&old_hotkey)); + assert_eq!(Owner::::get(&new_hotkey), coldkey); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_owned_hotkeys --exact --nocapture +#[test] +fn test_swap_owned_hotkeys() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let mut weight = Weight::zero(); + + OwnedHotkeys::::insert(&coldkey, vec![old_hotkey]); + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + let hotkeys = OwnedHotkeys::::get(&coldkey); + assert!(!hotkeys.contains(&old_hotkey)); + assert!(hotkeys.contains(&new_hotkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_total_hotkey_stake --exact --nocapture +#[test] +fn test_swap_total_hotkey_stake() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let mut weight = Weight::zero(); + + TotalHotkeyStake::::insert(&old_hotkey, 100); + TotalHotkeyStake::::insert(&new_hotkey, 50); + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert!(!TotalHotkeyStake::::contains_key(&old_hotkey)); + assert_eq!(TotalHotkeyStake::::get(&new_hotkey), 150); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_total_hotkey_coldkey_stakes_this_interval --exact --nocapture +#[test] +fn test_swap_total_hotkey_coldkey_stakes_this_interval() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let mut weight = Weight::zero(); + + TotalHotkeyColdkeyStakesThisInterval::::insert(&old_hotkey, &coldkey, (100, 1000)); + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert!(!TotalHotkeyColdkeyStakesThisInterval::::contains_key(&old_hotkey, &coldkey)); + assert_eq!(TotalHotkeyColdkeyStakesThisInterval::::get(&new_hotkey, &coldkey), (100, 1000)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_last_tx_block --exact --nocapture +#[test] +fn test_swap_last_tx_block() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let mut weight = Weight::zero(); + + LastTxBlock::::insert(&old_hotkey, 1000); + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert!(!LastTxBlock::::contains_key(&old_hotkey)); + assert_eq!(LastTxBlock::::get(&new_hotkey), SubtensorModule::get_current_block_as_u64()); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_last_tx_block_delegate_take --exact --nocapture +#[test] +fn test_swap_last_tx_block_delegate_take() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let mut weight = Weight::zero(); + + pallet_subtensor::LastTxBlockDelegateTake::::insert(&old_hotkey, 1000); + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert!(!LastTxBlockDelegateTake::::contains_key(&old_hotkey)); + assert_eq!(LastTxBlockDelegateTake::::get(&new_hotkey), SubtensorModule::get_current_block_as_u64()); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_senate_members --exact --nocapture +#[test] +fn test_swap_senate_members() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let mut weight = Weight::zero(); + + // Assuming there's a way to add a member to the senate + // SenateMembers::add_member(&old_hotkey); + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + // Assert that the old_hotkey is no longer a member and new_hotkey is now a member + // assert!(!SenateMembers::is_member(&old_hotkey)); + // assert!(SenateMembers::is_member(&new_hotkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_delegates --exact --nocapture +#[test] +fn test_swap_delegates() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let mut weight = Weight::zero(); + + Delegates::::insert(&old_hotkey, 100); + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert!(!Delegates::::contains_key(&old_hotkey)); + assert_eq!(Delegates::::get(&new_hotkey), 100); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_subnet_membership --exact --nocapture +#[test] +fn test_swap_subnet_membership() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let netuid = 0u16; + let mut weight = Weight::zero(); + + add_network(netuid, 0, 1); + IsNetworkMember::::insert(&old_hotkey, netuid, true); + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert!(!IsNetworkMember::::contains_key(&old_hotkey, netuid)); + assert!(IsNetworkMember::::get(&new_hotkey, netuid)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_uids_and_keys --exact --nocapture +#[test] +fn test_swap_uids_and_keys() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let netuid = 0u16; + let uid = 5u16; + let mut weight = Weight::zero(); + + add_network(netuid, 0, 1); + IsNetworkMember::::insert(&old_hotkey, netuid, true); + Uids::::insert(netuid, &old_hotkey, uid); + Keys::::insert(netuid, uid, old_hotkey); + + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert_eq!(Uids::::get(netuid, &old_hotkey), None); + assert_eq!(Uids::::get(netuid, &new_hotkey), Some(uid)); + assert_eq!(Keys::::get(netuid, uid), new_hotkey); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_prometheus --exact --nocapture +#[test] +fn test_swap_prometheus() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let netuid = 0u16; + let prometheus_info = PrometheusInfo::default(); + let mut weight = Weight::zero(); + + add_network(netuid, 0, 1); + IsNetworkMember::::insert(&old_hotkey, netuid, true); + Prometheus::::insert(netuid, &old_hotkey, prometheus_info.clone()); + + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert!(!Prometheus::::contains_key(netuid, &old_hotkey)); + assert_eq!(Prometheus::::get(netuid, &new_hotkey), Some(prometheus_info)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_axons --exact --nocapture +#[test] +fn test_swap_axons() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let netuid = 0u16; + let axon_info = AxonInfo::default(); + let mut weight = Weight::zero(); + + add_network(netuid, 0, 1); + IsNetworkMember::::insert(&old_hotkey, netuid, true); + Axons::::insert(netuid, &old_hotkey, axon_info.clone()); + + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert!(!Axons::::contains_key(netuid, &old_hotkey)); + assert_eq!(Axons::::get(netuid, &new_hotkey), Some(axon_info)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_weight_commits --exact --nocapture +#[test] +fn test_swap_weight_commits() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let netuid = 0u16; + let weight_commits = (H256::from_low_u64_be(100), 200); + let mut weight = Weight::zero(); + + add_network(netuid, 0, 1); + IsNetworkMember::::insert(&old_hotkey, netuid, true); + WeightCommits::::insert(netuid, &old_hotkey, weight_commits.clone()); + + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert!(!WeightCommits::::contains_key(netuid, &old_hotkey)); + assert_eq!(WeightCommits::::get(netuid, &new_hotkey), Some(weight_commits)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_loaded_emission --exact --nocapture +#[test] +fn test_swap_loaded_emission() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let netuid = 0u16; + let server_emission = 1000u64; + let validator_emission = 1000u64; + let mut weight = Weight::zero(); + + add_network(netuid, 0, 1); + IsNetworkMember::::insert(&old_hotkey, netuid, true); + LoadedEmission::::insert(netuid, vec![(old_hotkey, server_emission, validator_emission)]); + + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + let new_loaded_emission = LoadedEmission::::get(netuid); + assert_eq!(new_loaded_emission, Some(vec![(new_hotkey, server_emission, validator_emission)])); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_stake --exact --nocapture +#[test] +fn test_swap_stake() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let stake_amount = 100u64; + let mut weight = Weight::zero(); + + Stake::::insert(&old_hotkey, &coldkey, stake_amount); + + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert!(!Stake::::contains_key(&old_hotkey, &coldkey)); + assert_eq!(Stake::::get(&new_hotkey, &coldkey), stake_amount); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_staking_hotkeys --exact --nocapture +#[test] +fn test_swap_staking_hotkeys() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let mut weight = Weight::zero(); + + Stake::::insert(&old_hotkey, &coldkey, 100); + StakingHotkeys::::insert(&coldkey, vec![old_hotkey]); + + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + let staking_hotkeys = StakingHotkeys::::get(&coldkey); + assert!(!staking_hotkeys.contains(&old_hotkey)); + assert!(staking_hotkeys.contains(&new_hotkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_hotkey_with_multiple_coldkeys --exact --nocapture +#[test] +fn test_swap_hotkey_with_multiple_coldkeys() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey1 = U256::from(3); + let coldkey2 = U256::from(4); + let mut weight = Weight::zero(); + + Stake::::insert(&old_hotkey, &coldkey1, 100); + Stake::::insert(&old_hotkey, &coldkey2, 200); + StakingHotkeys::::insert(&coldkey1, vec![old_hotkey]); + StakingHotkeys::::insert(&coldkey2, vec![old_hotkey]); + + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey1, &mut weight)); + + assert_eq!(Stake::::get(&new_hotkey, &coldkey1), 100); + assert_eq!(Stake::::get(&new_hotkey, &coldkey2), 200); + assert!(StakingHotkeys::::get(&coldkey1).contains(&new_hotkey)); + assert!(StakingHotkeys::::get(&coldkey2).contains(&new_hotkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_hotkey_with_existing_stake --exact --nocapture +#[test] +fn test_swap_hotkey_with_existing_stake() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let mut weight = Weight::zero(); + + Stake::::insert(&old_hotkey, &coldkey, 100); + Stake::::insert(&new_hotkey, &coldkey, 50); + + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert_eq!(Stake::::get(&new_hotkey, &coldkey), 150); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_hotkey_with_multiple_subnets --exact --nocapture +#[test] +fn test_swap_hotkey_with_multiple_subnets() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let netuid1 = 0; + let netuid2 = 1; + let mut weight = Weight::zero(); + + add_network(netuid1, 0, 1); + add_network(netuid2, 0, 1); + IsNetworkMember::::insert(&old_hotkey, netuid1, true); + IsNetworkMember::::insert(&old_hotkey, netuid2, true); + + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert!(IsNetworkMember::::get(&new_hotkey, netuid1)); + assert!(IsNetworkMember::::get(&new_hotkey, netuid2)); + assert!(!IsNetworkMember::::get(&old_hotkey, netuid1)); + assert!(!IsNetworkMember::::get(&old_hotkey, netuid2)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_staking_hotkeys_multiple_coldkeys --exact --nocapture +#[test] +fn test_swap_staking_hotkeys_multiple_coldkeys() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey1 = U256::from(3); + let coldkey2 = U256::from(4); + let mut weight = Weight::zero(); + + // Set up initial state + Stake::::insert(&old_hotkey, &coldkey1, 100); + Stake::::insert(&old_hotkey, &coldkey2, 200); + StakingHotkeys::::insert(&coldkey1, vec![old_hotkey]); + StakingHotkeys::::insert(&coldkey2, vec![old_hotkey, U256::from(5)]); + + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey1, &mut weight)); + + // Check if new_hotkey replaced old_hotkey in StakingHotkeys + assert!(StakingHotkeys::::get(&coldkey1).contains(&new_hotkey)); + assert!(!StakingHotkeys::::get(&coldkey1).contains(&old_hotkey)); + + // Check if new_hotkey replaced old_hotkey for coldkey2 as well + assert!(StakingHotkeys::::get(&coldkey2).contains(&new_hotkey)); + assert!(!StakingHotkeys::::get(&coldkey2).contains(&old_hotkey)); + assert!(StakingHotkeys::::get(&coldkey2).contains(&U256::from(5))); // Other hotkeys should remain + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_hotkey_with_no_stake --exact --nocapture +#[test] +fn test_swap_hotkey_with_no_stake() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let mut weight = Weight::zero(); + + // Set up initial state with no stake + Owner::::insert(&old_hotkey, &coldkey); + + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + // Check if ownership transferred + assert!(!Owner::::contains_key(&old_hotkey)); + assert_eq!(Owner::::get(&new_hotkey), coldkey); + + // Ensure no unexpected changes in Stake + assert!(!Stake::::contains_key(&old_hotkey, &coldkey)); + assert!(!Stake::::contains_key(&new_hotkey, &coldkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_hotkey_with_multiple_coldkeys_and_subnets --exact --nocapture +#[test] +fn test_swap_hotkey_with_multiple_coldkeys_and_subnets() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey1 = U256::from(3); + let coldkey2 = U256::from(4); + let netuid1 = 0; + let netuid2 = 1; + let mut weight = Weight::zero(); + + // Set up initial state + add_network(netuid1, 0, 1); + add_network(netuid2, 0, 1); + Owner::::insert(&old_hotkey, &coldkey1); + Stake::::insert(&old_hotkey, &coldkey1, 100); + Stake::::insert(&old_hotkey, &coldkey2, 200); + IsNetworkMember::::insert(&old_hotkey, netuid1, true); + IsNetworkMember::::insert(&old_hotkey, netuid2, true); + TotalHotkeyStake::::insert(&old_hotkey, 300); + + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey1, &mut weight)); + + // Check ownership transfer + assert!(!Owner::::contains_key(&old_hotkey)); + assert_eq!(Owner::::get(&new_hotkey), coldkey1); + + // Check stake transfer + assert_eq!(Stake::::get(&new_hotkey, &coldkey1), 100); + assert_eq!(Stake::::get(&new_hotkey, &coldkey2), 200); + assert!(!Stake::::contains_key(&old_hotkey, &coldkey1)); + assert!(!Stake::::contains_key(&old_hotkey, &coldkey2)); + + // Check subnet membership transfer + assert!(IsNetworkMember::::get(&new_hotkey, netuid1)); + assert!(IsNetworkMember::::get(&new_hotkey, netuid2)); + assert!(!IsNetworkMember::::get(&old_hotkey, netuid1)); + assert!(!IsNetworkMember::::get(&old_hotkey, netuid2)); + + // Check total stake transfer + assert_eq!(TotalHotkeyStake::::get(&new_hotkey), 300); + assert!(!TotalHotkeyStake::::contains_key(&old_hotkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_hotkey_error_cases --exact --nocapture +#[test] +fn test_swap_hotkey_error_cases() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let wrong_coldkey = U256::from(4); + + // Set up initial state + Owner::::insert(&old_hotkey, &coldkey); + TotalNetworks::::put(1); + LastTxBlock::::insert(&coldkey, 0); + + // Test not enough balance + let swap_cost = SubtensorModule::get_key_swap_cost(); + assert_noop!( + SubtensorModule::do_swap_hotkey(RuntimeOrigin::signed(coldkey), &old_hotkey, &new_hotkey), + Error::::NotEnoughBalanceToPaySwapHotKey + ); + + let initial_balance = SubtensorModule::get_key_swap_cost() + 1000; + SubtensorModule::add_balance_to_coldkey_account(&coldkey, initial_balance); + + // Test new hotkey same as old + assert_noop!( + SubtensorModule::do_swap_hotkey(RuntimeOrigin::signed(coldkey), &old_hotkey, &old_hotkey), + Error::::NewHotKeyIsSameWithOld + ); + + // Test new hotkey already registered + IsNetworkMember::::insert(&new_hotkey, 0, true); + assert_noop!( + SubtensorModule::do_swap_hotkey(RuntimeOrigin::signed(coldkey), &old_hotkey, &new_hotkey), + Error::::HotKeyAlreadyRegisteredInSubNet + ); + IsNetworkMember::::remove(&new_hotkey, 0); + + // Test non-associated coldkey + assert_noop!( + SubtensorModule::do_swap_hotkey(RuntimeOrigin::signed(wrong_coldkey), &old_hotkey, &new_hotkey), + Error::::NonAssociatedColdKey + ); + + + // Run the successful swap + assert_ok!(SubtensorModule::do_swap_hotkey(RuntimeOrigin::signed(coldkey), &old_hotkey, &new_hotkey)); + + // Check balance after swap + assert_eq!(Balances::free_balance(&coldkey), initial_balance - swap_cost); + }); +} From 7f938f7940810831203169062de60440a7caacc6 Mon Sep 17 00:00:00 2001 From: const Date: Mon, 22 Jul 2024 13:34:03 -0500 Subject: [PATCH 3/6] tests pass --- pallets/subtensor/src/swap_hotkey.rs | 12 +- pallets/subtensor/tests/swap.rs | 378 ------------------------- pallets/subtensor/tests/swap_hotkey.rs | 275 ++++++++++++++++++ 3 files changed, 279 insertions(+), 386 deletions(-) diff --git a/pallets/subtensor/src/swap_hotkey.rs b/pallets/subtensor/src/swap_hotkey.rs index 222a4ff37..a99e4b3dc 100644 --- a/pallets/subtensor/src/swap_hotkey.rs +++ b/pallets/subtensor/src/swap_hotkey.rs @@ -1,9 +1,6 @@ use super::*; -use crate::MIN_BALANCE_TO_PERFORM_COLDKEY_SWAP; -use frame_support::traits::fungible::Mutate; -use frame_support::traits::tokens::Preservation; -use frame_support::{storage::IterableStorageDoubleMap, weights::Weight}; -use sp_core::{Get, U256}; +use frame_support::weights::Weight; +use sp_core::Get; impl Pallet { /// Swaps the hotkey of a coldkey account. @@ -86,7 +83,7 @@ impl Pallet { Self::burn_tokens(actual_burn_amount); // Perform the hotkey swap - Self::perform_hotkey_swap(old_hotkey, new_hotkey, &coldkey, &mut weight); + let _ = Self::perform_hotkey_swap(old_hotkey, new_hotkey, &coldkey, &mut weight); // Update the last transaction block for the coldkey Self::set_last_tx_block(&coldkey, block); @@ -143,10 +140,9 @@ impl Pallet { // Swap LastTxBlock // LastTxBlock( hotkey ) --> u64 -- the last transaction block for the hotkey. - let old_last_tx_block: u64 = LastTxBlock::::get( old_hotkey ); LastTxBlock::::remove( old_hotkey ); LastTxBlock::::insert( new_hotkey, Self::get_current_block_as_u64() ); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + weight.saturating_accrue(T::DbWeight::get().reads_writes(0, 2)); // Swap LastTxBlockDelegateTake // LastTxBlockDelegateTake( hotkey ) --> u64 -- the last transaction block for the hotkey delegate take. diff --git a/pallets/subtensor/tests/swap.rs b/pallets/subtensor/tests/swap.rs index 86fe109be..f7f288cc2 100644 --- a/pallets/subtensor/tests/swap.rs +++ b/pallets/subtensor/tests/swap.rs @@ -9,384 +9,6 @@ use mock::*; use pallet_subtensor::*; use sp_core::U256; -// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap -- test_do_swap_hotkey_ok --exact --nocapture -#[test] -fn test_do_swap_hotkey_ok() { - 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; - - // 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); - - // Perform the swap - assert_ok!(SubtensorModule::do_swap_hotkey( - <::RuntimeOrigin>::signed(coldkey), - &old_hotkey, - &new_hotkey - )); - - // Verify the swap - assert_eq!( - SubtensorModule::get_owning_coldkey_for_hotkey(&new_hotkey), - coldkey - ); - assert_ne!( - SubtensorModule::get_owning_coldkey_for_hotkey(&old_hotkey), - coldkey - ); - - // Verify other storage changes - assert_ne!( - SubtensorModule::get_delegate(new_hotkey.encode()), - SubtensorModule::get_delegate(old_hotkey.encode()) - ); - assert_ne!( - SubtensorModule::get_last_tx_block(&new_hotkey), - SubtensorModule::get_last_tx_block(&old_hotkey) - ); - - // Verify raw storage maps - // Stake - for (coldkey, stake_amount) in Stake::::iter_prefix(old_hotkey) { - assert_eq!(Stake::::get(new_hotkey, coldkey), stake_amount); - } - - let mut weight = Weight::zero(); - - // IsNetworkMember - for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight) { - assert!(IsNetworkMember::::contains_key(new_hotkey, netuid)); - assert!(!IsNetworkMember::::contains_key(old_hotkey, netuid)); - } - - // Owner - assert_eq!(Owner::::get(new_hotkey), coldkey); - - // TotalHotkeyStake - assert_ne!( - TotalHotkeyStake::::get(new_hotkey), - TotalHotkeyStake::::get(old_hotkey) - ); - - // Delegates - assert_eq!( - Delegates::::get(new_hotkey), - Delegates::::get(old_hotkey) - ); - - // LastTxBlock - assert_eq!( - LastTxBlock::::get(new_hotkey), - LastTxBlock::::get(old_hotkey) - ); - - // Axons - for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight) { - assert_eq!( - Axons::::get(netuid, new_hotkey), - Axons::::get(netuid, old_hotkey) - ); - } - - // TotalHotkeyColdkeyStakesThisInterval - assert_eq!( - TotalHotkeyColdkeyStakesThisInterval::::get(new_hotkey, coldkey), - TotalHotkeyColdkeyStakesThisInterval::::get(old_hotkey, coldkey) - ); - }); -} - -#[test] -fn test_swap_hotkey_tx_rate_limit_exceeded() { - new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; - let tempo: u16 = 13; - let old_hotkey = U256::from(1); - let new_hotkey_1 = U256::from(2); - let new_hotkey_2 = U256::from(4); - let coldkey = U256::from(3); - let swap_cost = 1_000_000_000u64 * 2; - - let tx_rate_limit = 1; - - // Get the current transaction rate limit - let current_tx_rate_limit = SubtensorModule::get_tx_rate_limit(); - log::info!("current_tx_rate_limit: {:?}", current_tx_rate_limit); - - // Set the transaction rate limit - SubtensorModule::set_tx_rate_limit(tx_rate_limit); - // assert the rate limit is set to 1000 blocks - assert_eq!(SubtensorModule::get_tx_rate_limit(), tx_rate_limit); - - // 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); - - // Perform the first swap - assert_ok!(SubtensorModule::do_swap_hotkey( - <::RuntimeOrigin>::signed(coldkey), - &old_hotkey, - &new_hotkey_1 - )); - - // Attempt to perform another swap immediately, which should fail due to rate limit - assert_err!( - SubtensorModule::do_swap_hotkey( - <::RuntimeOrigin>::signed(coldkey), - &new_hotkey_1, - &new_hotkey_2 - ), - Error::::HotKeySetTxRateLimitExceeded - ); - - // move in time past the rate limit - step_block(1001); - assert_ok!(SubtensorModule::do_swap_hotkey( - <::RuntimeOrigin>::signed(coldkey), - &new_hotkey_1, - &new_hotkey_2 - )); - }); -} - -#[test] -fn test_do_swap_hotkey_err_not_owner() { - 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 not_owner_coldkey = U256::from(4); - let swap_cost = 1_000_000_000u64; - - // Setup initial state - add_network(netuid, tempo, 0); - register_ok_neuron(netuid, old_hotkey, coldkey, 0); - SubtensorModule::add_balance_to_coldkey_account(¬_owner_coldkey, swap_cost); - - // Attempt the swap with a non-owner coldkey - assert_err!( - SubtensorModule::do_swap_hotkey( - <::RuntimeOrigin>::signed(not_owner_coldkey), - &old_hotkey, - &new_hotkey - ), - Error::::NonAssociatedColdKey - ); - }); -} - -#[test] -fn test_swap_owner_success() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let mut weight = Weight::zero(); - - // Initialize Owner for old_hotkey - Owner::::insert(old_hotkey, coldkey); - - // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); - - // Verify the swap - assert_eq!(Owner::::get(new_hotkey), coldkey); - assert!(!Owner::::contains_key(old_hotkey)); - }); -} - -#[test] -fn test_swap_owner_old_hotkey_not_exist() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let mut weight = Weight::zero(); - - // Ensure old_hotkey does not exist - assert!(!Owner::::contains_key(old_hotkey)); - - // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); - - // Verify the swap - assert_eq!(Owner::::get(new_hotkey), coldkey); - assert!(!Owner::::contains_key(old_hotkey)); - }); -} - -#[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 mut weight = Weight::zero(); - - // Initialize Owner for old_hotkey and new_hotkey - Owner::::insert(old_hotkey, coldkey); - Owner::::insert(new_hotkey, another_coldkey); - - // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); - - // Verify the swap - assert_eq!(Owner::::get(new_hotkey), coldkey); - assert!(!Owner::::contains_key(old_hotkey)); - }); -} - -#[test] -fn test_swap_total_hotkey_stake_success() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let total_stake = 1000u64; - let mut weight = Weight::zero(); - - // Initialize TotalHotkeyStake for old_hotkey - TotalHotkeyStake::::insert(old_hotkey, total_stake); - - // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); - - // Verify the swap - assert_eq!(TotalHotkeyStake::::get(new_hotkey), total_stake); - assert!(!TotalHotkeyStake::::contains_key(old_hotkey)); - }); -} - - - -#[test] -fn test_swap_delegates_success() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let delegate_take = 10u16; - let mut weight = Weight::zero(); - - // Initialize Delegates for old_hotkey - Delegates::::insert(old_hotkey, delegate_take); - - // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); - - // Verify the swap - assert_eq!(Delegates::::get(new_hotkey), delegate_take); - assert!(!Delegates::::contains_key(old_hotkey)); - }); -} - -#[test] -fn test_swap_delegates_weight_update() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let delegate_take = 10u16; - let mut weight = Weight::zero(); - - // Initialize Delegates for old_hotkey - Delegates::::insert(old_hotkey, delegate_take); - - // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); - - // Verify the weight update - let expected_weight = ::DbWeight::get().reads_writes(1, 2); - assert_eq!(weight, expected_weight); - }); -} - -#[test] -fn test_swap_stake_success() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let stake_amount = 1000u64; - let mut weight = Weight::zero(); - - // Initialize Stake for old_hotkey - Stake::::insert(old_hotkey, coldkey, stake_amount); - - // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); - - // Verify the swap - assert_eq!(Stake::::get(new_hotkey, coldkey), stake_amount); - assert!(!Stake::::contains_key(old_hotkey, coldkey)); - }); -} - -#[test] -fn test_swap_stake_old_hotkey_not_exist() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let stake_amount = 1000u64; - let mut weight = Weight::zero(); - - // Initialize Stake for old_hotkey - Stake::::insert(old_hotkey, coldkey, stake_amount); - - // Ensure old_hotkey has a stake - assert!(Stake::::contains_key(old_hotkey, coldkey)); - - // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); - - // Verify that new_hotkey has the stake and old_hotkey does not - assert!(Stake::::contains_key(new_hotkey, coldkey)); - assert!(!Stake::::contains_key(old_hotkey, coldkey)); - }); -} - -#[test] -fn test_swap_total_hotkey_coldkey_stakes_this_interval_success() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let stake = (1000u64, 42u64); // Example tuple value - let mut weight = Weight::zero(); - - // Initialize TotalHotkeyColdkeyStakesThisInterval for old_hotkey - TotalHotkeyColdkeyStakesThisInterval::::insert(old_hotkey, coldkey, stake); - - // Perform the swap - SubtensorModule::perform_hotkey_swap( - &old_hotkey, - &new_hotkey, - &coldkey, - &mut weight, - ); - - // Verify the swap - assert_eq!( - TotalHotkeyColdkeyStakesThisInterval::::get(new_hotkey, coldkey), - stake - ); - assert!(!TotalHotkeyColdkeyStakesThisInterval::::contains_key( - old_hotkey, coldkey - )); - }); -} #[test] fn test_do_swap_coldkey_success() { diff --git a/pallets/subtensor/tests/swap_hotkey.rs b/pallets/subtensor/tests/swap_hotkey.rs index 22e266efa..35227d3b1 100644 --- a/pallets/subtensor/tests/swap_hotkey.rs +++ b/pallets/subtensor/tests/swap_hotkey.rs @@ -488,6 +488,281 @@ fn test_swap_hotkey_with_multiple_coldkeys_and_subnets() { }); } +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_hotkey_tx_rate_limit_exceeded --exact --nocapture +#[test] +fn test_swap_hotkey_tx_rate_limit_exceeded() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + let tempo: u16 = 13; + let old_hotkey = U256::from(1); + let new_hotkey_1 = U256::from(2); + let new_hotkey_2 = U256::from(4); + let coldkey = U256::from(3); + let swap_cost = 1_000_000_000u64 * 2; + + let tx_rate_limit = 1; + + // Get the current transaction rate limit + let current_tx_rate_limit = SubtensorModule::get_tx_rate_limit(); + log::info!("current_tx_rate_limit: {:?}", current_tx_rate_limit); + + // Set the transaction rate limit + SubtensorModule::set_tx_rate_limit(tx_rate_limit); + // assert the rate limit is set to 1000 blocks + assert_eq!(SubtensorModule::get_tx_rate_limit(), tx_rate_limit); + + // 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); + + // Perform the first swap + assert_ok!(SubtensorModule::do_swap_hotkey( + <::RuntimeOrigin>::signed(coldkey), + &old_hotkey, + &new_hotkey_1 + )); + + // Attempt to perform another swap immediately, which should fail due to rate limit + assert_err!( + SubtensorModule::do_swap_hotkey( + <::RuntimeOrigin>::signed(coldkey), + &new_hotkey_1, + &new_hotkey_2 + ), + Error::::HotKeySetTxRateLimitExceeded + ); + + // move in time past the rate limit + step_block(1001); + assert_ok!(SubtensorModule::do_swap_hotkey( + <::RuntimeOrigin>::signed(coldkey), + &new_hotkey_1, + &new_hotkey_2 + )); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_do_swap_hotkey_err_not_owner --exact --nocapture +#[test] +fn test_do_swap_hotkey_err_not_owner() { + 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 not_owner_coldkey = U256::from(4); + let swap_cost = 1_000_000_000u64; + + // Setup initial state + add_network(netuid, tempo, 0); + register_ok_neuron(netuid, old_hotkey, coldkey, 0); + SubtensorModule::add_balance_to_coldkey_account(¬_owner_coldkey, swap_cost); + + // Attempt the swap with a non-owner coldkey + assert_err!( + SubtensorModule::do_swap_hotkey( + <::RuntimeOrigin>::signed(not_owner_coldkey), + &old_hotkey, + &new_hotkey + ), + Error::::NonAssociatedColdKey + ); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_owner_success --exact --nocapture +#[test] +fn test_swap_owner_success() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let mut weight = Weight::zero(); + + // Initialize Owner for old_hotkey + Owner::::insert(old_hotkey, coldkey); + + // Perform the swap + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + + // Verify the swap + assert_eq!(Owner::::get(new_hotkey), coldkey); + assert!(!Owner::::contains_key(old_hotkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_owner_old_hotkey_not_exist --exact --nocapture +#[test] +fn test_swap_owner_old_hotkey_not_exist() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let mut weight = Weight::zero(); + + // Ensure old_hotkey does not exist + assert!(!Owner::::contains_key(old_hotkey)); + + // Perform the swap + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + + // Verify the swap + assert_eq!(Owner::::get(new_hotkey), coldkey); + assert!(!Owner::::contains_key(old_hotkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- 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 mut weight = Weight::zero(); + + // Initialize Owner for old_hotkey and new_hotkey + Owner::::insert(old_hotkey, coldkey); + Owner::::insert(new_hotkey, another_coldkey); + + // Perform the swap + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + + // Verify the swap + assert_eq!(Owner::::get(new_hotkey), coldkey); + assert!(!Owner::::contains_key(old_hotkey)); + }); +} + + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_total_hotkey_stake_success --exact --nocapture +#[test] +fn test_swap_total_hotkey_stake_success() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let total_stake = 1000u64; + let mut weight = Weight::zero(); + + // Initialize TotalHotkeyStake for old_hotkey + TotalHotkeyStake::::insert(old_hotkey, total_stake); + + // Perform the swap + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + + // Verify the swap + assert_eq!(TotalHotkeyStake::::get(new_hotkey), total_stake); + assert!(!TotalHotkeyStake::::contains_key(old_hotkey)); + }); +} + + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_delegates_success --exact --nocapture +#[test] +fn test_swap_delegates_success() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let delegate_take = 10u16; + let mut weight = Weight::zero(); + + // Initialize Delegates for old_hotkey + Delegates::::insert(old_hotkey, delegate_take); + + // Perform the swap + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + + // Verify the swap + assert_eq!(Delegates::::get(new_hotkey), delegate_take); + assert!(!Delegates::::contains_key(old_hotkey)); + }); +} + + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_stake_success --exact --nocapture +#[test] +fn test_swap_stake_success() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let stake_amount = 1000u64; + let mut weight = Weight::zero(); + + // Initialize Stake for old_hotkey + Stake::::insert(old_hotkey, coldkey, stake_amount); + + // Perform the swap + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + + // Verify the swap + assert_eq!(Stake::::get(new_hotkey, coldkey), stake_amount); + assert!(!Stake::::contains_key(old_hotkey, coldkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test 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(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let stake_amount = 1000u64; + let mut weight = Weight::zero(); + + // Initialize Stake for old_hotkey + Stake::::insert(old_hotkey, coldkey, stake_amount); + + // Ensure old_hotkey has a stake + assert!(Stake::::contains_key(old_hotkey, coldkey)); + + // Perform the swap + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + + // Verify that new_hotkey has the stake and old_hotkey does not + assert!(Stake::::contains_key(new_hotkey, coldkey)); + assert!(!Stake::::contains_key(old_hotkey, coldkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_total_hotkey_coldkey_stakes_this_interval_success --exact --nocapture +#[test] +fn test_swap_total_hotkey_coldkey_stakes_this_interval_success() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let stake = (1000u64, 42u64); // Example tuple value + let mut weight = Weight::zero(); + + // Initialize TotalHotkeyColdkeyStakesThisInterval for old_hotkey + TotalHotkeyColdkeyStakesThisInterval::::insert(old_hotkey, coldkey, stake); + + // Perform the swap + SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight, + ); + + // Verify the swap + assert_eq!( + TotalHotkeyColdkeyStakesThisInterval::::get(new_hotkey, coldkey), + stake + ); + assert!(!TotalHotkeyColdkeyStakesThisInterval::::contains_key( + old_hotkey, coldkey + )); + }); +} + // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_hotkey_error_cases --exact --nocapture #[test] fn test_swap_hotkey_error_cases() { From 659b53c5319c53ae31d5a05aca37d72e67eadd32 Mon Sep 17 00:00:00 2001 From: const Date: Mon, 22 Jul 2024 13:42:23 -0500 Subject: [PATCH 4/6] clean the code --- pallets/commitments/src/lib.rs | 9 +++ pallets/subtensor/src/swap_hotkey.rs | 106 ++++++++++++++++++--------- 2 files changed, 82 insertions(+), 33 deletions(-) diff --git a/pallets/commitments/src/lib.rs b/pallets/commitments/src/lib.rs index d5d132034..4663b2647 100644 --- a/pallets/commitments/src/lib.rs +++ b/pallets/commitments/src/lib.rs @@ -173,6 +173,15 @@ pub mod pallet { Ok(()) } + + pub fn swap_commitment( netuid: u16, new_hotkey: T::AccountId, old_hotkey: T::AccountId ) { + if let Some(commitment) = >::take(netuid, &old_hotkey) { + >::insert(netuid, &new_hotkey, commitment); + } + if let Some(last_commit) = >::take(netuid, &old_hotkey) { + >::insert(netuid, &new_hotkey, last_commit); + } + } } } diff --git a/pallets/subtensor/src/swap_hotkey.rs b/pallets/subtensor/src/swap_hotkey.rs index a99e4b3dc..02052e4dd 100644 --- a/pallets/subtensor/src/swap_hotkey.rs +++ b/pallets/subtensor/src/swap_hotkey.rs @@ -27,79 +27,118 @@ impl Pallet { old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, ) -> DispatchResultWithPostInfo { - // Ensure the origin is signed and get the coldkey + // 1. Ensure the origin is signed and get the coldkey let coldkey = ensure_signed(origin)?; - // Check if the coldkey is in arbitration + // 2. Check if the coldkey is in arbitration ensure!( !Self::coldkey_in_arbitration(&coldkey), Error::::ColdkeyIsInArbitration ); - // Initialize the weight for this operation + // 3. Initialize the weight for this operation let mut weight = T::DbWeight::get().reads(2); - // Ensure the new hotkey is different from the old one + // 4. Ensure the new hotkey is different from the old one ensure!(old_hotkey != new_hotkey, Error::::NewHotKeyIsSameWithOld); - // Ensure the new hotkey is not already registered on any network + + // 5. Ensure the new hotkey is not already registered on any network ensure!( !Self::is_hotkey_registered_on_any_network(new_hotkey), Error::::HotKeyAlreadyRegisteredInSubNet ); - // Update the weight for the checks above + // 6. Update the weight for the checks above weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 0)); - // Ensure the coldkey owns the old hotkey + + // 7. Ensure the coldkey owns the old hotkey ensure!( Self::coldkey_owns_hotkey(&coldkey, old_hotkey), Error::::NonAssociatedColdKey ); - // Get the current block number + // 8. Get the current block number let block: u64 = Self::get_current_block_as_u64(); - // Ensure the transaction rate limit is not exceeded + + // 9. Ensure the transaction rate limit is not exceeded ensure!( !Self::exceeds_tx_rate_limit(Self::get_last_tx_block(&coldkey), block), Error::::HotKeySetTxRateLimitExceeded ); - // Update the weight for reading the total networks + // 10. Update the weight for reading the total networks weight.saturating_accrue( T::DbWeight::get().reads((TotalNetworks::::get().saturating_add(1u16)) as u64), ); - // Get the cost for swapping the key + // 11. Get the cost for swapping the key let swap_cost = Self::get_key_swap_cost(); log::debug!("Swap cost: {:?}", swap_cost); - // Ensure the coldkey has enough balance to pay for the swap + // 12. Ensure the coldkey has enough balance to pay for the swap ensure!( Self::can_remove_balance_from_coldkey_account(&coldkey, swap_cost), Error::::NotEnoughBalanceToPaySwapHotKey ); - // Remove the swap cost from the coldkey's account + + // 13. Remove the swap cost from the coldkey's account let actual_burn_amount = Self::remove_balance_from_coldkey_account(&coldkey, swap_cost)?; - // Burn the tokens + + // 14. Burn the tokens Self::burn_tokens(actual_burn_amount); - // Perform the hotkey swap + // 15. Perform the hotkey swap let _ = Self::perform_hotkey_swap(old_hotkey, new_hotkey, &coldkey, &mut weight); - // Update the last transaction block for the coldkey + // 16. Update the last transaction block for the coldkey Self::set_last_tx_block(&coldkey, block); weight.saturating_accrue(T::DbWeight::get().writes(1)); - // Emit an event for the hotkey swap + // 17. Emit an event for the hotkey swap Self::deposit_event(Event::HotkeySwapped { coldkey, old_hotkey: old_hotkey.clone(), new_hotkey: new_hotkey.clone(), }); - // Return the weight of the operation + // 18. Return the weight of the operation Ok(Some(weight).into()) } + /// Performs the hotkey swap operation, transferring all associated data and state from the old hotkey to the new hotkey. + /// + /// This function executes a series of steps to ensure a complete transfer of all relevant information: + /// 1. Swaps the owner of the hotkey. + /// 2. Updates the list of owned hotkeys for the coldkey. + /// 3. Transfers the total hotkey stake. + /// 4. Moves all stake-related data for the interval. + /// 5. Updates the last transaction block for the new hotkey. + /// 6. Transfers the delegate take information. + /// 7. Swaps Senate membership if applicable. + /// 8. Updates delegate information. + /// 9. For each subnet: + /// - Updates network membership status. + /// - Transfers UID and key information. + /// - Moves Prometheus data. + /// - Updates axon information. + /// - Transfers weight commits. + /// - Updates loaded emission data. + /// 10. Transfers all stake information, including updating staking hotkeys for each coldkey. + /// + /// Throughout the process, the function accumulates the computational weight of operations performed. + /// + /// # Arguments + /// * `old_hotkey` - The AccountId of the current hotkey to be replaced. + /// * `new_hotkey` - The AccountId of the new hotkey to replace the old one. + /// * `coldkey` - The AccountId of the coldkey that owns both hotkeys. + /// * `weight` - A mutable reference to the Weight, updated as operations are performed. + /// + /// # Returns + /// * `DispatchResult` - Ok(()) if the swap was successful, or an error if any operation failed. + /// + /// # Note + /// This function performs extensive storage reads and writes, which can be computationally expensive. + /// The accumulated weight should be carefully considered in the context of block limits. pub fn perform_hotkey_swap( old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, coldkey: &T::AccountId, weight: &mut Weight ) -> DispatchResult { // 1. Swap owner. @@ -128,7 +167,7 @@ impl Pallet { TotalHotkeyStake::::insert( new_hotkey, old_total_hotkey_stake.saturating_add( new_total_hotkey_stake ) ); // Insert the new total hotkey stake via the addition. weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2)); - // Swap total hotkey stakes. + // 4. Swap total hotkey stakes. // TotalHotkeyColdkeyStakesThisInterval( hotkey ) --> (u64: stakes, u64: block_number) let stake_tuples: Vec<(T::AccountId, (u64, u64))> = TotalHotkeyColdkeyStakesThisInterval::::iter_prefix(old_hotkey).collect(); for (coldkey, stake_tup) in stake_tuples { @@ -138,59 +177,59 @@ impl Pallet { weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); } - // Swap LastTxBlock + // 5. Swap LastTxBlock // LastTxBlock( hotkey ) --> u64 -- the last transaction block for the hotkey. LastTxBlock::::remove( old_hotkey ); LastTxBlock::::insert( new_hotkey, Self::get_current_block_as_u64() ); weight.saturating_accrue(T::DbWeight::get().reads_writes(0, 2)); - // Swap LastTxBlockDelegateTake + // 6. Swap LastTxBlockDelegateTake // LastTxBlockDelegateTake( hotkey ) --> u64 -- the last transaction block for the hotkey delegate take. LastTxBlockDelegateTake::::remove( old_hotkey ); LastTxBlockDelegateTake::::insert( new_hotkey, Self::get_current_block_as_u64() ); weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - // Swap Senate members. + // 7. Swap Senate members. // Senate( hotkey ) --> ? if T::SenateMembers::is_member(old_hotkey) { T::SenateMembers::swap_member(old_hotkey, new_hotkey).map_err(|e| e.error)?; weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); } - // 4. Swap delegates. + // 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)); - // Swap all subnet specific info. + // 9. Swap all subnet specific info. let all_netuids: Vec = Self::get_all_subnet_netuids(); for netuid in all_netuids { - // 7.1 Remove the previous hotkey and insert the new hotkey from membership. + // 9.1 Remove the previous hotkey and insert the new hotkey from membership. // IsNetworkMember( hotkey, netuid ) -> bool -- is the hotkey a subnet member. let is_network_member: bool = IsNetworkMember::::get( old_hotkey, netuid ); IsNetworkMember::::remove( old_hotkey, netuid ); IsNetworkMember::::insert( new_hotkey, netuid, is_network_member ); weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - // 7.2 Swap Uids + Keys. + // 9.2 Swap Uids + Keys. // Keys( netuid, hotkey ) -> uid -- the uid the hotkey has in the network if it is a member. // Uids( netuid, hotkey ) -> uid -- the uids that the hotkey has. if is_network_member { - // 7.2.1 Swap the UIDS + // 9.2.1 Swap the UIDS if let Ok(old_uid) = Uids::::try_get(netuid, old_hotkey) { Uids::::remove(netuid, old_hotkey); Uids::::insert(netuid, new_hotkey, old_uid); weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - // 7.2.2 Swap the keys. + // 9.2.2 Swap the keys. Keys::::insert(netuid, old_uid, new_hotkey.clone()); weight.saturating_accrue(T::DbWeight::get().reads_writes(0, 1)); } } - // 7.3 Swap Prometheus. + // 9.3 Swap Prometheus. // Prometheus( netuid, hotkey ) -> prometheus -- the prometheus data that a hotkey has in the network. if is_network_member { if let Ok(old_prometheus_info) = Prometheus::::try_get(netuid, old_hotkey) { @@ -200,7 +239,7 @@ impl Pallet { } } - // 7.4. Swap axons. + // 9.4. Swap axons. // Axons( netuid, hotkey ) -> axon -- the axon that the hotkey has. if is_network_member { if let Ok(old_axon_info) = Axons::::try_get(netuid, old_hotkey) { @@ -210,7 +249,7 @@ impl Pallet { } } - // 7.5 Swap WeightCommits + // 9.5 Swap WeightCommits // WeightCommits( hotkey ) --> Vec -- the weight commits for the hotkey. if is_network_member { if let Ok(old_weight_commits) = WeightCommits::::try_get(netuid, old_hotkey) { @@ -220,7 +259,7 @@ impl Pallet { } } - // 7.5. Swap the subnet loaded emission. + // 9.6. Swap the subnet loaded emission. // LoadedEmission( netuid ) --> Vec<(hotkey, u64)> -- the loaded emission for the subnet. if is_network_member { if let Some(mut old_loaded_emission) = LoadedEmission::::get(netuid) { @@ -237,7 +276,7 @@ impl Pallet { } - // Swap Stake. + // 10. Swap Stake. // Stake( hotkey, coldkey ) -> stake -- the stake that the hotkey controls on behalf of the coldkey. let stakes: Vec<(T::AccountId, u64)> = Stake::::iter_prefix(old_hotkey).collect(); // Clear the entire old prefix here. @@ -263,6 +302,7 @@ impl Pallet { weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); } + // Return successful after swapping all the relevant terms. Ok(()) } From b8cfd6ce51967283b9610c81ef31bd9d2b6198e4 Mon Sep 17 00:00:00 2001 From: const Date: Mon, 22 Jul 2024 13:45:59 -0500 Subject: [PATCH 5/6] fix tests --- pallets/commitments/src/lib.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/pallets/commitments/src/lib.rs b/pallets/commitments/src/lib.rs index 4663b2647..d5d132034 100644 --- a/pallets/commitments/src/lib.rs +++ b/pallets/commitments/src/lib.rs @@ -173,15 +173,6 @@ pub mod pallet { Ok(()) } - - pub fn swap_commitment( netuid: u16, new_hotkey: T::AccountId, old_hotkey: T::AccountId ) { - if let Some(commitment) = >::take(netuid, &old_hotkey) { - >::insert(netuid, &new_hotkey, commitment); - } - if let Some(last_commit) = >::take(netuid, &old_hotkey) { - >::insert(netuid, &new_hotkey, last_commit); - } - } } } From 6b6460d4fc7864543af574d7390c53fa3556691d Mon Sep 17 00:00:00 2001 From: const Date: Mon, 22 Jul 2024 15:21:13 -0500 Subject: [PATCH 6/6] clippy and fmt --- pallets/subtensor/src/lib.rs | 6 +- pallets/subtensor/src/swap.rs | 4 - pallets/subtensor/src/swap_hotkey.rs | 57 +++--- pallets/subtensor/tests/swap.rs | 1 - pallets/subtensor/tests/swap_hotkey.rs | 248 ++++++++++++++++++++----- 5 files changed, 234 insertions(+), 82 deletions(-) diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index d492b5477..6a353eafb 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -1088,11 +1088,9 @@ pub mod pallet { pub type Active = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyBoolVec>; #[pallet::storage] // --- DMAP ( netuid ) --> rank - pub type Rank = - StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; + pub type Rank = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] // --- DMAP ( netuid ) --> trust - pub type Trust = - StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; + pub type Trust = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] // --- DMAP ( netuid ) --> consensus pub type Consensus = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; diff --git a/pallets/subtensor/src/swap.rs b/pallets/subtensor/src/swap.rs index 5d8f66c68..b6b0e9ba7 100644 --- a/pallets/subtensor/src/swap.rs +++ b/pallets/subtensor/src/swap.rs @@ -6,7 +6,6 @@ use frame_support::{storage::IterableStorageDoubleMap, weights::Weight}; use sp_core::{Get, U256}; impl Pallet { - /// Swaps the coldkey associated with a set of hotkeys from an old coldkey to a new coldkey. /// /// # Arguments @@ -378,7 +377,6 @@ impl Pallet { netuid_is_member } - /// Swaps the total stake associated with a coldkey from the old coldkey to the new coldkey. /// /// # Arguments @@ -635,6 +633,4 @@ impl Pallet { } weight.saturating_accrue(T::DbWeight::get().reads(TotalNetworks::::get() as u64)); } - - } diff --git a/pallets/subtensor/src/swap_hotkey.rs b/pallets/subtensor/src/swap_hotkey.rs index 02052e4dd..5c3fecbba 100644 --- a/pallets/subtensor/src/swap_hotkey.rs +++ b/pallets/subtensor/src/swap_hotkey.rs @@ -139,8 +139,12 @@ impl Pallet { /// # Note /// This function performs extensive storage reads and writes, which can be computationally expensive. /// The accumulated weight should be carefully considered in the context of block limits. - pub fn perform_hotkey_swap( old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, coldkey: &T::AccountId, weight: &mut Weight ) -> DispatchResult { - + pub fn perform_hotkey_swap( + old_hotkey: &T::AccountId, + new_hotkey: &T::AccountId, + coldkey: &T::AccountId, + weight: &mut Weight, + ) -> DispatchResult { // 1. Swap owner. // Owner( hotkey ) -> coldkey -- the coldkey that owns the hotkey. Owner::::remove(old_hotkey); @@ -153,7 +157,7 @@ impl Pallet { // Add the new key if needed. if !hotkeys.contains(new_hotkey) { hotkeys.push(new_hotkey.clone()); - } + } // Remove the old key. hotkeys.retain(|hk| *hk != *old_hotkey); OwnedHotkeys::::insert(coldkey, hotkeys); @@ -161,15 +165,19 @@ impl Pallet { // 3. Swap total hotkey stake. // TotalHotkeyStake( hotkey ) -> stake -- the total stake that the hotkey has across all delegates. - let old_total_hotkey_stake = TotalHotkeyStake::::get( old_hotkey ); // Get the old total hotkey stake. - let new_total_hotkey_stake = TotalHotkeyStake::::get( new_hotkey ); // Get the new total hotkey stake. - TotalHotkeyStake::::remove( old_hotkey ); // Remove the old total hotkey stake. - TotalHotkeyStake::::insert( new_hotkey, old_total_hotkey_stake.saturating_add( new_total_hotkey_stake ) ); // Insert the new total hotkey stake via the addition. + let old_total_hotkey_stake = TotalHotkeyStake::::get(old_hotkey); // Get the old total hotkey stake. + let new_total_hotkey_stake = TotalHotkeyStake::::get(new_hotkey); // Get the new total hotkey stake. + TotalHotkeyStake::::remove(old_hotkey); // Remove the old total hotkey stake. + TotalHotkeyStake::::insert( + new_hotkey, + old_total_hotkey_stake.saturating_add(new_total_hotkey_stake), + ); // Insert the new total hotkey stake via the addition. weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2)); // 4. Swap total hotkey stakes. // TotalHotkeyColdkeyStakesThisInterval( hotkey ) --> (u64: stakes, u64: block_number) - let stake_tuples: Vec<(T::AccountId, (u64, u64))> = TotalHotkeyColdkeyStakesThisInterval::::iter_prefix(old_hotkey).collect(); + let stake_tuples: Vec<(T::AccountId, (u64, u64))> = + TotalHotkeyColdkeyStakesThisInterval::::iter_prefix(old_hotkey).collect(); for (coldkey, stake_tup) in stake_tuples { // NOTE: You could use this to increase your allowed stake operations but this would cost. TotalHotkeyColdkeyStakesThisInterval::::insert(new_hotkey, &coldkey, stake_tup); @@ -179,14 +187,14 @@ impl Pallet { // 5. Swap LastTxBlock // LastTxBlock( hotkey ) --> u64 -- the last transaction block for the hotkey. - LastTxBlock::::remove( old_hotkey ); - LastTxBlock::::insert( new_hotkey, Self::get_current_block_as_u64() ); + LastTxBlock::::remove(old_hotkey); + LastTxBlock::::insert(new_hotkey, Self::get_current_block_as_u64()); weight.saturating_accrue(T::DbWeight::get().reads_writes(0, 2)); // 6. Swap LastTxBlockDelegateTake // LastTxBlockDelegateTake( hotkey ) --> u64 -- the last transaction block for the hotkey delegate take. - LastTxBlockDelegateTake::::remove( old_hotkey ); - LastTxBlockDelegateTake::::insert( new_hotkey, Self::get_current_block_as_u64() ); + LastTxBlockDelegateTake::::remove(old_hotkey); + LastTxBlockDelegateTake::::insert(new_hotkey, Self::get_current_block_as_u64()); weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); // 7. Swap Senate members. @@ -198,19 +206,19 @@ 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. + 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)); // 9. Swap all subnet specific info. let all_netuids: Vec = Self::get_all_subnet_netuids(); - for netuid in all_netuids { + for netuid in all_netuids { // 9.1 Remove the previous hotkey and insert the new hotkey from membership. // IsNetworkMember( hotkey, netuid ) -> bool -- is the hotkey a subnet member. - let is_network_member: bool = IsNetworkMember::::get( old_hotkey, netuid ); - IsNetworkMember::::remove( old_hotkey, netuid ); - IsNetworkMember::::insert( new_hotkey, netuid, is_network_member ); + let is_network_member: bool = IsNetworkMember::::get(old_hotkey, netuid); + IsNetworkMember::::remove(old_hotkey, netuid); + IsNetworkMember::::insert(new_hotkey, netuid, is_network_member); weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); // 9.2 Swap Uids + Keys. @@ -249,7 +257,7 @@ impl Pallet { } } - // 9.5 Swap WeightCommits + // 9.5 Swap WeightCommits // WeightCommits( hotkey ) --> Vec -- the weight commits for the hotkey. if is_network_member { if let Ok(old_weight_commits) = WeightCommits::::try_get(netuid, old_hotkey) { @@ -273,14 +281,13 @@ impl Pallet { weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); } } - } // 10. Swap Stake. // Stake( hotkey, coldkey ) -> stake -- the stake that the hotkey controls on behalf of the coldkey. let stakes: Vec<(T::AccountId, u64)> = Stake::::iter_prefix(old_hotkey).collect(); // Clear the entire old prefix here. - let _ = Stake::::clear_prefix( old_hotkey, stakes.len() as u32, None ); + let _ = Stake::::clear_prefix(old_hotkey, stakes.len() as u32, None); // Iterate over all the staking rows and insert them into the new hotkey. for (coldkey, old_stake_amount) in stakes { weight.saturating_accrue(T::DbWeight::get().reads(1)); @@ -290,7 +297,11 @@ impl Pallet { // Get the new stake value. let new_stake_value: u64 = Stake::::get(new_hotkey, &coldkey); // Insert the new stake value. - Stake::::insert(new_hotkey, &coldkey, new_stake_value.saturating_add(old_stake_amount)); + Stake::::insert( + new_hotkey, + &coldkey, + new_stake_value.saturating_add(old_stake_amount), + ); weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); // Swap StakingHotkeys. diff --git a/pallets/subtensor/tests/swap.rs b/pallets/subtensor/tests/swap.rs index f7f288cc2..0a3a85dff 100644 --- a/pallets/subtensor/tests/swap.rs +++ b/pallets/subtensor/tests/swap.rs @@ -9,7 +9,6 @@ use mock::*; use pallet_subtensor::*; use sp_core::U256; - #[test] fn test_do_swap_coldkey_success() { new_test_ext(1).execute_with(|| { diff --git a/pallets/subtensor/tests/swap_hotkey.rs b/pallets/subtensor/tests/swap_hotkey.rs index 35227d3b1..68f4ec49c 100644 --- a/pallets/subtensor/tests/swap_hotkey.rs +++ b/pallets/subtensor/tests/swap_hotkey.rs @@ -7,9 +7,8 @@ use frame_system::{Config, RawOrigin}; mod mock; use mock::*; use pallet_subtensor::*; -use sp_core::U256; use sp_core::H256; - +use sp_core::U256; // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_owner --exact --nocapture #[test] @@ -21,7 +20,12 @@ fn test_swap_owner() { let mut weight = Weight::zero(); Owner::::insert(&old_hotkey, &coldkey); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); assert!(!Owner::::contains_key(&old_hotkey)); assert_eq!(Owner::::get(&new_hotkey), coldkey); @@ -38,7 +42,12 @@ fn test_swap_owned_hotkeys() { let mut weight = Weight::zero(); OwnedHotkeys::::insert(&coldkey, vec![old_hotkey]); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); let hotkeys = OwnedHotkeys::::get(&coldkey); assert!(!hotkeys.contains(&old_hotkey)); @@ -57,7 +66,12 @@ fn test_swap_total_hotkey_stake() { TotalHotkeyStake::::insert(&old_hotkey, 100); TotalHotkeyStake::::insert(&new_hotkey, 50); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); assert!(!TotalHotkeyStake::::contains_key(&old_hotkey)); assert_eq!(TotalHotkeyStake::::get(&new_hotkey), 150); @@ -74,10 +88,21 @@ fn test_swap_total_hotkey_coldkey_stakes_this_interval() { let mut weight = Weight::zero(); TotalHotkeyColdkeyStakesThisInterval::::insert(&old_hotkey, &coldkey, (100, 1000)); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); - assert!(!TotalHotkeyColdkeyStakesThisInterval::::contains_key(&old_hotkey, &coldkey)); - assert_eq!(TotalHotkeyColdkeyStakesThisInterval::::get(&new_hotkey, &coldkey), (100, 1000)); + assert!(!TotalHotkeyColdkeyStakesThisInterval::::contains_key( + &old_hotkey, + &coldkey + )); + assert_eq!( + TotalHotkeyColdkeyStakesThisInterval::::get(&new_hotkey, &coldkey), + (100, 1000) + ); }); } @@ -91,10 +116,18 @@ fn test_swap_last_tx_block() { let mut weight = Weight::zero(); LastTxBlock::::insert(&old_hotkey, 1000); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); assert!(!LastTxBlock::::contains_key(&old_hotkey)); - assert_eq!(LastTxBlock::::get(&new_hotkey), SubtensorModule::get_current_block_as_u64()); + assert_eq!( + LastTxBlock::::get(&new_hotkey), + SubtensorModule::get_current_block_as_u64() + ); }); } @@ -108,10 +141,18 @@ fn test_swap_last_tx_block_delegate_take() { let mut weight = Weight::zero(); pallet_subtensor::LastTxBlockDelegateTake::::insert(&old_hotkey, 1000); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); assert!(!LastTxBlockDelegateTake::::contains_key(&old_hotkey)); - assert_eq!(LastTxBlockDelegateTake::::get(&new_hotkey), SubtensorModule::get_current_block_as_u64()); + assert_eq!( + LastTxBlockDelegateTake::::get(&new_hotkey), + SubtensorModule::get_current_block_as_u64() + ); }); } @@ -126,7 +167,12 @@ fn test_swap_senate_members() { // Assuming there's a way to add a member to the senate // SenateMembers::add_member(&old_hotkey); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); // Assert that the old_hotkey is no longer a member and new_hotkey is now a member // assert!(!SenateMembers::is_member(&old_hotkey)); @@ -144,7 +190,12 @@ fn test_swap_delegates() { let mut weight = Weight::zero(); Delegates::::insert(&old_hotkey, 100); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); assert!(!Delegates::::contains_key(&old_hotkey)); assert_eq!(Delegates::::get(&new_hotkey), 100); @@ -163,7 +214,12 @@ fn test_swap_subnet_membership() { add_network(netuid, 0, 1); IsNetworkMember::::insert(&old_hotkey, netuid, true); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); assert!(!IsNetworkMember::::contains_key(&old_hotkey, netuid)); assert!(IsNetworkMember::::get(&new_hotkey, netuid)); @@ -186,7 +242,12 @@ fn test_swap_uids_and_keys() { Uids::::insert(netuid, &old_hotkey, uid); Keys::::insert(netuid, uid, old_hotkey); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); assert_eq!(Uids::::get(netuid, &old_hotkey), None); assert_eq!(Uids::::get(netuid, &new_hotkey), Some(uid)); @@ -209,10 +270,18 @@ fn test_swap_prometheus() { IsNetworkMember::::insert(&old_hotkey, netuid, true); Prometheus::::insert(netuid, &old_hotkey, prometheus_info.clone()); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); assert!(!Prometheus::::contains_key(netuid, &old_hotkey)); - assert_eq!(Prometheus::::get(netuid, &new_hotkey), Some(prometheus_info)); + assert_eq!( + Prometheus::::get(netuid, &new_hotkey), + Some(prometheus_info) + ); }); } @@ -231,13 +300,18 @@ fn test_swap_axons() { IsNetworkMember::::insert(&old_hotkey, netuid, true); Axons::::insert(netuid, &old_hotkey, axon_info.clone()); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); assert!(!Axons::::contains_key(netuid, &old_hotkey)); assert_eq!(Axons::::get(netuid, &new_hotkey), Some(axon_info)); }); } - + // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_weight_commits --exact --nocapture #[test] fn test_swap_weight_commits() { @@ -253,10 +327,18 @@ fn test_swap_weight_commits() { IsNetworkMember::::insert(&old_hotkey, netuid, true); WeightCommits::::insert(netuid, &old_hotkey, weight_commits.clone()); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); assert!(!WeightCommits::::contains_key(netuid, &old_hotkey)); - assert_eq!(WeightCommits::::get(netuid, &new_hotkey), Some(weight_commits)); + assert_eq!( + WeightCommits::::get(netuid, &new_hotkey), + Some(weight_commits) + ); }); } @@ -274,12 +356,23 @@ fn test_swap_loaded_emission() { add_network(netuid, 0, 1); IsNetworkMember::::insert(&old_hotkey, netuid, true); - LoadedEmission::::insert(netuid, vec![(old_hotkey, server_emission, validator_emission)]); + LoadedEmission::::insert( + netuid, + vec![(old_hotkey, server_emission, validator_emission)], + ); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); let new_loaded_emission = LoadedEmission::::get(netuid); - assert_eq!(new_loaded_emission, Some(vec![(new_hotkey, server_emission, validator_emission)])); + assert_eq!( + new_loaded_emission, + Some(vec![(new_hotkey, server_emission, validator_emission)]) + ); }); } @@ -295,7 +388,12 @@ fn test_swap_stake() { Stake::::insert(&old_hotkey, &coldkey, stake_amount); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); assert!(!Stake::::contains_key(&old_hotkey, &coldkey)); assert_eq!(Stake::::get(&new_hotkey, &coldkey), stake_amount); @@ -314,7 +412,12 @@ fn test_swap_staking_hotkeys() { Stake::::insert(&old_hotkey, &coldkey, 100); StakingHotkeys::::insert(&coldkey, vec![old_hotkey]); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); let staking_hotkeys = StakingHotkeys::::get(&coldkey); assert!(!staking_hotkeys.contains(&old_hotkey)); @@ -337,7 +440,12 @@ fn test_swap_hotkey_with_multiple_coldkeys() { StakingHotkeys::::insert(&coldkey1, vec![old_hotkey]); StakingHotkeys::::insert(&coldkey2, vec![old_hotkey]); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey1, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey1, + &mut weight + )); assert_eq!(Stake::::get(&new_hotkey, &coldkey1), 100); assert_eq!(Stake::::get(&new_hotkey, &coldkey2), 200); @@ -358,7 +466,12 @@ fn test_swap_hotkey_with_existing_stake() { Stake::::insert(&old_hotkey, &coldkey, 100); Stake::::insert(&new_hotkey, &coldkey, 50); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); assert_eq!(Stake::::get(&new_hotkey, &coldkey), 150); }); @@ -380,7 +493,12 @@ fn test_swap_hotkey_with_multiple_subnets() { IsNetworkMember::::insert(&old_hotkey, netuid1, true); IsNetworkMember::::insert(&old_hotkey, netuid2, true); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); assert!(IsNetworkMember::::get(&new_hotkey, netuid1)); assert!(IsNetworkMember::::get(&new_hotkey, netuid2)); @@ -405,7 +523,12 @@ fn test_swap_staking_hotkeys_multiple_coldkeys() { StakingHotkeys::::insert(&coldkey1, vec![old_hotkey]); StakingHotkeys::::insert(&coldkey2, vec![old_hotkey, U256::from(5)]); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey1, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey1, + &mut weight + )); // Check if new_hotkey replaced old_hotkey in StakingHotkeys assert!(StakingHotkeys::::get(&coldkey1).contains(&new_hotkey)); @@ -414,7 +537,8 @@ fn test_swap_staking_hotkeys_multiple_coldkeys() { // Check if new_hotkey replaced old_hotkey for coldkey2 as well assert!(StakingHotkeys::::get(&coldkey2).contains(&new_hotkey)); assert!(!StakingHotkeys::::get(&coldkey2).contains(&old_hotkey)); - assert!(StakingHotkeys::::get(&coldkey2).contains(&U256::from(5))); // Other hotkeys should remain + assert!(StakingHotkeys::::get(&coldkey2).contains(&U256::from(5))); + // Other hotkeys should remain }); } @@ -430,7 +554,12 @@ fn test_swap_hotkey_with_no_stake() { // Set up initial state with no stake Owner::::insert(&old_hotkey, &coldkey); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); // Check if ownership transferred assert!(!Owner::::contains_key(&old_hotkey)); @@ -464,7 +593,12 @@ fn test_swap_hotkey_with_multiple_coldkeys_and_subnets() { IsNetworkMember::::insert(&old_hotkey, netuid2, true); TotalHotkeyStake::::insert(&old_hotkey, 300); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey1, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey1, + &mut weight + )); // Check ownership transfer assert!(!Owner::::contains_key(&old_hotkey)); @@ -637,7 +771,6 @@ fn test_swap_owner_new_hotkey_already_exists() { }); } - // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_total_hotkey_stake_success --exact --nocapture #[test] fn test_swap_total_hotkey_stake_success() { @@ -660,7 +793,6 @@ fn test_swap_total_hotkey_stake_success() { }); } - // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_delegates_success --exact --nocapture #[test] fn test_swap_delegates_success() { @@ -683,7 +815,6 @@ fn test_swap_delegates_success() { }); } - // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_stake_success --exact --nocapture #[test] fn test_swap_stake_success() { @@ -745,12 +876,7 @@ fn test_swap_total_hotkey_coldkey_stakes_this_interval_success() { TotalHotkeyColdkeyStakesThisInterval::::insert(old_hotkey, coldkey, stake); // Perform the swap - SubtensorModule::perform_hotkey_swap( - &old_hotkey, - &new_hotkey, - &coldkey, - &mut weight, - ); + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); // Verify the swap assert_eq!( @@ -780,7 +906,11 @@ fn test_swap_hotkey_error_cases() { // Test not enough balance let swap_cost = SubtensorModule::get_key_swap_cost(); assert_noop!( - SubtensorModule::do_swap_hotkey(RuntimeOrigin::signed(coldkey), &old_hotkey, &new_hotkey), + SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey + ), Error::::NotEnoughBalanceToPaySwapHotKey ); @@ -789,29 +919,47 @@ fn test_swap_hotkey_error_cases() { // Test new hotkey same as old assert_noop!( - SubtensorModule::do_swap_hotkey(RuntimeOrigin::signed(coldkey), &old_hotkey, &old_hotkey), + SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &old_hotkey + ), Error::::NewHotKeyIsSameWithOld ); // Test new hotkey already registered IsNetworkMember::::insert(&new_hotkey, 0, true); assert_noop!( - SubtensorModule::do_swap_hotkey(RuntimeOrigin::signed(coldkey), &old_hotkey, &new_hotkey), + SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey + ), Error::::HotKeyAlreadyRegisteredInSubNet ); IsNetworkMember::::remove(&new_hotkey, 0); // Test non-associated coldkey assert_noop!( - SubtensorModule::do_swap_hotkey(RuntimeOrigin::signed(wrong_coldkey), &old_hotkey, &new_hotkey), + SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(wrong_coldkey), + &old_hotkey, + &new_hotkey + ), Error::::NonAssociatedColdKey ); - // Run the successful swap - assert_ok!(SubtensorModule::do_swap_hotkey(RuntimeOrigin::signed(coldkey), &old_hotkey, &new_hotkey)); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey + )); // Check balance after swap - assert_eq!(Balances::free_balance(&coldkey), initial_balance - swap_cost); + assert_eq!( + Balances::free_balance(&coldkey), + initial_balance - swap_cost + ); }); }