From 60d0d7df323242e7679faf857e0cfdca105c22eb Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Mon, 17 Jun 2024 15:25:10 +0400 Subject: [PATCH 01/24] refactor: hotkey swap + tests --- pallets/subtensor/src/lib.rs | 13 +- pallets/subtensor/src/registration.rs | 139 +-- pallets/subtensor/src/swap.rs | 438 ++++++++++ pallets/subtensor/tests/mock.rs | 6 +- pallets/subtensor/tests/swap.rs | 1133 +++++++++++++++++++++++++ 5 files changed, 1583 insertions(+), 146 deletions(-) create mode 100644 pallets/subtensor/src/swap.rs create mode 100644 pallets/subtensor/tests/swap.rs diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index f50d0c722..049a52082 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -43,6 +43,7 @@ mod registration; mod root; mod serving; mod staking; +mod swap; mod uids; mod utils; mod weights; @@ -740,7 +741,7 @@ pub mod pallet { pub(super) type TxDelegateTakeRateLimit = StorageValue<_, u64, ValueQuery, DefaultTxDelegateTakeRateLimit>; #[pallet::storage] // --- MAP ( key ) --> last_block - pub(super) type LastTxBlock = + pub type LastTxBlock = StorageMap<_, Identity, T::AccountId, u64, ValueQuery, DefaultLastTxBlock>; #[pallet::storage] // --- MAP ( key ) --> last_block pub(super) type LastTxBlockDelegateTake = @@ -756,10 +757,10 @@ pub mod pallet { pub type ServingRateLimit = StorageMap<_, Identity, u16, u64, ValueQuery, DefaultServingRateLimit>; #[pallet::storage] // --- MAP ( netuid, hotkey ) --> axon_info - pub(super) type Axons = + pub type Axons = StorageDoubleMap<_, Identity, u16, Blake2_128Concat, T::AccountId, AxonInfoOf, OptionQuery>; #[pallet::storage] // --- MAP ( netuid, hotkey ) --> prometheus_info - pub(super) type Prometheus = StorageDoubleMap< + pub type Prometheus = StorageDoubleMap< _, Identity, u16, @@ -1013,13 +1014,13 @@ pub mod pallet { } #[pallet::storage] // --- DMAP ( netuid, hotkey ) --> uid - pub(super) type Uids = + pub type Uids = StorageDoubleMap<_, Identity, u16, Blake2_128Concat, T::AccountId, u16, OptionQuery>; #[pallet::storage] // --- DMAP ( netuid, uid ) --> hotkey - pub(super) type Keys = + pub type Keys = StorageDoubleMap<_, Identity, u16, Identity, u16, T::AccountId, ValueQuery, DefaultKey>; #[pallet::storage] // --- DMAP ( netuid ) --> (hotkey, se, ve) - pub(super) type LoadedEmission = + pub type LoadedEmission = StorageMap<_, Identity, u16, Vec<(T::AccountId, u64, u64)>, OptionQuery>; #[pallet::storage] // --- DMAP ( netuid ) --> active diff --git a/pallets/subtensor/src/registration.rs b/pallets/subtensor/src/registration.rs index dda00db54..da1d84183 100644 --- a/pallets/subtensor/src/registration.rs +++ b/pallets/subtensor/src/registration.rs @@ -1,6 +1,5 @@ use super::*; -use frame_support::storage::IterableStorageDoubleMap; -use sp_core::{Get, H256, U256}; +use sp_core::{H256, U256}; use sp_io::hashing::{keccak_256, sha2_256}; use sp_runtime::Saturating; use system::pallet_prelude::BlockNumberFor; @@ -591,140 +590,4 @@ impl Pallet { let vec_work: Vec = Self::hash_to_vec(work); (nonce, vec_work) } - - pub fn do_swap_hotkey( - origin: T::RuntimeOrigin, - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - ) -> DispatchResultWithPostInfo { - let coldkey = ensure_signed(origin)?; - - let mut weight = 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(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((TotalNetworks::::get().saturating_add(1)) as u64), - ); - - let swap_cost = 1_000_000_000u64; - 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); - - Owner::::remove(old_hotkey); - Owner::::insert(new_hotkey, coldkey.clone()); - weight.saturating_accrue(T::DbWeight::get().writes(2)); - - 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().writes(2)); - } - - 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().writes(2)); - } - - if let Ok(last_tx) = LastTxBlock::::try_get(old_hotkey) { - LastTxBlock::::remove(old_hotkey); - LastTxBlock::::insert(new_hotkey, last_tx); - - weight.saturating_accrue(T::DbWeight::get().writes(2)); - } - - let mut coldkey_stake: Vec<(T::AccountId, u64)> = vec![]; - for (coldkey, stake_amount) in Stake::::iter_prefix(old_hotkey) { - coldkey_stake.push((coldkey.clone(), stake_amount)); - } - - let _ = Stake::::clear_prefix(old_hotkey, coldkey_stake.len() as u32, None); - weight.saturating_accrue(T::DbWeight::get().writes(coldkey_stake.len() as u64)); - - for (coldkey, stake_amount) in coldkey_stake { - Stake::::insert(new_hotkey, coldkey, stake_amount); - weight.saturating_accrue(T::DbWeight::get().writes(1)); - } - - let mut netuid_is_member: Vec = vec![]; - for netuid in as IterableStorageDoubleMap>::iter_key_prefix(old_hotkey) { - netuid_is_member.push(netuid); - } - - 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)); - } - - 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().writes(2)); - } - } - - 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)); - - Keys::::insert(netuid, uid, new_hotkey); - - weight.saturating_accrue(T::DbWeight::get().writes(1)); - - LoadedEmission::::mutate(netuid, |emission_exists| match emission_exists { - Some(emissions) => { - if let Some(emission) = emissions.get_mut(uid as usize) { - let (_, se, ve) = emission; - *emission = (new_hotkey.clone(), *se, *ve); - } - } - None => {} - }); - - weight.saturating_accrue(T::DbWeight::get().writes(1)); - } - } - - 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()) - } } diff --git a/pallets/subtensor/src/swap.rs b/pallets/subtensor/src/swap.rs new file mode 100644 index 000000000..4d7aaf6f7 --- /dev/null +++ b/pallets/subtensor/src/swap.rs @@ -0,0 +1,438 @@ +use super::*; +use frame_support::{storage::IterableStorageDoubleMap, weights::Weight}; +use sp_core::Get; + +impl Pallet { + /// Swaps the hotkey of a coldkey account. + /// + /// # Arguments + /// + /// * `origin` - The origin of the transaction. + /// * `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)?; + + let mut weight = 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(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((TotalNetworks::::get() + 1u16) as u64)); + + let swap_cost = 1_000_000_000u64; + 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_last_tx_block(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_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()) + } + + /// Retrieves the network membership status for a given hotkey. + /// + /// # Arguments + /// + /// * `old_hotkey` - The hotkey to check for network membership. + /// + /// # Returns + /// + /// * `Result, Error>` - A vector of network IDs where the hotkey is a member. + pub fn get_netuid_is_member( + old_hotkey: &T::AccountId, + weight: &mut Weight, + ) -> Result, Error> { + let netuid_is_member: Vec = + as IterableStorageDoubleMap<_, _, _>>::iter_prefix(old_hotkey) + .map(|(netuid, _)| netuid) + .collect(); + weight.saturating_accrue(T::DbWeight::get().reads(netuid_is_member.len() as u64)); + Ok(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. + /// + /// # Returns + /// + /// * `Result<(), Error>` - The result of the operation. + pub fn swap_owner( + old_hotkey: &T::AccountId, + new_hotkey: &T::AccountId, + coldkey: &T::AccountId, + weight: &mut Weight, + ) -> DispatchResult { + Owner::::remove(old_hotkey); + Owner::::insert(new_hotkey, coldkey.clone()); + weight.saturating_accrue(T::DbWeight::get().writes(2)); + Ok(()) + } + + /// Swaps the total stake of the hotkey. + /// + /// # Arguments + /// + /// * `old_hotkey` - The old hotkey. + /// * `new_hotkey` - The new hotkey. + /// * `weight` - The weight of the transaction. + /// + /// # Returns + /// + /// * `Result<(), Error>` - The result of the operation. + pub fn swap_total_hotkey_stake( + old_hotkey: &T::AccountId, + new_hotkey: &T::AccountId, + weight: &mut Weight, + ) -> DispatchResult { + 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().writes(2)); + } + Ok(()) + } + + /// Swaps the delegates of the hotkey. + /// + /// # Arguments + /// + /// * `old_hotkey` - The old hotkey. + /// * `new_hotkey` - The new hotkey. + /// * `weight` - The weight of the transaction. + /// + /// # Returns + /// + /// * `Result<(), Error>` - The result of the operation. + pub fn swap_delegates( + old_hotkey: &T::AccountId, + new_hotkey: &T::AccountId, + weight: &mut Weight, + ) -> DispatchResult { + 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().writes(2)); + } + Ok(()) + } + + /// Swaps the last transaction block of the hotkey. + /// + /// # Arguments + /// + /// * `old_hotkey` - The old hotkey. + /// * `new_hotkey` - The new hotkey. + /// * `weight` - The weight of the transaction. + /// + /// # Returns + /// + /// * `Result<(), Error>` - The result of the operation. + pub fn swap_last_tx_block( + old_hotkey: &T::AccountId, + new_hotkey: &T::AccountId, + weight: &mut Weight, + ) -> DispatchResult { + if let Ok(last_tx) = LastTxBlock::::try_get(old_hotkey) { + LastTxBlock::::remove(old_hotkey); + LastTxBlock::::insert(new_hotkey, last_tx); + weight.saturating_accrue(T::DbWeight::get().writes(2)); + } + Ok(()) + } + + /// Swaps the stake of the hotkey. + /// + /// # Arguments + /// + /// * `old_hotkey` - The old hotkey. + /// * `new_hotkey` - The new hotkey. + /// * `weight` - The weight of the transaction. + /// + /// # Returns + /// + /// * `Result<(), Error>` - The result of the operation. + pub fn swap_stake( + old_hotkey: &T::AccountId, + new_hotkey: &T::AccountId, + weight: &mut Weight, + ) -> DispatchResult { + let mut writes = 0; + let stakes: Vec<(T::AccountId, u64)> = Stake::::iter_prefix(old_hotkey).collect(); + for (coldkey, stake_amount) in stakes { + Stake::::insert(new_hotkey, &coldkey, stake_amount); + Stake::::remove(old_hotkey, &coldkey); + writes += 2; // One write for insert and one for remove + } + *weight += T::DbWeight::get().writes(writes as u64); + Ok(()) + } + /// 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. + /// + /// # Returns + /// + /// * `Result<(), Error>` - The result of the operation. + pub fn swap_is_network_member( + old_hotkey: &T::AccountId, + new_hotkey: &T::AccountId, + netuid_is_member: &Vec, + weight: &mut Weight, + ) -> DispatchResult { + 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)); + } + Ok(()) + } + + /// 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. + /// + /// # Returns + /// + /// * `Result<(), Error>` - The result of the operation. + pub fn swap_axons( + old_hotkey: &T::AccountId, + new_hotkey: &T::AccountId, + netuid_is_member: &Vec, + weight: &mut Weight, + ) -> DispatchResult { + 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().writes(2)); + } + } + Ok(()) + } + /// 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. + /// + /// # Returns + /// + /// * `Result<(), Error>` - The result of the operation. + pub fn swap_keys( + old_hotkey: &T::AccountId, + new_hotkey: &T::AccountId, + netuid_is_member: &Vec, + weight: &mut Weight, + ) -> DispatchResult { + let mut writes = 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 += 2; + } + } + log::info!("writes: {:?}", writes); + *weight += T::DbWeight::get().writes(writes as u64); + Ok(()) + } + + /// 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. + /// + /// # Returns + /// + /// * `Result<(), Error>` - The result of the operation. + pub fn swap_loaded_emission( + old_hotkey: &T::AccountId, + new_hotkey: &T::AccountId, + netuid_is_member: &[u16], + weight: &mut Weight, + ) -> DispatchResult { + 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 += T::DbWeight::get().writes(netuid_is_member.len() as u64); + Ok(()) + } + + /// 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. + /// + /// # Returns + /// + /// * `Result<(), Error>` - The result of the operation. + pub fn swap_uids( + old_hotkey: &T::AccountId, + new_hotkey: &T::AccountId, + netuid_is_member: &Vec, + weight: &mut Weight, + ) -> DispatchResult { + 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)); + } + } + Ok(()) + } + + /// 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. + /// + /// # Returns + /// + /// * `Result<(), Error>` - The result of the operation. + pub fn swap_prometheus( + old_hotkey: &T::AccountId, + new_hotkey: &T::AccountId, + netuid_is_member: &Vec, + weight: &mut Weight, + ) -> DispatchResult { + 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().writes(2)); + } + } + Ok(()) + } + + /// 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. + /// + /// # Returns + /// + /// * `Result<(), Error>` - The result of the operation. + pub fn swap_total_hotkey_coldkey_stakes_this_interval( + old_hotkey: &T::AccountId, + new_hotkey: &T::AccountId, + weight: &mut Weight, + ) -> DispatchResult { + 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 + } + Ok(()) + } +} diff --git a/pallets/subtensor/tests/mock.rs b/pallets/subtensor/tests/mock.rs index f2eeddb3f..195063899 100644 --- a/pallets/subtensor/tests/mock.rs +++ b/pallets/subtensor/tests/mock.rs @@ -1,5 +1,7 @@ #![allow(clippy::arithmetic_side_effects, clippy::unwrap_used)] - +use frame_support::derive_impl; +use frame_support::dispatch::DispatchResultWithPostInfo; +use frame_support::weights::constants::RocksDbWeight; use frame_support::{ assert_ok, derive_impl, dispatch::DispatchResultWithPostInfo, @@ -88,7 +90,7 @@ impl system::Config for Test { type BaseCallFilter = Everything; type BlockWeights = (); type BlockLength = (); - type DbWeight = (); + type DbWeight = RocksDbWeight; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; type Hash = H256; diff --git a/pallets/subtensor/tests/swap.rs b/pallets/subtensor/tests/swap.rs new file mode 100644 index 000000000..d6052c8fc --- /dev/null +++ b/pallets/subtensor/tests/swap.rs @@ -0,0 +1,1133 @@ +use codec::Encode; +use frame_support::weights::Weight; +use frame_support::{assert_err, assert_ok}; +use frame_system::Config; +mod mock; +use mock::*; +use pallet_subtensor::*; +use sp_core::U256; + +#[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_eq!( + SubtensorModule::get_total_stake_for_hotkey(&new_hotkey), + SubtensorModule::get_total_stake_for_hotkey(&old_hotkey) + ); + assert_eq!( + SubtensorModule::get_delegate(new_hotkey.encode()), + SubtensorModule::get_delegate(old_hotkey.encode()) + ); + assert_eq!( + 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(); + // UIDs + for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight).unwrap() { + 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).unwrap() { + 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).unwrap() { + assert_eq!( + LoadedEmission::::get(netuid).unwrap(), + LoadedEmission::::get(netuid).unwrap() + ); + } + + // IsNetworkMember + for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight).unwrap() { + assert!(IsNetworkMember::::contains_key(&new_hotkey, netuid)); + assert!(!IsNetworkMember::::contains_key(&old_hotkey, netuid)); + } + + // Owner + assert_eq!(Owner::::get(&new_hotkey), coldkey); + + // TotalHotkeyStake + assert_eq!( + 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).unwrap() { + 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_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 i in 0..10 { + SubtensorModule::add_balance_to_coldkey_account(&coldkeys[i], swap_cost); + } + + // 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).unwrap() { + 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).unwrap() { + 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).unwrap() { + assert_eq!( + LoadedEmission::::get(netuid).unwrap(), + LoadedEmission::::get(netuid).unwrap() + ); + } + + // IsNetworkMember + for netuid in SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight).unwrap() { + 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]); + } 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] + ); + } + } + } + }); +} + +#[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 + assert_ok!(SubtensorModule::swap_owner( + &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 + assert_ok!(SubtensorModule::swap_owner( + &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 + assert_ok!(SubtensorModule::swap_owner( + &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_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 + assert_ok!(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 total_stake = 1000u64; + let mut weight = Weight::zero(); + + // Initialize TotalHotkeyStake for old_hotkey + TotalHotkeyStake::::insert(&old_hotkey, total_stake); + + // Perform the swap + assert_ok!(SubtensorModule::swap_total_hotkey_stake( + &old_hotkey, + &new_hotkey, + &mut weight + )); + + // Verify the swap + assert_eq!(TotalHotkeyStake::::get(&new_hotkey), total_stake); + assert!(!TotalHotkeyStake::::contains_key(&old_hotkey)); + }); +} + +#[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 + assert_ok!(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 + assert_ok!(SubtensorModule::swap_total_hotkey_stake( + &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_swap_delegates_success() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let delegate_take = 10u16; + let mut weight = Weight::zero(); + + // Initialize Delegates for old_hotkey + Delegates::::insert(&old_hotkey, delegate_take); + + // Perform the swap + assert_ok!(SubtensorModule::swap_delegates( + &old_hotkey, + &new_hotkey, + &mut weight + )); + + // Verify the swap + assert_eq!(Delegates::::get(&new_hotkey), delegate_take); + assert!(!Delegates::::contains_key(&old_hotkey)); + }); +} + +#[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 + assert_ok!(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 delegate_take = 10u16; + let mut weight = Weight::zero(); + + // Initialize Delegates for old_hotkey + Delegates::::insert(&old_hotkey, delegate_take); + + // Perform the swap + assert_ok!(SubtensorModule::swap_delegates( + &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_swap_last_tx_block_success() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let last_tx_block = 100u64; + let mut weight = Weight::zero(); + + // Initialize LastTxBlock for old_hotkey + LastTxBlock::::insert(&old_hotkey, last_tx_block); + + // Perform the swap + assert_ok!(SubtensorModule::swap_last_tx_block( + &old_hotkey, + &new_hotkey, + &mut weight + )); + + // Verify the swap + assert_eq!(LastTxBlock::::get(&new_hotkey), last_tx_block); + assert!(!LastTxBlock::::contains_key(&old_hotkey)); + }); +} + +#[test] +fn test_swap_last_tx_block_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!(!LastTxBlock::::contains_key(&old_hotkey)); + + // Perform the swap + assert_ok!(SubtensorModule::swap_last_tx_block( + &old_hotkey, + &new_hotkey, + &mut weight + )); + + // Verify that new_hotkey does not have a last transaction block + assert!(!LastTxBlock::::contains_key(&new_hotkey)); + }); +} + +#[test] +fn test_swap_last_tx_block_weight_update() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let last_tx_block = 100u64; + let mut weight = Weight::zero(); + + // Initialize LastTxBlock for old_hotkey + LastTxBlock::::insert(&old_hotkey, last_tx_block); + + // Perform the swap + assert_ok!(SubtensorModule::swap_last_tx_block( + &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_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 + assert_ok!(SubtensorModule::swap_stake( + &old_hotkey, + &new_hotkey, + &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 + assert_ok!(SubtensorModule::swap_stake( + &old_hotkey, + &new_hotkey, + &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_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 + assert_ok!(SubtensorModule::swap_stake( + &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_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 + assert_ok!(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 + assert_ok!(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 + assert_ok!(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 + assert_ok!(SubtensorModule::swap_axons( + &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_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 + assert_ok!(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.clone()); + } + + // Perform the swap + assert_ok!(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.clone(), se, ve)); + } else { + *emission_exists = Some(vec![(old_hotkey.clone(), se, ve)]); + } + }); + } + + // Perform the swap + assert_ok!(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.clone(), se, ve)); + } else { + *emission_exists = Some(vec![(old_hotkey.clone(), se, ve)]); + } + }); + } + + // Perform the swap + assert_ok!(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 + assert_ok!(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 + assert_ok!(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 + assert_ok!(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 + assert_ok!(SubtensorModule::swap_prometheus( + &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_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 + assert_ok!( + SubtensorModule::swap_total_hotkey_coldkey_stakes_this_interval( + &old_hotkey, + &new_hotkey, + &mut weight + ) + ); + + // Verify the swap + assert_eq!( + TotalHotkeyColdkeyStakesThisInterval::::get(&new_hotkey, &coldkey), + stake + ); + assert!(!TotalHotkeyColdkeyStakesThisInterval::::contains_key( + &old_hotkey, + &coldkey + )); + }); +} + +#[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 + assert_ok!( + 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); + }); +} From 616c3228b9c2152c25572814268aaf9dc88c3e5c Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Mon, 17 Jun 2024 15:29:54 +0400 Subject: [PATCH 02/24] chore: lints --- pallets/subtensor/src/swap.rs | 17 +++++++++----- pallets/subtensor/tests/swap.rs | 40 +++++++++++++++++++++++++-------- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/pallets/subtensor/src/swap.rs b/pallets/subtensor/src/swap.rs index 4d7aaf6f7..aa0bbf812 100644 --- a/pallets/subtensor/src/swap.rs +++ b/pallets/subtensor/src/swap.rs @@ -248,7 +248,7 @@ impl Pallet { pub fn swap_is_network_member( old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, - netuid_is_member: &Vec, + netuid_is_member: &[u16], weight: &mut Weight, ) -> DispatchResult { let _ = IsNetworkMember::::clear_prefix(old_hotkey, netuid_is_member.len() as u32, None); @@ -275,7 +275,7 @@ impl Pallet { pub fn swap_axons( old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, - netuid_is_member: &Vec, + netuid_is_member: &[u16], weight: &mut Weight, ) -> DispatchResult { for netuid in netuid_is_member.iter() { @@ -368,7 +368,7 @@ impl Pallet { pub fn swap_uids( old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, - netuid_is_member: &Vec, + netuid_is_member: &[u16], weight: &mut Weight, ) -> DispatchResult { for netuid in netuid_is_member.iter() { @@ -396,7 +396,7 @@ impl Pallet { pub fn swap_prometheus( old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, - netuid_is_member: &Vec, + netuid_is_member: &[u16], weight: &mut Weight, ) -> DispatchResult { for netuid in netuid_is_member.iter() { @@ -425,10 +425,15 @@ impl Pallet { new_hotkey: &T::AccountId, weight: &mut Weight, ) -> DispatchResult { - let stakes: Vec<(T::AccountId, (u64, u64))> = TotalHotkeyColdkeyStakesThisInterval::::iter_prefix(old_hotkey).collect(); + 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); + 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 diff --git a/pallets/subtensor/tests/swap.rs b/pallets/subtensor/tests/swap.rs index d6052c8fc..980f5b5a5 100644 --- a/pallets/subtensor/tests/swap.rs +++ b/pallets/subtensor/tests/swap.rs @@ -145,13 +145,16 @@ fn test_do_swap_hotkey_ok_robust() { 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)); + 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); } @@ -211,7 +214,9 @@ fn test_do_swap_hotkey_ok_robust() { let mut weight = Weight::zero(); // UIDs - for netuid in SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight).unwrap() { + for netuid in + SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight).unwrap() + { assert_eq!( Uids::::get(netuid, &new_hotkeys[i]), Uids::::get(netuid, &old_hotkeys[i]) @@ -219,7 +224,9 @@ fn test_do_swap_hotkey_ok_robust() { } // Prometheus - for netuid in SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight).unwrap() { + for netuid in + SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight).unwrap() + { assert_eq!( Prometheus::::get(netuid, &new_hotkeys[i]), Prometheus::::get(netuid, &old_hotkeys[i]) @@ -227,7 +234,9 @@ fn test_do_swap_hotkey_ok_robust() { } // LoadedEmission - for netuid in SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight).unwrap() { + for netuid in + SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight).unwrap() + { assert_eq!( LoadedEmission::::get(netuid).unwrap(), LoadedEmission::::get(netuid).unwrap() @@ -235,9 +244,17 @@ fn test_do_swap_hotkey_ok_robust() { } // IsNetworkMember - for netuid in SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight).unwrap() { - assert!(IsNetworkMember::::contains_key(&new_hotkeys[i], netuid)); - assert!(!IsNetworkMember::::contains_key(&old_hotkeys[i], netuid)); + for netuid in + SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight).unwrap() + { + assert!(IsNetworkMember::::contains_key( + &new_hotkeys[i], + netuid + )); + assert!(!IsNetworkMember::::contains_key( + &old_hotkeys[i], + netuid + )); } // Owner @@ -833,7 +850,12 @@ fn test_swap_keys_success() { // Verify the swap for netuid in &netuid_is_member { - log::info!("neutuid, uid, hotkey: {:?}, {:?}, {:?}", netuid, uid, new_hotkey); + log::info!( + "neutuid, uid, hotkey: {:?}, {:?}, {:?}", + netuid, + uid, + new_hotkey + ); assert_eq!(Keys::::get(netuid, uid), new_hotkey); } }); From affd4b8b5a6c575f7216c21fda5e162316894ad7 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Mon, 17 Jun 2024 16:02:11 +0400 Subject: [PATCH 03/24] chore: clippy --- pallets/subtensor/tests/swap.rs | 189 ++++++++++++++++---------------- 1 file changed, 94 insertions(+), 95 deletions(-) diff --git a/pallets/subtensor/tests/swap.rs b/pallets/subtensor/tests/swap.rs index 980f5b5a5..c9cb2a7af 100644 --- a/pallets/subtensor/tests/swap.rs +++ b/pallets/subtensor/tests/swap.rs @@ -55,24 +55,24 @@ fn test_do_swap_hotkey_ok() { // Verify raw storage maps // Stake - for (coldkey, stake_amount) in Stake::::iter_prefix(&old_hotkey) { - assert_eq!(Stake::::get(&new_hotkey, &coldkey), stake_amount); + for (coldkey, stake_amount) in Stake::::iter_prefix(old_hotkey) { + assert_eq!(Stake::::get(new_hotkey, coldkey), stake_amount); } let mut weight = Weight::zero(); // UIDs for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight).unwrap() { assert_eq!( - Uids::::get(netuid, &new_hotkey), - Uids::::get(netuid, &old_hotkey) + Uids::::get(netuid, new_hotkey), + Uids::::get(netuid, old_hotkey) ); } // Prometheus for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight).unwrap() { assert_eq!( - Prometheus::::get(netuid, &new_hotkey), - Prometheus::::get(netuid, &old_hotkey) + Prometheus::::get(netuid, new_hotkey), + Prometheus::::get(netuid, old_hotkey) ); } @@ -86,43 +86,43 @@ fn test_do_swap_hotkey_ok() { // IsNetworkMember for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight).unwrap() { - assert!(IsNetworkMember::::contains_key(&new_hotkey, netuid)); - assert!(!IsNetworkMember::::contains_key(&old_hotkey, netuid)); + assert!(IsNetworkMember::::contains_key(new_hotkey, netuid)); + assert!(!IsNetworkMember::::contains_key(old_hotkey, netuid)); } // Owner - assert_eq!(Owner::::get(&new_hotkey), coldkey); + assert_eq!(Owner::::get(new_hotkey), coldkey); // TotalHotkeyStake assert_eq!( - TotalHotkeyStake::::get(&new_hotkey), - TotalHotkeyStake::::get(&old_hotkey) + TotalHotkeyStake::::get(new_hotkey), + TotalHotkeyStake::::get(old_hotkey) ); // Delegates assert_eq!( - Delegates::::get(&new_hotkey), - Delegates::::get(&old_hotkey) + Delegates::::get(new_hotkey), + Delegates::::get(old_hotkey) ); // LastTxBlock assert_eq!( - LastTxBlock::::get(&new_hotkey), - LastTxBlock::::get(&old_hotkey) + LastTxBlock::::get(new_hotkey), + LastTxBlock::::get(old_hotkey) ); // Axons for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight).unwrap() { assert_eq!( - Axons::::get(netuid, &new_hotkey), - Axons::::get(netuid, &old_hotkey) + Axons::::get(netuid, new_hotkey), + Axons::::get(netuid, old_hotkey) ); } // TotalHotkeyColdkeyStakesThisInterval assert_eq!( - TotalHotkeyColdkeyStakesThisInterval::::get(&new_hotkey, &coldkey), - TotalHotkeyColdkeyStakesThisInterval::::get(&old_hotkey, &coldkey) + TotalHotkeyColdkeyStakesThisInterval::::get(new_hotkey, coldkey), + TotalHotkeyColdkeyStakesThisInterval::::get(old_hotkey, coldkey) ); }); } @@ -161,8 +161,8 @@ fn test_do_swap_hotkey_ok_robust() { } // Add balance to coldkeys for swap cost - for i in 0..10 { - SubtensorModule::add_balance_to_coldkey_account(&coldkeys[i], swap_cost); + for coldkey in coldkeys.iter().take(10) { + SubtensorModule::add_balance_to_coldkey_account(coldkey, swap_cost); } // Perform the swaps for only two hotkeys @@ -178,7 +178,7 @@ fn test_do_swap_hotkey_ok_robust() { )); // Verify the swaps - for netuid in 1..=num_subnets { + for _netuid in 1..=num_subnets { for i in 0..10 { if i == 0 || i == 1 { assert_eq!( @@ -208,8 +208,8 @@ fn test_do_swap_hotkey_ok_robust() { // 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); + 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(); @@ -218,8 +218,8 @@ fn test_do_swap_hotkey_ok_robust() { SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight).unwrap() { assert_eq!( - Uids::::get(netuid, &new_hotkeys[i]), - Uids::::get(netuid, &old_hotkeys[i]) + Uids::::get(netuid, new_hotkeys[i]), + Uids::::get(netuid, old_hotkeys[i]) ); } @@ -228,8 +228,8 @@ fn test_do_swap_hotkey_ok_robust() { SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight).unwrap() { assert_eq!( - Prometheus::::get(netuid, &new_hotkeys[i]), - Prometheus::::get(netuid, &old_hotkeys[i]) + Prometheus::::get(netuid, new_hotkeys[i]), + Prometheus::::get(netuid, old_hotkeys[i]) ); } @@ -248,17 +248,17 @@ fn test_do_swap_hotkey_ok_robust() { SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight).unwrap() { assert!(IsNetworkMember::::contains_key( - &new_hotkeys[i], + new_hotkeys[i], netuid )); assert!(!IsNetworkMember::::contains_key( - &old_hotkeys[i], + old_hotkeys[i], netuid )); } // Owner - assert_eq!(Owner::::get(&new_hotkeys[i]), coldkeys[i]); + assert_eq!(Owner::::get(new_hotkeys[i]), coldkeys[i]); } else { // Ensure other hotkeys remain unchanged assert_eq!( @@ -312,7 +312,7 @@ fn test_swap_owner_success() { let mut weight = Weight::zero(); // Initialize Owner for old_hotkey - Owner::::insert(&old_hotkey, &coldkey); + Owner::::insert(old_hotkey, coldkey); // Perform the swap assert_ok!(SubtensorModule::swap_owner( @@ -323,8 +323,8 @@ fn test_swap_owner_success() { )); // Verify the swap - assert_eq!(Owner::::get(&new_hotkey), coldkey); - assert!(!Owner::::contains_key(&old_hotkey)); + assert_eq!(Owner::::get(new_hotkey), coldkey); + assert!(!Owner::::contains_key(old_hotkey)); }); } @@ -337,7 +337,7 @@ fn test_swap_owner_old_hotkey_not_exist() { let mut weight = Weight::zero(); // Ensure old_hotkey does not exist - assert!(!Owner::::contains_key(&old_hotkey)); + assert!(!Owner::::contains_key(old_hotkey)); // Perform the swap assert_ok!(SubtensorModule::swap_owner( @@ -348,8 +348,8 @@ fn test_swap_owner_old_hotkey_not_exist() { )); // Verify the swap - assert_eq!(Owner::::get(&new_hotkey), coldkey); - assert!(!Owner::::contains_key(&old_hotkey)); + assert_eq!(Owner::::get(new_hotkey), coldkey); + assert!(!Owner::::contains_key(old_hotkey)); }); } @@ -363,8 +363,8 @@ fn test_swap_owner_new_hotkey_already_exists() { let mut weight = Weight::zero(); // Initialize Owner for old_hotkey and new_hotkey - Owner::::insert(&old_hotkey, &coldkey); - Owner::::insert(&new_hotkey, &another_coldkey); + Owner::::insert(old_hotkey, coldkey); + Owner::::insert(new_hotkey, another_coldkey); // Perform the swap assert_ok!(SubtensorModule::swap_owner( @@ -375,8 +375,8 @@ fn test_swap_owner_new_hotkey_already_exists() { )); // Verify the swap - assert_eq!(Owner::::get(&new_hotkey), coldkey); - assert!(!Owner::::contains_key(&old_hotkey)); + assert_eq!(Owner::::get(new_hotkey), coldkey); + assert!(!Owner::::contains_key(old_hotkey)); }); } @@ -389,7 +389,7 @@ fn test_swap_owner_weight_update() { let mut weight = Weight::zero(); // Initialize Owner for old_hotkey - Owner::::insert(&old_hotkey, &coldkey); + Owner::::insert(old_hotkey, coldkey); // Perform the swap assert_ok!(SubtensorModule::swap_owner( @@ -414,7 +414,7 @@ fn test_swap_total_hotkey_stake_success() { let mut weight = Weight::zero(); // Initialize TotalHotkeyStake for old_hotkey - TotalHotkeyStake::::insert(&old_hotkey, total_stake); + TotalHotkeyStake::::insert(old_hotkey, total_stake); // Perform the swap assert_ok!(SubtensorModule::swap_total_hotkey_stake( @@ -424,8 +424,8 @@ fn test_swap_total_hotkey_stake_success() { )); // Verify the swap - assert_eq!(TotalHotkeyStake::::get(&new_hotkey), total_stake); - assert!(!TotalHotkeyStake::::contains_key(&old_hotkey)); + assert_eq!(TotalHotkeyStake::::get(new_hotkey), total_stake); + assert!(!TotalHotkeyStake::::contains_key(old_hotkey)); }); } @@ -437,7 +437,7 @@ fn test_swap_total_hotkey_stake_old_hotkey_not_exist() { let mut weight = Weight::zero(); // Ensure old_hotkey does not exist - assert!(!TotalHotkeyStake::::contains_key(&old_hotkey)); + assert!(!TotalHotkeyStake::::contains_key(old_hotkey)); // Perform the swap assert_ok!(SubtensorModule::swap_total_hotkey_stake( @@ -447,7 +447,7 @@ fn test_swap_total_hotkey_stake_old_hotkey_not_exist() { )); // Verify that new_hotkey does not have a stake - assert!(!TotalHotkeyStake::::contains_key(&new_hotkey)); + assert!(!TotalHotkeyStake::::contains_key(new_hotkey)); }); } @@ -460,7 +460,7 @@ fn test_swap_total_hotkey_stake_weight_update() { let mut weight = Weight::zero(); // Initialize TotalHotkeyStake for old_hotkey - TotalHotkeyStake::::insert(&old_hotkey, total_stake); + TotalHotkeyStake::::insert(old_hotkey, total_stake); // Perform the swap assert_ok!(SubtensorModule::swap_total_hotkey_stake( @@ -484,7 +484,7 @@ fn test_swap_delegates_success() { let mut weight = Weight::zero(); // Initialize Delegates for old_hotkey - Delegates::::insert(&old_hotkey, delegate_take); + Delegates::::insert(old_hotkey, delegate_take); // Perform the swap assert_ok!(SubtensorModule::swap_delegates( @@ -494,8 +494,8 @@ fn test_swap_delegates_success() { )); // Verify the swap - assert_eq!(Delegates::::get(&new_hotkey), delegate_take); - assert!(!Delegates::::contains_key(&old_hotkey)); + assert_eq!(Delegates::::get(new_hotkey), delegate_take); + assert!(!Delegates::::contains_key(old_hotkey)); }); } @@ -507,7 +507,7 @@ fn test_swap_delegates_old_hotkey_not_exist() { let mut weight = Weight::zero(); // Ensure old_hotkey does not exist - assert!(!Delegates::::contains_key(&old_hotkey)); + assert!(!Delegates::::contains_key(old_hotkey)); // Perform the swap assert_ok!(SubtensorModule::swap_delegates( @@ -517,7 +517,7 @@ fn test_swap_delegates_old_hotkey_not_exist() { )); // Verify that new_hotkey does not have a delegate - assert!(!Delegates::::contains_key(&new_hotkey)); + assert!(!Delegates::::contains_key(new_hotkey)); }); } @@ -530,7 +530,7 @@ fn test_swap_delegates_weight_update() { let mut weight = Weight::zero(); // Initialize Delegates for old_hotkey - Delegates::::insert(&old_hotkey, delegate_take); + Delegates::::insert(old_hotkey, delegate_take); // Perform the swap assert_ok!(SubtensorModule::swap_delegates( @@ -554,7 +554,7 @@ fn test_swap_last_tx_block_success() { let mut weight = Weight::zero(); // Initialize LastTxBlock for old_hotkey - LastTxBlock::::insert(&old_hotkey, last_tx_block); + LastTxBlock::::insert(old_hotkey, last_tx_block); // Perform the swap assert_ok!(SubtensorModule::swap_last_tx_block( @@ -564,8 +564,8 @@ fn test_swap_last_tx_block_success() { )); // Verify the swap - assert_eq!(LastTxBlock::::get(&new_hotkey), last_tx_block); - assert!(!LastTxBlock::::contains_key(&old_hotkey)); + assert_eq!(LastTxBlock::::get(new_hotkey), last_tx_block); + assert!(!LastTxBlock::::contains_key(old_hotkey)); }); } @@ -577,7 +577,7 @@ fn test_swap_last_tx_block_old_hotkey_not_exist() { let mut weight = Weight::zero(); // Ensure old_hotkey does not exist - assert!(!LastTxBlock::::contains_key(&old_hotkey)); + assert!(!LastTxBlock::::contains_key(old_hotkey)); // Perform the swap assert_ok!(SubtensorModule::swap_last_tx_block( @@ -587,7 +587,7 @@ fn test_swap_last_tx_block_old_hotkey_not_exist() { )); // Verify that new_hotkey does not have a last transaction block - assert!(!LastTxBlock::::contains_key(&new_hotkey)); + assert!(!LastTxBlock::::contains_key(new_hotkey)); }); } @@ -600,7 +600,7 @@ fn test_swap_last_tx_block_weight_update() { let mut weight = Weight::zero(); // Initialize LastTxBlock for old_hotkey - LastTxBlock::::insert(&old_hotkey, last_tx_block); + LastTxBlock::::insert(old_hotkey, last_tx_block); // Perform the swap assert_ok!(SubtensorModule::swap_last_tx_block( @@ -625,7 +625,7 @@ fn test_swap_stake_success() { let mut weight = Weight::zero(); // Initialize Stake for old_hotkey - Stake::::insert(&old_hotkey, &coldkey, stake_amount); + Stake::::insert(old_hotkey, coldkey, stake_amount); // Perform the swap assert_ok!(SubtensorModule::swap_stake( @@ -635,8 +635,8 @@ fn test_swap_stake_success() { )); // Verify the swap - assert_eq!(Stake::::get(&new_hotkey, &coldkey), stake_amount); - assert!(!Stake::::contains_key(&old_hotkey, &coldkey)); + assert_eq!(Stake::::get(new_hotkey, coldkey), stake_amount); + assert!(!Stake::::contains_key(old_hotkey, coldkey)); }); } @@ -650,10 +650,10 @@ fn test_swap_stake_old_hotkey_not_exist() { let mut weight = Weight::zero(); // Initialize Stake for old_hotkey - Stake::::insert(&old_hotkey, &coldkey, stake_amount); + Stake::::insert(old_hotkey, coldkey, stake_amount); // Ensure old_hotkey has a stake - assert!(Stake::::contains_key(&old_hotkey, &coldkey)); + assert!(Stake::::contains_key(old_hotkey, coldkey)); // Perform the swap assert_ok!(SubtensorModule::swap_stake( @@ -663,8 +663,8 @@ fn test_swap_stake_old_hotkey_not_exist() { )); // 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)); + assert!(Stake::::contains_key(new_hotkey, coldkey)); + assert!(!Stake::::contains_key(old_hotkey, coldkey)); }); } @@ -678,7 +678,7 @@ fn test_swap_stake_weight_update() { let mut weight = Weight::zero(); // Initialize Stake for old_hotkey - Stake::::insert(&old_hotkey, &coldkey, stake_amount); + Stake::::insert(old_hotkey, coldkey, stake_amount); // Perform the swap assert_ok!(SubtensorModule::swap_stake( @@ -703,7 +703,7 @@ fn test_swap_is_network_member_success() { // Initialize IsNetworkMember for old_hotkey for netuid in &netuid_is_member { - IsNetworkMember::::insert(&old_hotkey, netuid, true); + IsNetworkMember::::insert(old_hotkey, netuid, true); } // Perform the swap @@ -716,8 +716,8 @@ fn test_swap_is_network_member_success() { // Verify the swap for netuid in &netuid_is_member { - assert!(IsNetworkMember::::contains_key(&new_hotkey, netuid)); - assert!(!IsNetworkMember::::contains_key(&old_hotkey, netuid)); + assert!(IsNetworkMember::::contains_key(new_hotkey, netuid)); + assert!(!IsNetworkMember::::contains_key(old_hotkey, netuid)); } }); } @@ -732,7 +732,7 @@ fn test_swap_is_network_member_weight_update() { // Initialize IsNetworkMember for old_hotkey for netuid in &netuid_is_member { - IsNetworkMember::::insert(&old_hotkey, netuid, true); + IsNetworkMember::::insert(old_hotkey, netuid, true); } // Perform the swap @@ -769,7 +769,7 @@ fn test_swap_axons_success() { // Initialize Axons for old_hotkey for netuid in &netuid_is_member { - Axons::::insert(netuid, &old_hotkey, axon_info.clone()); + Axons::::insert(netuid, old_hotkey, axon_info.clone()); } // Perform the swap @@ -782,8 +782,8 @@ fn test_swap_axons_success() { // 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)); + assert_eq!(Axons::::get(netuid, new_hotkey).unwrap(), axon_info); + assert!(!Axons::::contains_key(netuid, old_hotkey)); } }); } @@ -808,7 +808,7 @@ fn test_swap_axons_weight_update() { // Initialize Axons for old_hotkey for netuid in &netuid_is_member { - Axons::::insert(netuid, &old_hotkey, axon_info.clone()); + Axons::::insert(netuid, old_hotkey, axon_info.clone()); } // Perform the swap @@ -837,7 +837,7 @@ fn test_swap_keys_success() { // 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); + Keys::::insert(*netuid, uid, old_hotkey); } // Perform the swap @@ -872,7 +872,7 @@ fn test_swap_keys_weight_update() { // Initialize Keys for old_hotkey for netuid in &netuid_is_member { - Keys::::insert(*netuid, uid, old_hotkey.clone()); + Keys::::insert(*netuid, uid, old_hotkey); } // Perform the swap @@ -903,9 +903,9 @@ fn test_swap_loaded_emission_success() { for netuid in &netuid_is_member { LoadedEmission::::mutate(netuid, |emission_exists| { if let Some(emissions) = emission_exists { - emissions.push((old_hotkey.clone(), se, ve)); + emissions.push((old_hotkey, se, ve)); } else { - *emission_exists = Some(vec![(old_hotkey.clone(), se, ve)]); + *emission_exists = Some(vec![(old_hotkey, se, ve)]); } }); } @@ -942,9 +942,9 @@ fn test_swap_loaded_emission_weight_update() { for netuid in &netuid_is_member { LoadedEmission::::mutate(netuid, |emission_exists| { if let Some(emissions) = emission_exists { - emissions.push((old_hotkey.clone(), se, ve)); + emissions.push((old_hotkey, se, ve)); } else { - *emission_exists = Some(vec![(old_hotkey.clone(), se, ve)]); + *emission_exists = Some(vec![(old_hotkey, se, ve)]); } }); } @@ -974,7 +974,7 @@ fn test_swap_uids_success() { // Initialize Uids for old_hotkey for netuid in &netuid_is_member { - Uids::::insert(netuid, &old_hotkey, uid); + Uids::::insert(netuid, old_hotkey, uid); } // Perform the swap @@ -987,8 +987,8 @@ fn test_swap_uids_success() { // 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)); + assert_eq!(Uids::::get(netuid, new_hotkey).unwrap(), uid); + assert!(!Uids::::contains_key(netuid, old_hotkey)); } }); } @@ -1004,7 +1004,7 @@ fn test_swap_uids_weight_update() { // Initialize Uids for old_hotkey for netuid in &netuid_is_member { - Uids::::insert(netuid, &old_hotkey, uid); + Uids::::insert(netuid, old_hotkey, uid); } // Perform the swap @@ -1038,7 +1038,7 @@ fn test_swap_prometheus_success() { // Initialize Prometheus for old_hotkey for netuid in &netuid_is_member { - Prometheus::::insert(netuid, &old_hotkey, prometheus_info.clone()); + Prometheus::::insert(netuid, old_hotkey, prometheus_info.clone()); } // Perform the swap @@ -1052,10 +1052,10 @@ fn test_swap_prometheus_success() { // Verify the swap for netuid in &netuid_is_member { assert_eq!( - Prometheus::::get(netuid, &new_hotkey).unwrap(), + Prometheus::::get(netuid, new_hotkey).unwrap(), prometheus_info ); - assert!(!Prometheus::::contains_key(netuid, &old_hotkey)); + assert!(!Prometheus::::contains_key(netuid, old_hotkey)); } }); } @@ -1077,7 +1077,7 @@ fn test_swap_prometheus_weight_update() { // Initialize Prometheus for old_hotkey for netuid in &netuid_is_member { - Prometheus::::insert(netuid, &old_hotkey, prometheus_info.clone()); + Prometheus::::insert(netuid, old_hotkey, prometheus_info.clone()); } // Perform the swap @@ -1104,7 +1104,7 @@ fn test_swap_total_hotkey_coldkey_stakes_this_interval_success() { let mut weight = Weight::zero(); // Initialize TotalHotkeyColdkeyStakesThisInterval for old_hotkey - TotalHotkeyColdkeyStakesThisInterval::::insert(&old_hotkey, &coldkey, stake); + TotalHotkeyColdkeyStakesThisInterval::::insert(old_hotkey, coldkey, stake); // Perform the swap assert_ok!( @@ -1117,12 +1117,11 @@ fn test_swap_total_hotkey_coldkey_stakes_this_interval_success() { // Verify the swap assert_eq!( - TotalHotkeyColdkeyStakesThisInterval::::get(&new_hotkey, &coldkey), + TotalHotkeyColdkeyStakesThisInterval::::get(new_hotkey, coldkey), stake ); assert!(!TotalHotkeyColdkeyStakesThisInterval::::contains_key( - &old_hotkey, - &coldkey + old_hotkey, coldkey )); }); } @@ -1137,7 +1136,7 @@ fn test_swap_total_hotkey_coldkey_stakes_this_interval_weight_update() { let mut weight = Weight::zero(); // Initialize TotalHotkeyColdkeyStakesThisInterval for old_hotkey - TotalHotkeyColdkeyStakesThisInterval::::insert(&old_hotkey, &coldkey, stake); + TotalHotkeyColdkeyStakesThisInterval::::insert(old_hotkey, coldkey, stake); // Perform the swap assert_ok!( From 04637f810c44ffb272e956fa19ed1fbc0c459686 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Mon, 17 Jun 2024 17:31:13 +0400 Subject: [PATCH 04/24] chore: give 1k on faucet for easier to create networks locally --- pallets/subtensor/src/registration.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/subtensor/src/registration.rs b/pallets/subtensor/src/registration.rs index da1d84183..4688bcbb5 100644 --- a/pallets/subtensor/src/registration.rs +++ b/pallets/subtensor/src/registration.rs @@ -394,7 +394,7 @@ impl Pallet { UsedWork::::insert(work.clone(), current_block_number); // --- 5. Add Balance via faucet. - let balance_to_add: u64 = 100_000_000_000; + let balance_to_add: u64 = 1_000_000_000_000; Self::coinbase(100_000_000_000); // We are creating tokens here from the coinbase. Self::add_balance_to_coldkey_account(&coldkey, balance_to_add); From 62e5907ccaf9509888faecdbd7620146a4a2fa85 Mon Sep 17 00:00:00 2001 From: Keith Date: Mon, 17 Jun 2024 23:25:14 +0900 Subject: [PATCH 05/24] Correct the expected weights on the register extrinsic --- pallets/subtensor/tests/registration.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pallets/subtensor/tests/registration.rs b/pallets/subtensor/tests/registration.rs index 0da10bc48..8af83ad74 100644 --- a/pallets/subtensor/tests/registration.rs +++ b/pallets/subtensor/tests/registration.rs @@ -38,7 +38,9 @@ fn test_registration_subscribe_ok_dispatch_info_ok() { assert_eq!( call.get_dispatch_info(), DispatchInfo { - weight: frame_support::weights::Weight::from_parts(192_000_000, 0), + weight: frame_support::weights::Weight::from_parts(192_000_000, 0) + .saturating_add(::DbWeight::get().reads(24)) + .saturating_add(::DbWeight::get().writes(22)), class: DispatchClass::Normal, pays_fee: Pays::No } From 9667b49fdadfd8d3d17216dc7635582103054d93 Mon Sep 17 00:00:00 2001 From: distributedstatemachine <112424909+distributedstatemachine@users.noreply.github.com> Date: Mon, 17 Jun 2024 21:26:39 +0400 Subject: [PATCH 06/24] Update pallets/subtensor/src/swap.rs Co-authored-by: Keith --- pallets/subtensor/src/swap.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/subtensor/src/swap.rs b/pallets/subtensor/src/swap.rs index aa0bbf812..8185ba0f9 100644 --- a/pallets/subtensor/src/swap.rs +++ b/pallets/subtensor/src/swap.rs @@ -7,7 +7,7 @@ impl Pallet { /// /// # Arguments /// - /// * `origin` - The origin of the transaction. + /// * `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. /// From b60b544839f1f9c5811f05404116682991cc2e26 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Mon, 17 Jun 2024 21:31:34 +0400 Subject: [PATCH 07/24] chore: updates from using real weights in tests --- pallets/subtensor/tests/serving.rs | 4 ++-- pallets/subtensor/tests/staking.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pallets/subtensor/tests/serving.rs b/pallets/subtensor/tests/serving.rs index 851edeee2..41e9888cc 100644 --- a/pallets/subtensor/tests/serving.rs +++ b/pallets/subtensor/tests/serving.rs @@ -50,7 +50,7 @@ fn test_serving_subscribe_ok_dispatch_info_ok() { assert_eq!( call.get_dispatch_info(), DispatchInfo { - weight: frame_support::weights::Weight::from_parts(46_000_000, 0), + weight: frame_support::weights::Weight::from_parts(246_000_000, 0), class: DispatchClass::Normal, pays_fee: Pays::No } @@ -295,7 +295,7 @@ fn test_prometheus_serving_subscribe_ok_dispatch_info_ok() { assert_eq!( call.get_dispatch_info(), DispatchInfo { - weight: frame_support::weights::Weight::from_parts(45_000_000, 0), + weight: frame_support::weights::Weight::from_parts(245_000_000, 0), class: DispatchClass::Normal, pays_fee: Pays::No } diff --git a/pallets/subtensor/tests/staking.rs b/pallets/subtensor/tests/staking.rs index 766b3a495..529332f04 100644 --- a/pallets/subtensor/tests/staking.rs +++ b/pallets/subtensor/tests/staking.rs @@ -26,7 +26,7 @@ fn test_add_stake_dispatch_info_ok() { assert_eq!( call.get_dispatch_info(), DispatchInfo { - weight: frame_support::weights::Weight::from_parts(124_000_000, 0), + weight: frame_support::weights::Weight::from_parts(1_074_000_000, 0), class: DispatchClass::Normal, pays_fee: Pays::No } @@ -532,7 +532,7 @@ fn test_remove_stake_dispatch_info_ok() { assert_eq!( call.get_dispatch_info(), DispatchInfo { - weight: frame_support::weights::Weight::from_parts(111_000_000, 0) + weight: frame_support::weights::Weight::from_parts(1_061_000_000, 0) .add_proof_size(43991), class: DispatchClass::Normal, pays_fee: Pays::No From 31f320ccf1fabf29869c095568422730b7f57cb1 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Mon, 17 Jun 2024 22:21:54 +0400 Subject: [PATCH 08/24] chore: review comments , make swap cost a constant --- pallets/admin-utils/tests/mock.rs | 2 ++ pallets/subtensor/src/lib.rs | 8 ++++++++ pallets/subtensor/src/swap.rs | 22 ++++++++++++---------- pallets/subtensor/src/utils.rs | 5 +++++ pallets/subtensor/tests/mock.rs | 2 ++ pallets/subtensor/tests/registration.rs | 4 +++- runtime/src/lib.rs | 1 + 7 files changed, 33 insertions(+), 11 deletions(-) diff --git a/pallets/admin-utils/tests/mock.rs b/pallets/admin-utils/tests/mock.rs index 16a1f79f4..a78eb6d3d 100644 --- a/pallets/admin-utils/tests/mock.rs +++ b/pallets/admin-utils/tests/mock.rs @@ -110,6 +110,7 @@ parameter_types! { pub const InitialSubnetLimit: u16 = 10; // Max 10 subnets. pub const InitialNetworkRateLimit: u64 = 0; pub const InitialTargetStakesPerInterval: u16 = 1; + pub const InitialHotkeySwapCost: u64 = 1_000_000_000; pub const InitialAlphaHigh: u16 = 58982; // Represents 0.9 as per the production default pub const InitialAlphaLow: u16 = 45875; // Represents 0.7 as per the production default pub const InitialLiquidAlphaOn: bool = false; // Default value for LiquidAlphaOn @@ -164,6 +165,7 @@ impl pallet_subtensor::Config for Test { type InitialSubnetLimit = InitialSubnetLimit; type InitialNetworkRateLimit = InitialNetworkRateLimit; type InitialTargetStakesPerInterval = InitialTargetStakesPerInterval; + type HotkeySwapCost = InitialHotkeySwapCost; type AlphaHigh = InitialAlphaHigh; type AlphaLow = InitialAlphaLow; type LiquidAlphaOn = InitialLiquidAlphaOn; diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index 049a52082..7ca2a2777 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -239,6 +239,9 @@ pub mod pallet { /// Initial target stakes per interval issuance. #[pallet::constant] type InitialTargetStakesPerInterval: Get; + /// Cost of swapping a hotkey. + #[pallet::constant] + type HotkeySwapCost: Get; /// The upper bound for the alpha parameter. Used for Liquid Alpha. #[pallet::constant] type AlphaHigh: Get; @@ -272,6 +275,11 @@ pub mod pallet { pub fn TotalSupply() -> u64 { 21_000_000_000_000_000 // Rao => 21_000_000 Tao } + /// Hotkey swap cost. + #[pallet::type_value] + pub fn HotkeySwapCost() -> u64 { + 1_000_000_000 + } /// Default total stake. #[pallet::type_value] pub fn DefaultDefaultTake() -> u16 { diff --git a/pallets/subtensor/src/swap.rs b/pallets/subtensor/src/swap.rs index 8185ba0f9..873dcaa12 100644 --- a/pallets/subtensor/src/swap.rs +++ b/pallets/subtensor/src/swap.rs @@ -29,7 +29,15 @@ impl Pallet { ) -> DispatchResultWithPostInfo { let coldkey = ensure_signed(origin)?; - let mut weight = T::DbWeight::get().reads_writes(2, 0); + 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 @@ -41,18 +49,12 @@ impl Pallet { Error::::HotKeySetTxRateLimitExceeded ); - weight.saturating_accrue(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((TotalNetworks::::get() + 1u16) as u64)); - let swap_cost = 1_000_000_000u64; + let swap_cost = Self::get_hotkey_swap_cost(); + log::info!("Swap cost: {:?}", swap_cost); + ensure!( Self::can_remove_balance_from_coldkey_account(&coldkey, swap_cost), Error::::NotEnoughBalanceToPaySwapHotKey diff --git a/pallets/subtensor/src/utils.rs b/pallets/subtensor/src/utils.rs index 918343564..faaaecebb 100644 --- a/pallets/subtensor/src/utils.rs +++ b/pallets/subtensor/src/utils.rs @@ -3,6 +3,7 @@ use crate::{ system::{ensure_root, ensure_signed_or_root}, Error, }; +use sp_core::Get; use sp_core::U256; use substrate_fixed::types::I32F32; @@ -663,6 +664,10 @@ impl Pallet { NominatorMinRequiredStake::::put(min_stake); } + pub fn get_hotkey_swap_cost() -> u64 { + T::HotkeySwapCost::get() + } + pub fn get_alpha_values(netuid: u16) -> (u16, u16) { AlphaValues::::get(netuid) } diff --git a/pallets/subtensor/tests/mock.rs b/pallets/subtensor/tests/mock.rs index 195063899..cf58f49d2 100644 --- a/pallets/subtensor/tests/mock.rs +++ b/pallets/subtensor/tests/mock.rs @@ -162,6 +162,7 @@ parameter_types! { pub const InitialSubnetLimit: u16 = 10; // Max 10 subnets. pub const InitialNetworkRateLimit: u64 = 0; pub const InitialTargetStakesPerInterval: u16 = 2; + pub const InitialHotkeySwapCost: u64 = 1_000_000_000; pub const InitialAlphaHigh: u16 = 58982; // Represents 0.9 as per the production default pub const InitialAlphaLow: u16 = 45875; // Represents 0.7 as per the production default pub const InitialLiquidAlphaOn: bool = false; // Default value for LiquidAlphaOn @@ -365,6 +366,7 @@ impl pallet_subtensor::Config for Test { type InitialSubnetLimit = InitialSubnetLimit; type InitialNetworkRateLimit = InitialNetworkRateLimit; type InitialTargetStakesPerInterval = InitialTargetStakesPerInterval; + type HotkeySwapCost = InitialHotkeySwapCost; type AlphaHigh = InitialAlphaHigh; type AlphaLow = InitialAlphaLow; type LiquidAlphaOn = InitialLiquidAlphaOn; diff --git a/pallets/subtensor/tests/registration.rs b/pallets/subtensor/tests/registration.rs index 8af83ad74..77ec068fd 100644 --- a/pallets/subtensor/tests/registration.rs +++ b/pallets/subtensor/tests/registration.rs @@ -40,7 +40,9 @@ fn test_registration_subscribe_ok_dispatch_info_ok() { DispatchInfo { weight: frame_support::weights::Weight::from_parts(192_000_000, 0) .saturating_add(::DbWeight::get().reads(24)) - .saturating_add(::DbWeight::get().writes(22)), + .saturating_add( + ::DbWeight::get().writes(22) + ), class: DispatchClass::Normal, pays_fee: Pays::No } diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 1d01c0b92..4b8141928 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -879,6 +879,7 @@ impl pallet_subtensor::Config for Runtime { type InitialSubnetLimit = SubtensorInitialSubnetLimit; type InitialNetworkRateLimit = SubtensorInitialNetworkRateLimit; type InitialTargetStakesPerInterval = SubtensorInitialTargetStakesPerInterval; + type HotkeySwapCost = ConstU64<1_000_000_000>; type AlphaHigh = InitialAlphaHigh; type AlphaLow = InitialAlphaLow; type LiquidAlphaOn = InitialLiquidAlphaOn; From 8d7e1865f1947b80deac1d603d8132bfb1e1442e Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Mon, 17 Jun 2024 22:37:26 +0400 Subject: [PATCH 09/24] chore: runtime consts --- runtime/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 4b8141928..98d267c6d 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -825,6 +825,7 @@ parameter_types! { pub const SubtensorInitialNetworkLockReductionInterval: u64 = 14 * 7200; pub const SubtensorInitialNetworkRateLimit: u64 = 7200; pub const SubtensorInitialTargetStakesPerInterval: u16 = 1; + pub const SubtensorInitialHotkeySwapCost: u64 = 1_000_000_000; pub const InitialAlphaHigh: u16 = 58982; // Represents 0.9 as per the production default pub const InitialAlphaLow: u16 = 45875; // Represents 0.7 as per the production default pub const InitialLiquidAlphaOn: bool = false; // Default value for LiquidAlphaOn @@ -879,7 +880,7 @@ impl pallet_subtensor::Config for Runtime { type InitialSubnetLimit = SubtensorInitialSubnetLimit; type InitialNetworkRateLimit = SubtensorInitialNetworkRateLimit; type InitialTargetStakesPerInterval = SubtensorInitialTargetStakesPerInterval; - type HotkeySwapCost = ConstU64<1_000_000_000>; + type HotkeySwapCost = SubtensorInitialHotkeySwapCost; type AlphaHigh = InitialAlphaHigh; type AlphaLow = InitialAlphaLow; type LiquidAlphaOn = InitialLiquidAlphaOn; From 9eeff75a75d4e45382914bb6ca7d5c212ed0938d Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Tue, 18 Jun 2024 01:09:59 +0400 Subject: [PATCH 10/24] chore: clear prefix for removing old value from stake map --- pallets/subtensor/src/swap.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pallets/subtensor/src/swap.rs b/pallets/subtensor/src/swap.rs index 873dcaa12..5313113b7 100644 --- a/pallets/subtensor/src/swap.rs +++ b/pallets/subtensor/src/swap.rs @@ -227,11 +227,13 @@ impl Pallet { ) -> DispatchResult { let mut writes = 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); - Stake::::remove(old_hotkey, &coldkey); + let _ = Stake::::clear_prefix(old_hotkey, stake_count, None); writes += 2; // One write for insert and one for remove } + *weight += T::DbWeight::get().writes(writes as u64); Ok(()) } From 12161b09e5c1c93f2d9141a5cb244211a034e126 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Tue, 18 Jun 2024 01:26:04 +0400 Subject: [PATCH 11/24] chore: pr comments assert keys --- pallets/subtensor/tests/swap.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pallets/subtensor/tests/swap.rs b/pallets/subtensor/tests/swap.rs index c9cb2a7af..04819211a 100644 --- a/pallets/subtensor/tests/swap.rs +++ b/pallets/subtensor/tests/swap.rs @@ -178,7 +178,7 @@ fn test_do_swap_hotkey_ok_robust() { )); // Verify the swaps - for _netuid in 1..=num_subnets { + for netuid in 1..=num_subnets { for i in 0..10 { if i == 0 || i == 1 { assert_eq!( @@ -259,6 +259,13 @@ fn test_do_swap_hotkey_ok_robust() { // 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]); + } + } } else { // Ensure other hotkeys remain unchanged assert_eq!( From 966b5a2b3993ead1975b5c317e8df6f934d2dd30 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Tue, 18 Jun 2024 01:28:57 +0400 Subject: [PATCH 12/24] chore: pr comments: remove last tx block --- pallets/subtensor/src/swap.rs | 24 ----------- pallets/subtensor/tests/swap.rs | 70 --------------------------------- 2 files changed, 94 deletions(-) diff --git a/pallets/subtensor/src/swap.rs b/pallets/subtensor/src/swap.rs index 5313113b7..4f9eaf047 100644 --- a/pallets/subtensor/src/swap.rs +++ b/pallets/subtensor/src/swap.rs @@ -65,7 +65,6 @@ impl Pallet { 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_last_tx_block(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 @@ -185,29 +184,6 @@ impl Pallet { Ok(()) } - /// Swaps the last transaction block of the hotkey. - /// - /// # Arguments - /// - /// * `old_hotkey` - The old hotkey. - /// * `new_hotkey` - The new hotkey. - /// * `weight` - The weight of the transaction. - /// - /// # Returns - /// - /// * `Result<(), Error>` - The result of the operation. - pub fn swap_last_tx_block( - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - weight: &mut Weight, - ) -> DispatchResult { - if let Ok(last_tx) = LastTxBlock::::try_get(old_hotkey) { - LastTxBlock::::remove(old_hotkey); - LastTxBlock::::insert(new_hotkey, last_tx); - weight.saturating_accrue(T::DbWeight::get().writes(2)); - } - Ok(()) - } /// Swaps the stake of the hotkey. /// diff --git a/pallets/subtensor/tests/swap.rs b/pallets/subtensor/tests/swap.rs index 04819211a..f73b6e3f2 100644 --- a/pallets/subtensor/tests/swap.rs +++ b/pallets/subtensor/tests/swap.rs @@ -552,76 +552,6 @@ fn test_swap_delegates_weight_update() { }); } -#[test] -fn test_swap_last_tx_block_success() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let last_tx_block = 100u64; - let mut weight = Weight::zero(); - - // Initialize LastTxBlock for old_hotkey - LastTxBlock::::insert(old_hotkey, last_tx_block); - - // Perform the swap - assert_ok!(SubtensorModule::swap_last_tx_block( - &old_hotkey, - &new_hotkey, - &mut weight - )); - - // Verify the swap - assert_eq!(LastTxBlock::::get(new_hotkey), last_tx_block); - assert!(!LastTxBlock::::contains_key(old_hotkey)); - }); -} - -#[test] -fn test_swap_last_tx_block_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!(!LastTxBlock::::contains_key(old_hotkey)); - - // Perform the swap - assert_ok!(SubtensorModule::swap_last_tx_block( - &old_hotkey, - &new_hotkey, - &mut weight - )); - - // Verify that new_hotkey does not have a last transaction block - assert!(!LastTxBlock::::contains_key(new_hotkey)); - }); -} - -#[test] -fn test_swap_last_tx_block_weight_update() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let last_tx_block = 100u64; - let mut weight = Weight::zero(); - - // Initialize LastTxBlock for old_hotkey - LastTxBlock::::insert(old_hotkey, last_tx_block); - - // Perform the swap - assert_ok!(SubtensorModule::swap_last_tx_block( - &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_swap_stake_success() { new_test_ext(1).execute_with(|| { From 062fa09a1acf38763193a760796e38159c1fb61f Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Tue, 18 Jun 2024 01:36:55 +0400 Subject: [PATCH 13/24] chore: fmt --- pallets/subtensor/src/swap.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/pallets/subtensor/src/swap.rs b/pallets/subtensor/src/swap.rs index 4f9eaf047..e6f8fb6e6 100644 --- a/pallets/subtensor/src/swap.rs +++ b/pallets/subtensor/src/swap.rs @@ -184,7 +184,6 @@ impl Pallet { Ok(()) } - /// Swaps the stake of the hotkey. /// /// # Arguments From 52831fa9f687e285d2a5fba0666216128cf6b61a Mon Sep 17 00:00:00 2001 From: Keith Date: Tue, 18 Jun 2024 11:52:55 +0900 Subject: [PATCH 14/24] Use concrete numbers for weight expectations --- pallets/subtensor/tests/registration.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pallets/subtensor/tests/registration.rs b/pallets/subtensor/tests/registration.rs index 77ec068fd..676d49a44 100644 --- a/pallets/subtensor/tests/registration.rs +++ b/pallets/subtensor/tests/registration.rs @@ -38,11 +38,7 @@ fn test_registration_subscribe_ok_dispatch_info_ok() { assert_eq!( call.get_dispatch_info(), DispatchInfo { - weight: frame_support::weights::Weight::from_parts(192_000_000, 0) - .saturating_add(::DbWeight::get().reads(24)) - .saturating_add( - ::DbWeight::get().writes(22) - ), + weight: frame_support::weights::Weight::from_parts(2_992_000_000, 0), class: DispatchClass::Normal, pays_fee: Pays::No } From b0e5673ccf5fba642fe78d7d0d7d2761157aaca3 Mon Sep 17 00:00:00 2001 From: distributedstatemachine <112424909+distributedstatemachine@users.noreply.github.com> Date: Tue, 18 Jun 2024 09:28:45 +0400 Subject: [PATCH 15/24] Update pallets/subtensor/src/swap.rs Co-authored-by: orriin <167025436+orriin@users.noreply.github.com> --- pallets/subtensor/src/swap.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/subtensor/src/swap.rs b/pallets/subtensor/src/swap.rs index e6f8fb6e6..0b527b935 100644 --- a/pallets/subtensor/src/swap.rs +++ b/pallets/subtensor/src/swap.rs @@ -53,7 +53,7 @@ impl Pallet { .saturating_accrue(T::DbWeight::get().reads((TotalNetworks::::get() + 1u16) as u64)); let swap_cost = Self::get_hotkey_swap_cost(); - log::info!("Swap cost: {:?}", swap_cost); + log::debug!("Swap cost: {:?}", swap_cost); ensure!( Self::can_remove_balance_from_coldkey_account(&coldkey, swap_cost), From 5938d1609f4e81db8ce7f0b22b983cb2e4f6f432 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Tue, 18 Jun 2024 11:54:37 +0400 Subject: [PATCH 16/24] chore: add test_swap_hotkey_tx_rate_limit_exceeded --- pallets/subtensor/tests/swap.rs | 57 +++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/pallets/subtensor/tests/swap.rs b/pallets/subtensor/tests/swap.rs index f73b6e3f2..3a2118c4a 100644 --- a/pallets/subtensor/tests/swap.rs +++ b/pallets/subtensor/tests/swap.rs @@ -282,6 +282,63 @@ fn test_do_swap_hotkey_ok_robust() { }); } +#[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(|| { From 2e6422d7ca36280b3d7af4208bea6031490f5e27 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Tue, 18 Jun 2024 11:58:33 +0400 Subject: [PATCH 17/24] chore: fmt --- pallets/subtensor/tests/swap.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/pallets/subtensor/tests/swap.rs b/pallets/subtensor/tests/swap.rs index 3a2118c4a..40c9a9a2a 100644 --- a/pallets/subtensor/tests/swap.rs +++ b/pallets/subtensor/tests/swap.rs @@ -291,7 +291,7 @@ fn test_swap_hotkey_tx_rate_limit_exceeded() { 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 swap_cost = 1_000_000_000u64 * 2; let tx_rate_limit = 1; @@ -299,10 +299,10 @@ fn test_swap_hotkey_tx_rate_limit_exceeded() { 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); + // 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); @@ -316,7 +316,6 @@ fn test_swap_hotkey_tx_rate_limit_exceeded() { &new_hotkey_1 )); - // Attempt to perform another swap immediately, which should fail due to rate limit assert_err!( SubtensorModule::do_swap_hotkey( @@ -327,7 +326,6 @@ fn test_swap_hotkey_tx_rate_limit_exceeded() { Error::::HotKeySetTxRateLimitExceeded ); - // move in time past the rate limit step_block(1001); assert_ok!(SubtensorModule::do_swap_hotkey( @@ -335,7 +333,6 @@ fn test_swap_hotkey_tx_rate_limit_exceeded() { &new_hotkey_1, &new_hotkey_2 )); - }); } From c595f44a5a0eb5fe2764f88fb987aa6d366ad01e Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Tue, 18 Jun 2024 14:36:08 +0400 Subject: [PATCH 18/24] chore: review comments --- pallets/subtensor/src/swap.rs | 107 ++++++++-------- pallets/subtensor/tests/swap.rs | 213 +++++++++----------------------- 2 files changed, 109 insertions(+), 211 deletions(-) diff --git a/pallets/subtensor/src/swap.rs b/pallets/subtensor/src/swap.rs index 0b527b935..c203f89bc 100644 --- a/pallets/subtensor/src/swap.rs +++ b/pallets/subtensor/src/swap.rs @@ -62,22 +62,22 @@ impl Pallet { 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)?; + 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)?; + 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_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_total_hotkey_coldkey_stakes_this_interval(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)); @@ -100,16 +100,13 @@ impl Pallet { /// # Returns /// /// * `Result, Error>` - A vector of network IDs where the hotkey is a member. - pub fn get_netuid_is_member( - old_hotkey: &T::AccountId, - weight: &mut Weight, - ) -> Result, Error> { + pub fn get_netuid_is_member(old_hotkey: &T::AccountId, weight: &mut Weight) -> Vec { let netuid_is_member: Vec = as IterableStorageDoubleMap<_, _, _>>::iter_prefix(old_hotkey) .map(|(netuid, _)| netuid) .collect(); weight.saturating_accrue(T::DbWeight::get().reads(netuid_is_member.len() as u64)); - Ok(netuid_is_member) + netuid_is_member } /// Swaps the owner of the hotkey. @@ -129,11 +126,10 @@ impl Pallet { new_hotkey: &T::AccountId, coldkey: &T::AccountId, weight: &mut Weight, - ) -> DispatchResult { + ) { Owner::::remove(old_hotkey); Owner::::insert(new_hotkey, coldkey.clone()); weight.saturating_accrue(T::DbWeight::get().writes(2)); - Ok(()) } /// Swaps the total stake of the hotkey. @@ -144,20 +140,22 @@ impl Pallet { /// * `new_hotkey` - The new hotkey. /// * `weight` - The weight of the transaction. /// - /// # Returns + /// # Weight Calculation /// - /// * `Result<(), Error>` - The result of the operation. + /// * 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, - ) -> DispatchResult { + ) { 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().writes(2)); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + } else { + weight.saturating_accrue(T::DbWeight::get().reads(1)); } - Ok(()) } /// Swaps the delegates of the hotkey. @@ -168,20 +166,22 @@ impl Pallet { /// * `new_hotkey` - The new hotkey. /// * `weight` - The weight of the transaction. /// - /// # Returns + /// # Weight Calculation /// - /// * `Result<(), Error>` - The result of the operation. + /// * 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, - ) -> DispatchResult { + ) { 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().writes(2)); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + } else { + weight.saturating_accrue(T::DbWeight::get().reads(1)); } - Ok(()) } /// Swaps the stake of the hotkey. @@ -195,11 +195,7 @@ impl Pallet { /// # Returns /// /// * `Result<(), Error>` - The result of the operation. - pub fn swap_stake( - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - weight: &mut Weight, - ) -> DispatchResult { + pub fn swap_stake(old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, weight: &mut Weight) { let mut writes = 0; let stakes: Vec<(T::AccountId, u64)> = Stake::::iter_prefix(old_hotkey).collect(); let stake_count = stakes.len() as u32; @@ -210,7 +206,6 @@ impl Pallet { } *weight += T::DbWeight::get().writes(writes as u64); - Ok(()) } /// Swaps the network membership status of the hotkey. /// @@ -229,14 +224,13 @@ impl Pallet { new_hotkey: &T::AccountId, netuid_is_member: &[u16], weight: &mut Weight, - ) -> DispatchResult { + ) { 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)); } - Ok(()) } /// Swaps the axons of the hotkey. @@ -248,24 +242,27 @@ impl Pallet { /// * `netuid_is_member` - A vector of network IDs where the hotkey is a member. /// * `weight` - The weight of the transaction. /// - /// # Returns + /// # Weight Calculation /// - /// * `Result<(), Error>` - The result of the operation. + /// * 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, - ) -> DispatchResult { + ) { 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().writes(2)); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + } else { + weight.saturating_accrue(T::DbWeight::get().reads(1)); } } - Ok(()) } + /// Swaps the references in the keys storage map of the hotkey. /// /// # Arguments @@ -281,9 +278,9 @@ impl Pallet { pub fn swap_keys( old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, - netuid_is_member: &Vec, + netuid_is_member: &[u16], weight: &mut Weight, - ) -> DispatchResult { + ) { let mut writes = 0; for netuid in netuid_is_member { let keys: Vec<(u16, T::AccountId)> = Keys::::iter_prefix(netuid).collect(); @@ -297,7 +294,6 @@ impl Pallet { } log::info!("writes: {:?}", writes); *weight += T::DbWeight::get().writes(writes as u64); - Ok(()) } /// Swaps the loaded emission of the hotkey. @@ -317,7 +313,7 @@ impl Pallet { new_hotkey: &T::AccountId, netuid_is_member: &[u16], weight: &mut Weight, - ) -> DispatchResult { + ) { for netuid in netuid_is_member { if let Some(mut emissions) = LoadedEmission::::get(netuid) { for emission in emissions.iter_mut() { @@ -329,7 +325,6 @@ impl Pallet { } } *weight += T::DbWeight::get().writes(netuid_is_member.len() as u64); - Ok(()) } /// Swaps the UIDs of the hotkey. @@ -349,7 +344,7 @@ impl Pallet { new_hotkey: &T::AccountId, netuid_is_member: &[u16], weight: &mut Weight, - ) -> DispatchResult { + ) { for netuid in netuid_is_member.iter() { if let Ok(uid) = Uids::::try_get(netuid, old_hotkey) { Uids::::remove(netuid, old_hotkey); @@ -357,7 +352,6 @@ impl Pallet { weight.saturating_accrue(T::DbWeight::get().writes(2)); } } - Ok(()) } /// Swaps the Prometheus data of the hotkey. @@ -369,23 +363,25 @@ impl Pallet { /// * `netuid_is_member` - A vector of network IDs where the hotkey is a member. /// * `weight` - The weight of the transaction. /// - /// # Returns + /// # Weight Calculation /// - /// * `Result<(), Error>` - The result of the operation. + /// * 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, - ) -> DispatchResult { + ) { 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().writes(2)); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + } else { + weight.saturating_accrue(T::DbWeight::get().reads(1)); } } - Ok(()) } /// Swaps the total hotkey-coldkey stakes for the current interval. @@ -403,7 +399,7 @@ impl Pallet { old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, weight: &mut Weight, - ) -> DispatchResult { + ) { let stakes: Vec<(T::AccountId, (u64, u64))> = TotalHotkeyColdkeyStakesThisInterval::::iter_prefix(old_hotkey).collect(); log::info!("Stakes to swap: {:?}", stakes); @@ -417,6 +413,5 @@ impl Pallet { TotalHotkeyColdkeyStakesThisInterval::::remove(old_hotkey, &coldkey); weight.saturating_accrue(T::DbWeight::get().writes(2)); // One write for insert and one for remove } - Ok(()) } } diff --git a/pallets/subtensor/tests/swap.rs b/pallets/subtensor/tests/swap.rs index 40c9a9a2a..1bbe0344d 100644 --- a/pallets/subtensor/tests/swap.rs +++ b/pallets/subtensor/tests/swap.rs @@ -61,7 +61,7 @@ fn test_do_swap_hotkey_ok() { let mut weight = Weight::zero(); // UIDs - for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight).unwrap() { + for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight) { assert_eq!( Uids::::get(netuid, new_hotkey), Uids::::get(netuid, old_hotkey) @@ -69,7 +69,7 @@ fn test_do_swap_hotkey_ok() { } // Prometheus - for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight).unwrap() { + for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight) { assert_eq!( Prometheus::::get(netuid, new_hotkey), Prometheus::::get(netuid, old_hotkey) @@ -77,7 +77,7 @@ fn test_do_swap_hotkey_ok() { } // LoadedEmission - for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight).unwrap() { + for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight) { assert_eq!( LoadedEmission::::get(netuid).unwrap(), LoadedEmission::::get(netuid).unwrap() @@ -85,7 +85,7 @@ fn test_do_swap_hotkey_ok() { } // IsNetworkMember - for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight).unwrap() { + 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)); } @@ -112,7 +112,7 @@ fn test_do_swap_hotkey_ok() { ); // Axons - for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight).unwrap() { + for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight) { assert_eq!( Axons::::get(netuid, new_hotkey), Axons::::get(netuid, old_hotkey) @@ -215,7 +215,7 @@ fn test_do_swap_hotkey_ok_robust() { let mut weight = Weight::zero(); // UIDs for netuid in - SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight).unwrap() + SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight) { assert_eq!( Uids::::get(netuid, new_hotkeys[i]), @@ -225,7 +225,7 @@ fn test_do_swap_hotkey_ok_robust() { // Prometheus for netuid in - SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight).unwrap() + SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight) { assert_eq!( Prometheus::::get(netuid, new_hotkeys[i]), @@ -235,7 +235,7 @@ fn test_do_swap_hotkey_ok_robust() { // LoadedEmission for netuid in - SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight).unwrap() + SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight) { assert_eq!( LoadedEmission::::get(netuid).unwrap(), @@ -245,7 +245,7 @@ fn test_do_swap_hotkey_ok_robust() { // IsNetworkMember for netuid in - SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight).unwrap() + SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight) { assert!(IsNetworkMember::::contains_key( new_hotkeys[i], @@ -376,12 +376,7 @@ fn test_swap_owner_success() { Owner::::insert(old_hotkey, coldkey); // Perform the swap - assert_ok!(SubtensorModule::swap_owner( - &old_hotkey, - &new_hotkey, - &coldkey, - &mut weight - )); + SubtensorModule::swap_owner(&old_hotkey, &new_hotkey, &coldkey, &mut weight); // Verify the swap assert_eq!(Owner::::get(new_hotkey), coldkey); @@ -401,12 +396,7 @@ fn test_swap_owner_old_hotkey_not_exist() { assert!(!Owner::::contains_key(old_hotkey)); // Perform the swap - assert_ok!(SubtensorModule::swap_owner( - &old_hotkey, - &new_hotkey, - &coldkey, - &mut weight - )); + SubtensorModule::swap_owner(&old_hotkey, &new_hotkey, &coldkey, &mut weight); // Verify the swap assert_eq!(Owner::::get(new_hotkey), coldkey); @@ -428,12 +418,7 @@ fn test_swap_owner_new_hotkey_already_exists() { Owner::::insert(new_hotkey, another_coldkey); // Perform the swap - assert_ok!(SubtensorModule::swap_owner( - &old_hotkey, - &new_hotkey, - &coldkey, - &mut weight - )); + SubtensorModule::swap_owner(&old_hotkey, &new_hotkey, &coldkey, &mut weight); // Verify the swap assert_eq!(Owner::::get(new_hotkey), coldkey); @@ -453,12 +438,7 @@ fn test_swap_owner_weight_update() { Owner::::insert(old_hotkey, coldkey); // Perform the swap - assert_ok!(SubtensorModule::swap_owner( - &old_hotkey, - &new_hotkey, - &coldkey, - &mut weight - )); + SubtensorModule::swap_owner(&old_hotkey, &new_hotkey, &coldkey, &mut weight); // Verify the weight update let expected_weight = ::DbWeight::get().writes(2); @@ -478,11 +458,7 @@ fn test_swap_total_hotkey_stake_success() { TotalHotkeyStake::::insert(old_hotkey, total_stake); // Perform the swap - assert_ok!(SubtensorModule::swap_total_hotkey_stake( - &old_hotkey, - &new_hotkey, - &mut weight - )); + SubtensorModule::swap_total_hotkey_stake(&old_hotkey, &new_hotkey, &mut weight); // Verify the swap assert_eq!(TotalHotkeyStake::::get(new_hotkey), total_stake); @@ -501,11 +477,7 @@ fn test_swap_total_hotkey_stake_old_hotkey_not_exist() { assert!(!TotalHotkeyStake::::contains_key(old_hotkey)); // Perform the swap - assert_ok!(SubtensorModule::swap_total_hotkey_stake( - &old_hotkey, - &new_hotkey, - &mut weight - )); + 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)); @@ -524,14 +496,10 @@ fn test_swap_total_hotkey_stake_weight_update() { TotalHotkeyStake::::insert(old_hotkey, total_stake); // Perform the swap - assert_ok!(SubtensorModule::swap_total_hotkey_stake( - &old_hotkey, - &new_hotkey, - &mut weight - )); + SubtensorModule::swap_total_hotkey_stake(&old_hotkey, &new_hotkey, &mut weight); // Verify the weight update - let expected_weight = ::DbWeight::get().writes(2); + let expected_weight = ::DbWeight::get().reads_writes(1, 2); assert_eq!(weight, expected_weight); }); } @@ -548,11 +516,7 @@ fn test_swap_delegates_success() { Delegates::::insert(old_hotkey, delegate_take); // Perform the swap - assert_ok!(SubtensorModule::swap_delegates( - &old_hotkey, - &new_hotkey, - &mut weight - )); + SubtensorModule::swap_delegates(&old_hotkey, &new_hotkey, &mut weight); // Verify the swap assert_eq!(Delegates::::get(new_hotkey), delegate_take); @@ -571,11 +535,7 @@ fn test_swap_delegates_old_hotkey_not_exist() { assert!(!Delegates::::contains_key(old_hotkey)); // Perform the swap - assert_ok!(SubtensorModule::swap_delegates( - &old_hotkey, - &new_hotkey, - &mut weight - )); + SubtensorModule::swap_delegates(&old_hotkey, &new_hotkey, &mut weight); // Verify that new_hotkey does not have a delegate assert!(!Delegates::::contains_key(new_hotkey)); @@ -594,14 +554,10 @@ fn test_swap_delegates_weight_update() { Delegates::::insert(old_hotkey, delegate_take); // Perform the swap - assert_ok!(SubtensorModule::swap_delegates( - &old_hotkey, - &new_hotkey, - &mut weight - )); + SubtensorModule::swap_delegates(&old_hotkey, &new_hotkey, &mut weight); // Verify the weight update - let expected_weight = ::DbWeight::get().writes(2); + let expected_weight = ::DbWeight::get().reads_writes(1, 2); assert_eq!(weight, expected_weight); }); } @@ -619,11 +575,7 @@ fn test_swap_stake_success() { Stake::::insert(old_hotkey, coldkey, stake_amount); // Perform the swap - assert_ok!(SubtensorModule::swap_stake( - &old_hotkey, - &new_hotkey, - &mut weight - )); + SubtensorModule::swap_stake(&old_hotkey, &new_hotkey, &mut weight); // Verify the swap assert_eq!(Stake::::get(new_hotkey, coldkey), stake_amount); @@ -647,11 +599,7 @@ fn test_swap_stake_old_hotkey_not_exist() { assert!(Stake::::contains_key(old_hotkey, coldkey)); // Perform the swap - assert_ok!(SubtensorModule::swap_stake( - &old_hotkey, - &new_hotkey, - &mut weight - )); + SubtensorModule::swap_stake(&old_hotkey, &new_hotkey, &mut weight); // Verify that new_hotkey has the stake and old_hotkey does not assert!(Stake::::contains_key(new_hotkey, coldkey)); @@ -672,11 +620,7 @@ fn test_swap_stake_weight_update() { Stake::::insert(old_hotkey, coldkey, stake_amount); // Perform the swap - assert_ok!(SubtensorModule::swap_stake( - &old_hotkey, - &new_hotkey, - &mut weight - )); + SubtensorModule::swap_stake(&old_hotkey, &new_hotkey, &mut weight); // Verify the weight update let expected_weight = ::DbWeight::get().writes(2); @@ -698,12 +642,12 @@ fn test_swap_is_network_member_success() { } // Perform the swap - assert_ok!(SubtensorModule::swap_is_network_member( + SubtensorModule::swap_is_network_member( &old_hotkey, &new_hotkey, &netuid_is_member, - &mut weight - )); + &mut weight, + ); // Verify the swap for netuid in &netuid_is_member { @@ -727,12 +671,12 @@ fn test_swap_is_network_member_weight_update() { } // Perform the swap - assert_ok!(SubtensorModule::swap_is_network_member( + SubtensorModule::swap_is_network_member( &old_hotkey, &new_hotkey, &netuid_is_member, - &mut weight - )); + &mut weight, + ); // Verify the weight update let expected_weight = ::DbWeight::get().writes(4); @@ -764,12 +708,7 @@ fn test_swap_axons_success() { } // Perform the swap - assert_ok!(SubtensorModule::swap_axons( - &old_hotkey, - &new_hotkey, - &netuid_is_member, - &mut weight - )); + SubtensorModule::swap_axons(&old_hotkey, &new_hotkey, &netuid_is_member, &mut weight); // Verify the swap for netuid in &netuid_is_member { @@ -803,16 +742,12 @@ fn test_swap_axons_weight_update() { } // Perform the swap - assert_ok!(SubtensorModule::swap_axons( - &old_hotkey, - &new_hotkey, - &netuid_is_member, - &mut weight - )); + SubtensorModule::swap_axons(&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); + let expected_weight = netuid_is_member.len() as u64 + * ::DbWeight::get().reads_writes(1, 2); + assert_eq!(weight, expected_weight.into()); }); } @@ -832,12 +767,7 @@ fn test_swap_keys_success() { } // Perform the swap - assert_ok!(SubtensorModule::swap_keys( - &old_hotkey, - &new_hotkey, - &netuid_is_member, - &mut weight - )); + SubtensorModule::swap_keys(&old_hotkey, &new_hotkey, &netuid_is_member, &mut weight); // Verify the swap for netuid in &netuid_is_member { @@ -867,12 +797,7 @@ fn test_swap_keys_weight_update() { } // Perform the swap - assert_ok!(SubtensorModule::swap_keys( - &old_hotkey, - &new_hotkey, - &netuid_is_member, - &mut weight - )); + SubtensorModule::swap_keys(&old_hotkey, &new_hotkey, &netuid_is_member, &mut weight); // Verify the weight update let expected_weight = ::DbWeight::get().writes(4); @@ -902,12 +827,12 @@ fn test_swap_loaded_emission_success() { } // Perform the swap - assert_ok!(SubtensorModule::swap_loaded_emission( + SubtensorModule::swap_loaded_emission( &old_hotkey, &new_hotkey, &netuid_is_member, - &mut weight - )); + &mut weight, + ); // Verify the swap for netuid in &netuid_is_member { @@ -941,12 +866,12 @@ fn test_swap_loaded_emission_weight_update() { } // Perform the swap - assert_ok!(SubtensorModule::swap_loaded_emission( + SubtensorModule::swap_loaded_emission( &old_hotkey, &new_hotkey, &netuid_is_member, - &mut weight - )); + &mut weight, + ); // Verify the weight update let expected_weight = ::DbWeight::get().writes(2); @@ -969,12 +894,7 @@ fn test_swap_uids_success() { } // Perform the swap - assert_ok!(SubtensorModule::swap_uids( - &old_hotkey, - &new_hotkey, - &netuid_is_member, - &mut weight - )); + SubtensorModule::swap_uids(&old_hotkey, &new_hotkey, &netuid_is_member, &mut weight); // Verify the swap for netuid in &netuid_is_member { @@ -999,12 +919,7 @@ fn test_swap_uids_weight_update() { } // Perform the swap - assert_ok!(SubtensorModule::swap_uids( - &old_hotkey, - &new_hotkey, - &netuid_is_member, - &mut weight - )); + SubtensorModule::swap_uids(&old_hotkey, &new_hotkey, &netuid_is_member, &mut weight); // Verify the weight update let expected_weight = ::DbWeight::get().writes(4); @@ -1033,12 +948,7 @@ fn test_swap_prometheus_success() { } // Perform the swap - assert_ok!(SubtensorModule::swap_prometheus( - &old_hotkey, - &new_hotkey, - &netuid_is_member, - &mut weight - )); + SubtensorModule::swap_prometheus(&old_hotkey, &new_hotkey, &netuid_is_member, &mut weight); // Verify the swap for netuid in &netuid_is_member { @@ -1072,15 +982,11 @@ fn test_swap_prometheus_weight_update() { } // Perform the swap - assert_ok!(SubtensorModule::swap_prometheus( - &old_hotkey, - &new_hotkey, - &netuid_is_member, - &mut weight - )); + SubtensorModule::swap_prometheus(&old_hotkey, &new_hotkey, &netuid_is_member, &mut weight); // Verify the weight update - let expected_weight = ::DbWeight::get().writes(4); + let expected_weight = netuid_is_member.len() as u64 + * ::DbWeight::get().reads_writes(1, 2); assert_eq!(weight, expected_weight); }); } @@ -1098,12 +1004,10 @@ fn test_swap_total_hotkey_coldkey_stakes_this_interval_success() { TotalHotkeyColdkeyStakesThisInterval::::insert(old_hotkey, coldkey, stake); // Perform the swap - assert_ok!( - SubtensorModule::swap_total_hotkey_coldkey_stakes_this_interval( - &old_hotkey, - &new_hotkey, - &mut weight - ) + SubtensorModule::swap_total_hotkey_coldkey_stakes_this_interval( + &old_hotkey, + &new_hotkey, + &mut weight, ); // Verify the swap @@ -1130,12 +1034,11 @@ fn test_swap_total_hotkey_coldkey_stakes_this_interval_weight_update() { TotalHotkeyColdkeyStakesThisInterval::::insert(old_hotkey, coldkey, stake); // Perform the swap - assert_ok!( - SubtensorModule::swap_total_hotkey_coldkey_stakes_this_interval( - &old_hotkey, - &new_hotkey, - &mut weight - ) + + SubtensorModule::swap_total_hotkey_coldkey_stakes_this_interval( + &old_hotkey, + &new_hotkey, + &mut weight, ); // Verify the weight update From b9e6a26532f2d016e70ce78b6244731be49ba1b3 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Fri, 21 Jun 2024 21:49:42 +0400 Subject: [PATCH 19/24] fix: pr comments --- pallets/subtensor/src/swap.rs | 35 ++++++++--------------------------- 1 file changed, 8 insertions(+), 27 deletions(-) diff --git a/pallets/subtensor/src/swap.rs b/pallets/subtensor/src/swap.rs index c203f89bc..692640d34 100644 --- a/pallets/subtensor/src/swap.rs +++ b/pallets/subtensor/src/swap.rs @@ -99,7 +99,7 @@ impl Pallet { /// /// # Returns /// - /// * `Result, Error>` - A vector of network IDs where the hotkey is a member. + /// * `Vec` - A vector of network IDs where the hotkey is a member. pub fn get_netuid_is_member(old_hotkey: &T::AccountId, weight: &mut Weight) -> Vec { let netuid_is_member: Vec = as IterableStorageDoubleMap<_, _, _>>::iter_prefix(old_hotkey) @@ -118,9 +118,6 @@ impl Pallet { /// * `coldkey` - The coldkey owning the hotkey. /// * `weight` - The weight of the transaction. /// - /// # Returns - /// - /// * `Result<(), Error>` - The result of the operation. pub fn swap_owner( old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, @@ -191,22 +188,23 @@ impl Pallet { /// * `old_hotkey` - The old hotkey. /// * `new_hotkey` - The new hotkey. /// * `weight` - The weight of the transaction. - /// - /// # Returns - /// - /// * `Result<(), Error>` - The result of the operation. pub fn swap_stake(old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, weight: &mut Weight) { let mut writes = 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); - let _ = Stake::::clear_prefix(old_hotkey, stake_count, None); - writes += 2; // One write for insert and one for remove + writes += 1; // 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 += 1; // One write for clear_prefix *weight += T::DbWeight::get().writes(writes as u64); } + /// Swaps the network membership status of the hotkey. /// /// # Arguments @@ -215,10 +213,6 @@ impl Pallet { /// * `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. - /// - /// # Returns - /// - /// * `Result<(), Error>` - The result of the operation. pub fn swap_is_network_member( old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, @@ -271,10 +265,6 @@ impl Pallet { /// * `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. - /// - /// # Returns - /// - /// * `Result<(), Error>` - The result of the operation. pub fn swap_keys( old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, @@ -305,9 +295,6 @@ impl Pallet { /// * `netuid_is_member` - A vector of network IDs where the hotkey is a member. /// * `weight` - The weight of the transaction. /// - /// # Returns - /// - /// * `Result<(), Error>` - The result of the operation. pub fn swap_loaded_emission( old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, @@ -336,9 +323,6 @@ impl Pallet { /// * `netuid_is_member` - A vector of network IDs where the hotkey is a member. /// * `weight` - The weight of the transaction. /// - /// # Returns - /// - /// * `Result<(), Error>` - The result of the operation. pub fn swap_uids( old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, @@ -392,9 +376,6 @@ impl Pallet { /// * `new_hotkey` - The new hotkey. /// * `weight` - The weight of the transaction. /// - /// # Returns - /// - /// * `Result<(), Error>` - The result of the operation. pub fn swap_total_hotkey_coldkey_stakes_this_interval( old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, From 8626ca343fd55b0f76cc306572ead068181a1479 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Fri, 21 Jun 2024 21:49:59 +0400 Subject: [PATCH 20/24] chore: lint --- pallets/subtensor/src/swap.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pallets/subtensor/src/swap.rs b/pallets/subtensor/src/swap.rs index 692640d34..4f8097d26 100644 --- a/pallets/subtensor/src/swap.rs +++ b/pallets/subtensor/src/swap.rs @@ -192,12 +192,12 @@ impl Pallet { let mut writes = 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 += 1; // 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 += 1; // One write for clear_prefix From 2fc9e3193f70dbea2f9ffadf070f15de32ca237f Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Sat, 22 Jun 2024 00:48:02 +0400 Subject: [PATCH 21/24] fix: remove unused function --- pallets/subtensor/src/lib.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index 7ca2a2777..64aefcfee 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -275,11 +275,6 @@ pub mod pallet { pub fn TotalSupply() -> u64 { 21_000_000_000_000_000 // Rao => 21_000_000 Tao } - /// Hotkey swap cost. - #[pallet::type_value] - pub fn HotkeySwapCost() -> u64 { - 1_000_000_000 - } /// Default total stake. #[pallet::type_value] pub fn DefaultDefaultTake() -> u16 { From 7518c5560910f61737b157601f4ca9bfcf961fe1 Mon Sep 17 00:00:00 2001 From: Sam Johnson Date: Fri, 21 Jun 2024 17:34:01 -0400 Subject: [PATCH 22/24] clippy fix --- pallets/subtensor/tests/swap.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/subtensor/tests/swap.rs b/pallets/subtensor/tests/swap.rs index 1bbe0344d..2a12ed312 100644 --- a/pallets/subtensor/tests/swap.rs +++ b/pallets/subtensor/tests/swap.rs @@ -747,7 +747,7 @@ fn test_swap_axons_weight_update() { // Verify the weight update let expected_weight = netuid_is_member.len() as u64 * ::DbWeight::get().reads_writes(1, 2); - assert_eq!(weight, expected_weight.into()); + assert_eq!(weight, expected_weight); }); } From cadbe595ad978ed579f9ae040dbe210258640a00 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Tue, 2 Jul 2024 23:33:46 +0400 Subject: [PATCH 23/24] chore: conflicts, lints --- justfile | 8 ++++++-- pallets/subtensor/src/swap.rs | 21 +++++++++++---------- pallets/subtensor/tests/mock.rs | 2 +- pallets/subtensor/tests/swap.rs | 2 ++ 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/justfile b/justfile index 0a02ee7d3..a75b0052b 100644 --- a/justfile +++ b/justfile @@ -35,6 +35,11 @@ clippy-fix: -A clippy::todo \ -A clippy::unimplemented \ -A clippy::indexing_slicing + @echo "Running cargo clippy with automatic fixes on potentially dirty code..." + cargo +{{RUSTV}} clippy --fix --allow-dirty --workspace --all-targets -- \ + -A clippy::todo \ + -A clippy::unimplemented \ + -A clippy::indexing_slicing fix: @echo "Running cargo fix..." cargo +{{RUSTV}} fix --workspace @@ -46,5 +51,4 @@ lint: @echo "Running cargo clippy with automatic fixes on potentially dirty code..." just clippy-fix @echo "Running cargo clippy..." - just clippy - + just clippy \ No newline at end of file diff --git a/pallets/subtensor/src/swap.rs b/pallets/subtensor/src/swap.rs index 4f8097d26..ce090d736 100644 --- a/pallets/subtensor/src/swap.rs +++ b/pallets/subtensor/src/swap.rs @@ -49,8 +49,9 @@ impl Pallet { Error::::HotKeySetTxRateLimitExceeded ); - weight - .saturating_accrue(T::DbWeight::get().reads((TotalNetworks::::get() + 1u16) as u64)); + weight.saturating_accrue( + T::DbWeight::get().reads((TotalNetworks::::get().saturating_add(1u16)) as u64), + ); let swap_cost = Self::get_hotkey_swap_cost(); log::debug!("Swap cost: {:?}", swap_cost); @@ -189,20 +190,20 @@ impl Pallet { /// * `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 = 0; + 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 += 1; // One write for insert + 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 += 1; // One write for clear_prefix + writes = writes.saturating_add(1); // One write for insert; // One write for clear_prefix - *weight += T::DbWeight::get().writes(writes as u64); + weight.saturating_accrue(T::DbWeight::get().writes(writes)); } /// Swaps the network membership status of the hotkey. @@ -271,7 +272,7 @@ impl Pallet { netuid_is_member: &[u16], weight: &mut Weight, ) { - let mut writes = 0; + 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 { @@ -279,11 +280,11 @@ impl Pallet { log::info!("old hotkey found: {:?}", old_hotkey); Keys::::insert(netuid, uid, new_hotkey.clone()); } - writes += 2; + writes = writes.saturating_add(2u64); } } log::info!("writes: {:?}", writes); - *weight += T::DbWeight::get().writes(writes as u64); + weight.saturating_accrue(T::DbWeight::get().writes(writes)); } /// Swaps the loaded emission of the hotkey. @@ -311,7 +312,7 @@ impl Pallet { LoadedEmission::::insert(netuid, emissions); } } - *weight += T::DbWeight::get().writes(netuid_is_member.len() as u64); + weight.saturating_accrue(T::DbWeight::get().writes(netuid_is_member.len() as u64)); } /// Swaps the UIDs of the hotkey. diff --git a/pallets/subtensor/tests/mock.rs b/pallets/subtensor/tests/mock.rs index cf58f49d2..d4f5940b8 100644 --- a/pallets/subtensor/tests/mock.rs +++ b/pallets/subtensor/tests/mock.rs @@ -3,7 +3,7 @@ use frame_support::derive_impl; use frame_support::dispatch::DispatchResultWithPostInfo; use frame_support::weights::constants::RocksDbWeight; use frame_support::{ - assert_ok, derive_impl, + assert_ok, dispatch::DispatchResultWithPostInfo, parameter_types, traits::{Everything, Hooks}, diff --git a/pallets/subtensor/tests/swap.rs b/pallets/subtensor/tests/swap.rs index 2a12ed312..af7d19d2d 100644 --- a/pallets/subtensor/tests/swap.rs +++ b/pallets/subtensor/tests/swap.rs @@ -1,3 +1,5 @@ +#![allow(unused, clippy::indexing_slicing, clippy::panic, clippy::unwrap_used)] + use codec::Encode; use frame_support::weights::Weight; use frame_support::{assert_err, assert_ok}; From 2dda611455da8fd9e7a295ac635b04d0ea862de6 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Tue, 2 Jul 2024 23:43:50 +0400 Subject: [PATCH 24/24] chore: lints --- pallets/subtensor/tests/mock.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pallets/subtensor/tests/mock.rs b/pallets/subtensor/tests/mock.rs index d4f5940b8..3e7e74f95 100644 --- a/pallets/subtensor/tests/mock.rs +++ b/pallets/subtensor/tests/mock.rs @@ -3,9 +3,7 @@ use frame_support::derive_impl; use frame_support::dispatch::DispatchResultWithPostInfo; use frame_support::weights::constants::RocksDbWeight; use frame_support::{ - assert_ok, - dispatch::DispatchResultWithPostInfo, - parameter_types, + assert_ok, parameter_types, traits::{Everything, Hooks}, weights, };