From 3c17efbbb676af2431617655fca5b2363d03b149 Mon Sep 17 00:00:00 2001 From: Keith Date: Fri, 24 May 2024 23:47:51 +0800 Subject: [PATCH 01/51] Ban unsafe arithmetic operations --- Cargo.toml | 3 + node/src/chain_spec/finney.rs | 6 +- node/src/chain_spec/testnet.rs | 6 +- pallets/admin-utils/src/benchmarking.rs | 1 + pallets/admin-utils/tests/mock.rs | 2 + pallets/collective/src/benchmarking.rs | 3 +- pallets/collective/src/lib.rs | 29 +++-- pallets/collective/src/tests.rs | 2 +- pallets/commitments/src/benchmarking.rs | 7 +- pallets/commitments/src/lib.rs | 13 ++- pallets/commitments/src/types.rs | 7 +- pallets/registry/src/benchmarking.rs | 7 +- pallets/registry/src/lib.rs | 15 +-- pallets/registry/src/types.rs | 7 +- pallets/subtensor/src/benchmarks.rs | 2 +- pallets/subtensor/src/block_step.rs | 95 ++++++++++------ pallets/subtensor/src/delegate_info.rs | 10 +- pallets/subtensor/src/epoch.rs | 36 +++--- pallets/subtensor/src/lib.rs | 29 +++-- pallets/subtensor/src/math.rs | 145 +++++++++++++++--------- pallets/subtensor/src/migration.rs | 11 +- pallets/subtensor/src/registration.rs | 32 +++--- pallets/subtensor/src/root.rs | 56 +++++---- pallets/subtensor/src/serving.rs | 4 +- pallets/subtensor/src/staking.rs | 6 +- pallets/subtensor/src/subnet_info.rs | 2 +- pallets/subtensor/src/uids.rs | 8 +- pallets/subtensor/src/utils.rs | 4 +- pallets/subtensor/src/weights.rs | 23 ++-- pallets/subtensor/tests/block_step.rs | 3 +- pallets/subtensor/tests/difficulty.rs | 2 + pallets/subtensor/tests/epoch.rs | 6 + pallets/subtensor/tests/migration.rs | 2 + pallets/subtensor/tests/mock.rs | 8 +- pallets/subtensor/tests/registration.rs | 2 + pallets/subtensor/tests/root.rs | 2 + pallets/subtensor/tests/senate.rs | 2 + pallets/subtensor/tests/staking.rs | 2 + pallets/subtensor/tests/uids.rs | 2 + pallets/subtensor/tests/weights.rs | 2 + runtime/src/check_nonce.rs | 5 +- runtime/src/lib.rs | 13 ++- runtime/tests/metadata.rs | 2 + runtime/tests/pallet_proxy.rs | 2 + 44 files changed, 398 insertions(+), 228 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 56e40c924..51849096a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,10 @@ members = [ resolver = "2" [workspace.lints.clippy] +indexing-slicing = "deny" +arithmetic-side-effects = "deny" type_complexity = "allow" +unwrap-used = "deny" [workspace.dependencies] cargo-husky = { version = "1", default-features = false } diff --git a/node/src/chain_spec/finney.rs b/node/src/chain_spec/finney.rs index 37fa1b073..3694c3d39 100644 --- a/node/src/chain_spec/finney.rs +++ b/node/src/chain_spec/finney.rs @@ -5,7 +5,7 @@ use super::*; pub fn finney_mainnet_config() -> Result { let path: PathBuf = std::path::PathBuf::from("./snapshot.json"); - let wasm_binary = WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?; + let wasm_binary = WASM_BINARY.ok_or("Development wasm not available".to_string())?; // We mmap the file into memory first, as this is *a lot* faster than using // `serde_json::from_reader`. See https://github.com/serde-rs/json/issues/160 @@ -53,7 +53,9 @@ pub fn finney_mainnet_config() -> Result { let key_account = sp_runtime::AccountId32::from(key); processed_balances.push((key_account, *amount)); - balances_issuance += *amount; + balances_issuance = balances_issuance + .checked_add(*amount) + .ok_or("Balances issuance overflowed".to_string())?; } // Give front-ends necessary data to present to users diff --git a/node/src/chain_spec/testnet.rs b/node/src/chain_spec/testnet.rs index 01c95c376..ff6c8cc39 100644 --- a/node/src/chain_spec/testnet.rs +++ b/node/src/chain_spec/testnet.rs @@ -20,7 +20,7 @@ pub fn finney_testnet_config() -> Result { }; let old_state: ColdkeyHotkeys = - json::from_slice(&bytes).map_err(|e| format!("Error parsing genesis file: {}", e))?; + json::from_slice(&bytes).map_err(|e| format!("Error parsing genesis file: {e}"))?; let mut processed_stakes: Vec<( sp_runtime::AccountId32, @@ -53,7 +53,9 @@ pub fn finney_testnet_config() -> Result { let key_account = sp_runtime::AccountId32::from(key); processed_balances.push((key_account, *amount)); - balances_issuance += *amount; + balances_issuance = balances_issuance + .checked_add(*amount) + .ok_or("Balances issuance overflowed".to_string())?; } // Give front-ends necessary data to present to users diff --git a/pallets/admin-utils/src/benchmarking.rs b/pallets/admin-utils/src/benchmarking.rs index 756864940..0158311f7 100644 --- a/pallets/admin-utils/src/benchmarking.rs +++ b/pallets/admin-utils/src/benchmarking.rs @@ -1,5 +1,6 @@ //! Benchmarking setup #![cfg(feature = "runtime-benchmarks")] +#![allow(clippy::arithmetic_side_effects)] use super::*; #[allow(unused)] diff --git a/pallets/admin-utils/tests/mock.rs b/pallets/admin-utils/tests/mock.rs index c0985b010..c6c3d7323 100644 --- a/pallets/admin-utils/tests/mock.rs +++ b/pallets/admin-utils/tests/mock.rs @@ -1,3 +1,5 @@ +#![allow(clippy::arithmetic_side_effects, clippy::unwrap_used)] + use frame_support::{ assert_ok, derive_impl, parameter_types, traits::{Everything, Hooks}, diff --git a/pallets/collective/src/benchmarking.rs b/pallets/collective/src/benchmarking.rs index cf44e9948..380a78395 100644 --- a/pallets/collective/src/benchmarking.rs +++ b/pallets/collective/src/benchmarking.rs @@ -16,6 +16,7 @@ // limitations under the License. //! Staking pallet benchmarking. +#![allow(clippy::arithmetic_side_effects, clippy::indexing_slicing)] use super::*; use crate::Pallet as Collective; @@ -70,7 +71,7 @@ benchmarks_instance_pallet! { // Proposals should be different so that different proposal hashes are generated let proposal: T::Proposal = SystemCall::::remark { remark: id_to_remark_data(i, length) }.into(); Collective::::propose( - SystemOrigin::Signed(old_members.last().unwrap().clone()).into(), + SystemOrigin::Signed(old_members.last().expect("m is greater than 0; old_members must have at least 1 element; qed").clone()).into(), Box::new(proposal.clone()), MAX_BYTES, TryInto::>::try_into(3u64).ok().expect("convert u64 to block number.") diff --git a/pallets/collective/src/lib.rs b/pallets/collective/src/lib.rs index c1bcad3e7..3be6529e0 100644 --- a/pallets/collective/src/lib.rs +++ b/pallets/collective/src/lib.rs @@ -54,7 +54,7 @@ use frame_support::{ use scale_info::TypeInfo; use sp_io::storage; use sp_runtime::traits::Dispatchable; -use sp_runtime::{traits::Hash, RuntimeDebug}; +use sp_runtime::{traits::Hash, RuntimeDebug, Saturating}; use sp_std::{marker::PhantomData, prelude::*, result}; #[cfg(test)] @@ -119,7 +119,7 @@ impl DefaultVote for MoreThanMajorityThenPrimeDefaultVote { _no_votes: MemberCount, len: MemberCount, ) -> bool { - let more_than_majority = yes_votes * 2 > len; + let more_than_majority = yes_votes.saturating_mul(2) > len; more_than_majority || prime_vote.unwrap_or(false) } } @@ -545,7 +545,9 @@ pub mod pallet { Error::::DurationLowerThanConfiguredMotionDuration ); - let threshold = (T::GetVotingMembers::get_count() / 2) + 1; + let threshold = T::GetVotingMembers::get_count() + .saturating_div(2) + .saturating_add(1); let members = Self::members(); let (proposal_len, active_proposals) = @@ -716,10 +718,15 @@ impl, I: 'static> Pallet { })?; let index = Self::proposal_count(); - >::mutate(|i| *i += 1); + >::try_mutate(|i| { + *i = i + .checked_add(1) + .ok_or(Error::::TooManyActiveProposals)?; + Ok::<(), Error>(()) + })?; >::insert(proposal_hash, proposal); let votes = { - let end = frame_system::Pallet::::block_number() + duration; + let end = frame_system::Pallet::::block_number().saturating_add(duration); Votes { index, threshold, @@ -862,10 +869,10 @@ impl, I: 'static> Pallet { // default voting strategy. let default = T::DefaultVote::default_vote(prime_vote, yes_votes, no_votes, seats); - let abstentions = seats - (yes_votes + no_votes); + let abstentions = seats.saturating_sub(yes_votes.saturating_add(no_votes)); match default { - true => yes_votes += abstentions, - false => no_votes += abstentions, + true => yes_votes = yes_votes.saturating_add(abstentions), + false => no_votes = no_votes.saturating_add(abstentions), } let approved = yes_votes >= voting.threshold; @@ -981,7 +988,7 @@ impl, I: 'static> Pallet { Voting::::remove(proposal_hash); let num_proposals = Proposals::::mutate(|proposals| { proposals.retain(|h| h != &proposal_hash); - proposals.len() + 1 // calculate weight based on original length + proposals.len().saturating_add(1) // calculate weight based on original length }); num_proposals as u32 } @@ -1154,7 +1161,7 @@ impl< type Success = (); fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { - RawOrigin::Members(n, m) if n * D > N * m => Ok(()), + RawOrigin::Members(n, m) if n.saturating_mul(D) > N.saturating_mul(m) => Ok(()), r => Err(O::from(r)), }) } @@ -1179,7 +1186,7 @@ impl< type Success = (); fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { - RawOrigin::Members(n, m) if n * D >= N * m => Ok(()), + RawOrigin::Members(n, m) if n.saturating_mul(D) >= N.saturating_mul(m) => Ok(()), r => Err(O::from(r)), }) } diff --git a/pallets/collective/src/tests.rs b/pallets/collective/src/tests.rs index 672556edb..91fca58d4 100644 --- a/pallets/collective/src/tests.rs +++ b/pallets/collective/src/tests.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#![allow(non_camel_case_types)] +#![allow(non_camel_case_types, clippy::indexing_slicing, clippy::unwrap_used)] use super::{Event as CollectiveEvent, *}; use crate as pallet_collective; diff --git a/pallets/commitments/src/benchmarking.rs b/pallets/commitments/src/benchmarking.rs index 1b877a8ce..54247bb9d 100644 --- a/pallets/commitments/src/benchmarking.rs +++ b/pallets/commitments/src/benchmarking.rs @@ -1,5 +1,6 @@ //! Benchmarking setup #![cfg(feature = "runtime-benchmarks")] +#![allow(clippy::arithmetic_side_effects)] use super::*; #[allow(unused)] @@ -17,7 +18,11 @@ fn assert_last_event(generic_event: ::RuntimeEvent) { // This creates an `IdentityInfo` object with `num_fields` extra fields. // All data is pre-populated with some arbitrary bytes. fn create_identity_info(_num_fields: u32) -> CommitmentInfo { - let _data = Data::Raw(vec![0; 32].try_into().unwrap()); + let _data = Data::Raw( + vec![0; 32] + .try_into() + .expect("vec length is less than 64; qed"), + ); CommitmentInfo { fields: Default::default(), diff --git a/pallets/commitments/src/lib.rs b/pallets/commitments/src/lib.rs index 6e252ecea..09e73d516 100644 --- a/pallets/commitments/src/lib.rs +++ b/pallets/commitments/src/lib.rs @@ -14,7 +14,7 @@ pub use types::*; pub use weights::WeightInfo; use frame_support::traits::Currency; -use sp_runtime::traits::Zero; +use sp_runtime::{traits::Zero, Saturating}; use sp_std::boxed::Box; type BalanceOf = @@ -138,12 +138,12 @@ pub mod pallet { let cur_block = >::block_number(); if let Some(last_commit) = >::get(netuid, &who) { ensure!( - cur_block >= last_commit + T::RateLimit::get(), + cur_block >= last_commit.saturating_add(T::RateLimit::get()), Error::::CommitmentSetRateLimitExceeded ); } - let fd = >::from(extra_fields) * T::FieldDeposit::get(); + let fd = >::from(extra_fields).saturating_mul(T::FieldDeposit::get()); let mut id = match >::get(netuid, &who) { Some(mut id) => { id.info = *info; @@ -158,12 +158,13 @@ pub mod pallet { }; let old_deposit = id.deposit; - id.deposit = T::InitialDeposit::get() + fd; + id.deposit = T::InitialDeposit::get().saturating_add(fd); if id.deposit > old_deposit { - T::Currency::reserve(&who, id.deposit - old_deposit)?; + T::Currency::reserve(&who, id.deposit.saturating_sub(old_deposit))?; } if old_deposit > id.deposit { - let err_amount = T::Currency::unreserve(&who, old_deposit - id.deposit); + let err_amount = + T::Currency::unreserve(&who, old_deposit.saturating_sub(id.deposit)); debug_assert!(err_amount.is_zero()); } diff --git a/pallets/commitments/src/types.rs b/pallets/commitments/src/types.rs index 6ca9ee603..5a1d0bd64 100644 --- a/pallets/commitments/src/types.rs +++ b/pallets/commitments/src/types.rs @@ -66,7 +66,7 @@ impl Decode for Data { Ok(match b { 0 => Data::None, n @ 1..=129 => { - let mut r: BoundedVec<_, _> = vec![0u8; n as usize - 1] + let mut r: BoundedVec<_, _> = vec![0u8; (n as usize).saturating_sub(1)] .try_into() .expect("bound checked in match arm condition; qed"); input.read(&mut r[..])?; @@ -86,8 +86,8 @@ impl Encode for Data { match self { Data::None => vec![0u8; 1], Data::Raw(ref x) => { - let l = x.len().min(128); - let mut r = vec![l as u8 + 1]; + let l = x.len().min(128) as u8; + let mut r = vec![l.saturating_add(1)]; r.extend_from_slice(&x[..]); r } @@ -344,6 +344,7 @@ impl< } #[cfg(test)] +#[allow(clippy::indexing_slicing, clippy::unwrap_used)] mod tests { use super::*; diff --git a/pallets/registry/src/benchmarking.rs b/pallets/registry/src/benchmarking.rs index bb2c4ac06..ee2088478 100644 --- a/pallets/registry/src/benchmarking.rs +++ b/pallets/registry/src/benchmarking.rs @@ -1,5 +1,6 @@ //! Benchmarking setup #![cfg(feature = "runtime-benchmarks")] +#![allow(clippy::arithmetic_side_effects, clippy::unwrap_used)] use super::*; #[allow(unused)] @@ -19,7 +20,11 @@ fn assert_last_event(generic_event: ::RuntimeEvent) { // This creates an `IdentityInfo` object with `num_fields` extra fields. // All data is pre-populated with some arbitrary bytes. fn create_identity_info(_num_fields: u32) -> IdentityInfo { - let data = Data::Raw(vec![0; 32].try_into().unwrap()); + let data = Data::Raw( + vec![0; 32] + .try_into() + .expect("size does not exceed 64; qed"), + ); IdentityInfo { additional: Default::default(), diff --git a/pallets/registry/src/lib.rs b/pallets/registry/src/lib.rs index 026c03260..59c004449 100644 --- a/pallets/registry/src/lib.rs +++ b/pallets/registry/src/lib.rs @@ -16,7 +16,7 @@ use frame_support::traits::tokens::{ fungible::{self, MutateHold as _}, Precision, }; -use sp_runtime::traits::Zero; +use sp_runtime::{traits::Zero, Saturating}; use sp_std::boxed::Box; type BalanceOf = @@ -133,7 +133,7 @@ pub mod pallet { Error::::TooManyFieldsInIdentityInfo ); - let fd = >::from(extra_fields) * T::FieldDeposit::get(); + let fd = >::from(extra_fields).saturating_mul(T::FieldDeposit::get()); let mut id = match >::get(&identified) { Some(mut id) => { id.info = *info; @@ -146,23 +146,24 @@ pub mod pallet { }; let old_deposit = id.deposit; - id.deposit = T::InitialDeposit::get() + fd; + id.deposit = T::InitialDeposit::get().saturating_add(fd); if id.deposit > old_deposit { T::Currency::hold( &HoldReason::RegistryIdentity.into(), &who, - id.deposit - old_deposit, + id.deposit.saturating_sub(old_deposit), )?; } if old_deposit > id.deposit { let release_res = T::Currency::release( &HoldReason::RegistryIdentity.into(), &who, - old_deposit - id.deposit, + old_deposit.saturating_sub(id.deposit), Precision::BestEffort, ); - debug_assert!(release_res - .is_ok_and(|released_amount| released_amount == (old_deposit - id.deposit))); + debug_assert!(release_res.is_ok_and( + |released_amount| released_amount == old_deposit.saturating_sub(id.deposit) + )); } >::insert(&identified, id); diff --git a/pallets/registry/src/types.rs b/pallets/registry/src/types.rs index 0573392cd..12ee857d2 100644 --- a/pallets/registry/src/types.rs +++ b/pallets/registry/src/types.rs @@ -67,7 +67,7 @@ impl Decode for Data { Ok(match b { 0 => Data::None, n @ 1..=65 => { - let mut r: BoundedVec<_, _> = vec![0u8; n as usize - 1] + let mut r: BoundedVec<_, _> = vec![0u8; (n as usize).saturating_sub(1)] .try_into() .expect("bound checked in match arm condition; qed"); input.read(&mut r[..])?; @@ -87,8 +87,8 @@ impl Encode for Data { match self { Data::None => vec![0u8; 1], Data::Raw(ref x) => { - let l = x.len().min(64); - let mut r = vec![l as u8 + 1]; + let l = x.len().min(64) as u8; + let mut r = vec![l.saturating_add(1)]; r.extend_from_slice(&x[..]); r } @@ -403,6 +403,7 @@ impl< } #[cfg(test)] +#[allow(clippy::indexing_slicing, clippy::unwrap_used)] mod tests { use super::*; diff --git a/pallets/subtensor/src/benchmarks.rs b/pallets/subtensor/src/benchmarks.rs index a7dd29fbb..403ba413e 100644 --- a/pallets/subtensor/src/benchmarks.rs +++ b/pallets/subtensor/src/benchmarks.rs @@ -1,5 +1,5 @@ //! Subtensor pallet benchmarking. - +#![allow(clippy::arithmetic_side_effects, clippy::unwrap_used)] #![cfg(feature = "runtime-benchmarks")] use crate::Pallet as Subtensor; diff --git a/pallets/subtensor/src/block_step.rs b/pallets/subtensor/src/block_step.rs index 80733e6b7..cdd470cd0 100644 --- a/pallets/subtensor/src/block_step.rs +++ b/pallets/subtensor/src/block_step.rs @@ -1,6 +1,7 @@ use super::*; use frame_support::storage::IterableStorageDoubleMap; use frame_support::storage::IterableStorageMap; +use sp_runtime::Saturating; use substrate_fixed::types::I110F18; use substrate_fixed::types::I64F64; use substrate_fixed::types::I96F32; @@ -27,6 +28,7 @@ impl Pallet { Ok(()) } + #[allow(clippy::arithmetic_side_effects)] /// Helper function which returns the number of blocks remaining before we will run the epoch on this /// network. Networks run their epoch when (block_number + netuid + 1 ) % (tempo + 1) = 0 /// @@ -42,9 +44,13 @@ impl Pallet { if tempo == 0 { return 1000; } - tempo as u64 - (block_number + netuid as u64 + 1) % (tempo as u64 + 1) + (tempo as u64).saturating_sub( + block_number.saturating_add(netuid as u64).saturating_add(1) + % (tempo as u64).saturating_add(1), + ) } + #[allow(clippy::arithmetic_side_effects)] /// Helper function returns the number of tuples to drain on a particular step based on /// the remaining tuples to sink and the block number /// @@ -55,18 +61,20 @@ impl Pallet { n_remaining: usize, ) -> usize { let blocks_until_epoch: u64 = Self::blocks_until_next_epoch(netuid, tempo, block_number); - if blocks_until_epoch / 2 == 0 { + if blocks_until_epoch.saturating_div(2) == 0 { return n_remaining; } // drain all. - if tempo / 2 == 0 { + if tempo.saturating_div(2) == 0 { return n_remaining; } // drain all if n_remaining == 0 { return 0; } // nothing to drain at all. // Else return enough tuples to drain all within half the epoch length. - let to_sink_via_tempo: usize = n_remaining / (tempo as usize / 2); - let to_sink_via_blocks_until_epoch: usize = n_remaining / (blocks_until_epoch as usize / 2); + let to_sink_via_tempo: usize = + n_remaining.saturating_div((tempo as usize).saturating_div(2)); + let to_sink_via_blocks_until_epoch: usize = + n_remaining.saturating_div((blocks_until_epoch as usize).saturating_div(2)); if to_sink_via_tempo > to_sink_via_blocks_until_epoch { to_sink_via_tempo } else { @@ -95,7 +103,7 @@ impl Pallet { *server_amount, *validator_amount, ); - total_emitted += *server_amount + *validator_amount; + total_emitted.saturating_accrue((*server_amount).saturating_add(*validator_amount)); } LoadedEmission::::remove(netuid); TotalIssuance::::put(TotalIssuance::::get().saturating_add(total_emitted)); @@ -142,7 +150,9 @@ impl Pallet { Self::coinbase(cut.to_num::()); } // --- 5. Add remaining amount to the network's pending emission. - PendingEmission::::mutate(netuid, |queued| *queued += remaining.to_num::()); + PendingEmission::::mutate(netuid, |queued| { + queued.saturating_accrue(remaining.to_num::()) + }); log::debug!( "netuid_i: {:?} queued_emission: +{:?} ", netuid, @@ -154,7 +164,7 @@ impl Pallet { // --- 3.1 No epoch, increase blocks since last step and continue, Self::set_blocks_since_last_step( netuid, - Self::get_blocks_since_last_step(netuid) + 1, + Self::get_blocks_since_last_step(netuid).saturating_add(1), ); continue; } @@ -176,7 +186,7 @@ impl Pallet { // --- 9. Check that the emission does not exceed the allowed total. let emission_sum: u128 = emission_tuples_this_block .iter() - .map(|(_account_id, ve, se)| *ve as u128 + *se as u128) + .map(|(_account_id, ve, se)| (*ve as u128).saturating_add(*se as u128)) .sum(); if emission_sum > emission_to_drain as u128 { continue; @@ -208,7 +218,10 @@ impl Pallet { // --- 1. Check if the hotkey is a delegate. If not, we simply pass the stake through to the // coldkey - hotkey account as normal. if !Self::hotkey_is_delegate(hotkey) { - Self::increase_stake_on_hotkey_account(hotkey, server_emission + validator_emission); + Self::increase_stake_on_hotkey_account( + hotkey, + server_emission.saturating_add(validator_emission), + ); return; } // Then this is a delegate, we distribute validator_emission, then server_emission. @@ -218,7 +231,7 @@ impl Pallet { let total_hotkey_stake: u64 = Self::get_total_stake_for_hotkey(hotkey); let delegate_take: u64 = Self::calculate_delegate_proportional_take(hotkey, validator_emission); - let validator_emission_minus_take: u64 = validator_emission - delegate_take; + let validator_emission_minus_take: u64 = validator_emission.saturating_sub(delegate_take); let mut remaining_validator_emission: u64 = validator_emission_minus_take; // 3. -- The remaining emission goes to the owners in proportion to the stake delegated. @@ -244,14 +257,14 @@ impl Pallet { hotkey, stake_proportion ); - remaining_validator_emission -= stake_proportion; + remaining_validator_emission.saturating_reduce(stake_proportion); } // --- 5. Last increase final account balance of delegate after 4, since 5 will change the stake proportion of // the delegate and effect calculation in 4. Self::increase_stake_on_hotkey_account( hotkey, - delegate_take + remaining_validator_emission, + delegate_take.saturating_add(remaining_validator_emission), ); log::debug!("delkey: {:?} delegate_take: +{:?} ", hotkey, delegate_take); // Also emit the server_emission to the hotkey @@ -311,8 +324,10 @@ impl Pallet { if total_stake == 0 { return 0; }; - let stake_proportion: I64F64 = I64F64::from_num(stake) / I64F64::from_num(total_stake); - let proportional_emission: I64F64 = I64F64::from_num(emission) * stake_proportion; + let stake_proportion: I64F64 = + I64F64::from_num(stake).saturating_div(I64F64::from_num(total_stake)); + let proportional_emission: I64F64 = + I64F64::from_num(emission).saturating_mul(stake_proportion); proportional_emission.to_num::() } @@ -320,9 +335,9 @@ impl Pallet { /// pub fn calculate_delegate_proportional_take(hotkey: &T::AccountId, emission: u64) -> u64 { if Self::hotkey_is_delegate(hotkey) { - let take_proportion: I64F64 = - I64F64::from_num(Delegates::::get(hotkey)) / I64F64::from_num(u16::MAX); - let take_emission: I64F64 = take_proportion * I64F64::from_num(emission); + let take_proportion: I64F64 = I64F64::from_num(Delegates::::get(hotkey)) + .saturating_div(I64F64::from_num(u16::MAX)); + let take_emission: I64F64 = take_proportion.saturating_mul(I64F64::from_num(emission)); take_emission.to_num::() } else { 0 @@ -349,7 +364,7 @@ impl Pallet { // --- 3. Check if we are at the adjustment interval for this network. // If so, we need to adjust the registration difficulty based on target and actual registrations. - if (current_block - last_adjustment_block) >= adjustment_interval as u64 { + if current_block.saturating_sub(last_adjustment_block) >= adjustment_interval as u64 { log::debug!("interval reached."); // --- 4. Get the current counters for this network w.r.t burn and difficulty values. @@ -496,14 +511,21 @@ impl Pallet { target_registrations_per_interval: u16, ) -> u64 { let updated_difficulty: I110F18 = I110F18::from_num(current_difficulty) - * I110F18::from_num(registrations_this_interval + target_registrations_per_interval) - / I110F18::from_num( - target_registrations_per_interval + target_registrations_per_interval, + .saturating_mul(I110F18::from_num( + registrations_this_interval.saturating_add(target_registrations_per_interval), + )) + .saturating_div(I110F18::from_num( + target_registrations_per_interval.saturating_add(target_registrations_per_interval), + )); + let alpha: I110F18 = I110F18::from_num(Self::get_adjustment_alpha(netuid)) + .saturating_div(I110F18::from_num(u64::MAX)); + let next_value: I110F18 = alpha + .saturating_mul(I110F18::from_num(current_difficulty)) + .saturating_add( + I110F18::from_num(1.0) + .saturating_sub(alpha) + .saturating_mul(updated_difficulty), ); - let alpha: I110F18 = - I110F18::from_num(Self::get_adjustment_alpha(netuid)) / I110F18::from_num(u64::MAX); - let next_value: I110F18 = alpha * I110F18::from_num(current_difficulty) - + (I110F18::from_num(1.0) - alpha) * updated_difficulty; if next_value >= I110F18::from_num(Self::get_max_difficulty(netuid)) { Self::get_max_difficulty(netuid) } else if next_value <= I110F18::from_num(Self::get_min_difficulty(netuid)) { @@ -523,14 +545,21 @@ impl Pallet { target_registrations_per_interval: u16, ) -> u64 { let updated_burn: I110F18 = I110F18::from_num(current_burn) - * I110F18::from_num(registrations_this_interval + target_registrations_per_interval) - / I110F18::from_num( - target_registrations_per_interval + target_registrations_per_interval, + .saturating_mul(I110F18::from_num( + registrations_this_interval.saturating_add(target_registrations_per_interval), + )) + .saturating_div(I110F18::from_num( + target_registrations_per_interval.saturating_add(target_registrations_per_interval), + )); + let alpha: I110F18 = I110F18::from_num(Self::get_adjustment_alpha(netuid)) + .saturating_div(I110F18::from_num(u64::MAX)); + let next_value: I110F18 = alpha + .saturating_mul(I110F18::from_num(current_burn)) + .saturating_add( + I110F18::from_num(1.0) + .saturating_sub(alpha) + .saturating_mul(updated_burn), ); - let alpha: I110F18 = - I110F18::from_num(Self::get_adjustment_alpha(netuid)) / I110F18::from_num(u64::MAX); - let next_value: I110F18 = alpha * I110F18::from_num(current_burn) - + (I110F18::from_num(1.0) - alpha) * updated_burn; if next_value >= I110F18::from_num(Self::get_max_burn_as_u64(netuid)) { Self::get_max_burn_as_u64(netuid) } else if next_value <= I110F18::from_num(Self::get_min_burn_as_u64(netuid)) { diff --git a/pallets/subtensor/src/delegate_info.rs b/pallets/subtensor/src/delegate_info.rs index b33415a3b..1f8b06b69 100644 --- a/pallets/subtensor/src/delegate_info.rs +++ b/pallets/subtensor/src/delegate_info.rs @@ -52,8 +52,9 @@ impl Pallet { let emission: U64F64 = Self::get_emission_for_uid(*netuid, uid).into(); let tempo: U64F64 = Self::get_tempo(*netuid).into(); - let epochs_per_day: U64F64 = U64F64::from_num(7200) / tempo; - emissions_per_day += emission * epochs_per_day; + let epochs_per_day: U64F64 = U64F64::from_num(7200).saturating_div(tempo); + emissions_per_day = + emissions_per_day.saturating_add(emission.saturating_mul(epochs_per_day)); } } @@ -65,8 +66,9 @@ impl Pallet { let mut return_per_1000: U64F64 = U64F64::from_num(0); if total_stake > U64F64::from_num(0) { - return_per_1000 = (emissions_per_day * U64F64::from_num(0.82)) - / (total_stake / U64F64::from_num(1000)); + return_per_1000 = emissions_per_day + .saturating_mul(U64F64::from_num(0.82)) + .saturating_div(total_stake.saturating_div(U64F64::from_num(1000))); } return DelegateInfo { diff --git a/pallets/subtensor/src/epoch.rs b/pallets/subtensor/src/epoch.rs index cc146dd59..cd2666d9d 100644 --- a/pallets/subtensor/src/epoch.rs +++ b/pallets/subtensor/src/epoch.rs @@ -32,7 +32,7 @@ impl Pallet { // Inactive mask. let inactive: Vec = last_update .iter() - .map(|updated| *updated + activity_cutoff < current_block) + .map(|updated| updated.saturating_add(activity_cutoff) < current_block) .collect(); log::trace!("Inactive:\n{:?}\n", inactive.clone()); @@ -175,9 +175,10 @@ impl Pallet { // log::trace!( "ΔB:\n{:?}\n", &bonds_delta ); // Compute bonds moving average. - let bonds_moving_average: I64F64 = - I64F64::from_num(Self::get_bonds_moving_average(netuid)) / I64F64::from_num(1_000_000); - let alpha: I32F32 = I32F32::from_num(1) - I32F32::from_num(bonds_moving_average); + let bonds_moving_average: I64F64 = I64F64::from_num(Self::get_bonds_moving_average(netuid)) + .saturating_div(I64F64::from_num(1_000_000)); + let alpha: I32F32 = + I32F32::from_num(1).saturating_sub(I32F32::from_num(bonds_moving_average)); let mut ema_bonds: Vec> = mat_ema(&bonds_delta, &bonds, alpha); inplace_col_normalize(&mut ema_bonds); // sum_i b_ij = 1 // log::trace!( "emaB:\n{:?}\n", &ema_bonds ); @@ -198,7 +199,7 @@ impl Pallet { let combined_emission: Vec = incentive .iter() .zip(dividends.clone()) - .map(|(ii, di)| ii + di) + .map(|(ii, di)| ii.saturating_add(di)) .collect(); let emission_sum: I32F32 = combined_emission.iter().sum(); @@ -228,7 +229,7 @@ impl Pallet { let server_emission: Vec = normalized_server_emission .iter() - .map(|se: &I32F32| I96F32::from_num(*se) * float_rao_emission) + .map(|se: &I32F32| I96F32::from_num(*se).saturating_mul(float_rao_emission)) .collect(); let server_emission: Vec = server_emission .iter() @@ -237,7 +238,7 @@ impl Pallet { let validator_emission: Vec = normalized_validator_emission .iter() - .map(|ve: &I32F32| I96F32::from_num(*ve) * float_rao_emission) + .map(|ve: &I32F32| I96F32::from_num(*ve).saturating_mul(float_rao_emission)) .collect(); let validator_emission: Vec = validator_emission .iter() @@ -247,7 +248,7 @@ impl Pallet { // Used only to track combined emission in the storage. let combined_emission: Vec = normalized_combined_emission .iter() - .map(|ce: &I32F32| I96F32::from_num(*ce) * float_rao_emission) + .map(|ce: &I32F32| I96F32::from_num(*ce).saturating_mul(float_rao_emission)) .collect(); let combined_emission: Vec = combined_emission .iter() @@ -376,7 +377,7 @@ impl Pallet { // Inactive mask. let inactive: Vec = last_update .iter() - .map(|updated| *updated + activity_cutoff < current_block) + .map(|updated| updated.saturating_add(activity_cutoff) < current_block) .collect(); log::trace!("Inactive: {:?}", inactive.clone()); @@ -535,9 +536,10 @@ impl Pallet { // log::trace!( "ΔB (norm): {:?}", &bonds_delta ); // Compute bonds moving average. - let bonds_moving_average: I64F64 = - I64F64::from_num(Self::get_bonds_moving_average(netuid)) / I64F64::from_num(1_000_000); - let alpha: I32F32 = I32F32::from_num(1) - I32F32::from_num(bonds_moving_average); + let bonds_moving_average: I64F64 = I64F64::from_num(Self::get_bonds_moving_average(netuid)) + .saturating_div(I64F64::from_num(1_000_000)); + let alpha: I32F32 = + I32F32::from_num(1).saturating_sub(I32F32::from_num(bonds_moving_average)); let mut ema_bonds: Vec> = mat_ema_sparse(&bonds_delta, &bonds, alpha); // Normalize EMA bonds. @@ -558,7 +560,7 @@ impl Pallet { let combined_emission: Vec = incentive .iter() .zip(dividends.clone()) - .map(|(ii, di)| ii + di) + .map(|(ii, di)| ii.saturating_add(di)) .collect(); let emission_sum: I32F32 = combined_emission.iter().sum(); @@ -588,7 +590,7 @@ impl Pallet { let server_emission: Vec = normalized_server_emission .iter() - .map(|se: &I32F32| I96F32::from_num(*se) * float_rao_emission) + .map(|se: &I32F32| I96F32::from_num(*se).saturating_mul(float_rao_emission)) .collect(); let server_emission: Vec = server_emission .iter() @@ -597,7 +599,7 @@ impl Pallet { let validator_emission: Vec = normalized_validator_emission .iter() - .map(|ve: &I32F32| I96F32::from_num(*ve) * float_rao_emission) + .map(|ve: &I32F32| I96F32::from_num(*ve).saturating_mul(float_rao_emission)) .collect(); let validator_emission: Vec = validator_emission .iter() @@ -607,7 +609,7 @@ impl Pallet { // Only used to track emission in storage. let combined_emission: Vec = normalized_combined_emission .iter() - .map(|ce: &I32F32| I96F32::from_num(*ce) * float_rao_emission) + .map(|ce: &I32F32| I96F32::from_num(*ce).saturating_mul(float_rao_emission)) .collect(); let combined_emission: Vec = combined_emission .iter() @@ -704,7 +706,7 @@ impl Pallet { I32F32::from_num(Self::get_rho(netuid)) } pub fn get_float_kappa(netuid: u16) -> I32F32 { - I32F32::from_num(Self::get_kappa(netuid)) / I32F32::from_num(u16::MAX) + I32F32::from_num(Self::get_kappa(netuid)).saturating_div(I32F32::from_num(u16::MAX)) } pub fn get_normalized_stake(netuid: u16) -> Vec { diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index 61eb17f4a..ccf44419b 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -1145,7 +1145,7 @@ pub mod pallet { // Set max allowed uids MaxAllowedUids::::insert(netuid, max_uids); - let mut next_uid = 0; + let mut next_uid = 0u16; for (coldkey, hotkeys) in self.stakes.iter() { for (hotkey, stake_uid) in hotkeys.iter() { @@ -1184,7 +1184,9 @@ pub mod pallet { Stake::::insert(hotkey.clone(), coldkey.clone(), stake); - next_uid += 1; + next_uid = next_uid.checked_add(1).expect( + "should not have total number of hotkey accounts larger than u16::MAX", + ); } } @@ -1192,7 +1194,11 @@ pub mod pallet { SubnetworkN::::insert(netuid, next_uid); // --- Increase total network count. - TotalNetworks::::mutate(|n| *n += 1); + TotalNetworks::::mutate(|n| { + *n = n.checked_add(1).expect( + "should not have total number of networks larger than u16::MAX in genesis", + ) + }); // Get the root network uid. let root_netuid: u16 = 0; @@ -1201,7 +1207,11 @@ pub mod pallet { NetworksAdded::::insert(root_netuid, true); // Increment the number of total networks. - TotalNetworks::::mutate(|n| *n += 1); + TotalNetworks::::mutate(|n| { + *n = n.checked_add(1).expect( + "should not have total number of networks larger than u16::MAX in genesis", + ) + }); // Set the number of validators to 1. SubnetworkN::::insert(root_netuid, 0); @@ -1214,7 +1224,7 @@ pub mod pallet { // Set the min allowed weights to zero, no weights restrictions. MinAllowedWeights::::insert(root_netuid, 0); - // Set the max weight limit to infitiy, no weight restrictions. + // Set the max weight limit to infinity, no weight restrictions. MaxWeightsLimit::::insert(root_netuid, u16::MAX); // Add default root tempo. @@ -2062,8 +2072,8 @@ pub mod pallet { let _stake = Self::get_total_stake_for_hotkey(hotkey); let current_block_number: u64 = Self::get_current_block_as_u64(); let default_priority: u64 = - current_block_number - Self::get_last_update_for_uid(netuid, uid); - return default_priority + u32::max_value() as u64; + current_block_number.saturating_sub(Self::get_last_update_for_uid(netuid, uid)); + return default_priority.saturating_add(u32::max_value() as u64); } 0 } @@ -2091,7 +2101,7 @@ pub mod pallet { return false; } if Self::get_registrations_this_interval(netuid) - >= Self::get_target_registrations_per_interval(netuid) * 3 + >= Self::get_target_registrations_per_interval(netuid).saturating_mul(3) { return false; } @@ -2244,7 +2254,8 @@ where Pallet::::get_registrations_this_interval(*netuid); let max_registrations_per_interval = Pallet::::get_target_registrations_per_interval(*netuid); - if registrations_this_interval >= (max_registrations_per_interval * 3) { + if registrations_this_interval >= (max_registrations_per_interval.saturating_mul(3)) + { // If the registration limit for the interval is exceeded, reject the transaction return InvalidTransaction::ExhaustsResources.into(); } diff --git a/pallets/subtensor/src/math.rs b/pallets/subtensor/src/math.rs index e10cc0001..f7784ea1c 100644 --- a/pallets/subtensor/src/math.rs +++ b/pallets/subtensor/src/math.rs @@ -1,4 +1,4 @@ -use sp_runtime::traits::CheckedAdd; +use sp_runtime::{traits::CheckedAdd, Saturating}; use sp_std::vec; use substrate_fixed::transcendental::exp; use substrate_fixed::types::{I32F32, I64F64}; @@ -44,12 +44,12 @@ pub fn u16_to_fixed(x: u16) -> I32F32 { #[allow(dead_code)] pub fn u16_proportion_to_fixed(x: u16) -> I32F32 { - I32F32::from_num(x) / I32F32::from_num(u16::MAX) + I32F32::from_num(x).saturating_div(I32F32::from_num(u16::MAX)) } #[allow(dead_code)] pub fn fixed_proportion_to_u16(x: I32F32) -> u16 { - fixed_to_u16(x * I32F32::from_num(u16::MAX)) + fixed_to_u16(x.saturating_mul(I32F32::from_num(u16::MAX))) } #[allow(dead_code)] @@ -93,25 +93,38 @@ pub fn vec_max_upscale_to_u16(vec: &[I32F32]) -> Vec { if *val == I32F32::from_num(0) { return vec .iter() - .map(|e: &I32F32| (e * u16_max).to_num::()) + .map(|e: &I32F32| e.saturating_mul(u16_max).to_num::()) .collect(); } if *val > threshold { return vec .iter() - .map(|e: &I32F32| (e * (u16_max / *val)).round().to_num::()) + .map(|e: &I32F32| { + e.saturating_mul(u16_max.saturating_div(*val)) + .round() + .to_num::() + }) .collect(); } return vec .iter() - .map(|e: &I32F32| ((e * u16_max) / *val).round().to_num::()) + .map(|e: &I32F32| { + e.saturating_mul(u16_max) + .saturating_div(*val) + .round() + .to_num::() + }) .collect(); } None => { let sum: I32F32 = vec.iter().sum(); return vec .iter() - .map(|e: &I32F32| ((e * u16_max) / sum).to_num::()) + .map(|e: &I32F32| { + e.saturating_mul(u16_max) + .saturating_div(sum) + .to_num::() + }) .collect(); } } @@ -127,7 +140,8 @@ pub fn vec_u16_max_upscale_to_u16(vec: &[u16]) -> Vec { #[allow(dead_code)] // Checks if u16 vector, when normalized, has a max value not greater than a u16 ratio max_limit. pub fn check_vec_max_limited(vec: &[u16], max_limit: u16) -> bool { - let max_limit_fixed: I32F32 = I32F32::from_num(max_limit) / I32F32::from_num(u16::MAX); + let max_limit_fixed: I32F32 = + I32F32::from_num(max_limit).saturating_div(I32F32::from_num(u16::MAX)); let mut vec_fixed: Vec = vec.iter().map(|e: &u16| I32F32::from_num(*e)).collect(); inplace_normalize(&mut vec_fixed); let max_value: Option<&I32F32> = vec_fixed.iter().max(); @@ -196,7 +210,7 @@ pub fn exp_safe(input: I32F32) -> I32F32 { pub fn sigmoid_safe(input: I32F32, rho: I32F32, kappa: I32F32) -> I32F32 { let one: I32F32 = I32F32::from_num(1); let offset: I32F32 = input.saturating_sub(kappa); // (input - kappa) - let neg_rho: I32F32 = rho.saturating_mul(-one); // -rho + let neg_rho: I32F32 = rho.saturating_mul(one.saturating_neg()); // -rho let exp_input: I32F32 = neg_rho.saturating_mul(offset); // -rho*(input-kappa) let exp_output: I32F32 = exp_safe(exp_input); // exp(-rho*(input-kappa)) let denominator: I32F32 = exp_output.saturating_add(one); // 1 + exp(-rho*(input-kappa)) @@ -214,7 +228,7 @@ pub fn is_topk(vector: &[I32F32], k: usize) -> Vec { } let mut idxs: Vec = (0..n).collect(); idxs.sort_by_key(|&idx| &vector[idx]); // ascending stable sort - for &idx in idxs.iter().take(n - k) { + for &idx in idxs.iter().take(n.saturating_sub(k)) { result[idx] = false; } result @@ -225,7 +239,7 @@ pub fn is_topk(vector: &[I32F32], k: usize) -> Vec { pub fn normalize(x: &[I32F32]) -> Vec { let x_sum: I32F32 = sum(x); if x_sum != I32F32::from_num(0.0_f32) { - return x.iter().map(|xi| xi / x_sum).collect(); + return x.iter().map(|xi| xi.saturating_div(x_sum)).collect(); } else { x.to_vec() } @@ -238,7 +252,8 @@ pub fn inplace_normalize(x: &mut [I32F32]) { if x_sum == I32F32::from_num(0.0_f32) { return; } - x.iter_mut().for_each(|value| *value /= x_sum); + x.into_iter() + .for_each(|value| *value = value.saturating_div(x_sum)); } // Normalizes (sum to 1 except 0) the input vector directly in-place, using the sum arg. @@ -247,7 +262,8 @@ pub fn inplace_normalize_using_sum(x: &mut [I32F32], x_sum: I32F32) { if x_sum == I32F32::from_num(0.0_f32) { return; } - x.iter_mut().for_each(|value| *value /= x_sum); + x.into_iter() + .for_each(|value| *value = value.saturating_div(x_sum)); } // Normalizes (sum to 1 except 0) the I64F64 input vector directly in-place. @@ -257,7 +273,8 @@ pub fn inplace_normalize_64(x: &mut [I64F64]) { if x_sum == I64F64::from_num(0) { return; } - x.iter_mut().for_each(|value| *value /= x_sum); + x.into_iter() + .for_each(|value| *value = value.saturating_div(x_sum)); } /// Normalizes (sum to 1 except 0) each row (dim=0) of a I64F64 matrix in-place. @@ -267,7 +284,7 @@ pub fn inplace_row_normalize_64(x: &mut [Vec]) { let row_sum: I64F64 = row.iter().sum(); if row_sum > I64F64::from_num(0.0_f64) { row.iter_mut() - .for_each(|x_ij: &mut I64F64| *x_ij /= row_sum); + .for_each(|x_ij: &mut I64F64| *x_ij = x_ij.saturating_div(row_sum)); } } } @@ -280,7 +297,7 @@ pub fn vecdiv(x: &[I32F32], y: &[I32F32]) -> Vec { .zip(y) .map(|(x_i, y_i)| { if *y_i != 0 { - x_i / y_i + x_i.saturating_div(*y_i) } else { I32F32::from_num(0) } @@ -294,8 +311,8 @@ pub fn inplace_row_normalize(x: &mut [Vec]) { for row in x { let row_sum: I32F32 = row.iter().sum(); if row_sum > I32F32::from_num(0.0_f32) { - row.iter_mut() - .for_each(|x_ij: &mut I32F32| *x_ij /= row_sum); + row.into_iter() + .for_each(|x_ij: &mut I32F32| *x_ij = x_ij.saturating_div(row_sum)); } } } @@ -308,7 +325,7 @@ pub fn inplace_row_normalize_sparse(sparse_matrix: &mut [Vec<(u16, I32F32)>]) { if row_sum > I32F32::from_num(0.0) { sparse_row .iter_mut() - .for_each(|(_j, value)| *value /= row_sum); + .for_each(|(_j, value)| *value = value.saturating_div(row_sum)); } } } @@ -347,7 +364,7 @@ pub fn col_sum(x: &[Vec]) -> Vec { .fold(vec![I32F32::from_num(0); cols], |acc, next_row| { acc.into_iter() .zip(next_row) - .map(|(acc_elem, next_elem)| acc_elem + next_elem) + .map(|(acc_elem, next_elem)| acc_elem.saturating_add(*next_elem)) .collect() }) } @@ -358,7 +375,7 @@ pub fn col_sum_sparse(sparse_matrix: &[Vec<(u16, I32F32)>], columns: u16) -> Vec let mut result: Vec = vec![I32F32::from_num(0); columns as usize]; for sparse_row in sparse_matrix { for (j, value) in sparse_row { - result[*j as usize] += value; + result[*j as usize] = result[*j as usize].saturating_add(*value); } } result @@ -370,7 +387,7 @@ pub fn inplace_col_normalize_sparse(sparse_matrix: &mut [Vec<(u16, I32F32)>], co let mut col_sum: Vec = vec![I32F32::from_num(0.0); columns as usize]; // assume square matrix, rows=cols for sparse_row in sparse_matrix.iter() { for (j, value) in sparse_row.iter() { - col_sum[*j as usize] += value; + col_sum[*j as usize] = col_sum[*j as usize].saturating_add(*value); } } for sparse_row in sparse_matrix { @@ -378,7 +395,7 @@ pub fn inplace_col_normalize_sparse(sparse_matrix: &mut [Vec<(u16, I32F32)>], co if col_sum[*j as usize] == I32F32::from_num(0.0_f32) { continue; } - *value /= col_sum[*j as usize]; + *value = value.saturating_div(col_sum[*j as usize]); } } } @@ -398,7 +415,7 @@ pub fn inplace_col_normalize(x: &mut [Vec]) { .fold(vec![I32F32::from_num(0.0); cols], |acc, row| { row.iter_mut() .zip(acc) - .map(|(&mut m_val, acc_val)| acc_val + m_val) + .map(|(&mut m_val, acc_val)| acc_val.saturating_add(m_val)) .collect() }); x.iter_mut().for_each(|row| { @@ -406,7 +423,7 @@ pub fn inplace_col_normalize(x: &mut [Vec]) { .zip(&col_sums) .filter(|(_, col_sum)| **col_sum != I32F32::from_num(0_f32)) .for_each(|(m_val, col_sum)| { - *m_val /= col_sum; + *m_val = m_val.saturating_div(*col_sum); }); }); } @@ -427,7 +444,7 @@ pub fn inplace_col_max_upscale_sparse(sparse_matrix: &mut [Vec<(u16, I32F32)>], if col_max[*j as usize] == I32F32::from_num(0.0_f32) { continue; } - *value /= col_max[*j as usize]; + *value = value.saturating_div(col_max[*j as usize]); } } } @@ -455,7 +472,7 @@ pub fn inplace_col_max_upscale(x: &mut [Vec]) { .zip(&col_maxes) .filter(|(_, col_max)| **col_max != I32F32::from_num(0)) .for_each(|(m_val, col_max)| { - *m_val /= col_max; + *m_val = m_val.saturating_div(*col_max); }); }); } @@ -604,7 +621,11 @@ pub fn row_hadamard(matrix: &[Vec], vector: &[I32F32]) -> Vec], vector: &[I32F32]) -> Vec { // Compute ranks: r_j = SUM(i) w_ij * s_i // Compute trust scores: t_j = SUM(i) w_ij * s_i // result_j = SUM(i) vector_i * matrix_ij - acc_val + vec_val * m_val + acc_val.saturating_add(vec_val.saturating_mul(*m_val)) }) .collect() }, @@ -674,7 +695,7 @@ pub fn matmul_64(matrix: &[Vec], vector: &[I64F64]) -> Vec { // Compute ranks: r_j = SUM(i) w_ij * s_i // Compute trust scores: t_j = SUM(i) w_ij * s_i // result_j = SUM(i) vector_i * matrix_ij - acc_val + vec_val * m_val + acc_val.saturating_add(vec_val.saturating_mul(*m_val)) }) .collect() }) @@ -699,7 +720,7 @@ pub fn matmul_transpose(matrix: &[Vec], vector: &[I32F32]) -> Vec = (0..use_stake.len()).collect(); - let minority: I32F32 = stake_sum - majority; + let minority: I32F32 = stake_sum.saturating_sub(majority); let mut use_score: Vec> = vec![vec![zero; use_stake.len()]; columns as usize]; let mut median: Vec = vec![zero; columns as usize]; let mut k: usize = 0; @@ -978,7 +1002,7 @@ pub fn weighted_median_col_sparse( for (c, val) in score[r].iter() { use_score[*c as usize][k] = *val; } - k += 1; + k.saturating_inc(); } for c in 0..columns as usize { median[c] = weighted_median( @@ -1009,7 +1033,7 @@ pub fn hadamard(mat1: &[Vec], mat2: &[Vec]) -> Vec> assert!(row1.len() == row2.len()); row1.iter() .zip(row2) - .map(|(elem1, elem2)| elem1 * elem2) + .map(|(elem1, elem2)| elem1.saturating_mul(*elem2)) .collect() }) .collect() @@ -1029,14 +1053,14 @@ pub fn hadamard_sparse( for i in 0..rows { let mut row1: Vec = vec![zero; columns as usize]; for (j, value) in mat1[i].iter() { - row1[*j as usize] += value; + row1[*j as usize] = row1[*j as usize].saturating_add(*value); } let mut row2: Vec = vec![zero; columns as usize]; for (j, value) in mat2[i].iter() { - row2[*j as usize] += value; + row2[*j as usize] = row2[*j as usize].saturating_add(*value); } for j in 0..columns as usize { - let prod: I32F32 = row1[j] * row2[j]; + let prod: I32F32 = row1[j].saturating_mul(row2[j]); if zero < prod { result[i].push((j as u16, prod)) } @@ -1056,14 +1080,18 @@ pub fn mat_ema(new: &[Vec], old: &[Vec], alpha: I32F32) -> Vec> = vec![vec![]; n]; for i in 0..new.len() { let mut row: Vec = vec![zero; n]; for (j, value) in new[i].iter() { - row[*j as usize] += alpha * value; + row[*j as usize] = row[*j as usize].saturating_add(alpha.saturating_mul(*value)); } for (j, value) in old[i].iter() { - row[*j as usize] += one_minus_alpha * value; + row[*j as usize] = + row[*j as usize].saturating_add(one_minus_alpha.saturating_mul(*value)); } for (j, value) in row.iter().enumerate() { if *value > zero { @@ -1114,7 +1143,11 @@ pub fn sparse_threshold(w: &[Vec<(u16, I32F32)>], threshold: I32F32) -> Vec(test: bool) -> Weight { weight = weight.saturating_add(T::DbWeight::get().reads(1)); // Compute the total issuance value - let total_issuance_value: u64 = stake_sum + total_balance_sum + locked_sum; + let total_issuance_value: u64 = stake_sum + .saturating_add(total_balance_sum) + .saturating_add(locked_sum); // Update the total issuance in storage TotalIssuance::::put(total_issuance_value); @@ -134,7 +137,7 @@ pub fn migrate_create_root_network() -> Weight { NetworksAdded::::insert(root_netuid, true); // Increment the number of total networks. - TotalNetworks::::mutate(|n| *n += 1); + TotalNetworks::::mutate(|n| n.saturating_inc()); // Set the maximum number to the number of senate members. MaxAllowedUids::::insert(root_netuid, 64); @@ -201,7 +204,7 @@ pub fn migrate_delete_subnet_3() -> Weight { NetworksAdded::::remove(netuid); // --- 6. Decrement the network counter. - TotalNetworks::::mutate(|n| *n -= 1); + TotalNetworks::::mutate(|n| n.saturating_dec()); // --- 7. Remove various network-related storages. NetworkRegisteredAt::::remove(netuid); @@ -285,7 +288,7 @@ pub fn migrate_delete_subnet_21() -> Weight { NetworksAdded::::remove(netuid); // --- 6. Decrement the network counter. - TotalNetworks::::mutate(|n| *n -= 1); + TotalNetworks::::mutate(|n| n.saturating_dec()); // --- 7. Remove various network-related storages. NetworkRegisteredAt::::remove(netuid); diff --git a/pallets/subtensor/src/registration.rs b/pallets/subtensor/src/registration.rs index 88730f7c3..dda00db54 100644 --- a/pallets/subtensor/src/registration.rs +++ b/pallets/subtensor/src/registration.rs @@ -2,6 +2,7 @@ use super::*; use frame_support::storage::IterableStorageDoubleMap; use sp_core::{Get, H256, U256}; use sp_io::hashing::{keccak_256, sha2_256}; +use sp_runtime::Saturating; use system::pallet_prelude::BlockNumberFor; const LOG_TARGET: &str = "runtime::subtensor::registration"; @@ -74,7 +75,7 @@ impl Pallet { // --- 4. Ensure we are not exceeding the max allowed registrations per interval. ensure!( Self::get_registrations_this_interval(netuid) - < Self::get_target_registrations_per_interval(netuid) * 3, + < Self::get_target_registrations_per_interval(netuid).saturating_mul(3), Error::::TooManyRegistrationsThisInterval ); @@ -143,9 +144,9 @@ impl Pallet { } // --- 14. Record the registration and increment block and interval counters. - BurnRegistrationsThisInterval::::mutate(netuid, |val| *val += 1); - RegistrationsThisInterval::::mutate(netuid, |val| *val += 1); - RegistrationsThisBlock::::mutate(netuid, |val| *val += 1); + BurnRegistrationsThisInterval::::mutate(netuid, |val| val.saturating_inc()); + RegistrationsThisInterval::::mutate(netuid, |val| val.saturating_inc()); + RegistrationsThisBlock::::mutate(netuid, |val| val.saturating_inc()); Self::increase_rao_recycled(netuid, Self::get_burn_as_u64(netuid)); // --- 15. Deposit successful event. @@ -259,7 +260,7 @@ impl Pallet { // --- 5. Ensure we are not exceeding the max allowed registrations per interval. ensure!( Self::get_registrations_this_interval(netuid) - < Self::get_target_registrations_per_interval(netuid) * 3, + < Self::get_target_registrations_per_interval(netuid).saturating_mul(3), Error::::TooManyRegistrationsThisInterval ); @@ -277,7 +278,7 @@ impl Pallet { Error::::InvalidWorkBlock ); ensure!( - current_block_number - block_number < 3, + current_block_number.saturating_sub(block_number) < 3, Error::::InvalidWorkBlock ); @@ -338,9 +339,9 @@ impl Pallet { } // --- 12. Record the registration and increment block and interval counters. - POWRegistrationsThisInterval::::mutate(netuid, |val| *val += 1); - RegistrationsThisInterval::::mutate(netuid, |val| *val += 1); - RegistrationsThisBlock::::mutate(netuid, |val| *val += 1); + POWRegistrationsThisInterval::::mutate(netuid, |val| val.saturating_inc()); + RegistrationsThisInterval::::mutate(netuid, |val| val.saturating_inc()); + RegistrationsThisBlock::::mutate(netuid, |val| val.saturating_inc()); // --- 13. Deposit successful event. log::info!( @@ -376,7 +377,7 @@ impl Pallet { Error::::InvalidWorkBlock ); ensure!( - current_block_number - block_number < 3, + current_block_number.saturating_sub(block_number) < 3, Error::::InvalidWorkBlock ); @@ -440,7 +441,7 @@ impl Pallet { Self::get_neuron_block_at_registration(netuid, neuron_uid_i); #[allow(clippy::comparison_chain)] if min_score == pruning_score { - if current_block - block_at_registration < immunity_period { + if current_block.saturating_sub(block_at_registration) < immunity_period { //neuron is in immunity period if min_score_in_immunity_period > pruning_score { min_score_in_immunity_period = pruning_score; @@ -452,7 +453,7 @@ impl Pallet { } // Find min pruning score. else if min_score > pruning_score { - if current_block - block_at_registration < immunity_period { + if current_block.saturating_sub(block_at_registration) < immunity_period { //neuron is in immunity period if min_score_in_immunity_period > pruning_score { min_score_in_immunity_period = pruning_score; @@ -584,7 +585,7 @@ impl Pallet { let mut nonce: u64 = start_nonce; let mut work: H256 = Self::create_seal_hash(block_number, nonce, hotkey); while !Self::hash_meets_difficulty(&work, difficulty) { - nonce += 1; + nonce.saturating_inc(); work = Self::create_seal_hash(block_number, nonce, hotkey); } let vec_work: Vec = Self::hash_to_vec(work); @@ -618,8 +619,9 @@ impl Pallet { Error::::HotKeyAlreadyRegisteredInSubNet ); - weight - .saturating_accrue(T::DbWeight::get().reads((TotalNetworks::::get() + 1u16) as u64)); + weight.saturating_accrue( + T::DbWeight::get().reads((TotalNetworks::::get().saturating_add(1)) as u64), + ); let swap_cost = 1_000_000_000u64; ensure!( diff --git a/pallets/subtensor/src/root.rs b/pallets/subtensor/src/root.rs index 42c783c3b..4874c337f 100644 --- a/pallets/subtensor/src/root.rs +++ b/pallets/subtensor/src/root.rs @@ -21,6 +21,7 @@ use frame_support::dispatch::Pays; use frame_support::storage::{IterableStorageDoubleMap, IterableStorageMap}; use frame_support::traits::Get; use frame_support::weights::Weight; +use sp_runtime::Saturating; use sp_std::vec; use substrate_fixed::{ transcendental::log2, @@ -156,9 +157,19 @@ impl Pallet { // Calculate the logarithmic residual of the issuance against half the total supply. let residual: I96F32 = log2( I96F32::from_num(1.0) - / (I96F32::from_num(1.0) - - total_issuance - / (I96F32::from_num(2.0) * I96F32::from_num(10_500_000_000_000_000.0))), + .checked_div( + I96F32::from_num(1.0) + .checked_sub( + total_issuance + .checked_div( + I96F32::from_num(2.0) + .saturating_mul(I96F32::from_num(10_500_000_000_000_000.0)), + ) + .ok_or("Logarithm calculation failed")?, + ) + .ok_or("Logarithm calculation failed")?, + ) + .ok_or("Logarithm calculation failed")?, ) .map_err(|_| "Logarithm calculation failed")?; // Floor the residual to smooth out the emission rate. @@ -169,12 +180,12 @@ impl Pallet { // Multiply 2.0 by itself floored_residual times to calculate the power of 2. let mut multiplier: I96F32 = I96F32::from_num(1.0); for _ in 0..floored_residual_int { - multiplier *= I96F32::from_num(2.0); + multiplier = multiplier.saturating_mul(I96F32::from_num(2.0)); } - let block_emission_percentage: I96F32 = I96F32::from_num(1.0) / multiplier; + let block_emission_percentage: I96F32 = I96F32::from_num(1.0).saturating_div(multiplier); // Calculate the actual emission based on the emission rate - let block_emission: I96F32 = - block_emission_percentage * I96F32::from_num(DefaultBlockEmission::::get()); + let block_emission: I96F32 = block_emission_percentage + .saturating_mul(I96F32::from_num(DefaultBlockEmission::::get())); // Convert to u64 let block_emission_u64: u64 = block_emission.to_num::(); if BlockEmission::::get() != block_emission_u64 { @@ -384,10 +395,10 @@ impl Pallet { let mut trust = vec![I64F64::from_num(0); total_networks as usize]; let mut total_stake: I64F64 = I64F64::from_num(0); for (weights, hotkey_stake) in weights.iter().zip(stake_i64) { - total_stake += hotkey_stake; + total_stake = total_stake.saturating_add(hotkey_stake); for (weight, trust_score) in weights.iter().zip(&mut trust) { if *weight > 0 { - *trust_score += hotkey_stake; + *trust_score = trust_score.saturating_add(hotkey_stake); } } } @@ -411,13 +422,15 @@ impl Pallet { let one = I64F64::from_num(1); let mut consensus = vec![I64F64::from_num(0); total_networks as usize]; for (trust_score, consensus_i) in trust.iter_mut().zip(&mut consensus) { - let shifted_trust = *trust_score - I64F64::from_num(Self::get_float_kappa(0)); // Range( -kappa, 1 - kappa ) - let temperatured_trust = shifted_trust * I64F64::from_num(Self::get_rho(0)); // Range( -rho * kappa, rho ( 1 - kappa ) ) + let shifted_trust = + trust_score.saturating_sub(I64F64::from_num(Self::get_float_kappa(0))); // Range( -kappa, 1 - kappa ) + let temperatured_trust = + shifted_trust.saturating_mul(I64F64::from_num(Self::get_rho(0))); // Range( -rho * kappa, rho ( 1 - kappa ) ) let exponentiated_trust: I64F64 = - substrate_fixed::transcendental::exp(-temperatured_trust) + substrate_fixed::transcendental::exp(temperatured_trust.saturating_neg()) .expect("temperatured_trust is on range( -rho * kappa, rho ( 1 - kappa ) )"); - *consensus_i = one / (one + exponentiated_trust); + *consensus_i = one.saturating_div(one.saturating_add(exponentiated_trust)); } log::debug!("C:\n{:?}\n", &consensus); @@ -425,7 +438,7 @@ impl Pallet { for ((emission, consensus_i), rank) in weighted_emission.iter_mut().zip(&consensus).zip(&ranks) { - *emission = *consensus_i * (*rank); + *emission = consensus_i.saturating_mul(*rank); } inplace_normalize_64(&mut weighted_emission); log::debug!("Ei64:\n{:?}\n", &weighted_emission); @@ -433,7 +446,7 @@ impl Pallet { // -- 11. Converts the normalized 64-bit fixed point rank values to u64 for the final emission calculation. let emission_as_tao: Vec = weighted_emission .iter() - .map(|v: &I64F64| *v * block_emission) + .map(|v: &I64F64| v.saturating_mul(block_emission)) .collect(); // --- 12. Converts the normalized 64-bit fixed point rank values to u64 for the final emission calculation. @@ -486,7 +499,7 @@ impl Pallet { // --- 3. Ensure that the number of registrations in this interval doesn't exceed thrice the target limit. ensure!( Self::get_registrations_this_interval(root_netuid) - < Self::get_target_registrations_per_interval(root_netuid) * 3, + < Self::get_target_registrations_per_interval(root_netuid).saturating_mul(3), Error::::TooManyRegistrationsThisInterval ); @@ -584,8 +597,8 @@ impl Pallet { } // --- 14. Update the registration counters for both the block and interval. - RegistrationsThisInterval::::mutate(root_netuid, |val| *val += 1); - RegistrationsThisBlock::::mutate(root_netuid, |val| *val += 1); + RegistrationsThisInterval::::mutate(root_netuid, |val| val.saturating_inc()); + RegistrationsThisBlock::::mutate(root_netuid, |val| val.saturating_inc()); // --- 15. Log and announce the successful registration. log::info!( @@ -812,7 +825,7 @@ impl Pallet { // We subtract one because we don't want root subnet to count towards total let mut next_available_netuid = 0; loop { - next_available_netuid += 1; + next_available_netuid.saturating_inc(); if !Self::if_subnet_exist(next_available_netuid) { log::debug!("got subnet id: {:?}", next_available_netuid); break next_available_netuid; @@ -911,7 +924,7 @@ impl Pallet { NetworkModality::::insert(netuid, 0); // --- 5. Increase total network count. - TotalNetworks::::mutate(|n| *n += 1); + TotalNetworks::::mutate(|n| n.saturating_inc()); // --- 6. Set all default values **explicitly**. Self::set_network_registration_allowed(netuid, true); @@ -1003,7 +1016,7 @@ impl Pallet { NetworksAdded::::remove(netuid); // --- 6. Decrement the network counter. - TotalNetworks::::mutate(|n| *n -= 1); + TotalNetworks::::mutate(|n| n.saturating_dec()); // --- 7. Remove various network-related storages. NetworkRegisteredAt::::remove(netuid); @@ -1067,6 +1080,7 @@ impl Pallet { SubnetOwner::::remove(netuid); } + #[allow(clippy::arithmetic_side_effects)] /// This function calculates the lock cost for a network based on the last lock amount, minimum lock cost, last lock block, and current block. /// The lock cost is calculated using the formula: /// lock_cost = (last_lock * mult) - (last_lock / lock_reduction_interval) * (current_block - last_lock_block) diff --git a/pallets/subtensor/src/serving.rs b/pallets/subtensor/src/serving.rs index 116d95982..eb7fa4369 100644 --- a/pallets/subtensor/src/serving.rs +++ b/pallets/subtensor/src/serving.rs @@ -222,7 +222,7 @@ impl Pallet { ) -> bool { let rate_limit: u64 = Self::get_serving_rate_limit(netuid); let last_serve = prev_axon_info.block; - rate_limit == 0 || last_serve == 0 || current_block - last_serve >= rate_limit + rate_limit == 0 || last_serve == 0 || current_block.saturating_sub(last_serve) >= rate_limit } pub fn prometheus_passes_rate_limit( @@ -232,7 +232,7 @@ impl Pallet { ) -> bool { let rate_limit: u64 = Self::get_serving_rate_limit(netuid); let last_serve = prev_prometheus_info.block; - rate_limit == 0 || last_serve == 0 || current_block - last_serve >= rate_limit + rate_limit == 0 || last_serve == 0 || current_block.saturating_sub(last_serve) >= rate_limit } pub fn has_axon_info(netuid: u16, hotkey: &T::AccountId) -> bool { diff --git a/pallets/subtensor/src/staking.rs b/pallets/subtensor/src/staking.rs index 08b65b8a7..7c3328396 100644 --- a/pallets/subtensor/src/staking.rs +++ b/pallets/subtensor/src/staking.rs @@ -346,7 +346,7 @@ impl Pallet { Self::set_stakes_this_interval_for_coldkey_hotkey( &coldkey, &hotkey, - stakes_this_interval + 1, + stakes_this_interval.saturating_add(1), block, ); log::info!( @@ -452,7 +452,7 @@ impl Pallet { Self::set_stakes_this_interval_for_coldkey_hotkey( &coldkey, &hotkey, - unstakes_this_interval + 1, + unstakes_this_interval.saturating_add(1), block, ); log::info!( @@ -530,7 +530,7 @@ impl Pallet { TotalHotkeyColdkeyStakesThisInterval::::get(coldkey, hotkey); // Calculate the block number after which the stakes for the hotkey should be reset. - let block_to_reset_after = block_last_staked_at + stake_interval; + let block_to_reset_after = block_last_staked_at.saturating_add(stake_interval); // If the current block number is beyond the reset point, // it indicates the end of the staking interval for the hotkey. diff --git a/pallets/subtensor/src/subnet_info.rs b/pallets/subtensor/src/subnet_info.rs index cf6b66aea..ef92b2da6 100644 --- a/pallets/subtensor/src/subnet_info.rs +++ b/pallets/subtensor/src/subnet_info.rs @@ -117,7 +117,7 @@ impl Pallet { } let mut subnets_info = Vec::>>::new(); - for netuid_ in 0..(max_netuid + 1) { + for netuid_ in 0..=max_netuid { if subnet_netuids.contains(&netuid_) { subnets_info.push(Self::get_subnet_info(netuid_)); } diff --git a/pallets/subtensor/src/uids.rs b/pallets/subtensor/src/uids.rs index 4ae2c24de..fff358f1c 100644 --- a/pallets/subtensor/src/uids.rs +++ b/pallets/subtensor/src/uids.rs @@ -59,7 +59,7 @@ impl Pallet { ); // 2. Get and increase the uid count. - SubnetworkN::::insert(netuid, next_uid + 1); + SubnetworkN::::insert(netuid, next_uid.saturating_add(1)); // 3. Expand Yuma Consensus with new position. Rank::::mutate(netuid, |v| v.push(0)); @@ -126,11 +126,7 @@ impl Pallet { /// Return the total number of subnetworks available on the chain. /// pub fn get_number_of_subnets() -> u16 { - let mut number_of_subnets: u16 = 0; - for (_, _) in as IterableStorageMap>::iter() { - number_of_subnets += 1; - } - number_of_subnets + as IterableStorageMap>::iter().count() as u16 } /// Return a list of all networks a hotkey is registered on. diff --git a/pallets/subtensor/src/utils.rs b/pallets/subtensor/src/utils.rs index 54b7818c9..546875b27 100644 --- a/pallets/subtensor/src/utils.rs +++ b/pallets/subtensor/src/utils.rs @@ -291,7 +291,7 @@ impl Pallet { return false; } - current_block - prev_tx_block <= rate_limit + current_block.saturating_sub(prev_tx_block) <= rate_limit } pub fn exceeds_tx_delegate_take_rate_limit(prev_tx_block: u64, current_block: u64) -> bool { let rate_limit: u64 = Self::get_tx_delegate_take_rate_limit(); @@ -299,7 +299,7 @@ impl Pallet { return false; } - current_block - prev_tx_block <= rate_limit + current_block.saturating_sub(prev_tx_block) <= rate_limit } // ======================== diff --git a/pallets/subtensor/src/weights.rs b/pallets/subtensor/src/weights.rs index 72c811f80..ec06182b7 100644 --- a/pallets/subtensor/src/weights.rs +++ b/pallets/subtensor/src/weights.rs @@ -325,7 +325,8 @@ impl Pallet { if last_set_weights == 0 { return true; } // (Storage default) Never set weights. - return (current_block - last_set_weights) >= Self::get_weights_set_rate_limit(netuid); + return current_block.saturating_sub(last_set_weights) + >= Self::get_weights_set_rate_limit(netuid); } // --- 3. Non registered peers cant pass. false @@ -398,6 +399,7 @@ impl Pallet { false } + #[allow(clippy::arithmetic_side_effects)] /// Returns normalized the passed positive integer weights so that they sum to u16 max value. pub fn normalize_weights(mut weights: Vec) -> Vec { let sum: u64 = weights.iter().map(|x| *x as u64).sum(); @@ -405,7 +407,9 @@ impl Pallet { return weights; } weights.iter_mut().for_each(|x| { - *x = (*x as u64 * u16::max_value() as u64 / sum) as u16; + *x = (*x as u64) + .saturating_mul(u16::max_value() as u64) + .saturating_div(sum) as u16; }); weights } @@ -448,6 +452,7 @@ impl Pallet { uids.len() <= subnetwork_n as usize } + #[allow(clippy::arithmetic_side_effects)] pub fn can_commit(netuid: u16, who: &T::AccountId) -> bool { if let Some((_hash, commit_block)) = WeightCommits::::get(netuid, who) { let interval: u64 = Self::get_commit_reveal_weights_interval(netuid); @@ -456,11 +461,12 @@ impl Pallet { } let current_block: u64 = Self::get_current_block_as_u64(); - let interval_start: u64 = current_block - (current_block % interval); - let last_commit_interval_start: u64 = commit_block - (commit_block % interval); + let interval_start: u64 = current_block.saturating_sub(current_block % interval); + let last_commit_interval_start: u64 = + commit_block.saturating_sub(commit_block % interval); // Allow commit if we're within the interval bounds - if current_block <= interval_start + interval + if current_block <= interval_start.saturating_add(interval) && interval_start > last_commit_interval_start { return true; @@ -472,19 +478,20 @@ impl Pallet { } } + #[allow(clippy::arithmetic_side_effects)] pub fn is_reveal_block_range(netuid: u16, commit_block: u64) -> bool { let interval: u64 = Self::get_commit_reveal_weights_interval(netuid); if interval == 0 { return true; //prevent division by 0 } - let commit_interval_start: u64 = commit_block - (commit_block % interval); // Find the start of the interval in which the commit occurred - let reveal_interval_start: u64 = commit_interval_start + interval; // Start of the next interval after the commit interval + let commit_interval_start: u64 = commit_block.saturating_sub(commit_block % interval); // Find the start of the interval in which the commit occurred + let reveal_interval_start: u64 = commit_interval_start.saturating_add(interval); // Start of the next interval after the commit interval let current_block: u64 = Self::get_current_block_as_u64(); // Allow reveal if the current block is within the interval following the commit's interval if current_block >= reveal_interval_start - && current_block < reveal_interval_start + interval + && current_block < reveal_interval_start.saturating_add(interval) { return true; } diff --git a/pallets/subtensor/tests/block_step.rs b/pallets/subtensor/tests/block_step.rs index eb97fe692..cc6c88092 100644 --- a/pallets/subtensor/tests/block_step.rs +++ b/pallets/subtensor/tests/block_step.rs @@ -1,3 +1,5 @@ +#![allow(clippy::unwrap_used)] + mod mock; use frame_support::assert_ok; use frame_system::Config; @@ -5,7 +7,6 @@ use mock::*; use sp_core::U256; #[test] -#[allow(clippy::unwrap_used)] fn test_loaded_emission() { new_test_ext(1).execute_with(|| { let n: u16 = 100; diff --git a/pallets/subtensor/tests/difficulty.rs b/pallets/subtensor/tests/difficulty.rs index 24552261d..05238bc43 100644 --- a/pallets/subtensor/tests/difficulty.rs +++ b/pallets/subtensor/tests/difficulty.rs @@ -1,3 +1,5 @@ +#![allow(clippy::unwrap_used)] + use crate::mock::*; mod mock; use sp_core::U256; diff --git a/pallets/subtensor/tests/epoch.rs b/pallets/subtensor/tests/epoch.rs index 0bfd11ba4..78ed7b145 100644 --- a/pallets/subtensor/tests/epoch.rs +++ b/pallets/subtensor/tests/epoch.rs @@ -1,3 +1,9 @@ +#![allow( + clippy::arithmetic_side_effects, + clippy::indexing_slicing, + clippy::unwrap_used +)] + use crate::mock::*; use frame_support::assert_ok; use frame_system::Config; diff --git a/pallets/subtensor/tests/migration.rs b/pallets/subtensor/tests/migration.rs index 2f634d7c0..c921124f4 100644 --- a/pallets/subtensor/tests/migration.rs +++ b/pallets/subtensor/tests/migration.rs @@ -1,3 +1,5 @@ +#![allow(clippy::unwrap_used)] + mod mock; use frame_support::assert_ok; use frame_system::Config; diff --git a/pallets/subtensor/tests/mock.rs b/pallets/subtensor/tests/mock.rs index 9995acf84..d772a8d47 100644 --- a/pallets/subtensor/tests/mock.rs +++ b/pallets/subtensor/tests/mock.rs @@ -1,7 +1,9 @@ -use frame_support::derive_impl; -use frame_support::dispatch::DispatchResultWithPostInfo; +#![allow(clippy::arithmetic_side_effects, clippy::unwrap_used)] + use frame_support::{ - assert_ok, parameter_types, + assert_ok, derive_impl, + dispatch::DispatchResultWithPostInfo, + parameter_types, traits::{Everything, Hooks}, weights, }; diff --git a/pallets/subtensor/tests/registration.rs b/pallets/subtensor/tests/registration.rs index 5ee941f26..0da10bc48 100644 --- a/pallets/subtensor/tests/registration.rs +++ b/pallets/subtensor/tests/registration.rs @@ -1,3 +1,5 @@ +#![allow(clippy::unwrap_used)] + use frame_support::traits::Currency; use crate::mock::*; diff --git a/pallets/subtensor/tests/root.rs b/pallets/subtensor/tests/root.rs index 7958c9c81..7c6622670 100644 --- a/pallets/subtensor/tests/root.rs +++ b/pallets/subtensor/tests/root.rs @@ -1,3 +1,5 @@ +#![allow(clippy::indexing_slicing, clippy::unwrap_used)] + use crate::mock::*; use frame_support::{assert_err, assert_ok}; use frame_system::Config; diff --git a/pallets/subtensor/tests/senate.rs b/pallets/subtensor/tests/senate.rs index a21fbce01..ac020ae04 100644 --- a/pallets/subtensor/tests/senate.rs +++ b/pallets/subtensor/tests/senate.rs @@ -1,3 +1,5 @@ +#![allow(clippy::unwrap_used)] + mod mock; use mock::*; diff --git a/pallets/subtensor/tests/staking.rs b/pallets/subtensor/tests/staking.rs index ffe9de27a..766b3a495 100644 --- a/pallets/subtensor/tests/staking.rs +++ b/pallets/subtensor/tests/staking.rs @@ -1,3 +1,5 @@ +#![allow(clippy::unwrap_used)] + use frame_support::{assert_err, assert_noop, assert_ok, traits::Currency}; use frame_system::Config; mod mock; diff --git a/pallets/subtensor/tests/uids.rs b/pallets/subtensor/tests/uids.rs index b8a969943..82adc6b8a 100644 --- a/pallets/subtensor/tests/uids.rs +++ b/pallets/subtensor/tests/uids.rs @@ -1,3 +1,5 @@ +#![allow(clippy::unwrap_used)] + use crate::mock::*; use frame_support::assert_ok; use frame_system::Config; diff --git a/pallets/subtensor/tests/weights.rs b/pallets/subtensor/tests/weights.rs index bb7f11908..feb183492 100644 --- a/pallets/subtensor/tests/weights.rs +++ b/pallets/subtensor/tests/weights.rs @@ -1,3 +1,5 @@ +#![allow(clippy::indexing_slicing)] + mod mock; use frame_support::{ assert_err, assert_ok, diff --git a/runtime/src/check_nonce.rs b/runtime/src/check_nonce.rs index e6e992ccf..4000e2192 100644 --- a/runtime/src/check_nonce.rs +++ b/runtime/src/check_nonce.rs @@ -8,6 +8,7 @@ use sp_runtime::{ InvalidTransaction, TransactionLongevity, TransactionValidity, TransactionValidityError, ValidTransaction, }, + Saturating, }; use sp_std::vec; @@ -82,7 +83,7 @@ where } .into()); } - account.nonce += T::Nonce::one(); + account.nonce.saturating_inc(); frame_system::Account::::insert(who, account); Ok(()) } @@ -111,7 +112,7 @@ where let provides = vec![Encode::encode(&(who, self.0))]; let requires = if account.nonce < self.0 { - vec![Encode::encode(&(who, self.0 - One::one()))] + vec![Encode::encode(&(who, self.0.saturating_sub(One::one())))] } else { vec![] }; diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index f9f8d599f..23c5d6e5f 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -1,6 +1,8 @@ #![cfg_attr(not(feature = "std"), no_std)] // `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. #![recursion_limit = "256"] +// Some arithmetic operations can't use the saturating equivalent, such as the PerThing types +#![allow(clippy::arithmetic_side_effects)] // Make the WASM binary available. #[cfg(feature = "std")] @@ -96,7 +98,9 @@ pub type Nonce = u32; pub const fn deposit(items: u32, bytes: u32) -> Balance { pub const ITEMS_FEE: Balance = 2_000 * 10_000; pub const BYTES_FEE: Balance = 100 * 10_000; - items as Balance * ITEMS_FEE + bytes as Balance * BYTES_FEE + (items as Balance) + .saturating_mul(ITEMS_FEE) + .saturating_add((bytes as Balance).saturating_mul(BYTES_FEE)) } // Opaque types. These are used by the CLI to instantiate machinery that don't need to know @@ -662,7 +666,11 @@ impl PrivilegeCmp for OriginPrivilegeCmp { r_yes_votes, r_count, )), // Equivalent to (l_yes_votes / l_count).cmp(&(r_yes_votes / r_count)) - ) => Some((l_yes_votes * r_count).cmp(&(r_yes_votes * l_count))), + ) => Some( + l_yes_votes + .saturating_mul(*r_count) + .cmp(&r_yes_votes.saturating_mul(*l_count)), + ), // For every other origin we don't care, as they are not used for `ScheduleOrigin`. _ => None, } @@ -1461,6 +1469,7 @@ impl_runtime_apis! { #[cfg(feature = "try-runtime")] impl frame_try_runtime::TryRuntime for Runtime { + #[allow(clippy::unwrap_used)] fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to // have a backtrace here. If any of the pre/post migration checks fail, we shall stop diff --git a/runtime/tests/metadata.rs b/runtime/tests/metadata.rs index 692676d79..975c96227 100644 --- a/runtime/tests/metadata.rs +++ b/runtime/tests/metadata.rs @@ -1,3 +1,5 @@ +#![allow(clippy::indexing_slicing)] + use frame_metadata::RuntimeMetadata; use node_subtensor_runtime::Runtime; use scale_info::TypeDef; diff --git a/runtime/tests/pallet_proxy.rs b/runtime/tests/pallet_proxy.rs index f04fda9f2..796dfc471 100644 --- a/runtime/tests/pallet_proxy.rs +++ b/runtime/tests/pallet_proxy.rs @@ -1,3 +1,5 @@ +#![allow(clippy::unwrap_used)] + use codec::Encode; use frame_support::{assert_ok, traits::InstanceFilter, BoundedVec}; use node_subtensor_runtime::{ From 68ab3359cb9af7d9b46ea22bae618fedd63a6d3d Mon Sep 17 00:00:00 2001 From: Sam Johnson Date: Wed, 19 Jun 2024 12:15:15 -0400 Subject: [PATCH 02/51] appease clippy --- pallets/subtensor/src/math.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pallets/subtensor/src/math.rs b/pallets/subtensor/src/math.rs index f7784ea1c..40ee7ebe8 100644 --- a/pallets/subtensor/src/math.rs +++ b/pallets/subtensor/src/math.rs @@ -252,7 +252,7 @@ pub fn inplace_normalize(x: &mut [I32F32]) { if x_sum == I32F32::from_num(0.0_f32) { return; } - x.into_iter() + x.iter_mut() .for_each(|value| *value = value.saturating_div(x_sum)); } @@ -262,7 +262,7 @@ pub fn inplace_normalize_using_sum(x: &mut [I32F32], x_sum: I32F32) { if x_sum == I32F32::from_num(0.0_f32) { return; } - x.into_iter() + x.iter_mut() .for_each(|value| *value = value.saturating_div(x_sum)); } @@ -273,7 +273,7 @@ pub fn inplace_normalize_64(x: &mut [I64F64]) { if x_sum == I64F64::from_num(0) { return; } - x.into_iter() + x.iter_mut() .for_each(|value| *value = value.saturating_div(x_sum)); } @@ -311,7 +311,7 @@ pub fn inplace_row_normalize(x: &mut [Vec]) { for row in x { let row_sum: I32F32 = row.iter().sum(); if row_sum > I32F32::from_num(0.0_f32) { - row.into_iter() + row.iter_mut() .for_each(|x_ij: &mut I32F32| *x_ij = x_ij.saturating_div(row_sum)); } } @@ -622,7 +622,7 @@ pub fn row_hadamard(matrix: &[Vec], vector: &[I32F32]) -> Vec Date: Fri, 21 Jun 2024 12:17:13 -0400 Subject: [PATCH 03/51] bump CI From f339e8e90c284862df2fa496d079a7c8cd95e1b8 Mon Sep 17 00:00:00 2001 From: Sam Johnson Date: Fri, 21 Jun 2024 14:39:49 -0400 Subject: [PATCH 04/51] bump CI From 9f09d9493bd3feb311e560536766ab470a98849e Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Fri, 21 Jun 2024 23:21:52 +0400 Subject: [PATCH 05/51] chore: clippy --- pallets/subtensor/src/root.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pallets/subtensor/src/root.rs b/pallets/subtensor/src/root.rs index ad764dc6a..8eeb9aa9a 100644 --- a/pallets/subtensor/src/root.rs +++ b/pallets/subtensor/src/root.rs @@ -577,8 +577,8 @@ impl Pallet { } // --- 15. Update the registration counters for both the block and interval. - RegistrationsThisInterval::::mutate(root_netuid, |val| *val += 1); - RegistrationsThisBlock::::mutate(root_netuid, |val| *val += 1); + RegistrationsThisInterval::::mutate(root_netuid, |val| val.saturating_inc()); + RegistrationsThisBlock::::mutate(root_netuid, |val| val.saturating_inc()); // --- 16. Log and announce the successful registration. log::info!( From a4f9ad71cc9f328a8d6205479bb9a269dbd70e64 Mon Sep 17 00:00:00 2001 From: Sam Johnson Date: Fri, 21 Jun 2024 16:25:18 -0400 Subject: [PATCH 06/51] re-generate Cargo.lock after merge --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index ceebcb9ae..7ea7732d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9142,7 +9142,7 @@ dependencies = [ "ahash 0.8.11", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.67", ] [[package]] From 74e1bebad902cf0f0245f561c85410b9fcbb1ae4 Mon Sep 17 00:00:00 2001 From: Sam Johnson Date: Fri, 21 Jun 2024 16:37:21 -0400 Subject: [PATCH 07/51] fix --- pallets/registry/src/types.rs | 2 +- pallets/subtensor/src/subnet_info.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pallets/registry/src/types.rs b/pallets/registry/src/types.rs index 3057aeaf4..030df6468 100644 --- a/pallets/registry/src/types.rs +++ b/pallets/registry/src/types.rs @@ -279,7 +279,7 @@ impl TypeInfo for IdentityFields { /// /// NOTE: This should be stored at the end of the storage item to facilitate the addition of extra /// fields in a backwards compatible way through a specialized `Decode` impl. -#[freeze_struct("70b183c8753429f1")] +#[freeze_struct("9d47309f8e379957")] #[derive( CloneNoBound, Encode, Decode, Eq, MaxEncodedLen, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo, )] diff --git a/pallets/subtensor/src/subnet_info.rs b/pallets/subtensor/src/subnet_info.rs index e2e7e0b71..bb6f5d4c8 100644 --- a/pallets/subtensor/src/subnet_info.rs +++ b/pallets/subtensor/src/subnet_info.rs @@ -4,7 +4,7 @@ use frame_support::storage::IterableStorageMap; extern crate alloc; use codec::Compact; -#[freeze_struct("4d3e8df520bbc960")] +#[freeze_struct("fe79d58173da662a")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug)] pub struct SubnetInfo { netuid: Compact, From ced39fdf60baf49259071723f5bd8b983f42936d Mon Sep 17 00:00:00 2001 From: Liam Date: Sun, 23 Jun 2024 14:37:20 +0300 Subject: [PATCH 08/51] override default pages to 60k --- node/src/command.rs | 50 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/node/src/command.rs b/node/src/command.rs index 23674ad17..2423d1456 100644 --- a/node/src/command.rs +++ b/node/src/command.rs @@ -17,7 +17,7 @@ use sp_runtime::traits::HashingFor; use node_subtensor_runtime::Block; use sc_cli::SubstrateCli; -use sc_service::PartialComponents; +use sc_service::{Configuration, PartialComponents}; impl SubstrateCli for Cli { fn impl_name() -> String { @@ -209,8 +209,56 @@ pub fn run() -> sc_cli::Result<()> { None => { let runner = cli.create_runner(&cli.run)?; runner.run_node_until_exit(|config| async move { + let config = override_default_heap_pages(config, 60_000); service::new_full(config).map_err(sc_cli::Error::Service) }) } } } + +/// Override default heap pages +fn override_default_heap_pages(config: Configuration, pages: u64) -> Configuration { + Configuration { + default_heap_pages: Some(pages), + impl_name: config.impl_name, + impl_version: config.impl_version, + role: config.role, + tokio_handle: config.tokio_handle, + transaction_pool: config.transaction_pool, + network: config.network, + keystore: config.keystore, + database: config.database, + trie_cache_maximum_size: config.trie_cache_maximum_size, + state_pruning: config.state_pruning, + blocks_pruning: config.blocks_pruning, + chain_spec: config.chain_spec, + wasm_method: config.wasm_method, + wasm_runtime_overrides: config.wasm_runtime_overrides, + rpc_addr: config.rpc_addr, + rpc_max_connections: config.rpc_max_connections, + rpc_cors: config.rpc_cors, + rpc_methods: config.rpc_methods, + rpc_max_request_size: config.rpc_max_request_size, + rpc_max_response_size: config.rpc_max_response_size, + rpc_id_provider: config.rpc_id_provider, + rpc_max_subs_per_conn: config.rpc_max_subs_per_conn, + rpc_port: config.rpc_port, + rpc_message_buffer_capacity: config.rpc_message_buffer_capacity, + rpc_batch_config: config.rpc_batch_config, + rpc_rate_limit: config.rpc_rate_limit, + prometheus_config: config.prometheus_config, + telemetry_endpoints: config.telemetry_endpoints, + offchain_worker: config.offchain_worker, + force_authoring: config.force_authoring, + disable_grandpa: config.disable_grandpa, + dev_key_seed: config.dev_key_seed, + tracing_targets: config.tracing_targets, + tracing_receiver: config.tracing_receiver, + max_runtime_instances: config.max_runtime_instances, + announce_block: config.announce_block, + data_path: config.data_path, + base_path: config.base_path, + informant_output_format: config.informant_output_format, + runtime_cache_size: config.runtime_cache_size, + } +} From f5dff31a751a24dfe19fd172500980a787cd67f5 Mon Sep 17 00:00:00 2001 From: Liam Date: Mon, 24 Jun 2024 13:26:54 +0300 Subject: [PATCH 09/51] update doc --- docs/running-subtensor-locally.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/running-subtensor-locally.md b/docs/running-subtensor-locally.md index 4d827d858..089f4d30a 100644 --- a/docs/running-subtensor-locally.md +++ b/docs/running-subtensor-locally.md @@ -174,7 +174,7 @@ You can now run the public subtensor node either as a lite node or as an archive To run a lite node connected to the mainchain, execute the below command (note the `--sync=warp` flag which runs the subtensor node in lite mode): ```bash title="With --sync=warp setting, for lite node" -./target/release/node-subtensor --chain raw_spec.json --base-path /tmp/blockchain --sync=warp --execution wasm --wasm-execution compiled --port 30333 --max-runtime-instances 32 --rpc-max-response-size 2048 --rpc-cors all --rpc-port 9944 --bootnodes /ip4/13.58.175.193/tcp/30333/p2p/12D3KooWDe7g2JbNETiKypcKT1KsCEZJbTzEHCn8hpd4PHZ6pdz5 --no-mdns --in-peers 8000 --out-peers 8000 --prometheus-external --rpc-external +./target/release/node-subtensor --chain raw_spec.json --base-path /tmp/blockchain --sync=warp --port 30333 --max-runtime-instances 32 --rpc-max-response-size 2048 --rpc-cors all --rpc-port 9944 --bootnodes /ip4/13.58.175.193/tcp/30333/p2p/12D3KooWDe7g2JbNETiKypcKT1KsCEZJbTzEHCn8hpd4PHZ6pdz5 --no-mdns --in-peers 8000 --out-peers 8000 --prometheus-external --rpc-external ``` ### Archive node on mainchain @@ -182,7 +182,7 @@ To run a lite node connected to the mainchain, execute the below command (note t To run an archive node connected to the mainchain, execute the below command (note the `--sync=full` which syncs the node to the full chain and `--pruning archive` flags, which disables the node's automatic pruning of older historical data): ```bash title="With --sync=full and --pruning archive setting, for archive node" -./target/release/node-subtensor --chain raw_spec.json --base-path /tmp/blockchain --sync=full --pruning archive --execution wasm --wasm-execution compiled --port 30333 --max-runtime-instances 32 --rpc-max-response-size 2048 --rpc-cors all --rpc-port 9944 --bootnodes /ip4/13.58.175.193/tcp/30333/p2p/12D3KooWDe7g2JbNETiKypcKT1KsCEZJbTzEHCn8hpd4PHZ6pdz5 --no-mdns --in-peers 8000 --out-peers 8000 --prometheus-external --rpc-external +./target/release/node-subtensor --chain raw_spec.json --base-path /tmp/blockchain --sync=full --pruning archive --port 30333 --max-runtime-instances 32 --rpc-max-response-size 2048 --rpc-cors all --rpc-port 9944 --bootnodes /ip4/13.58.175.193/tcp/30333/p2p/12D3KooWDe7g2JbNETiKypcKT1KsCEZJbTzEHCn8hpd4PHZ6pdz5 --no-mdns --in-peers 8000 --out-peers 8000 --prometheus-external --rpc-external ``` ### Lite node on testchain @@ -190,7 +190,7 @@ To run an archive node connected to the mainchain, execute the below command (no To run a lite node connected to the testchain, execute the below command: ```bash title="With bootnodes set to testnet and --sync=warp setting, for lite node." -./target/release/node-subtensor --chain raw_testspec.json --base-path /tmp/blockchain --sync=warp --execution wasm --wasm-execution compiled --port 30333 --max-runtime-instances 32 --rpc-max-response-size 2048 --rpc-cors all --rpc-port 9944 --bootnodes /dns/bootnode.test.finney.opentensor.ai/tcp/30333/p2p/12D3KooWPM4mLcKJGtyVtkggqdG84zWrd7Rij6PGQDoijh1X86Vr --no-mdns --in-peers 8000 --out-peers 8000 --prometheus-external --rpc-external +./target/release/node-subtensor --chain raw_testspec.json --base-path /tmp/blockchain --sync=warp --port 30333 --max-runtime-instances 32 --rpc-max-response-size 2048 --rpc-cors all --rpc-port 9944 --bootnodes /dns/bootnode.test.finney.opentensor.ai/tcp/30333/p2p/12D3KooWPM4mLcKJGtyVtkggqdG84zWrd7Rij6PGQDoijh1X86Vr --no-mdns --in-peers 8000 --out-peers 8000 --prometheus-external --rpc-external ``` ### Archive node on testchain @@ -198,8 +198,9 @@ To run a lite node connected to the testchain, execute the below command: To run an archive node connected to the testchain, execute the below command: ```bash title="With bootnodes set to testnet and --sync=full and --pruning archive setting, for archive node" -./target/release/node-subtensor --chain raw_testspec.json --base-path /tmp/blockchain --sync=full --pruning archive --execution wasm --wasm-execution compiled --port 30333 --max-runtime-instances 32 --rpc-max-response-size 2048 --rpc-cors all --rpc-port 9944 --bootnodes /dns/bootnode.test.finney.opentensor.ai/tcp/30333/p2p/12D3KooWPM4mLcKJGtyVtkggqdG84zWrd7Rij6PGQDoijh1X86Vr --no-mdns --in-peers 8000 --out-peers 8000 --prometheus-external --rpc-external +./target/release/node-subtensor --chain raw_testspec.json --base-path /tmp/blockchain --sync=full --pruning archive --port 30333 --max-runtime-instances 32 --rpc-max-response-size 2048 --rpc-cors all --rpc-port 9944 --bootnodes /dns/bootnode.test.finney.opentensor.ai/tcp/30333/p2p/12D3KooWPM4mLcKJGtyVtkggqdG84zWrd7Rij6PGQDoijh1X86Vr --no-mdns --in-peers 8000 --out-peers 8000 --prometheus-external --rpc-external ``` ## Running on cloud + We have not tested these installation scripts on any cloud service. In addition, if you are using Runpod cloud service, then note that this service is already [containerized](https://docs.runpod.io/pods/overview). Hence, the only option available to you is to compile from the source, as described in the above [Method 2: Using Source Code](#method-2-using-source-code) section. Note that these scripts have not been tested on Runpod. From abc7798173d1bffaf3a82a873c449e10ac74b751 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Tue, 25 Jun 2024 00:27:30 +0400 Subject: [PATCH 10/51] clippy --- pallets/subtensor/src/epoch.rs | 29 ++++++---------- pallets/subtensor/src/math.rs | 52 +++++++++++++++++----------- pallets/subtensor/src/subnet_info.rs | 2 +- pallets/subtensor/src/utils.rs | 6 ++-- pallets/subtensor/tests/math.rs | 3 ++ 5 files changed, 50 insertions(+), 42 deletions(-) diff --git a/pallets/subtensor/src/epoch.rs b/pallets/subtensor/src/epoch.rs index 775e082ac..22331d206 100644 --- a/pallets/subtensor/src/epoch.rs +++ b/pallets/subtensor/src/epoch.rs @@ -32,7 +32,7 @@ impl Pallet { // Inactive mask. let inactive: Vec = last_update .iter() - .map(|updated| updated.saturating_add(activity_cutoff) < current_block) + .map(|updated| *updated + activity_cutoff < current_block) .collect(); log::trace!("Inactive:\n{:?}\n", inactive.clone()); @@ -176,11 +176,6 @@ impl Pallet { // Compute the Exponential Moving Average (EMA) of bonds. let mut ema_bonds = Self::compute_ema_bonds(netuid, consensus.clone(), bonds_delta, bonds); - // Compute bonds moving average. - let bonds_moving_average: I64F64 = - I64F64::from_num(Self::get_bonds_moving_average(netuid)) / I64F64::from_num(1_000_000); - let alpha: I32F32 = I32F32::from_num(1) - I32F32::from_num(bonds_moving_average); - let mut ema_bonds: Vec> = mat_ema(&bonds_delta, &bonds, alpha); inplace_col_normalize(&mut ema_bonds); // sum_i b_ij = 1 log::trace!("emaB:\n{:?}\n", &ema_bonds); @@ -194,13 +189,11 @@ impl Pallet { // ================================= // Compute emission scores. - - // Compute normalized emission scores. range: I32F32(0, 1) // Compute normalized emission scores. range: I32F32(0, 1) let combined_emission: Vec = incentive .iter() .zip(dividends.clone()) - .map(|(ii, di)| ii.saturating_add(di)) + .map(|(ii, di)| ii + di) .collect(); let emission_sum: I32F32 = combined_emission.iter().sum(); @@ -230,7 +223,7 @@ impl Pallet { let server_emission: Vec = normalized_server_emission .iter() - .map(|se: &I32F32| I96F32::from_num(*se).saturating_mul(float_rao_emission)) + .map(|se: &I32F32| I96F32::from_num(*se) * float_rao_emission) .collect(); let server_emission: Vec = server_emission .iter() @@ -239,7 +232,7 @@ impl Pallet { let validator_emission: Vec = normalized_validator_emission .iter() - .map(|ve: &I32F32| I96F32::from_num(*ve).saturating_mul(float_rao_emission)) + .map(|ve: &I32F32| I96F32::from_num(*ve) * float_rao_emission) .collect(); let validator_emission: Vec = validator_emission .iter() @@ -249,7 +242,7 @@ impl Pallet { // Used only to track combined emission in the storage. let combined_emission: Vec = normalized_combined_emission .iter() - .map(|ce: &I32F32| I96F32::from_num(*ce).saturating_mul(float_rao_emission)) + .map(|ce: &I32F32| I96F32::from_num(*ce) * float_rao_emission) .collect(); let combined_emission: Vec = combined_emission .iter() @@ -378,7 +371,7 @@ impl Pallet { // Inactive mask. let inactive: Vec = last_update .iter() - .map(|updated| updated.saturating_add(activity_cutoff) < current_block) + .map(|updated| *updated + activity_cutoff < current_block) .collect(); log::trace!("Inactive: {:?}", inactive.clone()); @@ -558,7 +551,7 @@ impl Pallet { let combined_emission: Vec = incentive .iter() .zip(dividends.clone()) - .map(|(ii, di)| ii.saturating_add(di)) + .map(|(ii, di)| ii + di) .collect(); let emission_sum: I32F32 = combined_emission.iter().sum(); @@ -588,7 +581,7 @@ impl Pallet { let server_emission: Vec = normalized_server_emission .iter() - .map(|se: &I32F32| I96F32::from_num(*se).saturating_mul(float_rao_emission)) + .map(|se: &I32F32| I96F32::from_num(*se) * float_rao_emission) .collect(); let server_emission: Vec = server_emission .iter() @@ -597,7 +590,7 @@ impl Pallet { let validator_emission: Vec = normalized_validator_emission .iter() - .map(|ve: &I32F32| I96F32::from_num(*ve).saturating_mul(float_rao_emission)) + .map(|ve: &I32F32| I96F32::from_num(*ve) * float_rao_emission) .collect(); let validator_emission: Vec = validator_emission .iter() @@ -607,7 +600,7 @@ impl Pallet { // Only used to track emission in storage. let combined_emission: Vec = normalized_combined_emission .iter() - .map(|ce: &I32F32| I96F32::from_num(*ce).saturating_mul(float_rao_emission)) + .map(|ce: &I32F32| I96F32::from_num(*ce) * float_rao_emission) .collect(); let combined_emission: Vec = combined_emission .iter() @@ -713,7 +706,7 @@ impl Pallet { I32F32::from_num(Self::get_rho(netuid)) } pub fn get_float_kappa(netuid: u16) -> I32F32 { - I32F32::from_num(Self::get_kappa(netuid)).saturating_div(I32F32::from_num(u16::MAX)) + I32F32::from_num(Self::get_kappa(netuid)) / I32F32::from_num(u16::MAX) } pub fn get_normalized_stake(netuid: u16) -> Vec { diff --git a/pallets/subtensor/src/math.rs b/pallets/subtensor/src/math.rs index 3bdae9377..88078821e 100644 --- a/pallets/subtensor/src/math.rs +++ b/pallets/subtensor/src/math.rs @@ -3,7 +3,7 @@ use crate::alloc::borrow::ToOwned; #[allow(unused)] use num_traits::float::Float; -use sp_runtime::traits::CheckedAdd; +use sp_runtime::traits::{CheckedAdd, Saturating}; use sp_std::cmp::Ordering; use sp_std::vec; use substrate_fixed::transcendental::{exp, ln}; @@ -1200,8 +1200,8 @@ pub fn mat_ema_alpha_vec_sparse( for (j, value) in new[i].iter() { // Retrieve the alpha value for the current column. let alpha_val: I32F32 = alpha[*j as usize]; - // Compute the EMA component for the new value. - row[*j as usize] = alpha_val * value; + // Compute the EMA component for the new value using saturating multiplication. + row[*j as usize] = alpha_val.saturating_mul(*value); log::trace!( "new[{}][{}] * alpha[{}] = {} * {} = {}", i, @@ -1217,10 +1217,11 @@ pub fn mat_ema_alpha_vec_sparse( for (j, value) in old[i].iter() { // Retrieve the alpha value for the current column. let alpha_val: I32F32 = alpha[*j as usize]; - // Calculate the complement of the alpha value. - let one_minus_alpha: I32F32 = I32F32::from_num(1.0) - alpha_val; - // Compute the EMA component for the old value and add it to the row. - row[*j as usize] += one_minus_alpha * value; + // Calculate the complement of the alpha value using saturating subtraction. + let one_minus_alpha: I32F32 = I32F32::from_num(1.0).saturating_sub(alpha_val); + // Compute the EMA component for the old value and add it to the row using saturating operations. + row[*j as usize] = + row[*j as usize].saturating_add(one_minus_alpha.saturating_mul(*value)); log::trace!( "old[{}][{}] * (1 - alpha[{}]) = {} * {} = {}", i, @@ -1228,7 +1229,7 @@ pub fn mat_ema_alpha_vec_sparse( j, value, one_minus_alpha, - one_minus_alpha * value + one_minus_alpha.saturating_mul(*value) ); } @@ -1244,7 +1245,6 @@ pub fn mat_ema_alpha_vec_sparse( // Return the computed EMA sparse matrix. result } - /// Return matrix exponential moving average: `alpha_j * a_ij + one_minus_alpha_j * b_ij`. /// `alpha_` is the EMA coefficient passed as a vector per column. #[allow(dead_code)] @@ -1263,7 +1263,8 @@ pub fn mat_ema_alpha_vec( assert!(new[0].len() == alpha.len()); // Initialize the result matrix with zeros, having the same dimensions as the new matrix. - let mut result: Vec> = vec![vec![I32F32::from_num(0.0); new[0].len()]; new.len()]; + let mut result: Vec> = + vec![vec![I32F32::from_num(0.0); new.first().map_or(0, |row| row.len())]; new.len()]; // Iterate over each row of the matrices. for (i, (new_row, old_row)) in new.iter().zip(old).enumerate() { @@ -1272,11 +1273,13 @@ pub fn mat_ema_alpha_vec( // Iterate over each column of the current row. for (j, &alpha_val) in alpha.iter().enumerate().take(new_row.len()) { - // Calculate the complement of the alpha value. - let one_minus_alpha = I32F32::from_num(1.0) - alpha_val; + // Calculate the complement of the alpha value using saturating subtraction. + let one_minus_alpha = I32F32::from_num(1.0).saturating_sub(alpha_val); - // Compute the EMA for the current element. - result[i][j] = alpha_val * new_row[j] + one_minus_alpha * old_row[j]; + // Compute the EMA for the current element using saturating operations. + result[i][j] = alpha_val + .saturating_mul(new_row[j]) + .saturating_add(one_minus_alpha.saturating_mul(old_row[j])); } } @@ -1301,7 +1304,7 @@ pub fn quantile(data: &[I32F32], quantile: f64) -> I32F32 { } // Calculate the position in the sorted array corresponding to the quantile. - let pos = quantile * (len - 1) as f64; + let pos = quantile * (len.saturating_sub(1)) as f64; // Determine the lower index by flooring the position. let low = pos.floor() as usize; @@ -1311,17 +1314,26 @@ pub fn quantile(data: &[I32F32], quantile: f64) -> I32F32 { // If the low and high indices are the same, return the value at that index. if low == high { - sorted_data[low] + sorted_data + .get(low) + .copied() + .unwrap_or_else(|| I32F32::from_num(0)) } else { // Otherwise, perform linear interpolation between the low and high values. - let low_value = sorted_data[low]; - let high_value = sorted_data[high]; + let low_value = sorted_data + .get(low) + .copied() + .unwrap_or_else(|| I32F32::from_num(0)); + let high_value = sorted_data + .get(high) + .copied() + .unwrap_or_else(|| I32F32::from_num(0)); // Calculate the weight for interpolation. let weight = I32F32::from_num(pos - low as f64); - // Return the interpolated value. - low_value + (high_value - low_value) * weight + // Return the interpolated value using saturating operations. + low_value.saturating_add((high_value.saturating_sub(low_value)).saturating_mul(weight)) } } diff --git a/pallets/subtensor/src/subnet_info.rs b/pallets/subtensor/src/subnet_info.rs index 5bd652ace..4e9e756a0 100644 --- a/pallets/subtensor/src/subnet_info.rs +++ b/pallets/subtensor/src/subnet_info.rs @@ -27,7 +27,7 @@ pub struct SubnetInfo { owner: T::AccountId, } -#[freeze_struct("76f4053b3cc4c7ec")] +#[freeze_struct("55b472510f10e76a")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug)] pub struct SubnetHyperparams { rho: Compact, diff --git a/pallets/subtensor/src/utils.rs b/pallets/subtensor/src/utils.rs index dee30f358..193d625fc 100644 --- a/pallets/subtensor/src/utils.rs +++ b/pallets/subtensor/src/utils.rs @@ -669,9 +669,9 @@ impl Pallet { pub fn get_alpha_values_32(netuid: u16) -> (I32F32, I32F32) { let (alpha_low, alpha_high): (u16, u16) = AlphaValues::::get(netuid); - let converted_low = I32F32::from_num(alpha_low) / I32F32::from_num(u16::MAX); - let converted_high = I32F32::from_num(alpha_high) / I32F32::from_num(u16::MAX); - + let converted_low = I32F32::from_num(alpha_low).saturating_div(I32F32::from_num(u16::MAX)); + let converted_high = + I32F32::from_num(alpha_high).saturating_div(I32F32::from_num(u16::MAX)); (converted_low, converted_high) } diff --git a/pallets/subtensor/tests/math.rs b/pallets/subtensor/tests/math.rs index c2b1e7128..f48ffee1a 100644 --- a/pallets/subtensor/tests/math.rs +++ b/pallets/subtensor/tests/math.rs @@ -1,3 +1,6 @@ +#![allow(clippy::unwrap_used)] +#![allow(clippy::panic)] +#![allow(clippy::indexing_slicing)] use substrate_fixed::types::{I32F32, I64F64}; use pallet_subtensor::math::*; From b1c26b39d1e0a9ea504ca0a1a60a7d39e47adceb Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Tue, 25 Jun 2024 00:58:05 +0400 Subject: [PATCH 11/51] feat: clippy --- pallets/subtensor/src/epoch.rs | 28 +++++++------ pallets/subtensor/src/math.rs | 74 +++++++++++++-------------------- pallets/subtensor/tests/math.rs | 9 ++-- 3 files changed, 49 insertions(+), 62 deletions(-) diff --git a/pallets/subtensor/src/epoch.rs b/pallets/subtensor/src/epoch.rs index 22331d206..e90f4b73d 100644 --- a/pallets/subtensor/src/epoch.rs +++ b/pallets/subtensor/src/epoch.rs @@ -32,7 +32,7 @@ impl Pallet { // Inactive mask. let inactive: Vec = last_update .iter() - .map(|updated| *updated + activity_cutoff < current_block) + .map(|updated| updated.saturating_add(activity_cutoff) < current_block) .collect(); log::trace!("Inactive:\n{:?}\n", inactive.clone()); @@ -193,7 +193,7 @@ impl Pallet { let combined_emission: Vec = incentive .iter() .zip(dividends.clone()) - .map(|(ii, di)| ii + di) + .map(|(ii, di)| ii.saturating_add(di)) .collect(); let emission_sum: I32F32 = combined_emission.iter().sum(); @@ -223,7 +223,7 @@ impl Pallet { let server_emission: Vec = normalized_server_emission .iter() - .map(|se: &I32F32| I96F32::from_num(*se) * float_rao_emission) + .map(|se: &I32F32| I96F32::from_num(*se).saturating_mul(float_rao_emission)) .collect(); let server_emission: Vec = server_emission .iter() @@ -232,7 +232,7 @@ impl Pallet { let validator_emission: Vec = normalized_validator_emission .iter() - .map(|ve: &I32F32| I96F32::from_num(*ve) * float_rao_emission) + .map(|ve: &I32F32| I96F32::from_num(*ve).saturating_mul(float_rao_emission)) .collect(); let validator_emission: Vec = validator_emission .iter() @@ -242,7 +242,7 @@ impl Pallet { // Used only to track combined emission in the storage. let combined_emission: Vec = normalized_combined_emission .iter() - .map(|ce: &I32F32| I96F32::from_num(*ce) * float_rao_emission) + .map(|ce: &I32F32| I96F32::from_num(*ce).saturating_mul(float_rao_emission)) .collect(); let combined_emission: Vec = combined_emission .iter() @@ -371,7 +371,7 @@ impl Pallet { // Inactive mask. let inactive: Vec = last_update .iter() - .map(|updated| *updated + activity_cutoff < current_block) + .map(|updated| updated.saturating_add(activity_cutoff) < current_block) .collect(); log::trace!("Inactive: {:?}", inactive.clone()); @@ -551,7 +551,7 @@ impl Pallet { let combined_emission: Vec = incentive .iter() .zip(dividends.clone()) - .map(|(ii, di)| ii + di) + .map(|(ii, di)| ii.saturating_add(di)) .collect(); let emission_sum: I32F32 = combined_emission.iter().sum(); @@ -581,7 +581,7 @@ impl Pallet { let server_emission: Vec = normalized_server_emission .iter() - .map(|se: &I32F32| I96F32::from_num(*se) * float_rao_emission) + .map(|se: &I32F32| I96F32::from_num(*se).saturating_mul(float_rao_emission)) .collect(); let server_emission: Vec = server_emission .iter() @@ -590,7 +590,7 @@ impl Pallet { let validator_emission: Vec = normalized_validator_emission .iter() - .map(|ve: &I32F32| I96F32::from_num(*ve) * float_rao_emission) + .map(|ve: &I32F32| I96F32::from_num(*ve).saturating_mul(float_rao_emission)) .collect(); let validator_emission: Vec = validator_emission .iter() @@ -600,7 +600,7 @@ impl Pallet { // Only used to track emission in storage. let combined_emission: Vec = normalized_combined_emission .iter() - .map(|ce: &I32F32| I96F32::from_num(*ce) * float_rao_emission) + .map(|ce: &I32F32| I96F32::from_num(*ce).saturating_mul(float_rao_emission)) .collect(); let combined_emission: Vec = combined_emission .iter() @@ -706,7 +706,7 @@ impl Pallet { I32F32::from_num(Self::get_rho(netuid)) } pub fn get_float_kappa(netuid: u16) -> I32F32 { - I32F32::from_num(Self::get_kappa(netuid)) / I32F32::from_num(u16::MAX) + I32F32::from_num(Self::get_kappa(netuid)).saturating_div(I32F32::from_num(u16::MAX)) } pub fn get_normalized_stake(netuid: u16) -> Vec { @@ -855,8 +855,10 @@ impl Pallet { // Calculate the intercept 'b' of the logistic function. // b = ln((1 / alpha_low - 1)) + a * consensus_low - let b = safe_ln((I32F32::from_num(1.0) / alpha_low).saturating_sub(I32F32::from_num(1.0))) - .saturating_add(a.saturating_mul(consensus_low)); + let b = safe_ln( + (I32F32::from_num(1.0).saturating_div(alpha_low)).saturating_sub(I32F32::from_num(1.0)), + ) + .saturating_add(a.saturating_mul(consensus_low)); log::trace!("b: {:?}", b); // Return the calculated slope 'a' and intercept 'b'. diff --git a/pallets/subtensor/src/math.rs b/pallets/subtensor/src/math.rs index 88078821e..8b6e76f2c 100644 --- a/pallets/subtensor/src/math.rs +++ b/pallets/subtensor/src/math.rs @@ -1148,36 +1148,6 @@ pub fn sparse_threshold(w: &[Vec<(u16, I32F32)>], threshold: I32F32) -> Vec>, -// old: &Vec>, -// alpha: &Vec, -// ) -> Vec> { -// assert!(new.len() == old.len()); -// let n = new.len(); // assume square matrix, rows=cols -// let zero: I32F32 = I32F32::from_num(0.0); -// let mut result: Vec> = vec![vec![]; n]; -// for i in 0..new.len() { -// let mut row: Vec = vec![zero; n]; -// for (j, value) in new[i].iter() { -// let alpha_val: I32F32 = alpha[*j as usize]; -// row[*j as usize] += alpha_val * value; -// } -// for (j, value) in old[i].iter() { -// let one_minus_alpha: I32F32 = I32F32::from_num(1.0) - alpha[*j as usize]; -// row[*j as usize] += one_minus_alpha * value; -// } -// for (j, value) in row.iter().enumerate() { -// if *value > zero { -// result[i].push((j as u16, *value)) -// } -// } -// } -// result -// } - /// Calculates the exponential moving average (EMA) for a sparse matrix using dynamic alpha values. #[allow(dead_code)] pub fn mat_ema_alpha_vec_sparse( @@ -1192,16 +1162,18 @@ pub fn mat_ema_alpha_vec_sparse( let mut result: Vec> = vec![vec![]; n]; // Iterate over each row of the matrices. - for i in 0..new.len() { + for (i, (new_row, old_row)) in new.iter().zip(old).enumerate() { // Initialize a row of zeros for the result matrix. let mut row: Vec = vec![zero; n]; // Process the new matrix values. - for (j, value) in new[i].iter() { + for (j, value) in new_row.iter() { // Retrieve the alpha value for the current column. - let alpha_val: I32F32 = alpha[*j as usize]; + let alpha_val: I32F32 = alpha.get(*j as usize).copied().unwrap_or(zero); // Compute the EMA component for the new value using saturating multiplication. - row[*j as usize] = alpha_val.saturating_mul(*value); + if let Some(row_val) = row.get_mut(*j as usize) { + *row_val = alpha_val.saturating_mul(*value); + } log::trace!( "new[{}][{}] * alpha[{}] = {} * {} = {}", i, @@ -1209,19 +1181,20 @@ pub fn mat_ema_alpha_vec_sparse( j, value, alpha_val, - row[*j as usize] + row.get(*j as usize).unwrap_or(&zero) ); } // Process the old matrix values. - for (j, value) in old[i].iter() { + for (j, value) in old_row.iter() { // Retrieve the alpha value for the current column. - let alpha_val: I32F32 = alpha[*j as usize]; + let alpha_val: I32F32 = alpha.get(*j as usize).copied().unwrap_or(zero); // Calculate the complement of the alpha value using saturating subtraction. let one_minus_alpha: I32F32 = I32F32::from_num(1.0).saturating_sub(alpha_val); // Compute the EMA component for the old value and add it to the row using saturating operations. - row[*j as usize] = - row[*j as usize].saturating_add(one_minus_alpha.saturating_mul(*value)); + if let Some(row_val) = row.get_mut(*j as usize) { + *row_val = row_val.saturating_add(one_minus_alpha.saturating_mul(*value)); + } log::trace!( "old[{}][{}] * (1 - alpha[{}]) = {} * {} = {}", i, @@ -1236,8 +1209,10 @@ pub fn mat_ema_alpha_vec_sparse( // Collect the non-zero values into the result matrix. for (j, value) in row.iter().enumerate() { if *value > zero { - result[i].push((j as u16, *value)); - log::trace!("result[{}][{}] = {}", i, j, value); + if let Some(result_row) = result.get_mut(i) { + result_row.push((j as u16, *value)); + log::trace!("result[{}][{}] = {}", i, j, value); + } } } } @@ -1245,6 +1220,7 @@ pub fn mat_ema_alpha_vec_sparse( // Return the computed EMA sparse matrix. result } + /// Return matrix exponential moving average: `alpha_j * a_ij + one_minus_alpha_j * b_ij`. /// `alpha_` is the EMA coefficient passed as a vector per column. #[allow(dead_code)] @@ -1254,13 +1230,13 @@ pub fn mat_ema_alpha_vec( alpha: &[I32F32], ) -> Vec> { // Check if the new matrix is empty or its first row is empty. - if new.is_empty() || new[0].is_empty() { + if new.is_empty() || new.first().map_or(true, |row| row.is_empty()) { return vec![vec![]; 1]; } // Ensure the dimensions of the new and old matrices match. assert!(new.len() == old.len()); - assert!(new[0].len() == alpha.len()); + assert!(new.first().map_or(0, |row| row.len()) == alpha.len()); // Initialize the result matrix with zeros, having the same dimensions as the new matrix. let mut result: Vec> = @@ -1277,9 +1253,15 @@ pub fn mat_ema_alpha_vec( let one_minus_alpha = I32F32::from_num(1.0).saturating_sub(alpha_val); // Compute the EMA for the current element using saturating operations. - result[i][j] = alpha_val - .saturating_mul(new_row[j]) - .saturating_add(one_minus_alpha.saturating_mul(old_row[j])); + if let (Some(new_val), Some(old_val), Some(result_val)) = ( + new_row.get(j), + old_row.get(j), + result.get_mut(i).and_then(|row| row.get_mut(j)), + ) { + *result_val = alpha_val + .saturating_mul(*new_val) + .saturating_add(one_minus_alpha.saturating_mul(*old_val)); + } } } diff --git a/pallets/subtensor/tests/math.rs b/pallets/subtensor/tests/math.rs index f48ffee1a..bff4628df 100644 --- a/pallets/subtensor/tests/math.rs +++ b/pallets/subtensor/tests/math.rs @@ -1,6 +1,9 @@ -#![allow(clippy::unwrap_used)] -#![allow(clippy::panic)] -#![allow(clippy::indexing_slicing)] +#![allow( + clippy::unwrap_used, + clippy::panic, + clippy::indexing_slicing, + clippy::arithmetic_side_effects +)] use substrate_fixed::types::{I32F32, I64F64}; use pallet_subtensor::math::*; From 2b10e12b050ce1be6a943260fb0c4522b04d3bb3 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Mon, 17 Jun 2024 15:25:10 +0400 Subject: [PATCH 12/51] refactor: hotkey swap + tests --- pallets/subtensor/src/lib.rs | 13 +- pallets/subtensor/src/registration.rs | 138 +-- pallets/subtensor/src/swap.rs | 438 ++++++++++ pallets/subtensor/tests/mock.rs | 3 +- pallets/subtensor/tests/swap.rs | 1133 +++++++++++++++++++++++++ 5 files changed, 1581 insertions(+), 144 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 efb528cde..18ea0779f 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; @@ -744,7 +745,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 = @@ -760,10 +761,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, @@ -1017,13 +1018,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..fe9e18702 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; @@ -592,139 +591,4 @@ impl Pallet { (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 78aac3d95..4ec4aa415 100644 --- a/pallets/subtensor/tests/mock.rs +++ b/pallets/subtensor/tests/mock.rs @@ -1,5 +1,6 @@ #![allow(clippy::arithmetic_side_effects, clippy::unwrap_used)] +use frame_support::weights::constants::RocksDbWeight; use frame_support::{ assert_ok, derive_impl, dispatch::DispatchResultWithPostInfo, @@ -88,7 +89,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 7eb29f9b55d0303ff8a95356f541ffc443b5e349 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Mon, 17 Jun 2024 15:29:54 +0400 Subject: [PATCH 13/51] 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 6ddcfe2cb63a724650a9d6e861fc8435557ee54c Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Mon, 17 Jun 2024 16:02:11 +0400 Subject: [PATCH 14/51] 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 45e828d1f35b749c4ee87b517ce14f9e2859fe19 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Mon, 17 Jun 2024 17:31:13 +0400 Subject: [PATCH 15/51] 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 fe9e18702..9d95f52ef 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 c12ec3748134a8bae5a347529de21331234b7f90 Mon Sep 17 00:00:00 2001 From: Keith Date: Mon, 17 Jun 2024 23:25:14 +0900 Subject: [PATCH 16/51] 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 5eaa0883e232fc4eae653e8b8ffded3f323f3510 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 17/51] 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 969a4f89bbf325eb695f9d8904448ca7b0ee7a21 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Mon, 17 Jun 2024 21:31:34 +0400 Subject: [PATCH 18/51] 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 6b68263fdacf3d5da76e010e58cc882e842b7037 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Mon, 17 Jun 2024 22:21:54 +0400 Subject: [PATCH 19/51] 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 18ea0779f..504a9340e 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -241,6 +241,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; @@ -274,6 +277,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 193d625fc..15d659a51 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 4ec4aa415..240f42448 100644 --- a/pallets/subtensor/tests/mock.rs +++ b/pallets/subtensor/tests/mock.rs @@ -161,6 +161,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 @@ -370,6 +371,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 26b4aca4c..af89c620c 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -922,6 +922,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 ec27e77a43e38052eec20f34498079be695608f3 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Mon, 17 Jun 2024 22:37:26 +0400 Subject: [PATCH 20/51] 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 af89c620c..32a4f8b59 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -868,6 +868,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 @@ -922,7 +923,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 fc82551832fcb829cdeaec9000ff94823ff53c88 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Tue, 18 Jun 2024 01:09:59 +0400 Subject: [PATCH 21/51] 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 50574721d3d0958257b1a9a313b61fcca533646f Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Tue, 18 Jun 2024 01:26:04 +0400 Subject: [PATCH 22/51] 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 dd9672ba0b575553bb5f6d0248b7f639e8b7a6b6 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Tue, 18 Jun 2024 01:28:57 +0400 Subject: [PATCH 23/51] 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 60019a91d063801f9dd93a286c9017009dfd473b Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Tue, 18 Jun 2024 01:36:55 +0400 Subject: [PATCH 24/51] 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 2cd90dd5312925114caa15f063dc22ee0de18ac1 Mon Sep 17 00:00:00 2001 From: Keith Date: Tue, 18 Jun 2024 11:52:55 +0900 Subject: [PATCH 25/51] 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 5743ae79d7c8de5fd8073da1b2ecfb931c6aa5c4 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 26/51] 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 f358847c7eb02f6b557ca990f5e4b21e7aef57f7 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Tue, 18 Jun 2024 11:54:37 +0400 Subject: [PATCH 27/51] 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 768e8e4fd4b9c33697c4c951a3db238fb63accf0 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Tue, 18 Jun 2024 11:58:33 +0400 Subject: [PATCH 28/51] 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 cb078a202beb40993d6f1e158b475efb52c2c273 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Tue, 18 Jun 2024 14:36:08 +0400 Subject: [PATCH 29/51] 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 814447f3d082522c3729c8a2938b153233b0af6e Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Fri, 21 Jun 2024 21:49:42 +0400 Subject: [PATCH 30/51] 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 680e4ad684041363d7cce4b808e4db8f8e1074f2 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Fri, 21 Jun 2024 21:49:59 +0400 Subject: [PATCH 31/51] 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 f7b567a8c05dd9b5d947abcb0335c6c85fc881b4 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Sat, 22 Jun 2024 00:48:02 +0400 Subject: [PATCH 32/51] 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 504a9340e..af05db7b2 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -277,11 +277,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 78663d892547b787ebbf6cf7751e15ce828f0f6b Mon Sep 17 00:00:00 2001 From: Sam Johnson Date: Wed, 19 Jun 2024 11:49:25 -0400 Subject: [PATCH 33/51] add requirement for `devnet-companion` label for `devnet-ready` PRs --- .github/workflows/devnet-ready-labels.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/workflows/devnet-ready-labels.yml diff --git a/.github/workflows/devnet-ready-labels.yml b/.github/workflows/devnet-ready-labels.yml new file mode 100644 index 000000000..25d9bc479 --- /dev/null +++ b/.github/workflows/devnet-ready-labels.yml @@ -0,0 +1,17 @@ +name: Companion Labels (devnet) +on: + pull_request: + types: [opened, labeled, unlabeled, synchronize] + branches: [devnet-ready] +jobs: + check-labels: + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - uses: mheap/github-action-required-labels@v5 + with: + mode: minimum + count: 1 + labels: devnet-companion From 76d94396e6d9fec00f634d1f7ed772ba9a3d4881 Mon Sep 17 00:00:00 2001 From: Sam Johnson Date: Wed, 19 Jun 2024 11:50:58 -0400 Subject: [PATCH 34/51] add testnet-ready labels check --- .github/workflows/devnet-ready-labels.yml | 2 +- .github/workflows/testnet-ready-labels.yml | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/testnet-ready-labels.yml diff --git a/.github/workflows/devnet-ready-labels.yml b/.github/workflows/devnet-ready-labels.yml index 25d9bc479..ab53327e7 100644 --- a/.github/workflows/devnet-ready-labels.yml +++ b/.github/workflows/devnet-ready-labels.yml @@ -1,4 +1,4 @@ -name: Companion Labels (devnet) +name: devnet-companion Label Check on: pull_request: types: [opened, labeled, unlabeled, synchronize] diff --git a/.github/workflows/testnet-ready-labels.yml b/.github/workflows/testnet-ready-labels.yml new file mode 100644 index 000000000..8570d2011 --- /dev/null +++ b/.github/workflows/testnet-ready-labels.yml @@ -0,0 +1,17 @@ +name: testnet-companion Label Check +on: + pull_request: + types: [opened, labeled, unlabeled, synchronize] + branches: [testnet-ready] +jobs: + check-labels: + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - uses: mheap/github-action-required-labels@v5 + with: + mode: minimum + count: 1 + labels: testnet-companion From 6bd2e423e345b74a6324db0ea92c6f1839a5cefe Mon Sep 17 00:00:00 2001 From: Sam Johnson Date: Wed, 19 Jun 2024 11:52:15 -0400 Subject: [PATCH 35/51] update CONTRIBUTING.md with additional info --- CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d3616041b..084f3e960 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,9 +15,9 @@ add appropriate labels to your PR as shown below. Three positive reviews are required. 4. Once the required passing reviews have been obtained, you are ready to request that your PR be included in the next `devnet` deploy. To do this, you should open a companion PR merging - your branch into the `devnet-ready` branch. You must include a link to the parent PR in the - description and preface your PR title with "(Devnet Ready)" or the PR will be - closed/ignored. + a copy of your branch into the `devnet-ready` branch. You must include a link to the parent + PR in the description and preface your PR title with "(Devnet Ready)" or the PR will be + closed/ignored. Your companion PR should have the `devnet-companion` label. 5. A core team administrator will review your "(Devnet Ready)" PR, verifying that it logically matches the changes introduced in the parent PR (there will sometimes be minor differences due to merge conflicts) and will either request changes or approve the PR and merge it. Once From ad85c272b2dfb199918a6588a1231e8601e0fa1d Mon Sep 17 00:00:00 2001 From: Sam Johnson Date: Wed, 19 Jun 2024 11:55:14 -0400 Subject: [PATCH 36/51] update docs --- CONTRIBUTING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 084f3e960..132d360b8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -86,11 +86,13 @@ | `runtime` | PR contains substantive changes to runtime / pallet code | none | | `breaking-change` | PR requires synchronized changes with bittensor | Triggers an automatic bot message so the relevant teams are made aware of the change well in advance | | `migration` | PR contains one or more migrations | none | +| `devnet-companion` | Designates a devnet companion PR | Presence of `devnet-companion` label is checked | | `devnet-ready` | PR's branch has been merged into the `devnet-ready` branch and will be included in the next `devnet` deploy | none | | `on-devnet` | PR has been deployed to `devnet` | Removes `devnet-ready` | | `devnet-pass` | PR has passed manual testing on `devnet` | `devnet-pass` or `devnet-skip` required | | `devnet-skip` | Allows a critical hotfix PR to skip required testing on `devnet` | `devnet-pass` or `devnet-skip` required | | `devnet-fail` | PR has failed manual testing on `devnet` and requires modification | none | +| `testnet-companion` | Designates a testnet companion PR | Presence of `testnet-companion` label is checked | | `on-testnet` | PR has been deployed to `testnet` | none | | `testnet-pass` | PR has passed manual testing on `testnet` | `testnet-pass` or `testnet-skip` required | | `testnet-skip` | Allows a critical hotfix PR to skip required manual testing and SOP on `testnet` | `testnet-pass` or `testnet-skip` required | From 66c87afe41c8cfaf48ae70f4f7d18f8de34232b3 Mon Sep 17 00:00:00 2001 From: Sam Johnson Date: Fri, 21 Jun 2024 17:34:01 -0400 Subject: [PATCH 37/51] 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 01dca6a05f816c3da4cd8be84f3aab7885624744 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Tue, 25 Jun 2024 02:22:12 +0400 Subject: [PATCH 38/51] make clippy happy --- pallets/subtensor/src/registration.rs | 1 - pallets/subtensor/src/swap.rs | 21 +++++++++++---------- pallets/subtensor/tests/swap.rs | 2 ++ 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/pallets/subtensor/src/registration.rs b/pallets/subtensor/src/registration.rs index 9d95f52ef..4688bcbb5 100644 --- a/pallets/subtensor/src/registration.rs +++ b/pallets/subtensor/src/registration.rs @@ -590,5 +590,4 @@ impl Pallet { let vec_work: Vec = Self::hash_to_vec(work); (nonce, vec_work) } - } 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/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 ecb62213a1e1fb529cff6477d96b65e486bb703e Mon Sep 17 00:00:00 2001 From: Liam Date: Tue, 25 Jun 2024 14:49:52 +0300 Subject: [PATCH 39/51] update spec file usage --- docker-compose.yml | 10 +- docs/running-subtensor-locally.md | 8 +- scripts/run/subtensor.sh | 176 +++++++++++++++--------------- 3 files changed, 96 insertions(+), 98 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 7b76cd053..09638c174 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,4 @@ -version: '3.8' +version: "3.8" volumes: mainnet-lite-volume: @@ -38,7 +38,7 @@ services: - | node-subtensor \ --base-path /tmp/blockchain \ - --chain raw_spec.json \ + --chain raw_spec_finney.json \ --rpc-external --rpc-cors all \ --no-mdns \ --in-peers 500 --out-peers 500 \ @@ -56,7 +56,7 @@ services: - | node-subtensor \ --base-path /tmp/blockchain \ - --chain raw_spec.json \ + --chain raw_spec_finney.json \ --rpc-external --rpc-cors all \ --no-mdns \ --in-peers 500 --out-peers 500 \ @@ -74,7 +74,7 @@ services: - | node-subtensor \ --base-path /tmp/blockchain \ - --chain raw_testspec.json \ + --chain raw_spec_testfinney.json \ --rpc-external --rpc-cors all \ --no-mdns \ --in-peers 500 --out-peers 500 \ @@ -94,7 +94,7 @@ services: - | node-subtensor \ --base-path /tmp/blockchain \ - --chain raw_testspec.json \ + --chain raw_spec_testfinney.json \ --rpc-external --rpc-cors all \ --no-mdns \ --in-peers 500 --out-peers 500 \ diff --git a/docs/running-subtensor-locally.md b/docs/running-subtensor-locally.md index 089f4d30a..5f37e146f 100644 --- a/docs/running-subtensor-locally.md +++ b/docs/running-subtensor-locally.md @@ -174,7 +174,7 @@ You can now run the public subtensor node either as a lite node or as an archive To run a lite node connected to the mainchain, execute the below command (note the `--sync=warp` flag which runs the subtensor node in lite mode): ```bash title="With --sync=warp setting, for lite node" -./target/release/node-subtensor --chain raw_spec.json --base-path /tmp/blockchain --sync=warp --port 30333 --max-runtime-instances 32 --rpc-max-response-size 2048 --rpc-cors all --rpc-port 9944 --bootnodes /ip4/13.58.175.193/tcp/30333/p2p/12D3KooWDe7g2JbNETiKypcKT1KsCEZJbTzEHCn8hpd4PHZ6pdz5 --no-mdns --in-peers 8000 --out-peers 8000 --prometheus-external --rpc-external +./target/release/node-subtensor --chain raw_spec_finney.json --base-path /tmp/blockchain --sync=warp --port 30333 --max-runtime-instances 32 --rpc-max-response-size 2048 --rpc-cors all --rpc-port 9944 --bootnodes /ip4/13.58.175.193/tcp/30333/p2p/12D3KooWDe7g2JbNETiKypcKT1KsCEZJbTzEHCn8hpd4PHZ6pdz5 --no-mdns --in-peers 8000 --out-peers 8000 --prometheus-external --rpc-external ``` ### Archive node on mainchain @@ -182,7 +182,7 @@ To run a lite node connected to the mainchain, execute the below command (note t To run an archive node connected to the mainchain, execute the below command (note the `--sync=full` which syncs the node to the full chain and `--pruning archive` flags, which disables the node's automatic pruning of older historical data): ```bash title="With --sync=full and --pruning archive setting, for archive node" -./target/release/node-subtensor --chain raw_spec.json --base-path /tmp/blockchain --sync=full --pruning archive --port 30333 --max-runtime-instances 32 --rpc-max-response-size 2048 --rpc-cors all --rpc-port 9944 --bootnodes /ip4/13.58.175.193/tcp/30333/p2p/12D3KooWDe7g2JbNETiKypcKT1KsCEZJbTzEHCn8hpd4PHZ6pdz5 --no-mdns --in-peers 8000 --out-peers 8000 --prometheus-external --rpc-external +./target/release/node-subtensor --chain raw_spec_finney.json --base-path /tmp/blockchain --sync=full --pruning archive --port 30333 --max-runtime-instances 32 --rpc-max-response-size 2048 --rpc-cors all --rpc-port 9944 --bootnodes /ip4/13.58.175.193/tcp/30333/p2p/12D3KooWDe7g2JbNETiKypcKT1KsCEZJbTzEHCn8hpd4PHZ6pdz5 --no-mdns --in-peers 8000 --out-peers 8000 --prometheus-external --rpc-external ``` ### Lite node on testchain @@ -190,7 +190,7 @@ To run an archive node connected to the mainchain, execute the below command (no To run a lite node connected to the testchain, execute the below command: ```bash title="With bootnodes set to testnet and --sync=warp setting, for lite node." -./target/release/node-subtensor --chain raw_testspec.json --base-path /tmp/blockchain --sync=warp --port 30333 --max-runtime-instances 32 --rpc-max-response-size 2048 --rpc-cors all --rpc-port 9944 --bootnodes /dns/bootnode.test.finney.opentensor.ai/tcp/30333/p2p/12D3KooWPM4mLcKJGtyVtkggqdG84zWrd7Rij6PGQDoijh1X86Vr --no-mdns --in-peers 8000 --out-peers 8000 --prometheus-external --rpc-external +./target/release/node-subtensor --chain raw_spec_testfinney.json --base-path /tmp/blockchain --sync=warp --port 30333 --max-runtime-instances 32 --rpc-max-response-size 2048 --rpc-cors all --rpc-port 9944 --bootnodes /dns/bootnode.test.finney.opentensor.ai/tcp/30333/p2p/12D3KooWPM4mLcKJGtyVtkggqdG84zWrd7Rij6PGQDoijh1X86Vr --no-mdns --in-peers 8000 --out-peers 8000 --prometheus-external --rpc-external ``` ### Archive node on testchain @@ -198,7 +198,7 @@ To run a lite node connected to the testchain, execute the below command: To run an archive node connected to the testchain, execute the below command: ```bash title="With bootnodes set to testnet and --sync=full and --pruning archive setting, for archive node" -./target/release/node-subtensor --chain raw_testspec.json --base-path /tmp/blockchain --sync=full --pruning archive --port 30333 --max-runtime-instances 32 --rpc-max-response-size 2048 --rpc-cors all --rpc-port 9944 --bootnodes /dns/bootnode.test.finney.opentensor.ai/tcp/30333/p2p/12D3KooWPM4mLcKJGtyVtkggqdG84zWrd7Rij6PGQDoijh1X86Vr --no-mdns --in-peers 8000 --out-peers 8000 --prometheus-external --rpc-external +./target/release/node-subtensor --chain raw_spec_testfinney.json --base-path /tmp/blockchain --sync=full --pruning archive --port 30333 --max-runtime-instances 32 --rpc-max-response-size 2048 --rpc-cors all --rpc-port 9944 --bootnodes /dns/bootnode.test.finney.opentensor.ai/tcp/30333/p2p/12D3KooWPM4mLcKJGtyVtkggqdG84zWrd7Rij6PGQDoijh1X86Vr --no-mdns --in-peers 8000 --out-peers 8000 --prometheus-external --rpc-external ``` ## Running on cloud diff --git a/scripts/run/subtensor.sh b/scripts/run/subtensor.sh index e8fd3d58c..b28e8dd6f 100755 --- a/scripts/run/subtensor.sh +++ b/scripts/run/subtensor.sh @@ -4,52 +4,50 @@ # Helper functions # -function run_command() -{ - F_NETWORK=$1 - F_NODE_TYPE=$2 - F_BIN_PATH=$3 +function run_command() { + F_NETWORK=$1 + F_NODE_TYPE=$2 + F_BIN_PATH=$3 - # Different command options by network and node type - MAINNET_BOOTNODE='--bootnodes /dns/bootnode.finney.chain.opentensor.ai/tcp/30333/ws/p2p/12D3KooWRwbMb85RWnT8DSXSYMWQtuDwh4LJzndoRrTDotTR5gDC' - TESTNET_BOOTNODE='--bootnodes /dns/bootnode.test.finney.opentensor.ai/tcp/30333/ws/p2p/12D3KooWPM4mLcKJGtyVtkggqdG84zWrd7Rij6PGQDoijh1X86Vr' - NODE_TYPE_ARCHIVE='--pruning=archive' - NODE_TYPE_LITE='--sync warp' + # Different command options by network and node type + MAINNET_BOOTNODE='--bootnodes /dns/bootnode.finney.chain.opentensor.ai/tcp/30333/ws/p2p/12D3KooWRwbMb85RWnT8DSXSYMWQtuDwh4LJzndoRrTDotTR5gDC' + TESTNET_BOOTNODE='--bootnodes /dns/bootnode.test.finney.opentensor.ai/tcp/30333/ws/p2p/12D3KooWPM4mLcKJGtyVtkggqdG84zWrd7Rij6PGQDoijh1X86Vr' + NODE_TYPE_ARCHIVE='--pruning=archive' + NODE_TYPE_LITE='--sync warp' - # Options by the type of node we offer - MAINNET_ARCHIVE_OPTIONS="$MAINNET_BOOTNODE $NODE_TYPE_ARCHIVE" - MAINNET_LITE_OPTIONS="$MAINNET_BOOTNODE $NODE_TYPE_LITE" - TESTNET_ARCHIVE_OPTIONS="$TESTNET_BOOTNODE $NODE_TYPE_ARCHIVE" - TESTNET_LITE_OPTIONS="$TESTNET_BOOTNODE $NODE_TYPE_LITE" + # Options by the type of node we offer + MAINNET_ARCHIVE_OPTIONS="$MAINNET_BOOTNODE $NODE_TYPE_ARCHIVE" + MAINNET_LITE_OPTIONS="$MAINNET_BOOTNODE $NODE_TYPE_LITE" + TESTNET_ARCHIVE_OPTIONS="$TESTNET_BOOTNODE $NODE_TYPE_ARCHIVE" + TESTNET_LITE_OPTIONS="$TESTNET_BOOTNODE $NODE_TYPE_LITE" - # Checking options to use - if [[ "$F_NETWORK" == "mainnet" ]] && [[ "$F_NODE_TYPE" == "archive" ]]; then - SPECIFIC_OPTIONS=$MAINNET_ARCHIVE_OPTIONS - elif [[ "$F_NETWORK" == "mainnet" ]] && [[ "$F_NODE_TYPE" == "lite" ]]; then - SPECIFIC_OPTIONS=$MAINNET_LITE_OPTIONS - elif [[ "$F_NETWORK" == "testnet" ]] && [[ "$F_NODE_TYPE" == "archive" ]]; then - SPECIFIC_OPTIONS=$TESTNET_ARCHIVE_OPTIONS - elif [[ "$F_NETWORK" == "testnet" ]] && [[ "$F_NODE_TYPE" == "lite" ]]; then - SPECIFIC_OPTIONS=$TESTNET_LITE_OPTIONS - fi + # Checking options to use + if [[ "$F_NETWORK" == "mainnet" ]] && [[ "$F_NODE_TYPE" == "archive" ]]; then + SPECIFIC_OPTIONS=$MAINNET_ARCHIVE_OPTIONS + elif [[ "$F_NETWORK" == "mainnet" ]] && [[ "$F_NODE_TYPE" == "lite" ]]; then + SPECIFIC_OPTIONS=$MAINNET_LITE_OPTIONS + elif [[ "$F_NETWORK" == "testnet" ]] && [[ "$F_NODE_TYPE" == "archive" ]]; then + SPECIFIC_OPTIONS=$TESTNET_ARCHIVE_OPTIONS + elif [[ "$F_NETWORK" == "testnet" ]] && [[ "$F_NODE_TYPE" == "lite" ]]; then + SPECIFIC_OPTIONS=$TESTNET_LITE_OPTIONS + fi - if [ ! -f $F_BIN_PATH ]; then - echo "Binary '$F_BIN_PATH' does not exist. You can use -p or --bin-path to specify a different location." - echo "Please ensure you have compiled the binary first." - exit 1 - fi + if [ ! -f $F_BIN_PATH ]; then + echo "Binary '$F_BIN_PATH' does not exist. You can use -p or --bin-path to specify a different location." + echo "Please ensure you have compiled the binary first." + exit 1 + fi - # Command to run subtensor - $F_BIN_PATH \ - --base-path /tmp/blockchain \ - --chain ./raw_spec.json \ - --rpc-external --rpc-cors all \ - --no-mdns \ - --rpc-max-connections 10000 --in-peers 500 --out-peers 500 \ - $SPECIFIC_OPTIONS + # Command to run subtensor + $F_BIN_PATH \ + --base-path /tmp/blockchain \ + --chain ./raw_spec_finney.json \ + --rpc-external --rpc-cors all \ + --no-mdns \ + --rpc-max-connections 10000 --in-peers 500 --out-peers 500 \ + $SPECIFIC_OPTIONS } - # Default values EXEC_TYPE="docker" NETWORK="mainnet" @@ -60,69 +58,69 @@ BIN_PATH="./target/release/node-subtensor" # Getting arguments from user while [[ $# -gt 0 ]]; do case $1 in - -h|--help) - help - exit 0 - ;; - -e|--execution) - EXEC_TYPE="$2" - shift # past argument - shift # past value - ;; - -b|--build) - BUILD="--build" - shift # past argument - ;; - -n|--network) - NETWORK="$2" - shift - shift - ;; - -t|--node-type) - NODE_TYPE="$2" - shift - shift - ;; - -p|--bin-path) - BIN_PATH="$2" - shift - shift - ;; - -*|--*) - echo "Unknown option $1" - exit 1 - ;; - *) - POSITIONAL_ARGS+=("$1") - shift - ;; + -h | --help) + help + exit 0 + ;; + -e | --execution) + EXEC_TYPE="$2" + shift # past argument + shift # past value + ;; + -b | --build) + BUILD="--build" + shift # past argument + ;; + -n | --network) + NETWORK="$2" + shift + shift + ;; + -t | --node-type) + NODE_TYPE="$2" + shift + shift + ;; + -p | --bin-path) + BIN_PATH="$2" + shift + shift + ;; + -* | --*) + echo "Unknown option $1" + exit 1 + ;; + *) + POSITIONAL_ARGS+=("$1") + shift + ;; esac done # Verifying arguments values if ! [[ "$EXEC_TYPE" =~ ^(docker|binary)$ ]]; then - echo "Exec type not expected: $EXEC_TYPE" - exit 1 + echo "Exec type not expected: $EXEC_TYPE" + exit 1 fi if ! [[ "$NETWORK" =~ ^(mainnet|testnet)$ ]]; then - echo "Network not expected: $NETWORK" - exit 1 + echo "Network not expected: $NETWORK" + exit 1 fi if ! [[ "$NODE_TYPE" =~ ^(lite|archive)$ ]]; then - echo "Node type not expected: $NODE_TYPE" - exit 1 + echo "Node type not expected: $NODE_TYPE" + exit 1 fi # Running subtensor case $EXEC_TYPE in - docker) - docker compose down --remove-orphans - echo "Running docker compose up $BUILD --detach $NETWORK-$NODE_TYPE" - docker compose up $BUILD --detach $NETWORK-$NODE_TYPE - ;; - binary) - run_command $NETWORK $NODE_TYPE $BIN_PATH - ;; +docker) + docker compose down --remove-orphans + echo "Running docker compose up $BUILD --detach $NETWORK-$NODE_TYPE" + docker compose up $BUILD --detach $NETWORK-$NODE_TYPE + ;; +binary) + run_command $NETWORK $NODE_TYPE $BIN_PATH + ;; esac From 81ed321cc21f44c381cdddfef265a98ab438b94e Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Tue, 25 Jun 2024 15:04:57 +0400 Subject: [PATCH 40/51] feat: bump spec --- runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 32a4f8b59..f76ae4558 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -139,7 +139,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 153, + spec_version: 186, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From 2ea077b02ffcf710f31f16edafcb62419809c619 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Wed, 26 Jun 2024 03:29:06 +0400 Subject: [PATCH 41/51] feat: benchmark adjust senate --- pallets/subtensor/src/benchmarks.rs | 27 ++++++++++++++++++++++++++- pallets/subtensor/src/lib.rs | 7 ++++--- scripts/benchmark.sh | 2 +- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/pallets/subtensor/src/benchmarks.rs b/pallets/subtensor/src/benchmarks.rs index 403ba413e..1efd9523a 100644 --- a/pallets/subtensor/src/benchmarks.rs +++ b/pallets/subtensor/src/benchmarks.rs @@ -80,7 +80,7 @@ benchmarks! { // This is a whitelisted caller who can make transaction without weights. let caller: T::AccountId = whitelisted_caller::>(); let caller_origin = ::RuntimeOrigin::from(RawOrigin::Signed(caller.clone())); - let netuid: u16 = 1; + let netuid: u16 = 0; let version_key: u64 = 1; let tempo: u16 = 1; let modality: u16 = 0; @@ -428,4 +428,29 @@ reveal_weights { let _ = Subtensor::::commit_weights(::RuntimeOrigin::from(RawOrigin::Signed(hotkey.clone())), netuid, commit_hash); }: reveal_weights(RawOrigin::Signed(hotkey.clone()), netuid, uids, weight_values, salt, version_key) + + + adjust_senate { + migration::migrate_create_root_network::(); + let netuid: u16 = 1; + let tempo: u16 = 13; + let burn_cost = 1000; + let hotkey: T::AccountId = account("hot", 0, 1); + let coldkey: T::AccountId = account("cold", 0, 2); + + Subtensor::::init_new_network(netuid, 100); + Subtensor::::set_burn(netuid, 1); + Subtensor::::set_max_allowed_uids( netuid, 4096 ); + assert_eq!(Subtensor::::get_max_allowed_uids(netuid), 4096); + Subtensor::::set_burn(netuid, burn_cost); + + let amount_to_be_staked = 100_000_000_000; + Subtensor::::add_balance_to_coldkey_account(&coldkey.clone(), amount_to_be_staked); + + assert_ok!(Subtensor::::burned_register(RawOrigin::Signed(coldkey.clone()).into(), netuid, hotkey.clone())); + assert_ok!(Subtensor::::become_delegate(RawOrigin::Signed(coldkey.clone()).into(), hotkey.clone())); + assert_ok!(Subtensor::::root_register(RawOrigin::Signed(coldkey.clone()).into(), hotkey.clone())); + T::SenateMembers::remove_member(&hotkey).map_err(|_| "Failed to remove member")?; + + }: adjust_senate(RawOrigin::Signed(coldkey.clone()), hotkey.clone()) } diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index af05db7b2..1b545a514 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -1950,9 +1950,10 @@ pub mod pallet { /// Attempt to adjust the senate membership to include a hotkey #[pallet::call_index(63)] - #[pallet::weight((Weight::from_parts(0, 0) - .saturating_add(T::DbWeight::get().reads(0)) - .saturating_add(T::DbWeight::get().writes(0)), DispatchClass::Normal, Pays::Yes))] + #[pallet::weight((Weight::from_parts(50_000_000, 0) + .saturating_add(Weight::from_parts(0, 4632)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(1)), DispatchClass::Normal, Pays::Yes))] pub fn adjust_senate(origin: OriginFor, hotkey: T::AccountId) -> DispatchResult { Self::do_adjust_senate(origin, hotkey) } diff --git a/scripts/benchmark.sh b/scripts/benchmark.sh index 52b74778a..0cbb1506b 100755 --- a/scripts/benchmark.sh +++ b/scripts/benchmark.sh @@ -43,7 +43,7 @@ $BIN_PATH build-spec --disable-default-bootnode --raw --chain local > $TMP_SPEC $BIN_PATH benchmark pallet \ --chain=$TMP_SPEC \ --execution=native --wasm-execution=compiled \ - --pallet pallet-subtensor --extrinsic 'benchmark_dissolve_network' \ + --pallet pallet-subtensor --extrinsic 'adjust_senate' \ --output $OUTPUT_FILE rm $TMP_SPEC \ No newline at end of file From dc3f17815685a5a0f357685e0234b435bb338f2c Mon Sep 17 00:00:00 2001 From: Keith Date: Mon, 1 Jul 2024 17:01:28 +0200 Subject: [PATCH 42/51] Make weighted_median iterative --- pallets/subtensor/src/math.rs | 85 +++++++++++++++-------------------- 1 file changed, 37 insertions(+), 48 deletions(-) diff --git a/pallets/subtensor/src/math.rs b/pallets/subtensor/src/math.rs index 8b6e76f2c..dc067167f 100644 --- a/pallets/subtensor/src/math.rs +++ b/pallets/subtensor/src/math.rs @@ -888,59 +888,48 @@ pub fn weighted_median( score: &[I32F32], partition_idx: &[usize], minority: I32F32, - partition_lo: I32F32, - partition_hi: I32F32, + mut partition_lo: I32F32, + mut partition_hi: I32F32, ) -> I32F32 { - let n = partition_idx.len(); - if n == 0 { - return I32F32::from_num(0); - } - if n == 1 { - return score[partition_idx[0]]; - } - assert!(stake.len() == score.len()); - let mid_idx: usize = n.saturating_div(2); - let pivot: I32F32 = score[partition_idx[mid_idx]]; - let mut lo_stake: I32F32 = I32F32::from_num(0); - let mut hi_stake: I32F32 = I32F32::from_num(0); - let mut lower: Vec = vec![]; - let mut upper: Vec = vec![]; - for &idx in partition_idx { - if score[idx] == pivot { - continue; + let mut current_partition_idx = partition_idx.to_vec(); + while !current_partition_idx.is_empty() { + let n = current_partition_idx.len(); + if n == 1 { + return score[current_partition_idx[0]]; + } + let mid_idx: usize = n.saturating_div(2); + let pivot: I32F32 = score[current_partition_idx[mid_idx]]; + let mut lo_stake: I32F32 = I32F32::from_num(0); + let mut hi_stake: I32F32 = I32F32::from_num(0); + let mut lower: Vec = vec![]; + let mut upper: Vec = vec![]; + for &idx in ¤t_partition_idx { + if score[idx] == pivot { + continue; + } + if score[idx] < pivot { + lo_stake = lo_stake.saturating_add(stake[idx]); + lower.push(idx); + } else { + hi_stake = hi_stake.saturating_add(stake[idx]); + upper.push(idx); + } } - if score[idx] < pivot { - lo_stake = lo_stake.saturating_add(stake[idx]); - lower.push(idx); + if partition_lo.saturating_add(lo_stake) <= minority + && minority < partition_hi.saturating_sub(hi_stake) + { + return pivot; + } else if (minority < partition_lo.saturating_add(lo_stake)) && (!lower.is_empty()) { + current_partition_idx = lower; + partition_hi = partition_lo.saturating_add(lo_stake); + } else if (partition_hi.saturating_sub(hi_stake) <= minority) && (!upper.is_empty()) { + current_partition_idx = upper; + partition_lo = partition_hi.saturating_sub(hi_stake); } else { - hi_stake = hi_stake.saturating_add(stake[idx]); - upper.push(idx); + return pivot; } } - if (partition_lo.saturating_add(lo_stake) <= minority) - && (minority < partition_hi.saturating_sub(hi_stake)) - { - return pivot; - } else if (minority < partition_lo.saturating_add(lo_stake)) && (!lower.is_empty()) { - return weighted_median( - stake, - score, - &lower, - minority, - partition_lo, - partition_lo.saturating_add(lo_stake), - ); - } else if (partition_hi.saturating_sub(hi_stake) <= minority) && (!upper.is_empty()) { - return weighted_median( - stake, - score, - &upper, - minority, - partition_hi.saturating_sub(hi_stake), - partition_hi, - ); - } - pivot + I32F32::from_num(0) } /// Column-wise weighted median, e.g. stake-weighted median scores per server (column) over all validators (rows). From 177c47ac9ccfc356cd8901e814db903b8ba2988b Mon Sep 17 00:00:00 2001 From: Sam Johnson Date: Fri, 12 Jul 2024 12:29:15 -0400 Subject: [PATCH 43/51] fix merge conflict --- pallets/subtensor/tests/mock.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pallets/subtensor/tests/mock.rs b/pallets/subtensor/tests/mock.rs index ec7087eaf..3aa6123e1 100644 --- a/pallets/subtensor/tests/mock.rs +++ b/pallets/subtensor/tests/mock.rs @@ -1,7 +1,5 @@ #![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::weights::constants::WEIGHT_PER_SECOND; use frame_support::weights::Weight; use frame_support::{ @@ -9,6 +7,7 @@ use frame_support::{ dispatch::DispatchResultWithPostInfo, parameter_types, traits::{Everything, Hooks}, + weights::constants::RocksDbWeight, }; use frame_system as system; use frame_system::{limits, EnsureNever, EnsureRoot, RawOrigin}; From aa5e890dab6e2f55f419680e5316806c1feb2f2d Mon Sep 17 00:00:00 2001 From: Cameron Fairchild Date: Fri, 19 Jul 2024 09:02:42 -0400 Subject: [PATCH 44/51] Merge main into devnet ready 7 18 2024 (#650) * draft: hotkey swap for senate * feat: remove schedule coldkey swap * chore: fix tests * fixes for network resumption * chore: bump spec * fix: add back arbitration check * fix: hotkey * fix: coldkey arb swap hotkey * swap delegate stake also * add test for this * swap over stakinghotkeys map * check map first * add staking hotkeys test * no take * keep old stake * add check to test * fix some tests * fix delegate test * update staking hotekys maps * init * comment out * add admin swap * fix swap * .. * hotkey staking maps fix * remove staking hotkeys * remove commented code * cargo fmt * cargo fix --workspace * bump spec_version to 165 * swap hotkey benchmark removed * add migration and tests for total coldkey hotfix * adds new test for missing hotkey value * bump migration values * fmt * feat: try runtime passing * chore: remove commented code * chore: make logs human readable * chore: remove comments * Update pallets/subtensor/src/lib.rs Co-authored-by: Sam Johnson * add test first * clear map before rest of migration * track weight for clear/removal * add comment * rename test * add test for emission appends staking hotkeys map * Update runtime/src/lib.rs --------- Co-authored-by: Samuel Dare Co-authored-by: distributedstatemachine <112424909+distributedstatemachine@users.noreply.github.com> Co-authored-by: const Co-authored-by: Sam Johnson Co-authored-by: Unconst <32490803+unconst@users.noreply.github.com> --- pallets/admin-utils/tests/mock.rs | 4 +- pallets/subtensor/src/benchmarks.rs | 80 +++---- pallets/subtensor/src/lib.rs | 46 ++-- pallets/subtensor/src/migration.rs | 87 ++++++++ pallets/subtensor/src/swap.rs | 130 +++++++++-- pallets/subtensor/src/utils.rs | 4 +- pallets/subtensor/tests/migration.rs | 148 +++++++++++- pallets/subtensor/tests/mock.rs | 4 +- pallets/subtensor/tests/registration.rs | 284 ++++++++++++------------ pallets/subtensor/tests/staking.rs | 32 +++ pallets/subtensor/tests/swap.rs | 252 ++++++++++++++++++--- runtime/src/lib.rs | 9 +- 12 files changed, 819 insertions(+), 261 deletions(-) diff --git a/pallets/admin-utils/tests/mock.rs b/pallets/admin-utils/tests/mock.rs index 5f71626ad..dbf88bdfa 100644 --- a/pallets/admin-utils/tests/mock.rs +++ b/pallets/admin-utils/tests/mock.rs @@ -110,7 +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 InitialKeySwapCost: 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 @@ -166,7 +166,7 @@ impl pallet_subtensor::Config for Test { type InitialSubnetLimit = InitialSubnetLimit; type InitialNetworkRateLimit = InitialNetworkRateLimit; type InitialTargetStakesPerInterval = InitialTargetStakesPerInterval; - type HotkeySwapCost = InitialHotkeySwapCost; + type KeySwapCost = InitialKeySwapCost; type AlphaHigh = InitialAlphaHigh; type AlphaLow = InitialAlphaLow; type LiquidAlphaOn = InitialLiquidAlphaOn; diff --git a/pallets/subtensor/src/benchmarks.rs b/pallets/subtensor/src/benchmarks.rs index ee7a437a9..c6c9ac481 100644 --- a/pallets/subtensor/src/benchmarks.rs +++ b/pallets/subtensor/src/benchmarks.rs @@ -314,33 +314,33 @@ benchmarks! { assert_ok!(Subtensor::::register_network(RawOrigin::Signed(coldkey.clone()).into())); }: dissolve_network(RawOrigin::Signed(coldkey), 1) - swap_hotkey { - let seed: u32 = 1; - let coldkey: T::AccountId = account("Alice", 0, seed); - let old_hotkey: T::AccountId = account("Bob", 0, seed); - let new_hotkey: T::AccountId = account("Charlie", 0, seed); - - let netuid = 1u16; - Subtensor::::init_new_network(netuid, 100); - Subtensor::::set_min_burn(netuid, 1); - Subtensor::::set_max_burn(netuid, 1); - Subtensor::::set_target_registrations_per_interval(netuid, 256); - Subtensor::::set_max_registrations_per_block(netuid, 256); - - Subtensor::::add_balance_to_coldkey_account(&coldkey.clone(), 10_000_000_000u64); - assert_ok!(Subtensor::::burned_register(RawOrigin::Signed(coldkey.clone()).into(), netuid, old_hotkey.clone())); - assert_ok!(Subtensor::::become_delegate(RawOrigin::Signed(coldkey.clone()).into(), old_hotkey.clone())); - - let max_uids = Subtensor::::get_max_allowed_uids(netuid) as u32; - for i in 0..max_uids - 1 { - let coldkey: T::AccountId = account("Axon", 0, i); - let hotkey: T::AccountId = account("Hotkey", 0, i); - - Subtensor::::add_balance_to_coldkey_account(&coldkey.clone(), 10_000_000_000u64); - assert_ok!(Subtensor::::burned_register(RawOrigin::Signed(coldkey.clone()).into(), netuid, hotkey)); - assert_ok!(Subtensor::::add_stake(RawOrigin::Signed(coldkey).into(), old_hotkey.clone(), 1_000_000_000)); - } - }: _(RawOrigin::Signed(coldkey), old_hotkey, new_hotkey) + // swap_hotkey { + // let seed: u32 = 1; + // let coldkey: T::AccountId = account("Alice", 0, seed); + // let old_hotkey: T::AccountId = account("Bob", 0, seed); + // let new_hotkey: T::AccountId = account("Charlie", 0, seed); + + // let netuid = 1u16; + // Subtensor::::init_new_network(netuid, 100); + // Subtensor::::set_min_burn(netuid, 1); + // Subtensor::::set_max_burn(netuid, 1); + // Subtensor::::set_target_registrations_per_interval(netuid, 256); + // Subtensor::::set_max_registrations_per_block(netuid, 256); + + // Subtensor::::add_balance_to_coldkey_account(&coldkey.clone(), 10_000_000_000u64); + // assert_ok!(Subtensor::::burned_register(RawOrigin::Signed(coldkey.clone()).into(), netuid, old_hotkey.clone())); + // assert_ok!(Subtensor::::become_delegate(RawOrigin::Signed(coldkey.clone()).into(), old_hotkey.clone())); + + // let max_uids = Subtensor::::get_max_allowed_uids(netuid) as u32; + // for i in 0..max_uids - 1 { + // let coldkey: T::AccountId = account("Axon", 0, i); + // let hotkey: T::AccountId = account("Hotkey", 0, i); + + // Subtensor::::add_balance_to_coldkey_account(&coldkey.clone(), 10_000_000_000u64); + // assert_ok!(Subtensor::::burned_register(RawOrigin::Signed(coldkey.clone()).into(), netuid, hotkey)); + // assert_ok!(Subtensor::::add_stake(RawOrigin::Signed(coldkey).into(), old_hotkey.clone(), 1_000_000_000)); + // } + // }: _(RawOrigin::Signed(coldkey), old_hotkey, new_hotkey) commit_weights { let tempo: u16 = 1; @@ -429,30 +429,4 @@ reveal_weights { }: reveal_weights(RawOrigin::Signed(hotkey.clone()), netuid, uids, weight_values, salt, version_key) - schedule_coldkey_swap { - let seed: u32 = 1; - let old_coldkey: T::AccountId = account("OldColdkey", 0, seed); - let new_coldkey: T::AccountId = account("NewColdkey", 0, seed + 1); - let hotkey: T::AccountId = account("Hotkey", 0, seed); - - let netuid = 1u16; - let tempo = 1u16; - let block_number: u64 = Subtensor::::get_current_block_as_u64(); - let nonce = 0; - - // Initialize the network - Subtensor::::init_new_network(netuid, tempo); - Subtensor::::set_network_registration_allowed(netuid, true); - - // Add balance to the old coldkey account - let amount_to_be_staked: u64 = 1000000u32.into(); - Subtensor::::add_balance_to_coldkey_account(&old_coldkey.clone(), amount_to_be_staked+1000000000); - // Burned register the hotkey with the old coldkey - assert_ok!(Subtensor::::burned_register( - RawOrigin::Signed(old_coldkey.clone()).into(), - netuid, - hotkey.clone() - )); - - }: schedule_coldkey_swap(RawOrigin::Signed(old_coldkey.clone()), new_coldkey.clone(), vec![], block_number, nonce) } diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index 240e86a57..0f10bc581 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -84,7 +84,7 @@ pub mod pallet { /// Tracks version for migrations. Should be monotonic with respect to the /// order of migrations. (i.e. always increasing) - const STORAGE_VERSION: StorageVersion = StorageVersion::new(6); + const STORAGE_VERSION: StorageVersion = StorageVersion::new(7); /// Minimum balance required to perform a coldkey swap pub const MIN_BALANCE_TO_PERFORM_COLDKEY_SWAP: u64 = 100_000_000; // 0.1 TAO in RAO @@ -247,7 +247,7 @@ pub mod pallet { type InitialTargetStakesPerInterval: Get; /// Cost of swapping a hotkey. #[pallet::constant] - type HotkeySwapCost: Get; + type KeySwapCost: Get; /// The upper bound for the alpha parameter. Used for Liquid Alpha. #[pallet::constant] type AlphaHigh: Get; @@ -1140,6 +1140,9 @@ pub mod pallet { DefaultBonds, >; + #[pallet::storage] // --- Storage for migration run status + pub type HasMigrationRun = StorageMap<_, Identity, Vec, bool, ValueQuery>; + /// ================== /// ==== Genesis ===== /// ================== @@ -1419,7 +1422,9 @@ pub mod pallet { // Populate OwnedHotkeys map for coldkey swap. Doesn't update storage vesion. .saturating_add(migration::migrate_populate_owned::()) // Populate StakingHotkeys map for coldkey swap. Doesn't update storage vesion. - .saturating_add(migration::migrate_populate_staking_hotkeys::()); + .saturating_add(migration::migrate_populate_staking_hotkeys::()) + // Fix total coldkey stake. + .saturating_add(migration::migrate_fix_total_coldkey_stake::()); weight } @@ -2062,17 +2067,17 @@ pub mod pallet { } /// The extrinsic for user to change its hotkey - #[pallet::call_index(70)] - #[pallet::weight((Weight::from_parts(1_940_000_000, 0) - .saturating_add(T::DbWeight::get().reads(272)) - .saturating_add(T::DbWeight::get().writes(527)), DispatchClass::Operational, Pays::No))] - pub fn swap_hotkey( - origin: OriginFor, - hotkey: T::AccountId, - new_hotkey: T::AccountId, - ) -> DispatchResultWithPostInfo { - Self::do_swap_hotkey(origin, &hotkey, &new_hotkey) - } + ///#[pallet::call_index(70)] + ///#[pallet::weight((Weight::from_parts(1_940_000_000, 0) + ///.saturating_add(T::DbWeight::get().reads(272)) + ///.saturating_add(T::DbWeight::get().writes(527)), DispatchClass::Operational, Pays::No))] + ///pub fn swap_hotkey( + /// origin: OriginFor, + /// hotkey: T::AccountId, + /// new_hotkey: T::AccountId, + ///) -> DispatchResultWithPostInfo { + /// Self::do_swap_hotkey(origin, &hotkey, &new_hotkey) + ///} /// The extrinsic for user to change the coldkey associated with their account. /// @@ -2099,7 +2104,6 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { Self::do_swap_coldkey(origin, &new_coldkey) } - /// Unstakes all tokens associated with a hotkey and transfers them to a new coldkey. /// /// # Arguments @@ -2115,6 +2119,7 @@ pub mod pallet { /// # Weight /// /// Weight is calculated based on the number of database reads and writes. + #[cfg(test)] #[pallet::call_index(72)] #[pallet::weight((Weight::from_parts(21_000_000, 0) .saturating_add(T::DbWeight::get().reads(3)) @@ -2254,6 +2259,17 @@ pub mod pallet { pub fn dissolve_network(origin: OriginFor, netuid: u16) -> DispatchResult { Self::user_remove_network(origin, netuid) } + + /// Sets values for liquid alpha + #[pallet::call_index(64)] + #[pallet::weight((0, DispatchClass::Operational, Pays::No))] + pub fn sudo_hotfix_swap_coldkey_delegates( + _origin: OriginFor, + _old_coldkey: T::AccountId, + _new_coldkey: T::AccountId, + ) -> DispatchResult { + Ok(()) + } } // ---- Subtensor helper functions. diff --git a/pallets/subtensor/src/migration.rs b/pallets/subtensor/src/migration.rs index 35b3c4260..866ff08fd 100644 --- a/pallets/subtensor/src/migration.rs +++ b/pallets/subtensor/src/migration.rs @@ -1,4 +1,5 @@ use super::*; +use alloc::string::String; use frame_support::traits::DefensiveResult; use frame_support::{ pallet_prelude::{Identity, OptionQuery}, @@ -24,6 +25,92 @@ pub mod deprecated_loaded_emission_format { StorageMap, Identity, u16, Vec<(AccountIdOf, u64)>, OptionQuery>; } +/// Migrates and fixes the total coldkey stake. +/// +/// This function iterates through all staking hotkeys, calculates the total stake for each coldkey, +/// and updates the `TotalColdkeyStake` storage accordingly. The migration is only performed if the +/// on-chain storage version is 6. +/// +/// # Returns +/// The weight of the migration process. +pub fn do_migrate_fix_total_coldkey_stake() -> Weight { + // Initialize the weight with one read operation. + let mut weight = T::DbWeight::get().reads(1); + + // Clear everything from the map first, no limit (u32::MAX) + let removal_results = TotalColdkeyStake::::clear(u32::MAX, None); + // 1 read/write per removal + let entries_removed: u64 = removal_results.backend.into(); + weight = + weight.saturating_add(T::DbWeight::get().reads_writes(entries_removed, entries_removed)); + + // Iterate through all staking hotkeys. + for (coldkey, hotkey_vec) in StakingHotkeys::::iter() { + // Init the zero value. + let mut coldkey_stake_sum: u64 = 0; + weight = weight.saturating_add(T::DbWeight::get().reads(1)); + + // Calculate the total stake for the current coldkey. + for hotkey in hotkey_vec { + // Cant fail on retrieval. + coldkey_stake_sum = + coldkey_stake_sum.saturating_add(Stake::::get(hotkey, coldkey.clone())); + weight = weight.saturating_add(T::DbWeight::get().reads(1)); + } + // Update the `TotalColdkeyStake` storage with the calculated stake sum. + // Cant fail on insert. + TotalColdkeyStake::::insert(coldkey.clone(), coldkey_stake_sum); + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + } + weight +} + +/// Migrates and fixes the total coldkey stake. +/// +/// This function checks if the migration has already run, and if not, it performs the migration +/// to fix the total coldkey stake. It also marks the migration as completed after running. +/// +/// # Returns +/// The weight of the migration process. +pub fn migrate_fix_total_coldkey_stake() -> Weight { + let migration_name = b"fix_total_coldkey_stake_v7".to_vec(); + + // Initialize the weight with one read operation. + let mut weight = T::DbWeight::get().reads(1); + + // Check if the migration has already run + if HasMigrationRun::::get(&migration_name) { + log::info!( + "Migration '{:?}' has already run. Skipping.", + migration_name + ); + return Weight::zero(); + } + + log::info!( + "Running migration '{}'", + String::from_utf8_lossy(&migration_name) + ); + + // Run the migration + weight = weight.saturating_add(do_migrate_fix_total_coldkey_stake::()); + + // Mark the migration as completed + HasMigrationRun::::insert(&migration_name, true); + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + + // Set the storage version to 7 + StorageVersion::new(7).put::>(); + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + + log::info!( + "Migration '{:?}' completed. Storage version set to 7.", + String::from_utf8_lossy(&migration_name) + ); + + // Return the migration weight. + weight +} /// Performs migration to update the total issuance based on the sum of stakes and total balances. /// This migration is applicable only if the current storage version is 5, after which it updates the storage version to 6. /// diff --git a/pallets/subtensor/src/swap.rs b/pallets/subtensor/src/swap.rs index 24d67aeb4..8e4ca5cc9 100644 --- a/pallets/subtensor/src/swap.rs +++ b/pallets/subtensor/src/swap.rs @@ -31,6 +31,7 @@ impl Pallet { new_hotkey: &T::AccountId, ) -> DispatchResultWithPostInfo { let coldkey = ensure_signed(origin)?; + ensure!( !Self::coldkey_in_arbitration(&coldkey), Error::::ColdkeyIsInArbitration @@ -60,6 +61,16 @@ impl Pallet { T::DbWeight::get().reads((TotalNetworks::::get().saturating_add(1u16)) as u64), ); + let swap_cost = Self::get_key_swap_cost(); + log::debug!("Swap cost: {:?}", swap_cost); + + ensure!( + Self::can_remove_balance_from_coldkey_account(&coldkey, swap_cost), + Error::::NotEnoughBalanceToPaySwapHotKey + ); + let actual_burn_amount = Self::remove_balance_from_coldkey_account(&coldkey, swap_cost)?; + Self::burn_tokens(actual_burn_amount); + Self::swap_owner(old_hotkey, new_hotkey, &coldkey, &mut weight); Self::swap_total_hotkey_stake(old_hotkey, new_hotkey, &mut weight); Self::swap_delegates(old_hotkey, new_hotkey, &mut weight); @@ -74,6 +85,7 @@ impl Pallet { Self::swap_loaded_emission(old_hotkey, new_hotkey, &netuid_is_member, &mut weight); Self::swap_uids(old_hotkey, new_hotkey, &netuid_is_member, &mut weight); Self::swap_prometheus(old_hotkey, new_hotkey, &netuid_is_member, &mut weight); + Self::swap_senate_member(old_hotkey, new_hotkey, &mut weight)?; Self::swap_total_hotkey_coldkey_stakes_this_interval(old_hotkey, new_hotkey, &mut weight); @@ -140,6 +152,20 @@ impl Pallet { Error::::ColdKeyAlreadyAssociated ); + // Calculate and charge the swap fee + let swap_cost = Self::get_key_swap_cost(); + log::debug!("Coldkey swap cost: {:?}", swap_cost); + + ensure!( + Self::can_remove_balance_from_coldkey_account(&old_coldkey, swap_cost), + Error::::NotEnoughBalanceToPaySwapColdKey + ); + let actual_burn_amount = + Self::remove_balance_from_coldkey_account(&old_coldkey, swap_cost)?; + Self::burn_tokens(actual_burn_amount); + + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); + // Actually do the swap. weight = weight.saturating_add( Self::perform_swap_coldkey(&old_coldkey, new_coldkey) @@ -189,15 +215,15 @@ impl Pallet { /// /// This function calculates the remaining arbitration period by subtracting the current block number /// from the arbitration block number of the coldkey. - // pub fn get_remaining_arbitration_period(coldkey: &T::AccountId) -> u64 { - // let current_block: u64 = Self::get_current_block_as_u64(); - // let arbitration_block: u64 = ColdkeyArbitrationBlock::::get(coldkey); - // if arbitration_block > current_block { - // arbitration_block.saturating_sub(current_block) - // } else { - // 0 - // } - // } + pub fn get_remaining_arbitration_period(coldkey: &T::AccountId) -> u64 { + let current_block: u64 = Self::get_current_block_as_u64(); + let arbitration_block: u64 = ColdkeyArbitrationBlock::::get(coldkey); + if arbitration_block > current_block { + arbitration_block.saturating_sub(current_block) + } else { + 0 + } + } pub fn meets_min_allowed_coldkey_balance(coldkey: &T::AccountId) -> bool { let all_staked_keys: Vec = StakingHotkeys::::get(coldkey); @@ -825,7 +851,8 @@ impl Pallet { log::info!("Transferring stake for hotkey {:?}: {}", hotkey, stake); if stake > 0 { // Insert the stake for the hotkey and new coldkey - Stake::::insert(hotkey, new_coldkey, stake); + let old_stake = Stake::::get(hotkey, new_coldkey); + Stake::::insert(hotkey, new_coldkey, stake.saturating_add(old_stake)); total_transferred_stake = total_transferred_stake.saturating_add(stake); // Update the owner of the hotkey to the new coldkey @@ -835,6 +862,52 @@ impl Pallet { weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2)); } } + log::info!( + "Starting transfer of delegated stakes for old coldkey: {:?}", + old_coldkey + ); + + for staking_hotkey in StakingHotkeys::::get(old_coldkey) { + log::info!("Processing staking hotkey: {:?}", staking_hotkey); + if Stake::::contains_key(staking_hotkey.clone(), old_coldkey) { + let hotkey = &staking_hotkey; + // Retrieve and remove the stake associated with the hotkey and old coldkey + let stake: u64 = Stake::::get(hotkey, old_coldkey); + Stake::::remove(hotkey, old_coldkey); + log::info!( + "Transferring delegated stake for hotkey {:?}: {}", + hotkey, + stake + ); + if stake > 0 { + // Insert the stake for the hotkey and new coldkey + let old_stake = Stake::::get(hotkey, new_coldkey); + Stake::::insert(hotkey, new_coldkey, stake.saturating_add(old_stake)); + total_transferred_stake = total_transferred_stake.saturating_add(stake); + log::info!( + "Updated stake for hotkey {:?} under new coldkey {:?}: {}", + hotkey, + new_coldkey, + stake.saturating_add(old_stake) + ); + + // Update the transaction weight + weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 1)); + } + } else { + log::info!( + "No stake found for staking hotkey {:?} under old coldkey {:?}", + staking_hotkey, + old_coldkey + ); + weight.saturating_accrue(T::DbWeight::get().reads(1)); + } + } + + log::info!( + "Completed transfer of delegated stakes for old coldkey: {:?}", + old_coldkey + ); // Log the total transferred stake log::info!("Total transferred stake: {}", total_transferred_stake); @@ -862,13 +935,30 @@ impl Pallet { } // Update the list of owned hotkeys for both old and new coldkeys + + let mut new_owned_hotkeys = OwnedHotkeys::::get(new_coldkey); + for hotkey in old_owned_hotkeys { + if !new_owned_hotkeys.contains(&hotkey) { + new_owned_hotkeys.push(hotkey); + } + } + + OwnedHotkeys::::insert(new_coldkey, new_owned_hotkeys); OwnedHotkeys::::remove(old_coldkey); - OwnedHotkeys::::insert(new_coldkey, old_owned_hotkeys); weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); // Update the staking hotkeys for both old and new coldkeys - let staking_hotkeys: Vec = StakingHotkeys::::take(old_coldkey); - StakingHotkeys::::insert(new_coldkey, staking_hotkeys); + let staking_hotkeys: Vec = StakingHotkeys::::get(old_coldkey); + + let mut existing_staking_hotkeys = StakingHotkeys::::get(new_coldkey); + for hotkey in staking_hotkeys { + if !existing_staking_hotkeys.contains(&hotkey) { + existing_staking_hotkeys.push(hotkey); + } + } + + StakingHotkeys::::remove(old_coldkey); + StakingHotkeys::::insert(new_coldkey, existing_staking_hotkeys); weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); // Log the total stake of old and new coldkeys after the swap @@ -881,6 +971,7 @@ impl Pallet { TotalColdkeyStake::::get(new_coldkey) ); } + /// Swaps the total hotkey-coldkey stakes for the current interval from the old coldkey to the new coldkey. /// /// # Arguments @@ -948,4 +1039,17 @@ impl Pallet { } weight.saturating_accrue(T::DbWeight::get().reads(TotalNetworks::::get() as u64)); } + + pub fn swap_senate_member( + old_hotkey: &T::AccountId, + new_hotkey: &T::AccountId, + weight: &mut Weight, + ) -> DispatchResult { + weight.saturating_accrue(T::DbWeight::get().reads(1)); + if T::SenateMembers::is_member(old_hotkey) { + T::SenateMembers::swap_member(old_hotkey, new_hotkey).map_err(|e| e.error)?; + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + } + Ok(()) + } } diff --git a/pallets/subtensor/src/utils.rs b/pallets/subtensor/src/utils.rs index 94f18dfbf..c61133e94 100644 --- a/pallets/subtensor/src/utils.rs +++ b/pallets/subtensor/src/utils.rs @@ -671,8 +671,8 @@ impl Pallet { NominatorMinRequiredStake::::put(min_stake); } - pub fn get_hotkey_swap_cost() -> u64 { - T::HotkeySwapCost::get() + pub fn get_key_swap_cost() -> u64 { + T::KeySwapCost::get() } pub fn get_alpha_values(netuid: u16) -> (u16, u16) { diff --git a/pallets/subtensor/tests/migration.rs b/pallets/subtensor/tests/migration.rs index c921124f4..d47155862 100644 --- a/pallets/subtensor/tests/migration.rs +++ b/pallets/subtensor/tests/migration.rs @@ -1,9 +1,10 @@ #![allow(clippy::unwrap_used)] mod mock; -use frame_support::assert_ok; +use frame_support::{assert_ok, weights::Weight}; use frame_system::Config; use mock::*; +use pallet_subtensor::*; use sp_core::U256; #[test] @@ -276,3 +277,148 @@ fn test_migration_delete_subnet_21() { assert!(!SubtensorModule::if_subnet_exist(21)); }) } + +// SKIP_WASM_BUILD=1 RUST_LOG=info cargo test --test migration -- test_migrate_fix_total_coldkey_stake --exact --nocapture +// SKIP_WASM_BUILD=1 RUST_LOG=info cargo test --test migration -- test_migrate_fix_total_coldkey_stake --exact --nocapture +#[test] +fn test_migrate_fix_total_coldkey_stake() { + new_test_ext(1).execute_with(|| { + let migration_name = "fix_total_coldkey_stake_v7"; + let coldkey = U256::from(0); + TotalColdkeyStake::::insert(coldkey, 0); + StakingHotkeys::::insert(coldkey, vec![U256::from(1), U256::from(2), U256::from(3)]); + Stake::::insert(U256::from(1), U256::from(0), 10000); + Stake::::insert(U256::from(2), U256::from(0), 10000); + Stake::::insert(U256::from(3), U256::from(0), 10000); + + let weight = run_migration_and_check(migration_name); + assert!(weight != Weight::zero()); + assert_eq!(TotalColdkeyStake::::get(coldkey), 30000); + + let second_weight = run_migration_and_check(migration_name); + assert_eq!(second_weight, Weight::zero()); + assert_eq!(TotalColdkeyStake::::get(coldkey), 30000); + }) +} + +// SKIP_WASM_BUILD=1 RUST_LOG=info cargo test --test migration -- test_migrate_fix_total_coldkey_stake_value_already_in_total --exact --nocapture +#[test] +fn test_migrate_fix_total_coldkey_stake_value_already_in_total() { + new_test_ext(1).execute_with(|| { + let migration_name = "fix_total_coldkey_stake_v7"; + let coldkey = U256::from(0); + TotalColdkeyStake::::insert(coldkey, 100000000); + StakingHotkeys::::insert(coldkey, vec![U256::from(1), U256::from(2), U256::from(3)]); + Stake::::insert(U256::from(1), U256::from(0), 10000); + Stake::::insert(U256::from(2), U256::from(0), 10000); + Stake::::insert(U256::from(3), U256::from(0), 10000); + + let weight = run_migration_and_check(migration_name); + assert!(weight != Weight::zero()); + assert_eq!(TotalColdkeyStake::::get(coldkey), 30000); + }) +} + +// SKIP_WASM_BUILD=1 RUST_LOG=info cargo test --test migration -- test_migrate_fix_total_coldkey_stake_no_entry --exact --nocapture +#[test] +fn test_migrate_fix_total_coldkey_stake_no_entry() { + new_test_ext(1).execute_with(|| { + let migration_name = "fix_total_coldkey_stake_v7"; + let coldkey = U256::from(0); + StakingHotkeys::::insert(coldkey, vec![U256::from(1), U256::from(2), U256::from(3)]); + Stake::::insert(U256::from(1), U256::from(0), 10000); + Stake::::insert(U256::from(2), U256::from(0), 10000); + Stake::::insert(U256::from(3), U256::from(0), 10000); + + let weight = run_migration_and_check(migration_name); + assert!(weight != Weight::zero()); + assert_eq!(TotalColdkeyStake::::get(coldkey), 30000); + }) +} + +// SKIP_WASM_BUILD=1 RUST_LOG=info cargo test --test migration -- test_migrate_fix_total_coldkey_stake_no_entry_in_hotkeys --exact --nocapture +#[test] +fn test_migrate_fix_total_coldkey_stake_no_entry_in_hotkeys() { + new_test_ext(1).execute_with(|| { + let migration_name = "fix_total_coldkey_stake_v7"; + let coldkey = U256::from(0); + TotalColdkeyStake::::insert(coldkey, 100000000); + StakingHotkeys::::insert(coldkey, vec![U256::from(1), U256::from(2), U256::from(3)]); + + let weight = run_migration_and_check(migration_name); + assert!(weight != Weight::zero()); + assert_eq!(TotalColdkeyStake::::get(coldkey), 0); + }) +} + +// SKIP_WASM_BUILD=1 RUST_LOG=info cargo test --test migration -- test_migrate_fix_total_coldkey_stake_one_hotkey_stake_missing --exact --nocapture +#[test] +fn test_migrate_fix_total_coldkey_stake_one_hotkey_stake_missing() { + new_test_ext(1).execute_with(|| { + let migration_name = "fix_total_coldkey_stake_v7"; + let coldkey = U256::from(0); + TotalColdkeyStake::::insert(coldkey, 100000000); + StakingHotkeys::::insert(coldkey, vec![U256::from(1), U256::from(2), U256::from(3)]); + Stake::::insert(U256::from(1), U256::from(0), 10000); + Stake::::insert(U256::from(2), U256::from(0), 10000); + + let weight = run_migration_and_check(migration_name); + assert!(weight != Weight::zero()); + assert_eq!(TotalColdkeyStake::::get(coldkey), 20000); + }) +} + +// New test to check if migration runs only once +#[test] +fn test_migrate_fix_total_coldkey_stake_runs_once() { + new_test_ext(1).execute_with(|| { + let migration_name = "fix_total_coldkey_stake_v7"; + let coldkey = U256::from(0); + TotalColdkeyStake::::insert(coldkey, 0); + StakingHotkeys::::insert(coldkey, vec![U256::from(1), U256::from(2), U256::from(3)]); + Stake::::insert(U256::from(1), U256::from(0), 10000); + Stake::::insert(U256::from(2), U256::from(0), 10000); + Stake::::insert(U256::from(3), U256::from(0), 10000); + + // First run + let first_weight = run_migration_and_check(migration_name); + assert!(first_weight != Weight::zero()); + assert_eq!(TotalColdkeyStake::::get(coldkey), 30000); + + // Second run + let second_weight = run_migration_and_check(migration_name); + assert_eq!(second_weight, Weight::zero()); + assert_eq!(TotalColdkeyStake::::get(coldkey), 30000); + }) +} + +// SKIP_WASM_BUILD=1 RUST_LOG=info cargo test --test migration -- test_migrate_fix_total_coldkey_stake_starts_with_value_no_stake_map_entries --exact --nocapture +#[test] +fn test_migrate_fix_total_coldkey_stake_starts_with_value_no_stake_map_entries() { + new_test_ext(1).execute_with(|| { + let migration_name = "fix_total_coldkey_stake_v7"; + let coldkey = U256::from(0); + TotalColdkeyStake::::insert(coldkey, 123_456_789); + + // Notably, coldkey has no stake map or staking_hotkeys map entries + + let weight = run_migration_and_check(migration_name); + assert!(weight != Weight::zero()); + // Therefore 0 + assert_eq!(TotalColdkeyStake::::get(coldkey), 0); + }) +} + +fn run_migration_and_check(migration_name: &'static str) -> frame_support::weights::Weight { + // Execute the migration and store its weight + let weight: frame_support::weights::Weight = + pallet_subtensor::migration::migrate_fix_total_coldkey_stake::(); + + // Check if the migration has been marked as completed + assert!(HasMigrationRun::::get( + migration_name.as_bytes().to_vec() + )); + + // Return the weight of the executed migration + weight +} diff --git a/pallets/subtensor/tests/mock.rs b/pallets/subtensor/tests/mock.rs index 3aa6123e1..aa2c4ad30 100644 --- a/pallets/subtensor/tests/mock.rs +++ b/pallets/subtensor/tests/mock.rs @@ -165,7 +165,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 InitialKeySwapCost: 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 @@ -376,7 +376,7 @@ impl pallet_subtensor::Config for Test { type InitialSubnetLimit = InitialSubnetLimit; type InitialNetworkRateLimit = InitialNetworkRateLimit; type InitialTargetStakesPerInterval = InitialTargetStakesPerInterval; - type HotkeySwapCost = InitialHotkeySwapCost; + type KeySwapCost = InitialKeySwapCost; type AlphaHigh = InitialAlphaHigh; type AlphaLow = InitialAlphaLow; type LiquidAlphaOn = InitialLiquidAlphaOn; diff --git a/pallets/subtensor/tests/registration.rs b/pallets/subtensor/tests/registration.rs index 676d49a44..bd95ae3b1 100644 --- a/pallets/subtensor/tests/registration.rs +++ b/pallets/subtensor/tests/registration.rs @@ -1868,153 +1868,153 @@ fn test_registration_disabled() { }); } -#[ignore] -#[test] -fn test_hotkey_swap_ok() { - new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; - let tempo: u16 = 13; - let hotkey_account_id = U256::from(1); - let burn_cost = 1000; - let coldkey_account_id = U256::from(667); - - SubtensorModule::set_burn(netuid, burn_cost); - add_network(netuid, tempo, 0); - - // Give it some $$$ in his coldkey balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10_000_000_000); - - // Subscribe and check extrinsic output - assert_ok!(SubtensorModule::burned_register( - <::RuntimeOrigin>::signed(coldkey_account_id), - netuid, - hotkey_account_id - )); - - let new_hotkey = U256::from(1337); - assert_ok!(SubtensorModule::swap_hotkey( - <::RuntimeOrigin>::signed(coldkey_account_id), - hotkey_account_id, - new_hotkey - )); - assert_ne!( - SubtensorModule::get_owning_coldkey_for_hotkey(&hotkey_account_id), - coldkey_account_id - ); - assert_eq!( - SubtensorModule::get_owning_coldkey_for_hotkey(&new_hotkey), - coldkey_account_id - ); - }); -} - -#[ignore] -#[test] -fn test_hotkey_swap_not_owner() { - new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; - let tempo: u16 = 13; - let hotkey_account_id = U256::from(1); - let burn_cost = 1000; - let coldkey_account_id = U256::from(2); - let not_owner_coldkey = U256::from(3); - - SubtensorModule::set_burn(netuid, burn_cost); - add_network(netuid, tempo, 0); - - // Give it some $$$ in his coldkey balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); - - // Subscribe and check extrinsic output - assert_ok!(SubtensorModule::burned_register( - <::RuntimeOrigin>::signed(coldkey_account_id), - netuid, - hotkey_account_id - )); - - let new_hotkey = U256::from(4); - assert_err!( - SubtensorModule::swap_hotkey( - <::RuntimeOrigin>::signed(not_owner_coldkey), - hotkey_account_id, - new_hotkey - ), - Error::::NonAssociatedColdKey - ); - }); -} - -#[ignore] -#[test] -fn test_hotkey_swap_same_key() { - new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; - let tempo: u16 = 13; - let hotkey_account_id = U256::from(1); - let burn_cost = 1000; - let coldkey_account_id = U256::from(2); - - SubtensorModule::set_burn(netuid, burn_cost); - add_network(netuid, tempo, 0); - - // Give it some $$$ in his coldkey balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); +// #[ignore] +// #[test] +// fn test_hotkey_swap_ok() { +// new_test_ext(1).execute_with(|| { +// let netuid: u16 = 1; +// let tempo: u16 = 13; +// let hotkey_account_id = U256::from(1); +// let burn_cost = 1000; +// let coldkey_account_id = U256::from(667); + +// SubtensorModule::set_burn(netuid, burn_cost); +// add_network(netuid, tempo, 0); + +// // Give it some $$$ in his coldkey balance +// SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10_000_000_000); + +// // Subscribe and check extrinsic output +// assert_ok!(SubtensorModule::burned_register( +// <::RuntimeOrigin>::signed(coldkey_account_id), +// netuid, +// hotkey_account_id +// )); - // Subscribe and check extrinsic output - assert_ok!(SubtensorModule::burned_register( - <::RuntimeOrigin>::signed(coldkey_account_id), - netuid, - hotkey_account_id - )); +// let new_hotkey = U256::from(1337); +// assert_ok!(SubtensorModule::swap_hotkey( +// <::RuntimeOrigin>::signed(coldkey_account_id), +// hotkey_account_id, +// new_hotkey +// )); +// assert_ne!( +// SubtensorModule::get_owning_coldkey_for_hotkey(&hotkey_account_id), +// coldkey_account_id +// ); +// assert_eq!( +// SubtensorModule::get_owning_coldkey_for_hotkey(&new_hotkey), +// coldkey_account_id +// ); +// }); +// } - assert_err!( - SubtensorModule::swap_hotkey( - <::RuntimeOrigin>::signed(coldkey_account_id), - hotkey_account_id, - hotkey_account_id - ), - Error::::HotKeyAlreadyRegisteredInSubNet - ); - }); -} +// #[ignore] +// #[test] +// fn test_hotkey_swap_not_owner() { +// new_test_ext(1).execute_with(|| { +// let netuid: u16 = 1; +// let tempo: u16 = 13; +// let hotkey_account_id = U256::from(1); +// let burn_cost = 1000; +// let coldkey_account_id = U256::from(2); +// let not_owner_coldkey = U256::from(3); + +// SubtensorModule::set_burn(netuid, burn_cost); +// add_network(netuid, tempo, 0); + +// // Give it some $$$ in his coldkey balance +// SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); + +// // Subscribe and check extrinsic output +// assert_ok!(SubtensorModule::burned_register( +// <::RuntimeOrigin>::signed(coldkey_account_id), +// netuid, +// hotkey_account_id +// )); -#[ignore] -#[test] -fn test_hotkey_swap_registered_key() { - new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; - let tempo: u16 = 13; - let hotkey_account_id = U256::from(1); - let burn_cost = 1000; - let coldkey_account_id = U256::from(2); +// let new_hotkey = U256::from(4); +// assert_err!( +// SubtensorModule::swap_hotkey( +// <::RuntimeOrigin>::signed(not_owner_coldkey), +// hotkey_account_id, +// new_hotkey +// ), +// Error::::NonAssociatedColdKey +// ); +// }); +// } - SubtensorModule::set_burn(netuid, burn_cost); - add_network(netuid, tempo, 0); +// #[ignore] +// #[test] +// fn test_hotkey_swap_same_key() { +// new_test_ext(1).execute_with(|| { +// let netuid: u16 = 1; +// let tempo: u16 = 13; +// let hotkey_account_id = U256::from(1); +// let burn_cost = 1000; +// let coldkey_account_id = U256::from(2); + +// SubtensorModule::set_burn(netuid, burn_cost); +// add_network(netuid, tempo, 0); + +// // Give it some $$$ in his coldkey balance +// SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 10000); + +// // Subscribe and check extrinsic output +// assert_ok!(SubtensorModule::burned_register( +// <::RuntimeOrigin>::signed(coldkey_account_id), +// netuid, +// hotkey_account_id +// )); - // Give it some $$$ in his coldkey balance - SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 100_000_000_000); +// assert_err!( +// SubtensorModule::swap_hotkey( +// <::RuntimeOrigin>::signed(coldkey_account_id), +// hotkey_account_id, +// hotkey_account_id +// ), +// Error::::HotKeyAlreadyRegisteredInSubNet +// ); +// }); +// } - // Subscribe and check extrinsic output - assert_ok!(SubtensorModule::burned_register( - <::RuntimeOrigin>::signed(coldkey_account_id), - netuid, - hotkey_account_id - )); +// #[ignore] +// #[test] +// fn test_hotkey_swap_registered_key() { +// new_test_ext(1).execute_with(|| { +// let netuid: u16 = 1; +// let tempo: u16 = 13; +// let hotkey_account_id = U256::from(1); +// let burn_cost = 1000; +// let coldkey_account_id = U256::from(2); + +// SubtensorModule::set_burn(netuid, burn_cost); +// add_network(netuid, tempo, 0); + +// // Give it some $$$ in his coldkey balance +// SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 100_000_000_000); + +// // Subscribe and check extrinsic output +// assert_ok!(SubtensorModule::burned_register( +// <::RuntimeOrigin>::signed(coldkey_account_id), +// netuid, +// hotkey_account_id +// )); - let new_hotkey = U256::from(3); - assert_ok!(SubtensorModule::burned_register( - <::RuntimeOrigin>::signed(coldkey_account_id), - netuid, - new_hotkey - )); +// let new_hotkey = U256::from(3); +// assert_ok!(SubtensorModule::burned_register( +// <::RuntimeOrigin>::signed(coldkey_account_id), +// netuid, +// new_hotkey +// )); - assert_err!( - SubtensorModule::swap_hotkey( - <::RuntimeOrigin>::signed(coldkey_account_id), - hotkey_account_id, - new_hotkey - ), - Error::::HotKeyAlreadyRegisteredInSubNet - ); - }); -} +// assert_err!( +// SubtensorModule::swap_hotkey( +// <::RuntimeOrigin>::signed(coldkey_account_id), +// hotkey_account_id, +// new_hotkey +// ), +// Error::::HotKeyAlreadyRegisteredInSubNet +// ); +// }); +// } diff --git a/pallets/subtensor/tests/staking.rs b/pallets/subtensor/tests/staking.rs index 5db439e5b..cb2cac4ef 100644 --- a/pallets/subtensor/tests/staking.rs +++ b/pallets/subtensor/tests/staking.rs @@ -4719,3 +4719,35 @@ fn test_do_schedule_coldkey_swap_regular_user_passes_min_balance() { ); }); } + +// SKIP_WASM_BUILD=1 RUST_LOG=info cargo test --test staking -- test_emission_creates_staking_hotkeys_entry --exact --nocapture +#[test] +fn test_emission_creates_staking_hotkeys_entry() { + new_test_ext(1).execute_with(|| { + let hotkey0 = U256::from(1); + let hotkey1 = U256::from(2); + + let coldkey = U256::from(3); + + // Add to Owner map + Owner::::insert(hotkey0, coldkey); + Owner::::insert(hotkey1, coldkey); + OwnedHotkeys::::insert(coldkey, vec![hotkey0, hotkey1]); + + // Emit through hotkey + SubtensorModule::emit_inflation_through_hotkey_account(&hotkey0, 0, 1_000); + + // Verify StakingHotkeys has an entry + assert_eq!(StakingHotkeys::::get(coldkey).len(), 1); + assert!(StakingHotkeys::::get(coldkey).contains(&hotkey0)); + + // Try again with another emission on hotkey1 + SubtensorModule::emit_inflation_through_hotkey_account(&hotkey1, 0, 2_000); + + // Verify both hotkeys are now in the map + assert_eq!(StakingHotkeys::::get(coldkey).len(), 2); + let final_map = StakingHotkeys::::get(coldkey); + assert!(final_map.contains(&hotkey0)); + assert!(final_map.contains(&hotkey1)); + }) +} diff --git a/pallets/subtensor/tests/swap.rs b/pallets/subtensor/tests/swap.rs index 90ebdfdcb..21c3a983a 100644 --- a/pallets/subtensor/tests/swap.rs +++ b/pallets/subtensor/tests/swap.rs @@ -2,8 +2,8 @@ use codec::Encode; use frame_support::weights::Weight; -use frame_support::{assert_err, assert_ok}; -use frame_system::Config; +use frame_support::{assert_err, assert_noop, assert_ok}; +use frame_system::{Config, RawOrigin}; mod mock; use mock::*; use pallet_subtensor::*; @@ -167,6 +167,22 @@ fn test_do_swap_hotkey_ok_robust() { SubtensorModule::add_balance_to_coldkey_account(coldkey, swap_cost); } + // Add old_hotkeys[0] and old_hotkeys[1] to Senate + assert_ok!(SenateMembers::add_member( + RawOrigin::Root.into(), + old_hotkeys[0] + )); + assert_ok!(SenateMembers::add_member( + RawOrigin::Root.into(), + old_hotkeys[1] + )); + + // Verify initial Senate membership + assert!(Senate::is_member(&old_hotkeys[0])); + assert!(Senate::is_member(&old_hotkeys[1])); + assert!(!Senate::is_member(&new_hotkeys[0])); + assert!(!Senate::is_member(&new_hotkeys[1])); + // Perform the swaps for only two hotkeys assert_ok!(SubtensorModule::do_swap_hotkey( <::RuntimeOrigin>::signed(coldkeys[0]), @@ -268,6 +284,10 @@ fn test_do_swap_hotkey_ok_robust() { assert_eq!(Keys::::get(netuid, uid), new_hotkeys[i]); } } + + // Verify Senate membership swap + assert!(!Senate::is_member(&old_hotkeys[i])); + assert!(Senate::is_member(&new_hotkeys[i])); } else { // Ensure other hotkeys remain unchanged assert_eq!( @@ -278,6 +298,10 @@ fn test_do_swap_hotkey_ok_robust() { SubtensorModule::get_owning_coldkey_for_hotkey(&new_hotkeys[i]), coldkeys[i] ); + + // Verify Senate membership remains unchanged for other hotkeys + assert!(!Senate::is_member(&old_hotkeys[i])); + assert!(!Senate::is_member(&new_hotkeys[i])); } } } @@ -1059,7 +1083,8 @@ fn test_do_swap_coldkey_success() { let netuid = 1u16; let stake_amount1 = 1000u64; let stake_amount2 = 2000u64; - let free_balance_old = 12345u64 + MIN_BALANCE_TO_PERFORM_COLDKEY_SWAP; + let swap_cost = SubtensorModule::get_key_swap_cost(); + let free_balance_old = 12345u64 + swap_cost; // Setup initial state add_network(netuid, 13, 0); @@ -1158,7 +1183,7 @@ fn test_do_swap_coldkey_success() { // Verify balance transfer assert_eq!( SubtensorModule::get_coldkey_balance(&new_coldkey), - free_balance_old + free_balance_old - swap_cost ); assert_eq!(SubtensorModule::get_coldkey_balance(&old_coldkey), 0); @@ -1180,6 +1205,7 @@ fn test_do_swap_coldkey_success() { }); } +// SKIP_WASM_BUILD=1 RUST_LOG=info cargo test --test swap -- test_swap_stake_for_coldkey --exact --nocaptur #[test] fn test_swap_stake_for_coldkey() { new_test_ext(1).execute_with(|| { @@ -1189,13 +1215,22 @@ fn test_swap_stake_for_coldkey() { let hotkey2 = U256::from(4); let stake_amount1 = 1000u64; let stake_amount2 = 2000u64; + let stake_amount3 = 3000u64; let total_stake = stake_amount1 + stake_amount2; let mut weight = Weight::zero(); // Setup initial state OwnedHotkeys::::insert(old_coldkey, vec![hotkey1, hotkey2]); + StakingHotkeys::::insert(old_coldkey, vec![hotkey1, hotkey2]); Stake::::insert(hotkey1, old_coldkey, stake_amount1); Stake::::insert(hotkey2, old_coldkey, stake_amount2); + assert_eq!(Stake::::get(hotkey1, old_coldkey), stake_amount1); + assert_eq!(Stake::::get(hotkey1, old_coldkey), stake_amount1); + + // Insert existing for same hotkey1 + Stake::::insert(hotkey1, new_coldkey, stake_amount3); + StakingHotkeys::::insert(new_coldkey, vec![hotkey1]); + TotalHotkeyStake::::insert(hotkey1, stake_amount1); TotalHotkeyStake::::insert(hotkey2, stake_amount2); TotalColdkeyStake::::insert(old_coldkey, total_stake); @@ -1211,6 +1246,12 @@ fn test_swap_stake_for_coldkey() { // Perform the swap SubtensorModule::swap_stake_for_coldkey(&old_coldkey, &new_coldkey, &mut weight); + // Verify stake is additive, not replaced + assert_eq!( + Stake::::get(hotkey1, new_coldkey), + stake_amount1 + stake_amount3 + ); + // Verify ownership transfer assert_eq!( SubtensorModule::get_owned_hotkeys(&new_coldkey), @@ -1218,6 +1259,104 @@ fn test_swap_stake_for_coldkey() { ); assert_eq!(SubtensorModule::get_owned_hotkeys(&old_coldkey), vec![]); + // Verify stake transfer + assert_eq!(Stake::::get(hotkey2, new_coldkey), stake_amount2); + assert_eq!(Stake::::get(hotkey1, old_coldkey), 0); + assert_eq!(Stake::::get(hotkey2, old_coldkey), 0); + + // Verify TotalColdkeyStake + assert_eq!(TotalColdkeyStake::::get(new_coldkey), total_stake); + assert_eq!(TotalColdkeyStake::::get(old_coldkey), 0); + + // Verify TotalHotkeyStake remains unchanged + assert_eq!(TotalHotkeyStake::::get(hotkey1), stake_amount1); + assert_eq!(TotalHotkeyStake::::get(hotkey2), stake_amount2); + + // Verify total stake and issuance remain unchanged + assert_eq!( + SubtensorModule::get_total_stake(), + initial_total_stake, + "Total stake changed unexpectedly" + ); + assert_eq!( + SubtensorModule::get_total_issuance(), + initial_total_issuance, + "Total issuance changed unexpectedly" + ); + }); +} + +#[test] +fn test_swap_staking_hotkeys_for_coldkey() { + new_test_ext(1).execute_with(|| { + let old_coldkey = U256::from(1); + let new_coldkey = U256::from(2); + let hotkey1 = U256::from(3); + let hotkey2 = U256::from(4); + let stake_amount1 = 1000u64; + let stake_amount2 = 2000u64; + let total_stake = stake_amount1 + stake_amount2; + let mut weight = Weight::zero(); + + // Setup initial state + OwnedHotkeys::::insert(old_coldkey, vec![hotkey1, hotkey2]); + Stake::::insert(hotkey1, old_coldkey, stake_amount1); + Stake::::insert(hotkey2, old_coldkey, stake_amount2); + StakingHotkeys::::insert(old_coldkey, vec![hotkey1, hotkey2]); + TotalHotkeyStake::::insert(hotkey1, stake_amount1); + TotalHotkeyStake::::insert(hotkey2, stake_amount2); + TotalColdkeyStake::::insert(old_coldkey, total_stake); + + // Set up total issuance + TotalIssuance::::put(total_stake); + TotalStake::::put(total_stake); + + // Perform the swap + SubtensorModule::swap_stake_for_coldkey(&old_coldkey, &new_coldkey, &mut weight); + + // Verify StakingHotkeys transfer + assert_eq!( + StakingHotkeys::::get(new_coldkey), + vec![hotkey1, hotkey2] + ); + assert_eq!(StakingHotkeys::::get(old_coldkey), vec![]); + }); +} + +#[test] +fn test_swap_delegated_stake_for_coldkey() { + new_test_ext(1).execute_with(|| { + let old_coldkey = U256::from(1); + let new_coldkey = U256::from(2); + let hotkey1 = U256::from(3); + let hotkey2 = U256::from(4); + let stake_amount1 = 1000u64; + let stake_amount2 = 2000u64; + let total_stake = stake_amount1 + stake_amount2; + let mut weight = Weight::zero(); + + // Notice hotkey1 and hotkey2 are not in OwnedHotkeys + // coldkey therefore delegates stake to them + + // Setup initial state + StakingHotkeys::::insert(old_coldkey, vec![hotkey1, hotkey2]); + Stake::::insert(hotkey1, old_coldkey, stake_amount1); + Stake::::insert(hotkey2, old_coldkey, stake_amount2); + TotalHotkeyStake::::insert(hotkey1, stake_amount1); + TotalHotkeyStake::::insert(hotkey2, stake_amount2); + TotalColdkeyStake::::insert(old_coldkey, total_stake); + + // Set up total issuance + TotalIssuance::::put(total_stake); + TotalStake::::put(total_stake); + + // Record initial values + let initial_total_issuance = SubtensorModule::get_total_issuance(); + let initial_total_stake = SubtensorModule::get_total_stake(); + + // Perform the swap + SubtensorModule::swap_stake_for_coldkey(&old_coldkey, &new_coldkey, &mut weight); + // Verify stake transfer assert_eq!(Stake::::get(hotkey1, new_coldkey), stake_amount1); assert_eq!(Stake::::get(hotkey2, new_coldkey), stake_amount2); @@ -1332,6 +1471,7 @@ fn test_do_swap_coldkey_with_subnet_ownership() { let hotkey = U256::from(3); let netuid = 1u16; let stake_amount: u64 = 1000u64; + let swap_cost = SubtensorModule::get_key_swap_cost(); // Setup initial state add_network(netuid, 13, 0); @@ -1340,7 +1480,7 @@ fn test_do_swap_coldkey_with_subnet_ownership() { // Set TotalNetworks because swap relies on it pallet_subtensor::TotalNetworks::::set(1); - SubtensorModule::add_balance_to_coldkey_account(&old_coldkey, stake_amount); + SubtensorModule::add_balance_to_coldkey_account(&old_coldkey, stake_amount + swap_cost); SubnetOwner::::insert(netuid, old_coldkey); // Populate OwnedHotkeys map @@ -1666,24 +1806,84 @@ fn test_coldkey_swap_total() { }); } -// #[test] -// fn test_coldkey_arbitrated_sw() { -// new_test_ext(1).execute_with(|| { -// let coldkey = U256::from(1); -// let hotkey = U256::from(2); -// let netuid = 1u16; - -// // Setup initial state -// add_network(netuid, 13, 0); -// register_ok_neuron(netuid, hotkey, coldkey, 0); - -// // Check if coldkey has associated hotkeys -// assert!(SubtensorModule::coldkey_has_associated_hotkeys(&coldkey)); - -// // Check for a coldkey without associated hotkeys -// let unassociated_coldkey = U256::from(3); -// assert!(!SubtensorModule::coldkey_has_associated_hotkeys( -// &unassociated_coldkey -// )); -// }); -// } +#[test] +fn test_swap_senate_member() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let non_member_hotkey = U256::from(3); + let mut weight = Weight::zero(); + + // Setup: Add old_hotkey as a Senate member + assert_ok!(SenateMembers::add_member( + RawOrigin::Root.into(), + old_hotkey + )); + + // Test 1: Successful swap + assert_ok!(SubtensorModule::swap_senate_member( + &old_hotkey, + &new_hotkey, + &mut weight + )); + assert!(Senate::is_member(&new_hotkey)); + assert!(!Senate::is_member(&old_hotkey)); + + // Verify weight update + let expected_weight = ::DbWeight::get().reads_writes(2, 2); + assert_eq!(weight, expected_weight); + + // Reset weight for next test + weight = Weight::zero(); + + // Test 2: Swap with non-member (should not change anything) + assert_ok!(SubtensorModule::swap_senate_member( + &non_member_hotkey, + &new_hotkey, + &mut weight + )); + assert!(Senate::is_member(&new_hotkey)); + assert!(!Senate::is_member(&non_member_hotkey)); + + // Verify weight update (should only have read operations) + let expected_weight = ::DbWeight::get().reads(1); + assert_eq!(weight, expected_weight); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=info cargo test --test swap -- test_coldkey_delegations --exact --nocapture +#[test] +fn test_coldkey_delegations() { + new_test_ext(1).execute_with(|| { + let new_coldkey = U256::from(0); + let owner = U256::from(1); + let coldkey = U256::from(4); + let delegate = U256::from(2); + let netuid = 1u16; + add_network(netuid, 13, 0); + register_ok_neuron(netuid, delegate, owner, 0); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, 1000); + assert_ok!(SubtensorModule::do_become_delegate( + <::RuntimeOrigin>::signed(owner), + delegate, + u16::MAX / 10 + )); + assert_ok!(SubtensorModule::add_stake( + <::RuntimeOrigin>::signed(coldkey), + delegate, + 100 + )); + assert_ok!(SubtensorModule::perform_swap_coldkey( + &coldkey, + &new_coldkey + )); + assert_eq!(SubtensorModule::get_total_stake_for_hotkey(&delegate), 100); + assert_eq!(SubtensorModule::get_total_stake_for_coldkey(&coldkey), 0); + assert_eq!( + SubtensorModule::get_total_stake_for_coldkey(&new_coldkey), + 100 + ); + assert_eq!(Stake::::get(delegate, new_coldkey), 100); + assert_eq!(Stake::::get(delegate, coldkey), 0); + }); +} diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index de8be6e61..287ded7c5 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -139,7 +139,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 194, + spec_version: 195, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, @@ -312,8 +312,7 @@ impl Contains for SafeModeWhitelistedCalls { | RuntimeCall::SafeMode(_) | RuntimeCall::Timestamp(_) | RuntimeCall::SubtensorModule( - pallet_subtensor::Call::schedule_coldkey_swap { .. } - | pallet_subtensor::Call::set_weights { .. } + pallet_subtensor::Call::set_weights { .. } | pallet_subtensor::Call::set_root_weights { .. } | pallet_subtensor::Call::serve_axon { .. } ) @@ -877,7 +876,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 SubtensorInitialKeySwapCost: 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 @@ -933,7 +932,7 @@ impl pallet_subtensor::Config for Runtime { type InitialSubnetLimit = SubtensorInitialSubnetLimit; type InitialNetworkRateLimit = SubtensorInitialNetworkRateLimit; type InitialTargetStakesPerInterval = SubtensorInitialTargetStakesPerInterval; - type HotkeySwapCost = SubtensorInitialHotkeySwapCost; + type KeySwapCost = SubtensorInitialKeySwapCost; type AlphaHigh = InitialAlphaHigh; type AlphaLow = InitialAlphaLow; type LiquidAlphaOn = InitialLiquidAlphaOn; From 1c502952ec932ffab75fb28b3ad800becc91c0d2 Mon Sep 17 00:00:00 2001 From: Cameron Fairchild Date: Mon, 22 Jul 2024 11:19:43 -0400 Subject: [PATCH 45/51] Feat/devnet companion/check metadata hash extension (#649) * draft: hotkey swap for senate * feature-gate hash * use 1.10.0-rc2 * add feature * feat: remove schedule coldkey swap * chore: fix tests * fixes for network resumption * chore: bump spec * fix: add back arbitration check * fix: hotkey * fix: coldkey arb swap hotkey * swap delegate stake also * add test for this * swap over stakinghotkeys map * check map first * add staking hotkeys test * no take * keep old stake * add check to test * fix some tests * fix delegate test * update staking hotekys maps * init * comment out * add admin swap * fix swap * .. * hotkey staking maps fix * remove staking hotkeys * remove commented code * cargo fmt * cargo fix --workspace * bump spec_version to 165 * swap hotkey benchmark removed * add migration and tests for total coldkey hotfix * adds new test for missing hotkey value * bump migration values * fmt * lock file update * add production just target * fmt * clippy * benchmarking fix * feat: try runtime passing * chore: remove commented code * chore: make logs human readable * chore: remove comments * Update pallets/subtensor/src/lib.rs Co-authored-by: Sam Johnson * fmt * use rc3 with new fix polkadot-sdk/pull/4117 * incl lock * bump CI --------- Co-authored-by: Samuel Dare Co-authored-by: distributedstatemachine <112424909+distributedstatemachine@users.noreply.github.com> Co-authored-by: const Co-authored-by: Sam Johnson Co-authored-by: Unconst <32490803+unconst@users.noreply.github.com> --- Cargo.lock | 485 ++++++++++++++++++++++----------------- Cargo.toml | 139 +++++------ justfile | 6 +- node/Cargo.toml | 1 + node/src/benchmarking.rs | 2 + runtime/Cargo.toml | 3 + runtime/build.rs | 11 +- runtime/src/lib.rs | 1 + scripts/build.sh | 2 +- 9 files changed, 370 insertions(+), 280 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 868e85b89..4a50f8a12 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2308,7 +2308,7 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "fork-tree" version = "12.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "parity-scale-codec", ] @@ -2331,7 +2331,7 @@ checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" [[package]] name = "frame-benchmarking" version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "frame-support", "frame-support-procedural", @@ -2347,16 +2347,16 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", - "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", + "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "static_assertions", ] [[package]] name = "frame-benchmarking-cli" version = "32.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "Inflector", "array-bytes 6.2.3", @@ -2388,15 +2388,15 @@ dependencies = [ "sp-blockchain", "sp-core", "sp-database", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-inherents", "sp-io", "sp-keystore", "sp-runtime", "sp-state-machine", - "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-trie", - "sp-wasm-interface 20.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-wasm-interface 20.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "thiserror", "thousands", ] @@ -2404,7 +2404,7 @@ dependencies = [ [[package]] name = "frame-executive" version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "aquamarine 0.3.3", "frame-support", @@ -2416,8 +2416,8 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", - "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", + "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", ] [[package]] @@ -2432,10 +2432,25 @@ dependencies = [ "serde", ] +[[package]] +name = "frame-metadata-hash-extension" +version = "0.1.0" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" +dependencies = [ + "array-bytes 6.2.3", + "docify", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-runtime", +] + [[package]] name = "frame-support" version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "aquamarine 0.5.0", "array-bytes 6.2.3", @@ -2458,7 +2473,7 @@ dependencies = [ "sp-arithmetic", "sp-core", "sp-crypto-hashing-proc-macro", - "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-genesis-builder", "sp-inherents", "sp-io", @@ -2466,8 +2481,8 @@ dependencies = [ "sp-runtime", "sp-staking", "sp-state-machine", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", - "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", + "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-weights", "static_assertions", "tt-call", @@ -2476,7 +2491,7 @@ dependencies = [ [[package]] name = "frame-support-procedural" version = "23.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "Inflector", "cfg-expr", @@ -2495,7 +2510,7 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools" version = "10.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "frame-support-procedural-tools-derive", "proc-macro-crate 3.1.0", @@ -2507,7 +2522,7 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools-derive" version = "11.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "proc-macro2", "quote", @@ -2517,7 +2532,7 @@ dependencies = [ [[package]] name = "frame-system" version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "cfg-if", "docify", @@ -2529,7 +2544,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-version", "sp-weights", ] @@ -2537,7 +2552,7 @@ dependencies = [ [[package]] name = "frame-system-benchmarking" version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "frame-benchmarking", "frame-support", @@ -2546,13 +2561,13 @@ dependencies = [ "scale-info", "sp-core", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", ] [[package]] name = "frame-system-rpc-runtime-api" version = "26.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "parity-scale-codec", "sp-api", @@ -2561,13 +2576,13 @@ dependencies = [ [[package]] name = "frame-try-runtime" version = "0.34.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "frame-support", "parity-scale-codec", "sp-api", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", ] [[package]] @@ -4334,6 +4349,20 @@ dependencies = [ "hash-db", ] +[[package]] +name = "merkleized-metadata" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f313fcff1d2a4bcaa2deeaa00bf7530d77d5f7bd0467a117dde2e29a75a7a17a" +dependencies = [ + "array-bytes 6.2.3", + "blake3", + "frame-metadata", + "parity-scale-codec", + "scale-decode", + "scale-info", +] + [[package]] name = "merlin" version = "3.0.0" @@ -4644,6 +4673,7 @@ dependencies = [ "clap", "frame-benchmarking", "frame-benchmarking-cli", + "frame-metadata-hash-extension", "frame-system", "futures", "jsonrpsee", @@ -4699,6 +4729,7 @@ dependencies = [ "frame-benchmarking", "frame-executive", "frame-metadata", + "frame-metadata-hash-extension", "frame-support", "frame-system", "frame-system-benchmarking", @@ -4739,9 +4770,9 @@ dependencies = [ "sp-offchain", "sp-runtime", "sp-session", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", - "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", - "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", + "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", + "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-transaction-pool", "sp-version", "substrate-wasm-builder", @@ -4952,7 +4983,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-weights", "substrate-fixed", "subtensor-macros", @@ -4961,7 +4992,7 @@ dependencies = [ [[package]] name = "pallet-aura" version = "27.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "frame-support", "frame-system", @@ -4972,13 +5003,13 @@ dependencies = [ "sp-application-crypto", "sp-consensus-aura", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", ] [[package]] name = "pallet-authorship" version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "frame-support", "frame-system", @@ -4986,13 +5017,13 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", ] [[package]] name = "pallet-balances" version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "docify", "frame-benchmarking", @@ -5002,7 +5033,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", ] [[package]] @@ -5018,7 +5049,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "subtensor-macros", ] @@ -5036,14 +5067,14 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "subtensor-macros", ] [[package]] name = "pallet-grandpa" version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "frame-benchmarking", "frame-support", @@ -5060,13 +5091,13 @@ dependencies = [ "sp-runtime", "sp-session", "sp-staking", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", ] [[package]] name = "pallet-insecure-randomness-collective-flip" version = "16.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "frame-support", "frame-system", @@ -5074,13 +5105,13 @@ dependencies = [ "safe-mix", "scale-info", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", ] [[package]] name = "pallet-membership" version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "frame-benchmarking", "frame-support", @@ -5091,13 +5122,13 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", ] [[package]] name = "pallet-multisig" version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "frame-benchmarking", "frame-support", @@ -5107,13 +5138,13 @@ dependencies = [ "scale-info", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", ] [[package]] name = "pallet-preimage" version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "frame-benchmarking", "frame-support", @@ -5124,13 +5155,13 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", ] [[package]] name = "pallet-proxy" version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "frame-benchmarking", "frame-support", @@ -5139,7 +5170,7 @@ dependencies = [ "scale-info", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", ] [[package]] @@ -5155,14 +5186,14 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "subtensor-macros", ] [[package]] name = "pallet-safe-mode" version = "9.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "docify", "frame-benchmarking", @@ -5175,13 +5206,13 @@ dependencies = [ "scale-info", "sp-arithmetic", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", ] [[package]] name = "pallet-scheduler" version = "29.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "docify", "frame-benchmarking", @@ -5192,14 +5223,14 @@ dependencies = [ "scale-info", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-weights", ] [[package]] name = "pallet-session" version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "frame-support", "frame-system", @@ -5214,7 +5245,7 @@ dependencies = [ "sp-session", "sp-staking", "sp-state-machine", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-trie", ] @@ -5246,8 +5277,8 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", - "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", + "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-version", "substrate-fixed", "subtensor-macros", @@ -5256,7 +5287,7 @@ dependencies = [ [[package]] name = "pallet-sudo" version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "docify", "frame-benchmarking", @@ -5266,13 +5297,13 @@ dependencies = [ "scale-info", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", ] [[package]] name = "pallet-timestamp" version = "27.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "docify", "frame-benchmarking", @@ -5284,15 +5315,15 @@ dependencies = [ "sp-inherents", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", - "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", + "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-timestamp", ] [[package]] name = "pallet-transaction-payment" version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "frame-support", "frame-system", @@ -5302,13 +5333,13 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", ] [[package]] name = "pallet-transaction-payment-rpc" version = "30.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "jsonrpsee", "pallet-transaction-payment-rpc-runtime-api", @@ -5324,7 +5355,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc-runtime-api" version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "pallet-transaction-payment", "parity-scale-codec", @@ -5336,7 +5367,7 @@ dependencies = [ [[package]] name = "pallet-utility" version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "frame-benchmarking", "frame-support", @@ -5346,7 +5377,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", ] [[package]] @@ -6684,18 +6715,18 @@ dependencies = [ [[package]] name = "sc-allocator" version = "23.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "log", "sp-core", - "sp-wasm-interface 20.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-wasm-interface 20.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "thiserror", ] [[package]] name = "sc-basic-authorship" version = "0.34.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "futures", "futures-timer", @@ -6717,7 +6748,7 @@ dependencies = [ [[package]] name = "sc-block-builder" version = "0.33.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "parity-scale-codec", "sp-api", @@ -6732,7 +6763,7 @@ dependencies = [ [[package]] name = "sc-chain-spec" version = "27.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "array-bytes 6.2.3", "docify", @@ -6758,7 +6789,7 @@ dependencies = [ [[package]] name = "sc-chain-spec-derive" version = "11.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", @@ -6769,7 +6800,7 @@ dependencies = [ [[package]] name = "sc-cli" version = "0.36.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "array-bytes 6.2.3", "chrono", @@ -6810,7 +6841,7 @@ dependencies = [ [[package]] name = "sc-client-api" version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "fnv", "futures", @@ -6825,11 +6856,11 @@ dependencies = [ "sp-consensus", "sp-core", "sp-database", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-runtime", "sp-state-machine", "sp-statement-store", - "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-trie", "substrate-prometheus-endpoint", ] @@ -6837,7 +6868,7 @@ dependencies = [ [[package]] name = "sc-client-db" version = "0.35.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "hash-db", "kvdb", @@ -6863,7 +6894,7 @@ dependencies = [ [[package]] name = "sc-consensus" version = "0.33.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "async-trait", "futures", @@ -6888,7 +6919,7 @@ dependencies = [ [[package]] name = "sc-consensus-aura" version = "0.34.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "async-trait", "futures", @@ -6917,7 +6948,7 @@ dependencies = [ [[package]] name = "sc-consensus-grandpa" version = "0.19.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "ahash 0.8.11", "array-bytes 6.2.3", @@ -6960,7 +6991,7 @@ dependencies = [ [[package]] name = "sc-consensus-grandpa-rpc" version = "0.19.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "finality-grandpa", "futures", @@ -6980,7 +7011,7 @@ dependencies = [ [[package]] name = "sc-consensus-slots" version = "0.33.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "async-trait", "futures", @@ -7003,7 +7034,7 @@ dependencies = [ [[package]] name = "sc-executor" version = "0.32.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "parity-scale-codec", "parking_lot 0.12.3", @@ -7013,25 +7044,25 @@ dependencies = [ "schnellru", "sp-api", "sp-core", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-io", "sp-panic-handler", - "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-trie", "sp-version", - "sp-wasm-interface 20.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-wasm-interface 20.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "tracing", ] [[package]] name = "sc-executor-common" version = "0.29.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "polkavm", "sc-allocator", "sp-maybe-compressed-blob", - "sp-wasm-interface 20.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-wasm-interface 20.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "thiserror", "wasm-instrument", ] @@ -7039,18 +7070,18 @@ dependencies = [ [[package]] name = "sc-executor-polkavm" version = "0.29.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "log", "polkavm", "sc-executor-common", - "sp-wasm-interface 20.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-wasm-interface 20.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", ] [[package]] name = "sc-executor-wasmtime" version = "0.29.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "anyhow", "cfg-if", @@ -7060,15 +7091,15 @@ dependencies = [ "rustix 0.36.17", "sc-allocator", "sc-executor-common", - "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", - "sp-wasm-interface 20.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", + "sp-wasm-interface 20.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "wasmtime", ] [[package]] name = "sc-informant" version = "0.33.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "ansi_term", "futures", @@ -7085,7 +7116,7 @@ dependencies = [ [[package]] name = "sc-keystore" version = "25.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "array-bytes 6.2.3", "parking_lot 0.12.3", @@ -7099,7 +7130,7 @@ dependencies = [ [[package]] name = "sc-mixnet" version = "0.4.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "array-bytes 4.2.0", "arrayvec", @@ -7128,7 +7159,7 @@ dependencies = [ [[package]] name = "sc-network" version = "0.34.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "array-bytes 6.2.3", "async-channel", @@ -7171,7 +7202,7 @@ dependencies = [ [[package]] name = "sc-network-bitswap" version = "0.33.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "async-channel", "cid", @@ -7191,7 +7222,7 @@ dependencies = [ [[package]] name = "sc-network-common" version = "0.33.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "async-trait", "bitflags 1.3.2", @@ -7208,7 +7239,7 @@ dependencies = [ [[package]] name = "sc-network-gossip" version = "0.34.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "ahash 0.8.11", "futures", @@ -7227,7 +7258,7 @@ dependencies = [ [[package]] name = "sc-network-light" version = "0.33.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "array-bytes 6.2.3", "async-channel", @@ -7248,7 +7279,7 @@ dependencies = [ [[package]] name = "sc-network-sync" version = "0.33.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "array-bytes 6.2.3", "async-channel", @@ -7284,7 +7315,7 @@ dependencies = [ [[package]] name = "sc-network-transactions" version = "0.33.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "array-bytes 6.2.3", "futures", @@ -7303,7 +7334,7 @@ dependencies = [ [[package]] name = "sc-offchain" version = "29.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "array-bytes 6.2.3", "bytes", @@ -7326,7 +7357,7 @@ dependencies = [ "sc-utils", "sp-api", "sp-core", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-keystore", "sp-offchain", "sp-runtime", @@ -7337,7 +7368,7 @@ dependencies = [ [[package]] name = "sc-proposer-metrics" version = "0.17.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "log", "substrate-prometheus-endpoint", @@ -7346,7 +7377,7 @@ dependencies = [ [[package]] name = "sc-rpc" version = "29.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "futures", "jsonrpsee", @@ -7378,7 +7409,7 @@ dependencies = [ [[package]] name = "sc-rpc-api" version = "0.33.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -7398,7 +7429,7 @@ dependencies = [ [[package]] name = "sc-rpc-server" version = "11.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "futures", "governor", @@ -7416,7 +7447,7 @@ dependencies = [ [[package]] name = "sc-rpc-spec-v2" version = "0.34.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "array-bytes 6.2.3", "futures", @@ -7447,7 +7478,7 @@ dependencies = [ [[package]] name = "sc-service" version = "0.35.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "async-trait", "directories", @@ -7489,12 +7520,12 @@ dependencies = [ "sp-blockchain", "sp-consensus", "sp-core", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-keystore", "sp-runtime", "sp-session", "sp-state-machine", - "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-transaction-pool", "sp-transaction-storage-proof", "sp-trie", @@ -7511,7 +7542,7 @@ dependencies = [ [[package]] name = "sc-state-db" version = "0.30.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "log", "parity-scale-codec", @@ -7522,7 +7553,7 @@ dependencies = [ [[package]] name = "sc-sysinfo" version = "27.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "derive_more", "futures", @@ -7537,13 +7568,13 @@ dependencies = [ "sp-core", "sp-crypto-hashing", "sp-io", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", ] [[package]] name = "sc-telemetry" version = "15.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "chrono", "futures", @@ -7562,7 +7593,7 @@ dependencies = [ [[package]] name = "sc-tracing" version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "ansi_term", "chrono", @@ -7582,7 +7613,7 @@ dependencies = [ "sp-core", "sp-rpc", "sp-runtime", - "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "thiserror", "tracing", "tracing-log 0.1.4", @@ -7592,7 +7623,7 @@ dependencies = [ [[package]] name = "sc-tracing-proc-macro" version = "11.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", @@ -7603,7 +7634,7 @@ dependencies = [ [[package]] name = "sc-transaction-pool" version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "async-trait", "futures", @@ -7621,7 +7652,7 @@ dependencies = [ "sp-core", "sp-crypto-hashing", "sp-runtime", - "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-transaction-pool", "substrate-prometheus-endpoint", "thiserror", @@ -7630,7 +7661,7 @@ dependencies = [ [[package]] name = "sc-transaction-pool-api" version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "async-trait", "futures", @@ -7646,7 +7677,7 @@ dependencies = [ [[package]] name = "sc-utils" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "async-channel", "futures", @@ -7658,6 +7689,29 @@ dependencies = [ "sp-arithmetic", ] +[[package]] +name = "scale-bits" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57b1e7f6b65ed1f04e79a85a57d755ad56d76fdf1e9bddcc9ae14f71fcdcf54" +dependencies = [ + "parity-scale-codec", + "scale-type-resolver", +] + +[[package]] +name = "scale-decode" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e98f3262c250d90e700bb802eb704e1f841e03331c2eb815e46516c4edbf5b27" +dependencies = [ + "derive_more", + "parity-scale-codec", + "scale-bits", + "scale-type-resolver", + "smallvec", +] + [[package]] name = "scale-info" version = "2.11.3" @@ -7684,6 +7738,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "scale-type-resolver" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0cded6518aa0bd6c1be2b88ac81bf7044992f0f154bfbabd5ad34f43512abcb" + [[package]] name = "schannel" version = "0.1.23" @@ -8129,7 +8189,7 @@ dependencies = [ [[package]] name = "sp-api" version = "26.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "hash-db", "log", @@ -8137,12 +8197,12 @@ dependencies = [ "scale-info", "sp-api-proc-macro", "sp-core", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-metadata-ir", "sp-runtime", - "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-state-machine", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-trie", "sp-version", "thiserror", @@ -8151,7 +8211,7 @@ dependencies = [ [[package]] name = "sp-api-proc-macro" version = "15.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "Inflector", "blake2 0.10.6", @@ -8165,20 +8225,20 @@ dependencies = [ [[package]] name = "sp-application-crypto" version = "30.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "parity-scale-codec", "scale-info", "serde", "sp-core", "sp-io", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", ] [[package]] name = "sp-arithmetic" version = "23.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "docify", "integer-sqrt", @@ -8186,7 +8246,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "static_assertions", ] @@ -8211,7 +8271,7 @@ dependencies = [ [[package]] name = "sp-block-builder" version = "26.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "sp-api", "sp-inherents", @@ -8221,7 +8281,7 @@ dependencies = [ [[package]] name = "sp-blockchain" version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "futures", "log", @@ -8239,7 +8299,7 @@ dependencies = [ [[package]] name = "sp-consensus" version = "0.32.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "async-trait", "futures", @@ -8254,7 +8314,7 @@ dependencies = [ [[package]] name = "sp-consensus-aura" version = "0.32.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "async-trait", "parity-scale-codec", @@ -8270,7 +8330,7 @@ dependencies = [ [[package]] name = "sp-consensus-grandpa" version = "13.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "finality-grandpa", "log", @@ -8287,7 +8347,7 @@ dependencies = [ [[package]] name = "sp-consensus-slots" version = "0.32.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "parity-scale-codec", "scale-info", @@ -8298,7 +8358,7 @@ dependencies = [ [[package]] name = "sp-core" version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "array-bytes 6.2.3", "bandersnatch_vrfs", @@ -8329,11 +8389,11 @@ dependencies = [ "secrecy", "serde", "sp-crypto-hashing", - "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", - "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", - "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", + "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", + "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", + "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "ss58-registry", "substrate-bip39", "thiserror", @@ -8365,7 +8425,7 @@ dependencies = [ [[package]] name = "sp-crypto-hashing" version = "0.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "blake2b_simd", "byteorder", @@ -8378,7 +8438,7 @@ dependencies = [ [[package]] name = "sp-crypto-hashing-proc-macro" version = "0.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "quote", "sp-crypto-hashing", @@ -8388,7 +8448,7 @@ dependencies = [ [[package]] name = "sp-database" version = "10.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "kvdb", "parking_lot 0.12.3", @@ -8397,7 +8457,7 @@ dependencies = [ [[package]] name = "sp-debug-derive" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "proc-macro2", "quote", @@ -8417,11 +8477,11 @@ dependencies = [ [[package]] name = "sp-externalities" version = "0.25.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "environmental", "parity-scale-codec", - "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", ] [[package]] @@ -8437,7 +8497,7 @@ dependencies = [ [[package]] name = "sp-genesis-builder" version = "0.7.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "serde_json", "sp-api", @@ -8447,7 +8507,7 @@ dependencies = [ [[package]] name = "sp-inherents" version = "26.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "async-trait", "impl-trait-for-tuples", @@ -8460,7 +8520,7 @@ dependencies = [ [[package]] name = "sp-io" version = "30.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "bytes", "ed25519-dalek", @@ -8472,12 +8532,12 @@ dependencies = [ "secp256k1", "sp-core", "sp-crypto-hashing", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-keystore", - "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-state-machine", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", - "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", + "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-trie", "tracing", "tracing-core", @@ -8486,7 +8546,7 @@ dependencies = [ [[package]] name = "sp-keyring" version = "31.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "sp-core", "sp-runtime", @@ -8496,18 +8556,18 @@ dependencies = [ [[package]] name = "sp-keystore" version = "0.34.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "parity-scale-codec", "parking_lot 0.12.3", "sp-core", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", ] [[package]] name = "sp-maybe-compressed-blob" version = "11.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "thiserror", "zstd 0.12.4", @@ -8516,7 +8576,7 @@ dependencies = [ [[package]] name = "sp-metadata-ir" version = "0.6.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "frame-metadata", "parity-scale-codec", @@ -8526,7 +8586,7 @@ dependencies = [ [[package]] name = "sp-mixnet" version = "0.4.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "parity-scale-codec", "scale-info", @@ -8537,7 +8597,7 @@ dependencies = [ [[package]] name = "sp-offchain" version = "26.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "sp-api", "sp-core", @@ -8547,7 +8607,7 @@ dependencies = [ [[package]] name = "sp-panic-handler" version = "13.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "backtrace", "lazy_static", @@ -8557,7 +8617,7 @@ dependencies = [ [[package]] name = "sp-rpc" version = "26.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "rustc-hash", "serde", @@ -8567,7 +8627,7 @@ dependencies = [ [[package]] name = "sp-runtime" version = "31.0.1" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "docify", "either", @@ -8584,26 +8644,26 @@ dependencies = [ "sp-arithmetic", "sp-core", "sp-io", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-weights", ] [[package]] name = "sp-runtime-interface" version = "24.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "bytes", "impl-trait-for-tuples", "parity-scale-codec", "polkavm-derive", "primitive-types", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", - "sp-runtime-interface-proc-macro 17.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", - "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", - "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", - "sp-wasm-interface 20.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", + "sp-runtime-interface-proc-macro 17.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", + "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", + "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", + "sp-wasm-interface 20.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "static_assertions", ] @@ -8629,7 +8689,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" version = "17.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "Inflector", "expander", @@ -8655,7 +8715,7 @@ dependencies = [ [[package]] name = "sp-session" version = "27.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "parity-scale-codec", "scale-info", @@ -8669,7 +8729,7 @@ dependencies = [ [[package]] name = "sp-staking" version = "26.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", @@ -8682,7 +8742,7 @@ dependencies = [ [[package]] name = "sp-state-machine" version = "0.35.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "hash-db", "log", @@ -8691,7 +8751,7 @@ dependencies = [ "rand", "smallvec", "sp-core", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-panic-handler", "sp-trie", "thiserror", @@ -8702,7 +8762,7 @@ dependencies = [ [[package]] name = "sp-statement-store" version = "10.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "aes-gcm", "curve25519-dalek 4.1.3", @@ -8716,9 +8776,9 @@ dependencies = [ "sp-application-crypto", "sp-core", "sp-crypto-hashing", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-runtime", - "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "thiserror", "x25519-dalek 2.0.1", ] @@ -8726,7 +8786,7 @@ dependencies = [ [[package]] name = "sp-std" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" [[package]] name = "sp-std" @@ -8736,13 +8796,13 @@ source = "git+https://github.com/paritytech/polkadot-sdk#c4b3c1c6c6e492c4196e06f [[package]] name = "sp-storage" version = "19.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "impl-serde", "parity-scale-codec", "ref-cast", "serde", - "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", ] [[package]] @@ -8760,7 +8820,7 @@ dependencies = [ [[package]] name = "sp-timestamp" version = "26.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "async-trait", "parity-scale-codec", @@ -8772,7 +8832,7 @@ dependencies = [ [[package]] name = "sp-tracing" version = "16.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "parity-scale-codec", "tracing", @@ -8794,7 +8854,7 @@ dependencies = [ [[package]] name = "sp-transaction-pool" version = "26.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "sp-api", "sp-runtime", @@ -8803,7 +8863,7 @@ dependencies = [ [[package]] name = "sp-transaction-storage-proof" version = "26.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "async-trait", "parity-scale-codec", @@ -8817,7 +8877,7 @@ dependencies = [ [[package]] name = "sp-trie" version = "29.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "ahash 0.8.11", "hash-db", @@ -8830,7 +8890,7 @@ dependencies = [ "scale-info", "schnellru", "sp-core", - "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "thiserror", "tracing", "trie-db", @@ -8840,7 +8900,7 @@ dependencies = [ [[package]] name = "sp-version" version = "29.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "impl-serde", "parity-scale-codec", @@ -8849,7 +8909,7 @@ dependencies = [ "serde", "sp-crypto-hashing-proc-macro", "sp-runtime", - "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", "sp-version-proc-macro", "thiserror", ] @@ -8857,7 +8917,7 @@ dependencies = [ [[package]] name = "sp-version-proc-macro" version = "13.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "parity-scale-codec", "proc-macro2", @@ -8868,7 +8928,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" version = "20.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "anyhow", "impl-trait-for-tuples", @@ -8890,7 +8950,7 @@ dependencies = [ [[package]] name = "sp-weights" version = "27.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "bounded-collections", "parity-scale-codec", @@ -8898,7 +8958,7 @@ dependencies = [ "serde", "smallvec", "sp-arithmetic", - "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0)", + "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", ] [[package]] @@ -9037,7 +9097,7 @@ dependencies = [ [[package]] name = "substrate-bip39" version = "0.4.7" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "hmac 0.12.1", "pbkdf2", @@ -9049,7 +9109,7 @@ dependencies = [ [[package]] name = "substrate-build-script-utils" version = "11.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" [[package]] name = "substrate-fixed" @@ -9065,7 +9125,7 @@ dependencies = [ [[package]] name = "substrate-frame-rpc-system" version = "28.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "frame-system-rpc-runtime-api", "futures", @@ -9084,7 +9144,7 @@ dependencies = [ [[package]] name = "substrate-prometheus-endpoint" version = "0.17.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ "hyper", "log", @@ -9096,15 +9156,24 @@ dependencies = [ [[package]] name = "substrate-wasm-builder" version = "17.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.10.0#7049c3c98836b3e9253f6aaa69b6bf3d622e3962" +source = "git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3#8d2f55dfe06bae13e9f47ccf587acfd3fb9cd923" dependencies = [ + "array-bytes 6.2.3", "build-helper", "cargo_metadata", "console", "filetime", + "frame-metadata", + "merkleized-metadata", + "parity-scale-codec", "parity-wasm", "polkavm-linker", + "sc-executor", + "sp-core", + "sp-io", "sp-maybe-compressed-blob", + "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=v1.10.0-rc3)", + "sp-version", "strum 0.26.2", "tempfile", "toml 0.8.14", diff --git a/Cargo.toml b/Cargo.toml index 8d9eff122..4a7565a01 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,80 +39,81 @@ litep2p = { git = "https://github.com/paritytech/litep2p", branch = "master" } subtensor-macros = { path = "support/macros" } -frame-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -frame-benchmarking-cli = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } -frame-executive = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -frame-support = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -frame-system = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -frame-system-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -frame-try-runtime = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } +frame-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +frame-benchmarking-cli = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } +frame-executive = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +frame-metadata-hash-extension = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" , default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +frame-system-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +frame-try-runtime = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } -pallet-aura = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -pallet-grandpa = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -pallet-insecure-randomness-collective-flip = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -pallet-membership = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -pallet-multisig = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -pallet-preimage = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -pallet-proxy = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -pallet-safe-mode = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -pallet-scheduler = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -pallet-sudo = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -pallet-timestamp = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -pallet-utility = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } +pallet-aura = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +pallet-grandpa = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +pallet-insecure-randomness-collective-flip = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +pallet-membership = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +pallet-multisig = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +pallet-preimage = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +pallet-proxy = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +pallet-safe-mode = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +pallet-scheduler = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +pallet-sudo = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +pallet-timestamp = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +pallet-utility = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } -sc-basic-authorship = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } -sc-cli = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } -sc-client-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } -sc-consensus = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } -sc-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } -sc-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } -sc-consensus-grandpa-rpc = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } -sc-chain-spec-derive = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } -sc-chain-spec = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } -sc-consensus-slots = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } -sc-executor = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } -sc-keystore = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } -sc-network = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } -sc-offchain = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } -sc-rpc = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } -sc-rpc-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } -sc-service = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } -sc-telemetry = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } -sc-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } -sc-transaction-pool-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } +sc-basic-authorship = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } +sc-cli = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } +sc-client-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } +sc-consensus = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } +sc-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } +sc-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } +sc-consensus-grandpa-rpc = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } +sc-chain-spec-derive = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } +sc-chain-spec = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } +sc-consensus-slots = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } +sc-executor = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } +sc-keystore = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } +sc-network = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } +sc-offchain = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } +sc-rpc = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } +sc-rpc-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } +sc-service = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } +sc-telemetry = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } +sc-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } +sc-transaction-pool-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } -sp-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -sp-block-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -sp-blockchain = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -sp-consensus = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } -sp-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } -sp-genesis-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -sp-core = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -sp-inherents = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -sp-io = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -sp-keyring = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } -sp-offchain = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -sp-rpc = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -sp-session = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -sp-std = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -sp-storage = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -sp-timestamp = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } -sp-tracing = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -sp-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -sp-version = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } -sp-weights = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0", default-features = false } +sp-api = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +sp-block-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +sp-blockchain = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +sp-consensus = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } +sp-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } +sp-genesis-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +sp-inherents = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +sp-io = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +sp-keyring = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } +sp-offchain = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +sp-rpc = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +sp-session = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +sp-storage = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +sp-timestamp = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } +sp-tracing = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +sp-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +sp-version = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } +sp-weights = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3", default-features = false } -substrate-build-script-utils = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } +substrate-build-script-utils = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } substrate-fixed = { git = "https://github.com/encointer/substrate-fixed.git", tag = "v0.5.9" } -substrate-frame-rpc-system = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } -substrate-wasm-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "polkadot-v1.10.0" } +substrate-frame-rpc-system = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } +substrate-wasm-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", tag = "v1.10.0-rc3" } frame-metadata = "16" [profile.release] diff --git a/justfile b/justfile index e33fdf685..f99f3913a 100644 --- a/justfile +++ b/justfile @@ -47,4 +47,8 @@ lint: @echo "Running cargo clippy with automatic fixes on potentially dirty code..." just clippy-fix @echo "Running cargo clippy..." - just clippy \ No newline at end of file + just clippy + +production: + @echo "Running cargo build with metadata-hash generation..." + cargo +{{RUSTV}} build --profile production --features="runtime-benchmarks metadata-hash" diff --git a/node/Cargo.toml b/node/Cargo.toml index 7fc6eff48..0e1a418a3 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -54,6 +54,7 @@ sp-io = { workspace = true } sp-timestamp = { workspace = true } sp-inherents = { workspace = true } sp-keyring = { workspace = true } +frame-metadata-hash-extension = { workspace = true } frame-system = { workspace = true } pallet-transaction-payment = { workspace = true } pallet-commitments = { path = "../pallets/commitments" } diff --git a/node/src/benchmarking.rs b/node/src/benchmarking.rs index ba176e15f..cf48df62f 100644 --- a/node/src/benchmarking.rs +++ b/node/src/benchmarking.rs @@ -136,6 +136,7 @@ pub fn create_benchmark_extrinsic( pallet_transaction_payment::ChargeTransactionPayment::::from(0), pallet_subtensor::SubtensorSignedExtension::::new(), pallet_commitments::CommitmentsSignedExtension::::new(), + frame_metadata_hash_extension::CheckMetadataHash::::new(true), ); let raw_payload = runtime::SignedPayload::from_raw( @@ -152,6 +153,7 @@ pub fn create_benchmark_extrinsic( (), (), (), + None, ), ); let signature = raw_payload.using_encoded(|e| sender.sign(e)); diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index fcb02a24c..042d0337c 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -41,6 +41,7 @@ pallet-timestamp = { workspace = true } pallet-transaction-payment = { workspace = true } pallet-utility = { workspace = true } frame-executive = { workspace = true } +frame-metadata-hash-extension = { workspace = true } sp-api = { workspace = true } sp-block-builder = { workspace = true } sp-consensus-aura = { workspace = true } @@ -111,6 +112,7 @@ std = [ "codec/std", "scale-info/std", "frame-executive/std", + "frame-metadata-hash-extension/std", "frame-support/std", "frame-system-rpc-runtime-api/std", "frame-system/std", @@ -204,3 +206,4 @@ try-runtime = [ "pallet-commitments/try-runtime", "pallet-registry/try-runtime" ] +metadata-hash = ["substrate-wasm-builder/metadata-hash"] diff --git a/runtime/build.rs b/runtime/build.rs index 8f021e838..c0fa0405b 100644 --- a/runtime/build.rs +++ b/runtime/build.rs @@ -1,5 +1,5 @@ fn main() { - #[cfg(feature = "std")] + #[cfg(all(feature = "std", not(feature = "metadata-hash")))] { substrate_wasm_builder::WasmBuilder::new() .with_current_project() @@ -7,4 +7,13 @@ fn main() { .import_memory() .build(); } + #[cfg(all(feature = "std", feature = "metadata-hash"))] + { + substrate_wasm_builder::WasmBuilder::new() + .with_current_project() + .export_heap_base() + .import_memory() + .enable_metadata_hash("TAO", 9) + .build(); + } } diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 287ded7c5..6547a3f33 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -1282,6 +1282,7 @@ pub type SignedExtra = ( pallet_transaction_payment::ChargeTransactionPayment, pallet_subtensor::SubtensorSignedExtension, pallet_commitments::CommitmentsSignedExtension, + frame_metadata_hash_extension::CheckMetadataHash, ); type Migrations = pallet_grandpa::migrations::MigrateV4ToV5; diff --git a/scripts/build.sh b/scripts/build.sh index 548af664b..3f588a1cc 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -1,2 +1,2 @@ -cargo build --profile production --features runtime-benchmarks +cargo build --profile production --features "runtime-benchmarks metadata-hash" From 07e46e312b56dd129d5a9b73cb9f5080db1d0e45 Mon Sep 17 00:00:00 2001 From: const Date: Mon, 22 Jul 2024 12:28:42 -0500 Subject: [PATCH 46/51] initial --- pallets/subtensor/src/lib.rs | 2 +- pallets/subtensor/src/swap_hotkey.rs | 280 +++++++++++++++++++++++++++ 2 files changed, 281 insertions(+), 1 deletion(-) create mode 100644 pallets/subtensor/src/swap_hotkey.rs diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index f7824e2a3..cfb3a5828 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -367,7 +367,7 @@ pub mod pallet { pub type TotalColdkeyStake = StorageMap<_, Identity, T::AccountId, u64, ValueQuery, DefaultAccountTake>; #[pallet::storage] - /// MAP (hot, cold) --> stake | Returns a tuple (u64: stakes, u64: block_number) + /// MAP (hot, cold) --> u64, u64) | Returns a tuple (u64: stakes, u64: block_number) pub type TotalHotkeyColdkeyStakesThisInterval = StorageDoubleMap< _, Identity, diff --git a/pallets/subtensor/src/swap_hotkey.rs b/pallets/subtensor/src/swap_hotkey.rs new file mode 100644 index 000000000..068b24b78 --- /dev/null +++ b/pallets/subtensor/src/swap_hotkey.rs @@ -0,0 +1,280 @@ +use super::*; +use crate::MIN_BALANCE_TO_PERFORM_COLDKEY_SWAP; +use frame_support::traits::fungible::Mutate; +use frame_support::traits::tokens::Preservation; +use frame_support::{storage::IterableStorageDoubleMap, weights::Weight}; +use sp_core::{Get, U256}; + +impl Pallet { + /// Swaps the hotkey of a coldkey account. + /// + /// # Arguments + /// + /// * `origin` - The origin of the transaction, and also the coldkey account. + /// * `old_hotkey` - The old hotkey to be swapped. + /// * `new_hotkey` - The new hotkey to replace the old one. + /// + /// # Returns + /// + /// * `DispatchResultWithPostInfo` - The result of the dispatch. + /// + /// # Errors + /// + /// * `NonAssociatedColdKey` - If the coldkey does not own the old hotkey. + /// * `HotKeySetTxRateLimitExceeded` - If the transaction rate limit is exceeded. + /// * `NewHotKeyIsSameWithOld` - If the new hotkey is the same as the old hotkey. + /// * `HotKeyAlreadyRegisteredInSubNet` - If the new hotkey is already registered in the subnet. + /// * `NotEnoughBalanceToPaySwapHotKey` - If there is not enough balance to pay for the swap. + pub fn do_swap_hotkey( + origin: T::RuntimeOrigin, + old_hotkey: &T::AccountId, + new_hotkey: &T::AccountId, + ) -> DispatchResultWithPostInfo { + // Ensure the origin is signed and get the coldkey + let coldkey = ensure_signed(origin)?; + + // Check if the coldkey is in arbitration + ensure!( + !Self::coldkey_in_arbitration(&coldkey), + Error::::ColdkeyIsInArbitration + ); + + // Initialize the weight for this operation + let mut weight = T::DbWeight::get().reads(2); + + // Ensure the new hotkey is different from the old one + ensure!(old_hotkey != new_hotkey, Error::::NewHotKeyIsSameWithOld); + // Ensure the new hotkey is not already registered on any network + ensure!( + !Self::is_hotkey_registered_on_any_network(new_hotkey), + Error::::HotKeyAlreadyRegisteredInSubNet + ); + + // Update the weight for the checks above + weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 0)); + // Ensure the coldkey owns the old hotkey + ensure!( + Self::coldkey_owns_hotkey(&coldkey, old_hotkey), + Error::::NonAssociatedColdKey + ); + + // Get the current block number + let block: u64 = Self::get_current_block_as_u64(); + // Ensure the transaction rate limit is not exceeded + ensure!( + !Self::exceeds_tx_rate_limit(Self::get_last_tx_block(&coldkey), block), + Error::::HotKeySetTxRateLimitExceeded + ); + + // Update the weight for reading the total networks + weight.saturating_accrue( + T::DbWeight::get().reads((TotalNetworks::::get().saturating_add(1u16)) as u64), + ); + + // Get the cost for swapping the key + let swap_cost = Self::get_key_swap_cost(); + log::debug!("Swap cost: {:?}", swap_cost); + + // Ensure the coldkey has enough balance to pay for the swap + ensure!( + Self::can_remove_balance_from_coldkey_account(&coldkey, swap_cost), + Error::::NotEnoughBalanceToPaySwapHotKey + ); + // Remove the swap cost from the coldkey's account + let actual_burn_amount = Self::remove_balance_from_coldkey_account(&coldkey, swap_cost)?; + // Burn the tokens + Self::burn_tokens(actual_burn_amount); + + // Perform the hotkey swap + Self::perform_hotkey_swap(old_hotkey, new_hotkey, &coldkey, &mut weight); + + // Update the last transaction block for the coldkey + Self::set_last_tx_block(&coldkey, block); + weight.saturating_accrue(T::DbWeight::get().writes(1)); + + // Emit an event for the hotkey swap + Self::deposit_event(Event::HotkeySwapped { + coldkey, + old_hotkey: old_hotkey.clone(), + new_hotkey: new_hotkey.clone(), + }); + + // Return the weight of the operation + Ok(Some(weight).into()) + } + + pub fn perform_hotkey_swap( old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, coldkey: &T::AccountId, weight: &mut Weight ) { + + // 1. Swap owner. + // Owner( hotkey ) -> coldkey -- the coldkey that owns the hotkey. + Owner::::remove(old_hotkey); + Owner::::insert(new_hotkey, coldkey.clone()); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); + + // 2. Swap OwnedHotkeys. + // OwnedHotkeys( coldkey ) -> Vec -- the hotkeys that the coldkey owns. + let mut hotkeys = OwnedHotkeys::::get(coldkey); + // Add the new key if needed. + if !hotkeys.contains(new_hotkey) { + hotkeys.push(new_hotkey.clone()); + } + // Remove the old key. + hotkeys.retain(|hk| *hk != *old_hotkey); + OwnedHotkeys::::insert(coldkey, hotkeys); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); + + // 3. Swap total hotkey stake. + // TotalHotkeyStake( hotkey ) -> stake -- the total stake that the hotkey has across all delegates. + let old_total_hotkey_stake = TotalHotkeyStake::::get( old_hotkey ); // Get the old total hotkey stake. + let new_total_hotkey_stake = TotalHotkeyStake::::get( new_hotkey ); // Get the new total hotkey stake. + TotalHotkeyStake::::remove( old_hotkey ); // Remove the old total hotkey stake. + TotalHotkeyStake::::insert( new_hotkey, old_total_hotkey_stake.saturating_add( new_total_hotkey_stake ) ); // Insert the new total hotkey stake via the addition. + weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2)); + + // Swap total hotkey stakes. + // TotalHotkeyColdkeyStakesThisInterval( hotkey ) --> (u64: stakes, u64: block_number) + let stake_tuples: Vec<(T::AccountId, (u64, u64))> = TotalHotkeyColdkeyStakesThisInterval::::iter_prefix(old_hotkey).collect(); + for (coldkey, stake_tup) in stake_tuples { + // NOTE: You could use this to increase your allowed stake operations but this would cost. + TotalHotkeyColdkeyStakesThisInterval::::insert(new_hotkey, &coldkey, stake_tup); + TotalHotkeyColdkeyStakesThisInterval::::remove(old_hotkey, &coldkey); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + } + + // Swap LastTxBlock + // LastTxBlock( hotkey ) --> u64 -- the last transaction block for the hotkey. + let old_last_tx_block: u64 = LastTxBlock::::get( old_hotkey ); + LastTxBlock::::remove( old_hotkey ); + LastTxBlock::::insert( new_hotkey, Self::get_current_block_as_u64() ); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + + // Swap LastTxBlockDelegateTake + // LastTxBlockDelegateTake( hotkey ) --> u64 -- the last transaction block for the hotkey delegate take. + LastTxBlockDelegateTake::::remove( old_hotkey ); + LastTxBlockDelegateTake::::insert( new_hotkey, Self::get_current_block_as_u64() ); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + + // Swap Senate members. + // Senate( hotkey ) --> ? + if T::SenateMembers::is_member(old_hotkey) { + T::SenateMembers::swap_member(old_hotkey, new_hotkey).map_err(|e| e.error)?; + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + } + + // 4. Swap delegates. + // Delegates( hotkey ) -> take value -- the hotkey delegate take value. + let old_delegate_take = Delegates::::get( old_hotkey ); + Delegates::::remove( old_hotkey ); // Remove the old delegate take. + Delegates::::insert( new_hotkey, old_delegate_take ); // Insert the new delegate take. + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + + // Swap all subnet specific info. + let all_netuid: Vec = Self::get_all_subnet_netuids(); + for netuid in all_netuids { + // 7.1 Remove the previous hotkey and insert the new hotkey from membership. + // IsNetworkMember( hotkey, netuid ) -> bool -- is the hotkey a subnet member. + let is_network_member: bool = IsNetworkMember::::get( old_hotkey, netuid ); + IsNetworkMember::::remove( old_hotkey, netuid ); + IsNetworkMember::::insert( new_hotkey, netuid, is_network_member ); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + + // 7.2 Swap Uids + Keys. + // Keys( netuid, hotkey ) -> uid -- the uid the hotkey has in the network if it is a member. + // Uids( netuid, hotkey ) -> uid -- the uids that the hotkey has. + if is_network_member { + // 7.2.1 Swap the UIDS + let old_uid: u16 = Uids::::get(netuid, old_hotkey); + Uids::::remove(netuid, old_hotkey); + Uids::::insert(netuid, new_hotkey, old_uid); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + + // 7.2.2 Swap the keys. + Keys::::insert(netuid, old_uid, new_hotkey.clone()); + weight.saturating_accrue(T::DbWeight::get().reads_writes(0, 1)); + } + + // 7.3 Swap Prometheus. + // Prometheus( netuid, hotkey ) -> prometheus -- the prometheus data that a hotkey has in the network. + if is_network_member { + let old_prometheus_info: PrometheusInfo = Prometheus::::get(netuid, old_hotkey); + Prometheus::::remove(netuid, old_hotkey); + Prometheus::::insert(netuid, new_hotkey, old_prometheus_info); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + } + + // 7.4. Swap axons. + // Axons( netuid, hotkey ) -> axon -- the axon that the hotkey has. + if is_network_member { + let old_axon_info: AxonInfo = Axons::::get(netuid, old_hotkey); + Axons::::remove(netuid, old_hotkey); + Axons::::insert(netuid, new_hotkey, old_axon_info); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + } + + // 7.5 Swap WeightCommits + // WeightCommits( hotkey ) --> Vec -- the weight commits for the hotkey. + if is_network_member { + if let Ok(old_weight_commits) = WeightCommits::::try_get(old_hotkey) { + WeightCommits::::remove(old_hotkey); + WeightCommits::::insert(new_hotkey, old_weight_commits); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + } + } + + // 7.5. Swap the subnet loaded emission. + // LoadedEmission( netuid ) --> Vec<(hotkey, u64)> -- the loaded emission for the subnet. + if is_network_member { + if let Some(mut old_loaded_emission) = LoadedEmission::::get(netuid) { + for emission in old_loaded_emission.iter_mut() { + if emission.0 == *old_hotkey { + emission.0 = new_hotkey.clone(); + } + } + LoadedEmission::::remove(netuid); + LoadedEmission::::insert(netuid, old_loaded_emission); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + } + } + + } + + // Swap Stake. + // Stake( hotkey, coldkey ) -> stake -- the stake that the hotkey controls on behalf of the coldkey. + let stakes: Vec<(T::AccountId, u64)> = Stake::::iter_prefix(old_hotkey).collect(); + // Clear the entire old prefix here. + let _ = Stake::::clear_prefix( old_hotkey, stakes.len() as u32, None ); + // Iterate over all the staking rows and insert them into the new hotkey. + for (coldkey, old_stake_amount) in stakes { + weight.saturating_accrue(T::DbWeight::get().reads(1)); + + // Swap Stake value + // Stake( hotkey, coldkey ) -> stake -- the stake that the hotkey controls on behalf of the coldkey. + // Get the new stake value. + let new_stake_value: u64 = Stake::::get(new_hotkey, &coldkey); + // Insert the new stake value. + Stake::::insert(new_hotkey, &coldkey, new_stake_value.saturating_add(old_stake_amount)); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); + + // Swap StakingHotkeys. + // StakingHotkeys( coldkey ) --> Vec -- the hotkeys that the coldkey stakes. + let mut staking_hotkeys = StakingHotkeys::::get(&coldkey); + staking_hotkeys.retain(|hk| *hk != *old_hotkey && *hk != *new_hotkey); + staking_hotkeys.push(new_hotkey.clone()); + StakingHotkeys::::insert(coldkey.clone(), staking_hotkeys); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); + } + } + + pub fn swap_senate_member( + old_hotkey: &T::AccountId, + new_hotkey: &T::AccountId, + weight: &mut Weight, + ) -> DispatchResult { + weight.saturating_accrue(T::DbWeight::get().reads(1)); + if T::SenateMembers::is_member(old_hotkey) { + T::SenateMembers::swap_member(old_hotkey, new_hotkey).map_err(|e| e.error)?; + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + } + Ok(()) + } +} From 0432b53d428e1f7f5d2b449bbcb0a649e0e6a01d Mon Sep 17 00:00:00 2001 From: const Date: Mon, 22 Jul 2024 13:26:28 -0500 Subject: [PATCH 47/51] add tests --- pallets/subtensor/src/lib.rs | 35 +- pallets/subtensor/src/swap.rs | 417 +------------- pallets/subtensor/src/swap_hotkey.rs | 47 +- pallets/subtensor/tests/swap.rs | 719 +------------------------ pallets/subtensor/tests/swap_hotkey.rs | 542 +++++++++++++++++++ 5 files changed, 604 insertions(+), 1156 deletions(-) create mode 100644 pallets/subtensor/tests/swap_hotkey.rs diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index cfb3a5828..d492b5477 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -45,6 +45,7 @@ mod root; mod serving; mod staking; mod swap; +mod swap_hotkey; mod uids; mod utils; mod weights; @@ -272,7 +273,7 @@ pub mod pallet { } #[pallet::storage] - pub(super) type SenateRequiredStakePercentage = + pub type SenateRequiredStakePercentage = StorageValue<_, u64, ValueQuery, DefaultSenateRequiredStakePercentage>; /// ============================ @@ -796,15 +797,15 @@ pub mod pallet { } #[pallet::storage] // --- ITEM ( tx_rate_limit ) - pub(super) type TxRateLimit = StorageValue<_, u64, ValueQuery, DefaultTxRateLimit>; + pub type TxRateLimit = StorageValue<_, u64, ValueQuery, DefaultTxRateLimit>; #[pallet::storage] // --- ITEM ( tx_rate_limit ) - pub(super) type TxDelegateTakeRateLimit = + pub type TxDelegateTakeRateLimit = StorageValue<_, u64, ValueQuery, DefaultTxDelegateTakeRateLimit>; #[pallet::storage] // --- MAP ( key ) --> last_block pub type LastTxBlock = StorageMap<_, Identity, T::AccountId, u64, ValueQuery, DefaultLastTxBlock>; #[pallet::storage] // --- MAP ( key ) --> last_block - pub(super) type LastTxBlockDelegateTake = + pub type LastTxBlockDelegateTake = StorageMap<_, Identity, T::AccountId, u64, ValueQuery, DefaultLastTxBlock>; /// Default value for serving rate limit. @@ -1084,41 +1085,41 @@ pub mod pallet { StorageMap<_, Identity, u16, Vec<(T::AccountId, u64, u64)>, OptionQuery>; #[pallet::storage] // --- DMAP ( netuid ) --> active - pub(super) type Active = + pub type Active = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyBoolVec>; #[pallet::storage] // --- DMAP ( netuid ) --> rank - pub(super) type Rank = + pub type Rank = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] // --- DMAP ( netuid ) --> trust - pub(super) type Trust = + pub type Trust = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] // --- DMAP ( netuid ) --> consensus - pub(super) type Consensus = + pub type Consensus = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] // --- DMAP ( netuid ) --> incentive - pub(super) type Incentive = + pub type Incentive = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] // --- DMAP ( netuid ) --> dividends - pub(super) type Dividends = + pub type Dividends = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] // --- DMAP ( netuid ) --> emission - pub(super) type Emission = + pub type Emission = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU64Vec>; #[pallet::storage] // --- DMAP ( netuid ) --> last_update - pub(super) type LastUpdate = + pub type LastUpdate = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU64Vec>; #[pallet::storage] // --- DMAP ( netuid ) --> validator_trust - pub(super) type ValidatorTrust = + pub type ValidatorTrust = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] // --- DMAP ( netuid ) --> pruning_scores - pub(super) type PruningScores = + pub type PruningScores = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] // --- DMAP ( netuid ) --> validator_permit - pub(super) type ValidatorPermit = + pub type ValidatorPermit = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyBoolVec>; #[pallet::storage] // --- DMAP ( netuid, uid ) --> weights - pub(super) type Weights = StorageDoubleMap< + pub type Weights = StorageDoubleMap< _, Identity, u16, @@ -1129,7 +1130,7 @@ pub mod pallet { DefaultWeights, >; #[pallet::storage] // --- DMAP ( netuid, uid ) --> bonds - pub(super) type Bonds = StorageDoubleMap< + pub type Bonds = StorageDoubleMap< _, Identity, u16, diff --git a/pallets/subtensor/src/swap.rs b/pallets/subtensor/src/swap.rs index 8e4ca5cc9..5d8f66c68 100644 --- a/pallets/subtensor/src/swap.rs +++ b/pallets/subtensor/src/swap.rs @@ -6,100 +6,6 @@ use frame_support::{storage::IterableStorageDoubleMap, weights::Weight}; use sp_core::{Get, U256}; impl Pallet { - /// Swaps the hotkey of a coldkey account. - /// - /// # Arguments - /// - /// * `origin` - The origin of the transaction, and also the coldkey account. - /// * `old_hotkey` - The old hotkey to be swapped. - /// * `new_hotkey` - The new hotkey to replace the old one. - /// - /// # Returns - /// - /// * `DispatchResultWithPostInfo` - The result of the dispatch. - /// - /// # Errors - /// - /// * `NonAssociatedColdKey` - If the coldkey does not own the old hotkey. - /// * `HotKeySetTxRateLimitExceeded` - If the transaction rate limit is exceeded. - /// * `NewHotKeyIsSameWithOld` - If the new hotkey is the same as the old hotkey. - /// * `HotKeyAlreadyRegisteredInSubNet` - If the new hotkey is already registered in the subnet. - /// * `NotEnoughBalanceToPaySwapHotKey` - If there is not enough balance to pay for the swap. - pub fn do_swap_hotkey( - origin: T::RuntimeOrigin, - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - ) -> DispatchResultWithPostInfo { - let coldkey = ensure_signed(origin)?; - - ensure!( - !Self::coldkey_in_arbitration(&coldkey), - Error::::ColdkeyIsInArbitration - ); - - let mut weight = T::DbWeight::get().reads(2); - - ensure!(old_hotkey != new_hotkey, Error::::NewHotKeyIsSameWithOld); - ensure!( - !Self::is_hotkey_registered_on_any_network(new_hotkey), - Error::::HotKeyAlreadyRegisteredInSubNet - ); - - weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 0)); - ensure!( - Self::coldkey_owns_hotkey(&coldkey, old_hotkey), - Error::::NonAssociatedColdKey - ); - - let block: u64 = Self::get_current_block_as_u64(); - ensure!( - !Self::exceeds_tx_rate_limit(Self::get_last_tx_block(&coldkey), block), - Error::::HotKeySetTxRateLimitExceeded - ); - - weight.saturating_accrue( - T::DbWeight::get().reads((TotalNetworks::::get().saturating_add(1u16)) as u64), - ); - - let swap_cost = Self::get_key_swap_cost(); - log::debug!("Swap cost: {:?}", swap_cost); - - ensure!( - Self::can_remove_balance_from_coldkey_account(&coldkey, swap_cost), - Error::::NotEnoughBalanceToPaySwapHotKey - ); - let actual_burn_amount = Self::remove_balance_from_coldkey_account(&coldkey, swap_cost)?; - Self::burn_tokens(actual_burn_amount); - - Self::swap_owner(old_hotkey, new_hotkey, &coldkey, &mut weight); - Self::swap_total_hotkey_stake(old_hotkey, new_hotkey, &mut weight); - Self::swap_delegates(old_hotkey, new_hotkey, &mut weight); - Self::swap_stake(old_hotkey, new_hotkey, &mut weight); - - // Store the value of is_network_member for the old key - let netuid_is_member: Vec = Self::get_netuid_is_member(old_hotkey, &mut weight); - - Self::swap_is_network_member(old_hotkey, new_hotkey, &netuid_is_member, &mut weight); - Self::swap_axons(old_hotkey, new_hotkey, &netuid_is_member, &mut weight); - Self::swap_keys(old_hotkey, new_hotkey, &netuid_is_member, &mut weight); - Self::swap_loaded_emission(old_hotkey, new_hotkey, &netuid_is_member, &mut weight); - Self::swap_uids(old_hotkey, new_hotkey, &netuid_is_member, &mut weight); - Self::swap_prometheus(old_hotkey, new_hotkey, &netuid_is_member, &mut weight); - Self::swap_senate_member(old_hotkey, new_hotkey, &mut weight)?; - - Self::swap_total_hotkey_coldkey_stakes_this_interval(old_hotkey, new_hotkey, &mut weight); - - Self::set_last_tx_block(&coldkey, block); - weight.saturating_accrue(T::DbWeight::get().writes(1)); - - Self::deposit_event(Event::HotkeySwapped { - coldkey, - old_hotkey: old_hotkey.clone(), - new_hotkey: new_hotkey.clone(), - }); - - Ok(Some(weight).into()) - } /// Swaps the coldkey associated with a set of hotkeys from an old coldkey to a new coldkey. /// @@ -472,316 +378,6 @@ impl Pallet { netuid_is_member } - /// Swaps the owner of the hotkey. - /// - /// # Arguments - /// - /// * `old_hotkey` - The old hotkey. - /// * `new_hotkey` - The new hotkey. - /// * `coldkey` - The coldkey owning the hotkey. - /// * `weight` - The weight of the transaction. - /// - pub fn swap_owner( - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - coldkey: &T::AccountId, - weight: &mut Weight, - ) { - Owner::::remove(old_hotkey); - Owner::::insert(new_hotkey, coldkey.clone()); - - // Update OwnedHotkeys map - let mut hotkeys = OwnedHotkeys::::get(coldkey); - if !hotkeys.contains(new_hotkey) { - hotkeys.push(new_hotkey.clone()); - } - hotkeys.retain(|hk| *hk != *old_hotkey); - OwnedHotkeys::::insert(coldkey, hotkeys); - - weight.saturating_accrue(T::DbWeight::get().writes(2)); - } - - /// Swaps the total stake of the hotkey. - /// - /// # Arguments - /// - /// * `old_hotkey` - The old hotkey. - /// * `new_hotkey` - The new hotkey. - /// * `weight` - The weight of the transaction. - /// - /// # Weight Calculation - /// - /// * Reads: 1 if the old hotkey exists, otherwise 1 for the failed read. - /// * Writes: 2 if the old hotkey exists (one for removal and one for insertion). - pub fn swap_total_hotkey_stake( - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - weight: &mut Weight, - ) { - if let Ok(total_hotkey_stake) = TotalHotkeyStake::::try_get(old_hotkey) { - TotalHotkeyStake::::remove(old_hotkey); - TotalHotkeyStake::::insert(new_hotkey, total_hotkey_stake); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - } else { - weight.saturating_accrue(T::DbWeight::get().reads(1)); - } - } - - /// Swaps the delegates of the hotkey. - /// - /// # Arguments - /// - /// * `old_hotkey` - The old hotkey. - /// * `new_hotkey` - The new hotkey. - /// * `weight` - The weight of the transaction. - /// - /// # Weight Calculation - /// - /// * Reads: 1 if the old hotkey exists, otherwise 1 for the failed read. - /// * Writes: 2 if the old hotkey exists (one for removal and one for insertion). - pub fn swap_delegates( - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - weight: &mut Weight, - ) { - if let Ok(delegate_take) = Delegates::::try_get(old_hotkey) { - Delegates::::remove(old_hotkey); - Delegates::::insert(new_hotkey, delegate_take); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - } else { - weight.saturating_accrue(T::DbWeight::get().reads(1)); - } - } - - /// Swaps the stake of the hotkey. - /// - /// # Arguments - /// - /// * `old_hotkey` - The old hotkey. - /// * `new_hotkey` - The new hotkey. - /// * `weight` - The weight of the transaction. - pub fn swap_stake(old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, weight: &mut Weight) { - let mut writes: u64 = 0; - let stakes: Vec<(T::AccountId, u64)> = Stake::::iter_prefix(old_hotkey).collect(); - let stake_count = stakes.len() as u32; - - for (coldkey, stake_amount) in stakes { - Stake::::insert(new_hotkey, &coldkey, stake_amount); - writes = writes.saturating_add(1u64); // One write for insert - - // Update StakingHotkeys map - let mut staking_hotkeys = StakingHotkeys::::get(&coldkey); - if !staking_hotkeys.contains(new_hotkey) { - staking_hotkeys.push(new_hotkey.clone()); - writes = writes.saturating_add(1u64); // One write for insert - } - if let Some(pos) = staking_hotkeys.iter().position(|x| x == old_hotkey) { - staking_hotkeys.remove(pos); - writes = writes.saturating_add(1u64); // One write for remove - } - StakingHotkeys::::insert(coldkey.clone(), staking_hotkeys); - writes = writes.saturating_add(1u64); // One write for insert - } - - // Clear the prefix for the old hotkey after transferring all stakes - let _ = Stake::::clear_prefix(old_hotkey, stake_count, None); - writes = writes.saturating_add(1); // One write for insert; // One write for clear_prefix - - // TODO: Remove all entries for old hotkey from StakingHotkeys map - - weight.saturating_accrue(T::DbWeight::get().writes(writes)); - } - - /// Swaps the network membership status of the hotkey. - /// - /// # Arguments - /// - /// * `old_hotkey` - The old hotkey. - /// * `new_hotkey` - The new hotkey. - /// * `netuid_is_member` - A vector of network IDs where the hotkey is a member. - /// * `weight` - The weight of the transaction. - pub fn swap_is_network_member( - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - netuid_is_member: &[u16], - weight: &mut Weight, - ) { - let _ = IsNetworkMember::::clear_prefix(old_hotkey, netuid_is_member.len() as u32, None); - weight.saturating_accrue(T::DbWeight::get().writes(netuid_is_member.len() as u64)); - for netuid in netuid_is_member.iter() { - IsNetworkMember::::insert(new_hotkey, netuid, true); - weight.saturating_accrue(T::DbWeight::get().writes(1)); - } - } - - /// Swaps the axons of the hotkey. - /// - /// # Arguments - /// - /// * `old_hotkey` - The old hotkey. - /// * `new_hotkey` - The new hotkey. - /// * `netuid_is_member` - A vector of network IDs where the hotkey is a member. - /// * `weight` - The weight of the transaction. - /// - /// # Weight Calculation - /// - /// * Reads: 1 for each network ID if the old hotkey exists in that network. - /// * Writes: 2 for each network ID if the old hotkey exists in that network (one for removal and one for insertion). - pub fn swap_axons( - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - netuid_is_member: &[u16], - weight: &mut Weight, - ) { - for netuid in netuid_is_member.iter() { - if let Ok(axon_info) = Axons::::try_get(netuid, old_hotkey) { - Axons::::remove(netuid, old_hotkey); - Axons::::insert(netuid, new_hotkey, axon_info); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - } else { - weight.saturating_accrue(T::DbWeight::get().reads(1)); - } - } - } - - /// Swaps the references in the keys storage map of the hotkey. - /// - /// # Arguments - /// - /// * `old_hotkey` - The old hotkey. - /// * `new_hotkey` - The new hotkey. - /// * `netuid_is_member` - A vector of network IDs where the hotkey is a member. - /// * `weight` - The weight of the transaction. - pub fn swap_keys( - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - netuid_is_member: &[u16], - weight: &mut Weight, - ) { - let mut writes: u64 = 0; - for netuid in netuid_is_member { - let keys: Vec<(u16, T::AccountId)> = Keys::::iter_prefix(netuid).collect(); - for (uid, key) in keys { - if key == *old_hotkey { - log::info!("old hotkey found: {:?}", old_hotkey); - Keys::::insert(netuid, uid, new_hotkey.clone()); - } - writes = writes.saturating_add(2u64); - } - } - log::info!("writes: {:?}", writes); - weight.saturating_accrue(T::DbWeight::get().writes(writes)); - } - - /// Swaps the loaded emission of the hotkey. - /// - /// # Arguments - /// - /// * `old_hotkey` - The old hotkey. - /// * `new_hotkey` - The new hotkey. - /// * `netuid_is_member` - A vector of network IDs where the hotkey is a member. - /// * `weight` - The weight of the transaction. - /// - pub fn swap_loaded_emission( - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - netuid_is_member: &[u16], - weight: &mut Weight, - ) { - for netuid in netuid_is_member { - if let Some(mut emissions) = LoadedEmission::::get(netuid) { - for emission in emissions.iter_mut() { - if emission.0 == *old_hotkey { - emission.0 = new_hotkey.clone(); - } - } - LoadedEmission::::insert(netuid, emissions); - } - } - weight.saturating_accrue(T::DbWeight::get().writes(netuid_is_member.len() as u64)); - } - - /// Swaps the UIDs of the hotkey. - /// - /// # Arguments - /// - /// * `old_hotkey` - The old hotkey. - /// * `new_hotkey` - The new hotkey. - /// * `netuid_is_member` - A vector of network IDs where the hotkey is a member. - /// * `weight` - The weight of the transaction. - /// - pub fn swap_uids( - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - netuid_is_member: &[u16], - weight: &mut Weight, - ) { - for netuid in netuid_is_member.iter() { - if let Ok(uid) = Uids::::try_get(netuid, old_hotkey) { - Uids::::remove(netuid, old_hotkey); - Uids::::insert(netuid, new_hotkey, uid); - weight.saturating_accrue(T::DbWeight::get().writes(2)); - } - } - } - - /// Swaps the Prometheus data of the hotkey. - /// - /// # Arguments - /// - /// * `old_hotkey` - The old hotkey. - /// * `new_hotkey` - The new hotkey. - /// * `netuid_is_member` - A vector of network IDs where the hotkey is a member. - /// * `weight` - The weight of the transaction. - /// - /// # Weight Calculation - /// - /// * Reads: 1 for each network ID if the old hotkey exists in that network. - /// * Writes: 2 for each network ID if the old hotkey exists in that network (one for removal and one for insertion). - pub fn swap_prometheus( - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - netuid_is_member: &[u16], - weight: &mut Weight, - ) { - for netuid in netuid_is_member.iter() { - if let Ok(prometheus_info) = Prometheus::::try_get(netuid, old_hotkey) { - Prometheus::::remove(netuid, old_hotkey); - Prometheus::::insert(netuid, new_hotkey, prometheus_info); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - } else { - weight.saturating_accrue(T::DbWeight::get().reads(1)); - } - } - } - - /// Swaps the total hotkey-coldkey stakes for the current interval. - /// - /// # Arguments - /// - /// * `old_hotkey` - The old hotkey. - /// * `new_hotkey` - The new hotkey. - /// * `weight` - The weight of the transaction. - /// - pub fn swap_total_hotkey_coldkey_stakes_this_interval( - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - weight: &mut Weight, - ) { - let stakes: Vec<(T::AccountId, (u64, u64))> = - TotalHotkeyColdkeyStakesThisInterval::::iter_prefix(old_hotkey).collect(); - log::info!("Stakes to swap: {:?}", stakes); - for (coldkey, stake) in stakes { - log::info!( - "Swapping stake for coldkey: {:?}, stake: {:?}", - coldkey, - stake - ); - TotalHotkeyColdkeyStakesThisInterval::::insert(new_hotkey, &coldkey, stake); - TotalHotkeyColdkeyStakesThisInterval::::remove(old_hotkey, &coldkey); - weight.saturating_accrue(T::DbWeight::get().writes(2)); // One write for insert and one for remove - } - } /// Swaps the total stake associated with a coldkey from the old coldkey to the new coldkey. /// @@ -1040,16 +636,5 @@ impl Pallet { weight.saturating_accrue(T::DbWeight::get().reads(TotalNetworks::::get() as u64)); } - pub fn swap_senate_member( - old_hotkey: &T::AccountId, - new_hotkey: &T::AccountId, - weight: &mut Weight, - ) -> DispatchResult { - weight.saturating_accrue(T::DbWeight::get().reads(1)); - if T::SenateMembers::is_member(old_hotkey) { - T::SenateMembers::swap_member(old_hotkey, new_hotkey).map_err(|e| e.error)?; - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - } - Ok(()) - } + } diff --git a/pallets/subtensor/src/swap_hotkey.rs b/pallets/subtensor/src/swap_hotkey.rs index 068b24b78..222a4ff37 100644 --- a/pallets/subtensor/src/swap_hotkey.rs +++ b/pallets/subtensor/src/swap_hotkey.rs @@ -103,7 +103,7 @@ impl Pallet { Ok(Some(weight).into()) } - pub fn perform_hotkey_swap( old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, coldkey: &T::AccountId, weight: &mut Weight ) { + pub fn perform_hotkey_swap( old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, coldkey: &T::AccountId, weight: &mut Weight ) -> DispatchResult { // 1. Swap owner. // Owner( hotkey ) -> coldkey -- the coldkey that owns the hotkey. @@ -169,7 +169,7 @@ impl Pallet { weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); // Swap all subnet specific info. - let all_netuid: Vec = Self::get_all_subnet_netuids(); + let all_netuids: Vec = Self::get_all_subnet_netuids(); for netuid in all_netuids { // 7.1 Remove the previous hotkey and insert the new hotkey from membership. // IsNetworkMember( hotkey, netuid ) -> bool -- is the hotkey a subnet member. @@ -183,40 +183,43 @@ impl Pallet { // Uids( netuid, hotkey ) -> uid -- the uids that the hotkey has. if is_network_member { // 7.2.1 Swap the UIDS - let old_uid: u16 = Uids::::get(netuid, old_hotkey); - Uids::::remove(netuid, old_hotkey); - Uids::::insert(netuid, new_hotkey, old_uid); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - - // 7.2.2 Swap the keys. - Keys::::insert(netuid, old_uid, new_hotkey.clone()); - weight.saturating_accrue(T::DbWeight::get().reads_writes(0, 1)); + if let Ok(old_uid) = Uids::::try_get(netuid, old_hotkey) { + Uids::::remove(netuid, old_hotkey); + Uids::::insert(netuid, new_hotkey, old_uid); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + + // 7.2.2 Swap the keys. + Keys::::insert(netuid, old_uid, new_hotkey.clone()); + weight.saturating_accrue(T::DbWeight::get().reads_writes(0, 1)); + } } // 7.3 Swap Prometheus. // Prometheus( netuid, hotkey ) -> prometheus -- the prometheus data that a hotkey has in the network. if is_network_member { - let old_prometheus_info: PrometheusInfo = Prometheus::::get(netuid, old_hotkey); - Prometheus::::remove(netuid, old_hotkey); - Prometheus::::insert(netuid, new_hotkey, old_prometheus_info); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + if let Ok(old_prometheus_info) = Prometheus::::try_get(netuid, old_hotkey) { + Prometheus::::remove(netuid, old_hotkey); + Prometheus::::insert(netuid, new_hotkey, old_prometheus_info); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + } } // 7.4. Swap axons. // Axons( netuid, hotkey ) -> axon -- the axon that the hotkey has. if is_network_member { - let old_axon_info: AxonInfo = Axons::::get(netuid, old_hotkey); - Axons::::remove(netuid, old_hotkey); - Axons::::insert(netuid, new_hotkey, old_axon_info); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + if let Ok(old_axon_info) = Axons::::try_get(netuid, old_hotkey) { + Axons::::remove(netuid, old_hotkey); + Axons::::insert(netuid, new_hotkey, old_axon_info); + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + } } // 7.5 Swap WeightCommits // WeightCommits( hotkey ) --> Vec -- the weight commits for the hotkey. if is_network_member { - if let Ok(old_weight_commits) = WeightCommits::::try_get(old_hotkey) { - WeightCommits::::remove(old_hotkey); - WeightCommits::::insert(new_hotkey, old_weight_commits); + if let Ok(old_weight_commits) = WeightCommits::::try_get(netuid, old_hotkey) { + WeightCommits::::remove(netuid, old_hotkey); + WeightCommits::::insert(netuid, new_hotkey, old_weight_commits); weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); } } @@ -263,6 +266,8 @@ impl Pallet { StakingHotkeys::::insert(coldkey.clone(), staking_hotkeys); weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); } + + Ok(()) } pub fn swap_senate_member( diff --git a/pallets/subtensor/tests/swap.rs b/pallets/subtensor/tests/swap.rs index 21c3a983a..86fe109be 100644 --- a/pallets/subtensor/tests/swap.rs +++ b/pallets/subtensor/tests/swap.rs @@ -9,6 +9,7 @@ use mock::*; use pallet_subtensor::*; use sp_core::U256; +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap -- test_do_swap_hotkey_ok --exact --nocapture #[test] fn test_do_swap_hotkey_ok() { new_test_ext(1).execute_with(|| { @@ -42,15 +43,11 @@ fn test_do_swap_hotkey_ok() { ); // Verify other storage changes - assert_eq!( - SubtensorModule::get_total_stake_for_hotkey(&new_hotkey), - SubtensorModule::get_total_stake_for_hotkey(&old_hotkey) - ); - assert_eq!( + assert_ne!( SubtensorModule::get_delegate(new_hotkey.encode()), SubtensorModule::get_delegate(old_hotkey.encode()) ); - assert_eq!( + assert_ne!( SubtensorModule::get_last_tx_block(&new_hotkey), SubtensorModule::get_last_tx_block(&old_hotkey) ); @@ -62,29 +59,6 @@ fn test_do_swap_hotkey_ok() { } let mut weight = Weight::zero(); - // UIDs - for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight) { - assert_eq!( - Uids::::get(netuid, new_hotkey), - Uids::::get(netuid, old_hotkey) - ); - } - - // Prometheus - for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight) { - assert_eq!( - Prometheus::::get(netuid, new_hotkey), - Prometheus::::get(netuid, old_hotkey) - ); - } - - // LoadedEmission - for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight) { - assert_eq!( - LoadedEmission::::get(netuid).unwrap(), - LoadedEmission::::get(netuid).unwrap() - ); - } // IsNetworkMember for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight) { @@ -96,7 +70,7 @@ fn test_do_swap_hotkey_ok() { assert_eq!(Owner::::get(new_hotkey), coldkey); // TotalHotkeyStake - assert_eq!( + assert_ne!( TotalHotkeyStake::::get(new_hotkey), TotalHotkeyStake::::get(old_hotkey) ); @@ -129,185 +103,6 @@ fn test_do_swap_hotkey_ok() { }); } -#[test] -fn test_do_swap_hotkey_ok_robust() { - new_test_ext(1).execute_with(|| { - let num_subnets: u16 = 10; - let tempo: u16 = 13; - let swap_cost = 1_000_000_000u64; - - // Create 10 sets of keys - let mut old_hotkeys = vec![]; - let mut new_hotkeys = vec![]; - let mut coldkeys = vec![]; - - for i in 0..10 { - old_hotkeys.push(U256::from(i * 2 + 1)); - new_hotkeys.push(U256::from(i * 2 + 2)); - coldkeys.push(U256::from(i * 2 + 11)); - } - - // Setup initial state - for netuid in 1..=num_subnets { - add_network(netuid, tempo, 0); - SubtensorModule::set_max_registrations_per_block(netuid, 20); - SubtensorModule::set_target_registrations_per_interval(netuid, 1000); - log::info!( - "Registrations this interval for netuid {:?} is {:?}", - netuid, - SubtensorModule::get_target_registrations_per_interval(netuid) - ); - for i in 0..10 { - register_ok_neuron(netuid, old_hotkeys[i], coldkeys[i], 0); - } - } - - // Add balance to coldkeys for swap cost - for coldkey in coldkeys.iter().take(10) { - SubtensorModule::add_balance_to_coldkey_account(coldkey, swap_cost); - } - - // Add old_hotkeys[0] and old_hotkeys[1] to Senate - assert_ok!(SenateMembers::add_member( - RawOrigin::Root.into(), - old_hotkeys[0] - )); - assert_ok!(SenateMembers::add_member( - RawOrigin::Root.into(), - old_hotkeys[1] - )); - - // Verify initial Senate membership - assert!(Senate::is_member(&old_hotkeys[0])); - assert!(Senate::is_member(&old_hotkeys[1])); - assert!(!Senate::is_member(&new_hotkeys[0])); - assert!(!Senate::is_member(&new_hotkeys[1])); - - // Perform the swaps for only two hotkeys - assert_ok!(SubtensorModule::do_swap_hotkey( - <::RuntimeOrigin>::signed(coldkeys[0]), - &old_hotkeys[0], - &new_hotkeys[0] - )); - assert_ok!(SubtensorModule::do_swap_hotkey( - <::RuntimeOrigin>::signed(coldkeys[1]), - &old_hotkeys[1], - &new_hotkeys[1] - )); - - // Verify the swaps - for netuid in 1..=num_subnets { - for i in 0..10 { - if i == 0 || i == 1 { - assert_eq!( - SubtensorModule::get_owning_coldkey_for_hotkey(&new_hotkeys[i]), - coldkeys[i] - ); - assert_ne!( - SubtensorModule::get_owning_coldkey_for_hotkey(&old_hotkeys[i]), - coldkeys[i] - ); - - // Verify other storage changes - assert_eq!( - SubtensorModule::get_total_stake_for_hotkey(&new_hotkeys[i]), - SubtensorModule::get_total_stake_for_hotkey(&old_hotkeys[i]) - ); - - assert_eq!( - SubtensorModule::get_delegate(new_hotkeys[i].encode()), - SubtensorModule::get_delegate(old_hotkeys[i].encode()) - ); - - assert_eq!( - SubtensorModule::get_last_tx_block(&new_hotkeys[i]), - SubtensorModule::get_last_tx_block(&old_hotkeys[i]) - ); - - // Verify raw storage maps - // Stake - for (coldkey, stake_amount) in Stake::::iter_prefix(old_hotkeys[i]) { - assert_eq!(Stake::::get(new_hotkeys[i], coldkey), stake_amount); - } - - let mut weight = Weight::zero(); - // UIDs - for netuid in - SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight) - { - assert_eq!( - Uids::::get(netuid, new_hotkeys[i]), - Uids::::get(netuid, old_hotkeys[i]) - ); - } - - // Prometheus - for netuid in - SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight) - { - assert_eq!( - Prometheus::::get(netuid, new_hotkeys[i]), - Prometheus::::get(netuid, old_hotkeys[i]) - ); - } - - // LoadedEmission - for netuid in - SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight) - { - assert_eq!( - LoadedEmission::::get(netuid).unwrap(), - LoadedEmission::::get(netuid).unwrap() - ); - } - - // IsNetworkMember - for netuid in - SubtensorModule::get_netuid_is_member(&old_hotkeys[i], &mut weight) - { - assert!(IsNetworkMember::::contains_key( - new_hotkeys[i], - netuid - )); - assert!(!IsNetworkMember::::contains_key( - old_hotkeys[i], - netuid - )); - } - - // Owner - assert_eq!(Owner::::get(new_hotkeys[i]), coldkeys[i]); - - // Keys - for (uid, hotkey) in Keys::::iter_prefix(netuid) { - if hotkey == old_hotkeys[i] { - assert_eq!(Keys::::get(netuid, uid), new_hotkeys[i]); - } - } - - // Verify Senate membership swap - assert!(!Senate::is_member(&old_hotkeys[i])); - assert!(Senate::is_member(&new_hotkeys[i])); - } else { - // Ensure other hotkeys remain unchanged - assert_eq!( - SubtensorModule::get_owning_coldkey_for_hotkey(&old_hotkeys[i]), - coldkeys[i] - ); - assert_ne!( - SubtensorModule::get_owning_coldkey_for_hotkey(&new_hotkeys[i]), - coldkeys[i] - ); - - // Verify Senate membership remains unchanged for other hotkeys - assert!(!Senate::is_member(&old_hotkeys[i])); - assert!(!Senate::is_member(&new_hotkeys[i])); - } - } - } - }); -} - #[test] fn test_swap_hotkey_tx_rate_limit_exceeded() { new_test_ext(1).execute_with(|| { @@ -402,7 +197,7 @@ fn test_swap_owner_success() { Owner::::insert(old_hotkey, coldkey); // Perform the swap - SubtensorModule::swap_owner(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); // Verify the swap assert_eq!(Owner::::get(new_hotkey), coldkey); @@ -422,7 +217,7 @@ fn test_swap_owner_old_hotkey_not_exist() { assert!(!Owner::::contains_key(old_hotkey)); // Perform the swap - SubtensorModule::swap_owner(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); // Verify the swap assert_eq!(Owner::::get(new_hotkey), coldkey); @@ -444,7 +239,7 @@ fn test_swap_owner_new_hotkey_already_exists() { Owner::::insert(new_hotkey, another_coldkey); // Perform the swap - SubtensorModule::swap_owner(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); // Verify the swap assert_eq!(Owner::::get(new_hotkey), coldkey); @@ -452,31 +247,12 @@ fn test_swap_owner_new_hotkey_already_exists() { }); } -#[test] -fn test_swap_owner_weight_update() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let mut weight = Weight::zero(); - - // Initialize Owner for old_hotkey - Owner::::insert(old_hotkey, coldkey); - - // Perform the swap - SubtensorModule::swap_owner(&old_hotkey, &new_hotkey, &coldkey, &mut weight); - - // Verify the weight update - let expected_weight = ::DbWeight::get().writes(2); - assert_eq!(weight, expected_weight); - }); -} - #[test] fn test_swap_total_hotkey_stake_success() { new_test_ext(1).execute_with(|| { let old_hotkey = U256::from(1); let new_hotkey = U256::from(2); + let coldkey = U256::from(3); let total_stake = 1000u64; let mut weight = Weight::zero(); @@ -484,7 +260,7 @@ fn test_swap_total_hotkey_stake_success() { TotalHotkeyStake::::insert(old_hotkey, total_stake); // Perform the swap - SubtensorModule::swap_total_hotkey_stake(&old_hotkey, &new_hotkey, &mut weight); + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); // Verify the swap assert_eq!(TotalHotkeyStake::::get(new_hotkey), total_stake); @@ -492,49 +268,14 @@ fn test_swap_total_hotkey_stake_success() { }); } -#[test] -fn test_swap_total_hotkey_stake_old_hotkey_not_exist() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let mut weight = Weight::zero(); - - // Ensure old_hotkey does not exist - assert!(!TotalHotkeyStake::::contains_key(old_hotkey)); - - // Perform the swap - SubtensorModule::swap_total_hotkey_stake(&old_hotkey, &new_hotkey, &mut weight); - // Verify that new_hotkey does not have a stake - assert!(!TotalHotkeyStake::::contains_key(new_hotkey)); - }); -} - -#[test] -fn test_swap_total_hotkey_stake_weight_update() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let total_stake = 1000u64; - let mut weight = Weight::zero(); - - // Initialize TotalHotkeyStake for old_hotkey - TotalHotkeyStake::::insert(old_hotkey, total_stake); - - // Perform the swap - SubtensorModule::swap_total_hotkey_stake(&old_hotkey, &new_hotkey, &mut weight); - - // Verify the weight update - let expected_weight = ::DbWeight::get().reads_writes(1, 2); - assert_eq!(weight, expected_weight); - }); -} #[test] fn test_swap_delegates_success() { new_test_ext(1).execute_with(|| { let old_hotkey = U256::from(1); let new_hotkey = U256::from(2); + let coldkey = U256::from(3); let delegate_take = 10u16; let mut weight = Weight::zero(); @@ -542,7 +283,7 @@ fn test_swap_delegates_success() { Delegates::::insert(old_hotkey, delegate_take); // Perform the swap - SubtensorModule::swap_delegates(&old_hotkey, &new_hotkey, &mut weight); + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); // Verify the swap assert_eq!(Delegates::::get(new_hotkey), delegate_take); @@ -550,29 +291,12 @@ fn test_swap_delegates_success() { }); } -#[test] -fn test_swap_delegates_old_hotkey_not_exist() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let mut weight = Weight::zero(); - - // Ensure old_hotkey does not exist - assert!(!Delegates::::contains_key(old_hotkey)); - - // Perform the swap - SubtensorModule::swap_delegates(&old_hotkey, &new_hotkey, &mut weight); - - // Verify that new_hotkey does not have a delegate - assert!(!Delegates::::contains_key(new_hotkey)); - }); -} - #[test] fn test_swap_delegates_weight_update() { new_test_ext(1).execute_with(|| { let old_hotkey = U256::from(1); let new_hotkey = U256::from(2); + let coldkey = U256::from(3); let delegate_take = 10u16; let mut weight = Weight::zero(); @@ -580,7 +304,7 @@ fn test_swap_delegates_weight_update() { Delegates::::insert(old_hotkey, delegate_take); // Perform the swap - SubtensorModule::swap_delegates(&old_hotkey, &new_hotkey, &mut weight); + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); // Verify the weight update let expected_weight = ::DbWeight::get().reads_writes(1, 2); @@ -601,7 +325,7 @@ fn test_swap_stake_success() { Stake::::insert(old_hotkey, coldkey, stake_amount); // Perform the swap - SubtensorModule::swap_stake(&old_hotkey, &new_hotkey, &mut weight); + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); // Verify the swap assert_eq!(Stake::::get(new_hotkey, coldkey), stake_amount); @@ -625,7 +349,7 @@ fn test_swap_stake_old_hotkey_not_exist() { assert!(Stake::::contains_key(old_hotkey, coldkey)); // Perform the swap - SubtensorModule::swap_stake(&old_hotkey, &new_hotkey, &mut weight); + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); // Verify that new_hotkey has the stake and old_hotkey does not assert!(Stake::::contains_key(new_hotkey, coldkey)); @@ -633,390 +357,6 @@ fn test_swap_stake_old_hotkey_not_exist() { }); } -#[test] -fn test_swap_stake_weight_update() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let stake_amount = 1000u64; - let mut weight = Weight::zero(); - - // Initialize Stake for old_hotkey - Stake::::insert(old_hotkey, coldkey, stake_amount); - - // Perform the swap - SubtensorModule::swap_stake(&old_hotkey, &new_hotkey, &mut weight); - - // Verify the weight update - let expected_weight = ::DbWeight::get().writes(4); - assert_eq!(weight, expected_weight); - }); -} - -#[test] -fn test_swap_is_network_member_success() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let netuid_is_member = vec![1u16, 2u16]; - let mut weight = Weight::zero(); - - // Initialize IsNetworkMember for old_hotkey - for netuid in &netuid_is_member { - IsNetworkMember::::insert(old_hotkey, netuid, true); - } - - // Perform the swap - SubtensorModule::swap_is_network_member( - &old_hotkey, - &new_hotkey, - &netuid_is_member, - &mut weight, - ); - - // Verify the swap - for netuid in &netuid_is_member { - assert!(IsNetworkMember::::contains_key(new_hotkey, netuid)); - assert!(!IsNetworkMember::::contains_key(old_hotkey, netuid)); - } - }); -} - -#[test] -fn test_swap_is_network_member_weight_update() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let netuid_is_member = vec![1u16, 2u16]; - let mut weight = Weight::zero(); - - // Initialize IsNetworkMember for old_hotkey - for netuid in &netuid_is_member { - IsNetworkMember::::insert(old_hotkey, netuid, true); - } - - // Perform the swap - SubtensorModule::swap_is_network_member( - &old_hotkey, - &new_hotkey, - &netuid_is_member, - &mut weight, - ); - - // Verify the weight update - let expected_weight = ::DbWeight::get().writes(4); - assert_eq!(weight, expected_weight); - }); -} - -#[test] -fn test_swap_axons_success() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let netuid_is_member = vec![1u16, 2u16]; - let axon_info = AxonInfo { - block: 100, - version: 1, - ip: 0x1234567890abcdef, - port: 8080, - ip_type: 4, - protocol: 1, - placeholder1: 0, - placeholder2: 0, - }; - let mut weight = Weight::zero(); - - // Initialize Axons for old_hotkey - for netuid in &netuid_is_member { - Axons::::insert(netuid, old_hotkey, axon_info.clone()); - } - - // Perform the swap - SubtensorModule::swap_axons(&old_hotkey, &new_hotkey, &netuid_is_member, &mut weight); - - // Verify the swap - for netuid in &netuid_is_member { - assert_eq!(Axons::::get(netuid, new_hotkey).unwrap(), axon_info); - assert!(!Axons::::contains_key(netuid, old_hotkey)); - } - }); -} - -#[test] -fn test_swap_axons_weight_update() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let netuid_is_member = vec![1u16, 2u16]; - let axon_info = AxonInfo { - block: 100, - version: 1, - ip: 0x1234567890abcdef, - port: 8080, - ip_type: 4, - protocol: 1, - placeholder1: 0, - placeholder2: 0, - }; - let mut weight = Weight::zero(); - - // Initialize Axons for old_hotkey - for netuid in &netuid_is_member { - Axons::::insert(netuid, old_hotkey, axon_info.clone()); - } - - // Perform the swap - SubtensorModule::swap_axons(&old_hotkey, &new_hotkey, &netuid_is_member, &mut weight); - - // Verify the weight update - let expected_weight = netuid_is_member.len() as u64 - * ::DbWeight::get().reads_writes(1, 2); - assert_eq!(weight, expected_weight); - }); -} - -#[test] -fn test_swap_keys_success() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let netuid_is_member = vec![1u16, 2u16]; - let uid = 42u16; - let mut weight = Weight::zero(); - - // Initialize Keys for old_hotkey - for netuid in &netuid_is_member { - log::info!("Inserting old_hotkey:{:?} netuid:{:?}", old_hotkey, netuid); - Keys::::insert(*netuid, uid, old_hotkey); - } - - // Perform the swap - SubtensorModule::swap_keys(&old_hotkey, &new_hotkey, &netuid_is_member, &mut weight); - - // Verify the swap - for netuid in &netuid_is_member { - log::info!( - "neutuid, uid, hotkey: {:?}, {:?}, {:?}", - netuid, - uid, - new_hotkey - ); - assert_eq!(Keys::::get(netuid, uid), new_hotkey); - } - }); -} - -#[test] -fn test_swap_keys_weight_update() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let netuid_is_member = vec![1u16, 2u16]; - let uid = 42u16; - let mut weight = Weight::zero(); - - // Initialize Keys for old_hotkey - for netuid in &netuid_is_member { - Keys::::insert(*netuid, uid, old_hotkey); - } - - // Perform the swap - SubtensorModule::swap_keys(&old_hotkey, &new_hotkey, &netuid_is_member, &mut weight); - - // Verify the weight update - let expected_weight = ::DbWeight::get().writes(4); - assert_eq!(weight, expected_weight); - }); -} - -#[test] -fn test_swap_loaded_emission_success() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let netuid_is_member = vec![1u16, 2u16]; - let se = 100u64; - let ve = 200u64; - let mut weight = Weight::zero(); - - // Initialize LoadedEmission for old_hotkey - for netuid in &netuid_is_member { - LoadedEmission::::mutate(netuid, |emission_exists| { - if let Some(emissions) = emission_exists { - emissions.push((old_hotkey, se, ve)); - } else { - *emission_exists = Some(vec![(old_hotkey, se, ve)]); - } - }); - } - - // Perform the swap - SubtensorModule::swap_loaded_emission( - &old_hotkey, - &new_hotkey, - &netuid_is_member, - &mut weight, - ); - - // Verify the swap - for netuid in &netuid_is_member { - let emissions = LoadedEmission::::get(netuid).unwrap(); - assert!(emissions.iter().any(|(hk, _, _)| hk == &new_hotkey)); - assert!(!emissions.iter().any(|(hk, _, _)| hk == &old_hotkey)); - } - }); -} - -#[test] -fn test_swap_loaded_emission_weight_update() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let netuid_is_member = vec![1u16, 2u16]; - // let uid = 42u64; - let se = 100u64; - let ve = 200u64; - let mut weight = Weight::zero(); - - // Initialize LoadedEmission for old_hotkey - for netuid in &netuid_is_member { - LoadedEmission::::mutate(netuid, |emission_exists| { - if let Some(emissions) = emission_exists { - emissions.push((old_hotkey, se, ve)); - } else { - *emission_exists = Some(vec![(old_hotkey, se, ve)]); - } - }); - } - - // Perform the swap - SubtensorModule::swap_loaded_emission( - &old_hotkey, - &new_hotkey, - &netuid_is_member, - &mut weight, - ); - - // Verify the weight update - let expected_weight = ::DbWeight::get().writes(2); - assert_eq!(weight, expected_weight); - }); -} - -#[test] -fn test_swap_uids_success() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let netuid_is_member = vec![1u16, 2u16]; - let uid = 42u16; - let mut weight = Weight::zero(); - - // Initialize Uids for old_hotkey - for netuid in &netuid_is_member { - Uids::::insert(netuid, old_hotkey, uid); - } - - // Perform the swap - SubtensorModule::swap_uids(&old_hotkey, &new_hotkey, &netuid_is_member, &mut weight); - - // Verify the swap - for netuid in &netuid_is_member { - assert_eq!(Uids::::get(netuid, new_hotkey).unwrap(), uid); - assert!(!Uids::::contains_key(netuid, old_hotkey)); - } - }); -} - -#[test] -fn test_swap_uids_weight_update() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let netuid_is_member = vec![1u16, 2u16]; - let uid = 42u16; - let mut weight = Weight::zero(); - - // Initialize Uids for old_hotkey - for netuid in &netuid_is_member { - Uids::::insert(netuid, old_hotkey, uid); - } - - // Perform the swap - SubtensorModule::swap_uids(&old_hotkey, &new_hotkey, &netuid_is_member, &mut weight); - - // Verify the weight update - let expected_weight = ::DbWeight::get().writes(4); - assert_eq!(weight, expected_weight); - }); -} - -#[test] -fn test_swap_prometheus_success() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let netuid_is_member = vec![1u16, 2u16]; - let prometheus_info = PrometheusInfo { - block: 100, - version: 1, - ip: 0x1234567890abcdef, - port: 8080, - ip_type: 4, - }; - let mut weight = Weight::zero(); - - // Initialize Prometheus for old_hotkey - for netuid in &netuid_is_member { - Prometheus::::insert(netuid, old_hotkey, prometheus_info.clone()); - } - - // Perform the swap - SubtensorModule::swap_prometheus(&old_hotkey, &new_hotkey, &netuid_is_member, &mut weight); - - // Verify the swap - for netuid in &netuid_is_member { - assert_eq!( - Prometheus::::get(netuid, new_hotkey).unwrap(), - prometheus_info - ); - assert!(!Prometheus::::contains_key(netuid, old_hotkey)); - } - }); -} - -#[test] -fn test_swap_prometheus_weight_update() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let netuid_is_member = vec![1u16, 2u16]; - let prometheus_info = PrometheusInfo { - block: 100, - version: 1, - ip: 0x1234567890abcdef, - port: 8080, - ip_type: 4, - }; - let mut weight = Weight::zero(); - - // Initialize Prometheus for old_hotkey - for netuid in &netuid_is_member { - Prometheus::::insert(netuid, old_hotkey, prometheus_info.clone()); - } - - // Perform the swap - SubtensorModule::swap_prometheus(&old_hotkey, &new_hotkey, &netuid_is_member, &mut weight); - - // Verify the weight update - let expected_weight = netuid_is_member.len() as u64 - * ::DbWeight::get().reads_writes(1, 2); - assert_eq!(weight, expected_weight); - }); -} - #[test] fn test_swap_total_hotkey_coldkey_stakes_this_interval_success() { new_test_ext(1).execute_with(|| { @@ -1030,9 +370,10 @@ fn test_swap_total_hotkey_coldkey_stakes_this_interval_success() { TotalHotkeyColdkeyStakesThisInterval::::insert(old_hotkey, coldkey, stake); // Perform the swap - SubtensorModule::swap_total_hotkey_coldkey_stakes_this_interval( + SubtensorModule::perform_hotkey_swap( &old_hotkey, &new_hotkey, + &coldkey, &mut weight, ); @@ -1047,32 +388,6 @@ fn test_swap_total_hotkey_coldkey_stakes_this_interval_success() { }); } -#[test] -fn test_swap_total_hotkey_coldkey_stakes_this_interval_weight_update() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let stake = (1000u64, 42u64); - let mut weight = Weight::zero(); - - // Initialize TotalHotkeyColdkeyStakesThisInterval for old_hotkey - TotalHotkeyColdkeyStakesThisInterval::::insert(old_hotkey, coldkey, stake); - - // Perform the swap - - SubtensorModule::swap_total_hotkey_coldkey_stakes_this_interval( - &old_hotkey, - &new_hotkey, - &mut weight, - ); - - // Verify the weight update - let expected_weight = ::DbWeight::get().writes(2); - assert_eq!(weight, expected_weight); - }); -} - #[test] fn test_do_swap_coldkey_success() { new_test_ext(1).execute_with(|| { diff --git a/pallets/subtensor/tests/swap_hotkey.rs b/pallets/subtensor/tests/swap_hotkey.rs new file mode 100644 index 000000000..22e266efa --- /dev/null +++ b/pallets/subtensor/tests/swap_hotkey.rs @@ -0,0 +1,542 @@ +#![allow(unused, clippy::indexing_slicing, clippy::panic, clippy::unwrap_used)] + +use codec::Encode; +use frame_support::weights::Weight; +use frame_support::{assert_err, assert_noop, assert_ok}; +use frame_system::{Config, RawOrigin}; +mod mock; +use mock::*; +use pallet_subtensor::*; +use sp_core::U256; +use sp_core::H256; + + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_owner --exact --nocapture +#[test] +fn test_swap_owner() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let mut weight = Weight::zero(); + + Owner::::insert(&old_hotkey, &coldkey); + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert!(!Owner::::contains_key(&old_hotkey)); + assert_eq!(Owner::::get(&new_hotkey), coldkey); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_owned_hotkeys --exact --nocapture +#[test] +fn test_swap_owned_hotkeys() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let mut weight = Weight::zero(); + + OwnedHotkeys::::insert(&coldkey, vec![old_hotkey]); + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + let hotkeys = OwnedHotkeys::::get(&coldkey); + assert!(!hotkeys.contains(&old_hotkey)); + assert!(hotkeys.contains(&new_hotkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_total_hotkey_stake --exact --nocapture +#[test] +fn test_swap_total_hotkey_stake() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let mut weight = Weight::zero(); + + TotalHotkeyStake::::insert(&old_hotkey, 100); + TotalHotkeyStake::::insert(&new_hotkey, 50); + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert!(!TotalHotkeyStake::::contains_key(&old_hotkey)); + assert_eq!(TotalHotkeyStake::::get(&new_hotkey), 150); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_total_hotkey_coldkey_stakes_this_interval --exact --nocapture +#[test] +fn test_swap_total_hotkey_coldkey_stakes_this_interval() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let mut weight = Weight::zero(); + + TotalHotkeyColdkeyStakesThisInterval::::insert(&old_hotkey, &coldkey, (100, 1000)); + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert!(!TotalHotkeyColdkeyStakesThisInterval::::contains_key(&old_hotkey, &coldkey)); + assert_eq!(TotalHotkeyColdkeyStakesThisInterval::::get(&new_hotkey, &coldkey), (100, 1000)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_last_tx_block --exact --nocapture +#[test] +fn test_swap_last_tx_block() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let mut weight = Weight::zero(); + + LastTxBlock::::insert(&old_hotkey, 1000); + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert!(!LastTxBlock::::contains_key(&old_hotkey)); + assert_eq!(LastTxBlock::::get(&new_hotkey), SubtensorModule::get_current_block_as_u64()); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_last_tx_block_delegate_take --exact --nocapture +#[test] +fn test_swap_last_tx_block_delegate_take() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let mut weight = Weight::zero(); + + pallet_subtensor::LastTxBlockDelegateTake::::insert(&old_hotkey, 1000); + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert!(!LastTxBlockDelegateTake::::contains_key(&old_hotkey)); + assert_eq!(LastTxBlockDelegateTake::::get(&new_hotkey), SubtensorModule::get_current_block_as_u64()); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_senate_members --exact --nocapture +#[test] +fn test_swap_senate_members() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let mut weight = Weight::zero(); + + // Assuming there's a way to add a member to the senate + // SenateMembers::add_member(&old_hotkey); + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + // Assert that the old_hotkey is no longer a member and new_hotkey is now a member + // assert!(!SenateMembers::is_member(&old_hotkey)); + // assert!(SenateMembers::is_member(&new_hotkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_delegates --exact --nocapture +#[test] +fn test_swap_delegates() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let mut weight = Weight::zero(); + + Delegates::::insert(&old_hotkey, 100); + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert!(!Delegates::::contains_key(&old_hotkey)); + assert_eq!(Delegates::::get(&new_hotkey), 100); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_subnet_membership --exact --nocapture +#[test] +fn test_swap_subnet_membership() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let netuid = 0u16; + let mut weight = Weight::zero(); + + add_network(netuid, 0, 1); + IsNetworkMember::::insert(&old_hotkey, netuid, true); + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert!(!IsNetworkMember::::contains_key(&old_hotkey, netuid)); + assert!(IsNetworkMember::::get(&new_hotkey, netuid)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_uids_and_keys --exact --nocapture +#[test] +fn test_swap_uids_and_keys() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let netuid = 0u16; + let uid = 5u16; + let mut weight = Weight::zero(); + + add_network(netuid, 0, 1); + IsNetworkMember::::insert(&old_hotkey, netuid, true); + Uids::::insert(netuid, &old_hotkey, uid); + Keys::::insert(netuid, uid, old_hotkey); + + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert_eq!(Uids::::get(netuid, &old_hotkey), None); + assert_eq!(Uids::::get(netuid, &new_hotkey), Some(uid)); + assert_eq!(Keys::::get(netuid, uid), new_hotkey); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_prometheus --exact --nocapture +#[test] +fn test_swap_prometheus() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let netuid = 0u16; + let prometheus_info = PrometheusInfo::default(); + let mut weight = Weight::zero(); + + add_network(netuid, 0, 1); + IsNetworkMember::::insert(&old_hotkey, netuid, true); + Prometheus::::insert(netuid, &old_hotkey, prometheus_info.clone()); + + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert!(!Prometheus::::contains_key(netuid, &old_hotkey)); + assert_eq!(Prometheus::::get(netuid, &new_hotkey), Some(prometheus_info)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_axons --exact --nocapture +#[test] +fn test_swap_axons() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let netuid = 0u16; + let axon_info = AxonInfo::default(); + let mut weight = Weight::zero(); + + add_network(netuid, 0, 1); + IsNetworkMember::::insert(&old_hotkey, netuid, true); + Axons::::insert(netuid, &old_hotkey, axon_info.clone()); + + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert!(!Axons::::contains_key(netuid, &old_hotkey)); + assert_eq!(Axons::::get(netuid, &new_hotkey), Some(axon_info)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_weight_commits --exact --nocapture +#[test] +fn test_swap_weight_commits() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let netuid = 0u16; + let weight_commits = (H256::from_low_u64_be(100), 200); + let mut weight = Weight::zero(); + + add_network(netuid, 0, 1); + IsNetworkMember::::insert(&old_hotkey, netuid, true); + WeightCommits::::insert(netuid, &old_hotkey, weight_commits.clone()); + + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert!(!WeightCommits::::contains_key(netuid, &old_hotkey)); + assert_eq!(WeightCommits::::get(netuid, &new_hotkey), Some(weight_commits)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_loaded_emission --exact --nocapture +#[test] +fn test_swap_loaded_emission() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let netuid = 0u16; + let server_emission = 1000u64; + let validator_emission = 1000u64; + let mut weight = Weight::zero(); + + add_network(netuid, 0, 1); + IsNetworkMember::::insert(&old_hotkey, netuid, true); + LoadedEmission::::insert(netuid, vec![(old_hotkey, server_emission, validator_emission)]); + + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + let new_loaded_emission = LoadedEmission::::get(netuid); + assert_eq!(new_loaded_emission, Some(vec![(new_hotkey, server_emission, validator_emission)])); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_stake --exact --nocapture +#[test] +fn test_swap_stake() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let stake_amount = 100u64; + let mut weight = Weight::zero(); + + Stake::::insert(&old_hotkey, &coldkey, stake_amount); + + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert!(!Stake::::contains_key(&old_hotkey, &coldkey)); + assert_eq!(Stake::::get(&new_hotkey, &coldkey), stake_amount); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_staking_hotkeys --exact --nocapture +#[test] +fn test_swap_staking_hotkeys() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let mut weight = Weight::zero(); + + Stake::::insert(&old_hotkey, &coldkey, 100); + StakingHotkeys::::insert(&coldkey, vec![old_hotkey]); + + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + let staking_hotkeys = StakingHotkeys::::get(&coldkey); + assert!(!staking_hotkeys.contains(&old_hotkey)); + assert!(staking_hotkeys.contains(&new_hotkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_hotkey_with_multiple_coldkeys --exact --nocapture +#[test] +fn test_swap_hotkey_with_multiple_coldkeys() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey1 = U256::from(3); + let coldkey2 = U256::from(4); + let mut weight = Weight::zero(); + + Stake::::insert(&old_hotkey, &coldkey1, 100); + Stake::::insert(&old_hotkey, &coldkey2, 200); + StakingHotkeys::::insert(&coldkey1, vec![old_hotkey]); + StakingHotkeys::::insert(&coldkey2, vec![old_hotkey]); + + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey1, &mut weight)); + + assert_eq!(Stake::::get(&new_hotkey, &coldkey1), 100); + assert_eq!(Stake::::get(&new_hotkey, &coldkey2), 200); + assert!(StakingHotkeys::::get(&coldkey1).contains(&new_hotkey)); + assert!(StakingHotkeys::::get(&coldkey2).contains(&new_hotkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_hotkey_with_existing_stake --exact --nocapture +#[test] +fn test_swap_hotkey_with_existing_stake() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let mut weight = Weight::zero(); + + Stake::::insert(&old_hotkey, &coldkey, 100); + Stake::::insert(&new_hotkey, &coldkey, 50); + + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert_eq!(Stake::::get(&new_hotkey, &coldkey), 150); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_hotkey_with_multiple_subnets --exact --nocapture +#[test] +fn test_swap_hotkey_with_multiple_subnets() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let netuid1 = 0; + let netuid2 = 1; + let mut weight = Weight::zero(); + + add_network(netuid1, 0, 1); + add_network(netuid2, 0, 1); + IsNetworkMember::::insert(&old_hotkey, netuid1, true); + IsNetworkMember::::insert(&old_hotkey, netuid2, true); + + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + assert!(IsNetworkMember::::get(&new_hotkey, netuid1)); + assert!(IsNetworkMember::::get(&new_hotkey, netuid2)); + assert!(!IsNetworkMember::::get(&old_hotkey, netuid1)); + assert!(!IsNetworkMember::::get(&old_hotkey, netuid2)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_staking_hotkeys_multiple_coldkeys --exact --nocapture +#[test] +fn test_swap_staking_hotkeys_multiple_coldkeys() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey1 = U256::from(3); + let coldkey2 = U256::from(4); + let mut weight = Weight::zero(); + + // Set up initial state + Stake::::insert(&old_hotkey, &coldkey1, 100); + Stake::::insert(&old_hotkey, &coldkey2, 200); + StakingHotkeys::::insert(&coldkey1, vec![old_hotkey]); + StakingHotkeys::::insert(&coldkey2, vec![old_hotkey, U256::from(5)]); + + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey1, &mut weight)); + + // Check if new_hotkey replaced old_hotkey in StakingHotkeys + assert!(StakingHotkeys::::get(&coldkey1).contains(&new_hotkey)); + assert!(!StakingHotkeys::::get(&coldkey1).contains(&old_hotkey)); + + // Check if new_hotkey replaced old_hotkey for coldkey2 as well + assert!(StakingHotkeys::::get(&coldkey2).contains(&new_hotkey)); + assert!(!StakingHotkeys::::get(&coldkey2).contains(&old_hotkey)); + assert!(StakingHotkeys::::get(&coldkey2).contains(&U256::from(5))); // Other hotkeys should remain + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_hotkey_with_no_stake --exact --nocapture +#[test] +fn test_swap_hotkey_with_no_stake() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let mut weight = Weight::zero(); + + // Set up initial state with no stake + Owner::::insert(&old_hotkey, &coldkey); + + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + + // Check if ownership transferred + assert!(!Owner::::contains_key(&old_hotkey)); + assert_eq!(Owner::::get(&new_hotkey), coldkey); + + // Ensure no unexpected changes in Stake + assert!(!Stake::::contains_key(&old_hotkey, &coldkey)); + assert!(!Stake::::contains_key(&new_hotkey, &coldkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_hotkey_with_multiple_coldkeys_and_subnets --exact --nocapture +#[test] +fn test_swap_hotkey_with_multiple_coldkeys_and_subnets() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey1 = U256::from(3); + let coldkey2 = U256::from(4); + let netuid1 = 0; + let netuid2 = 1; + let mut weight = Weight::zero(); + + // Set up initial state + add_network(netuid1, 0, 1); + add_network(netuid2, 0, 1); + Owner::::insert(&old_hotkey, &coldkey1); + Stake::::insert(&old_hotkey, &coldkey1, 100); + Stake::::insert(&old_hotkey, &coldkey2, 200); + IsNetworkMember::::insert(&old_hotkey, netuid1, true); + IsNetworkMember::::insert(&old_hotkey, netuid2, true); + TotalHotkeyStake::::insert(&old_hotkey, 300); + + assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey1, &mut weight)); + + // Check ownership transfer + assert!(!Owner::::contains_key(&old_hotkey)); + assert_eq!(Owner::::get(&new_hotkey), coldkey1); + + // Check stake transfer + assert_eq!(Stake::::get(&new_hotkey, &coldkey1), 100); + assert_eq!(Stake::::get(&new_hotkey, &coldkey2), 200); + assert!(!Stake::::contains_key(&old_hotkey, &coldkey1)); + assert!(!Stake::::contains_key(&old_hotkey, &coldkey2)); + + // Check subnet membership transfer + assert!(IsNetworkMember::::get(&new_hotkey, netuid1)); + assert!(IsNetworkMember::::get(&new_hotkey, netuid2)); + assert!(!IsNetworkMember::::get(&old_hotkey, netuid1)); + assert!(!IsNetworkMember::::get(&old_hotkey, netuid2)); + + // Check total stake transfer + assert_eq!(TotalHotkeyStake::::get(&new_hotkey), 300); + assert!(!TotalHotkeyStake::::contains_key(&old_hotkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_hotkey_error_cases --exact --nocapture +#[test] +fn test_swap_hotkey_error_cases() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let wrong_coldkey = U256::from(4); + + // Set up initial state + Owner::::insert(&old_hotkey, &coldkey); + TotalNetworks::::put(1); + LastTxBlock::::insert(&coldkey, 0); + + // Test not enough balance + let swap_cost = SubtensorModule::get_key_swap_cost(); + assert_noop!( + SubtensorModule::do_swap_hotkey(RuntimeOrigin::signed(coldkey), &old_hotkey, &new_hotkey), + Error::::NotEnoughBalanceToPaySwapHotKey + ); + + let initial_balance = SubtensorModule::get_key_swap_cost() + 1000; + SubtensorModule::add_balance_to_coldkey_account(&coldkey, initial_balance); + + // Test new hotkey same as old + assert_noop!( + SubtensorModule::do_swap_hotkey(RuntimeOrigin::signed(coldkey), &old_hotkey, &old_hotkey), + Error::::NewHotKeyIsSameWithOld + ); + + // Test new hotkey already registered + IsNetworkMember::::insert(&new_hotkey, 0, true); + assert_noop!( + SubtensorModule::do_swap_hotkey(RuntimeOrigin::signed(coldkey), &old_hotkey, &new_hotkey), + Error::::HotKeyAlreadyRegisteredInSubNet + ); + IsNetworkMember::::remove(&new_hotkey, 0); + + // Test non-associated coldkey + assert_noop!( + SubtensorModule::do_swap_hotkey(RuntimeOrigin::signed(wrong_coldkey), &old_hotkey, &new_hotkey), + Error::::NonAssociatedColdKey + ); + + + // Run the successful swap + assert_ok!(SubtensorModule::do_swap_hotkey(RuntimeOrigin::signed(coldkey), &old_hotkey, &new_hotkey)); + + // Check balance after swap + assert_eq!(Balances::free_balance(&coldkey), initial_balance - swap_cost); + }); +} From 7f938f7940810831203169062de60440a7caacc6 Mon Sep 17 00:00:00 2001 From: const Date: Mon, 22 Jul 2024 13:34:03 -0500 Subject: [PATCH 48/51] tests pass --- pallets/subtensor/src/swap_hotkey.rs | 12 +- pallets/subtensor/tests/swap.rs | 378 ------------------------- pallets/subtensor/tests/swap_hotkey.rs | 275 ++++++++++++++++++ 3 files changed, 279 insertions(+), 386 deletions(-) diff --git a/pallets/subtensor/src/swap_hotkey.rs b/pallets/subtensor/src/swap_hotkey.rs index 222a4ff37..a99e4b3dc 100644 --- a/pallets/subtensor/src/swap_hotkey.rs +++ b/pallets/subtensor/src/swap_hotkey.rs @@ -1,9 +1,6 @@ use super::*; -use crate::MIN_BALANCE_TO_PERFORM_COLDKEY_SWAP; -use frame_support::traits::fungible::Mutate; -use frame_support::traits::tokens::Preservation; -use frame_support::{storage::IterableStorageDoubleMap, weights::Weight}; -use sp_core::{Get, U256}; +use frame_support::weights::Weight; +use sp_core::Get; impl Pallet { /// Swaps the hotkey of a coldkey account. @@ -86,7 +83,7 @@ impl Pallet { Self::burn_tokens(actual_burn_amount); // Perform the hotkey swap - Self::perform_hotkey_swap(old_hotkey, new_hotkey, &coldkey, &mut weight); + let _ = Self::perform_hotkey_swap(old_hotkey, new_hotkey, &coldkey, &mut weight); // Update the last transaction block for the coldkey Self::set_last_tx_block(&coldkey, block); @@ -143,10 +140,9 @@ impl Pallet { // Swap LastTxBlock // LastTxBlock( hotkey ) --> u64 -- the last transaction block for the hotkey. - let old_last_tx_block: u64 = LastTxBlock::::get( old_hotkey ); LastTxBlock::::remove( old_hotkey ); LastTxBlock::::insert( new_hotkey, Self::get_current_block_as_u64() ); - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); + weight.saturating_accrue(T::DbWeight::get().reads_writes(0, 2)); // Swap LastTxBlockDelegateTake // LastTxBlockDelegateTake( hotkey ) --> u64 -- the last transaction block for the hotkey delegate take. diff --git a/pallets/subtensor/tests/swap.rs b/pallets/subtensor/tests/swap.rs index 86fe109be..f7f288cc2 100644 --- a/pallets/subtensor/tests/swap.rs +++ b/pallets/subtensor/tests/swap.rs @@ -9,384 +9,6 @@ use mock::*; use pallet_subtensor::*; use sp_core::U256; -// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap -- test_do_swap_hotkey_ok --exact --nocapture -#[test] -fn test_do_swap_hotkey_ok() { - new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; - let tempo: u16 = 13; - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let swap_cost = 1_000_000_000u64; - - // Setup initial state - add_network(netuid, tempo, 0); - register_ok_neuron(netuid, old_hotkey, coldkey, 0); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, swap_cost); - - // Perform the swap - assert_ok!(SubtensorModule::do_swap_hotkey( - <::RuntimeOrigin>::signed(coldkey), - &old_hotkey, - &new_hotkey - )); - - // Verify the swap - assert_eq!( - SubtensorModule::get_owning_coldkey_for_hotkey(&new_hotkey), - coldkey - ); - assert_ne!( - SubtensorModule::get_owning_coldkey_for_hotkey(&old_hotkey), - coldkey - ); - - // Verify other storage changes - assert_ne!( - SubtensorModule::get_delegate(new_hotkey.encode()), - SubtensorModule::get_delegate(old_hotkey.encode()) - ); - assert_ne!( - SubtensorModule::get_last_tx_block(&new_hotkey), - SubtensorModule::get_last_tx_block(&old_hotkey) - ); - - // Verify raw storage maps - // Stake - for (coldkey, stake_amount) in Stake::::iter_prefix(old_hotkey) { - assert_eq!(Stake::::get(new_hotkey, coldkey), stake_amount); - } - - let mut weight = Weight::zero(); - - // IsNetworkMember - for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight) { - assert!(IsNetworkMember::::contains_key(new_hotkey, netuid)); - assert!(!IsNetworkMember::::contains_key(old_hotkey, netuid)); - } - - // Owner - assert_eq!(Owner::::get(new_hotkey), coldkey); - - // TotalHotkeyStake - assert_ne!( - TotalHotkeyStake::::get(new_hotkey), - TotalHotkeyStake::::get(old_hotkey) - ); - - // Delegates - assert_eq!( - Delegates::::get(new_hotkey), - Delegates::::get(old_hotkey) - ); - - // LastTxBlock - assert_eq!( - LastTxBlock::::get(new_hotkey), - LastTxBlock::::get(old_hotkey) - ); - - // Axons - for netuid in SubtensorModule::get_netuid_is_member(&old_hotkey, &mut weight) { - assert_eq!( - Axons::::get(netuid, new_hotkey), - Axons::::get(netuid, old_hotkey) - ); - } - - // TotalHotkeyColdkeyStakesThisInterval - assert_eq!( - TotalHotkeyColdkeyStakesThisInterval::::get(new_hotkey, coldkey), - TotalHotkeyColdkeyStakesThisInterval::::get(old_hotkey, coldkey) - ); - }); -} - -#[test] -fn test_swap_hotkey_tx_rate_limit_exceeded() { - new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; - let tempo: u16 = 13; - let old_hotkey = U256::from(1); - let new_hotkey_1 = U256::from(2); - let new_hotkey_2 = U256::from(4); - let coldkey = U256::from(3); - let swap_cost = 1_000_000_000u64 * 2; - - let tx_rate_limit = 1; - - // Get the current transaction rate limit - let current_tx_rate_limit = SubtensorModule::get_tx_rate_limit(); - log::info!("current_tx_rate_limit: {:?}", current_tx_rate_limit); - - // Set the transaction rate limit - SubtensorModule::set_tx_rate_limit(tx_rate_limit); - // assert the rate limit is set to 1000 blocks - assert_eq!(SubtensorModule::get_tx_rate_limit(), tx_rate_limit); - - // Setup initial state - add_network(netuid, tempo, 0); - register_ok_neuron(netuid, old_hotkey, coldkey, 0); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, swap_cost); - - // Perform the first swap - assert_ok!(SubtensorModule::do_swap_hotkey( - <::RuntimeOrigin>::signed(coldkey), - &old_hotkey, - &new_hotkey_1 - )); - - // Attempt to perform another swap immediately, which should fail due to rate limit - assert_err!( - SubtensorModule::do_swap_hotkey( - <::RuntimeOrigin>::signed(coldkey), - &new_hotkey_1, - &new_hotkey_2 - ), - Error::::HotKeySetTxRateLimitExceeded - ); - - // move in time past the rate limit - step_block(1001); - assert_ok!(SubtensorModule::do_swap_hotkey( - <::RuntimeOrigin>::signed(coldkey), - &new_hotkey_1, - &new_hotkey_2 - )); - }); -} - -#[test] -fn test_do_swap_hotkey_err_not_owner() { - new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; - let tempo: u16 = 13; - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let not_owner_coldkey = U256::from(4); - let swap_cost = 1_000_000_000u64; - - // Setup initial state - add_network(netuid, tempo, 0); - register_ok_neuron(netuid, old_hotkey, coldkey, 0); - SubtensorModule::add_balance_to_coldkey_account(¬_owner_coldkey, swap_cost); - - // Attempt the swap with a non-owner coldkey - assert_err!( - SubtensorModule::do_swap_hotkey( - <::RuntimeOrigin>::signed(not_owner_coldkey), - &old_hotkey, - &new_hotkey - ), - Error::::NonAssociatedColdKey - ); - }); -} - -#[test] -fn test_swap_owner_success() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let mut weight = Weight::zero(); - - // Initialize Owner for old_hotkey - Owner::::insert(old_hotkey, coldkey); - - // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); - - // Verify the swap - assert_eq!(Owner::::get(new_hotkey), coldkey); - assert!(!Owner::::contains_key(old_hotkey)); - }); -} - -#[test] -fn test_swap_owner_old_hotkey_not_exist() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let mut weight = Weight::zero(); - - // Ensure old_hotkey does not exist - assert!(!Owner::::contains_key(old_hotkey)); - - // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); - - // Verify the swap - assert_eq!(Owner::::get(new_hotkey), coldkey); - assert!(!Owner::::contains_key(old_hotkey)); - }); -} - -#[test] -fn test_swap_owner_new_hotkey_already_exists() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let another_coldkey = U256::from(4); - let mut weight = Weight::zero(); - - // Initialize Owner for old_hotkey and new_hotkey - Owner::::insert(old_hotkey, coldkey); - Owner::::insert(new_hotkey, another_coldkey); - - // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); - - // Verify the swap - assert_eq!(Owner::::get(new_hotkey), coldkey); - assert!(!Owner::::contains_key(old_hotkey)); - }); -} - -#[test] -fn test_swap_total_hotkey_stake_success() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let total_stake = 1000u64; - let mut weight = Weight::zero(); - - // Initialize TotalHotkeyStake for old_hotkey - TotalHotkeyStake::::insert(old_hotkey, total_stake); - - // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); - - // Verify the swap - assert_eq!(TotalHotkeyStake::::get(new_hotkey), total_stake); - assert!(!TotalHotkeyStake::::contains_key(old_hotkey)); - }); -} - - - -#[test] -fn test_swap_delegates_success() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let delegate_take = 10u16; - let mut weight = Weight::zero(); - - // Initialize Delegates for old_hotkey - Delegates::::insert(old_hotkey, delegate_take); - - // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); - - // Verify the swap - assert_eq!(Delegates::::get(new_hotkey), delegate_take); - assert!(!Delegates::::contains_key(old_hotkey)); - }); -} - -#[test] -fn test_swap_delegates_weight_update() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let delegate_take = 10u16; - let mut weight = Weight::zero(); - - // Initialize Delegates for old_hotkey - Delegates::::insert(old_hotkey, delegate_take); - - // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); - - // Verify the weight update - let expected_weight = ::DbWeight::get().reads_writes(1, 2); - assert_eq!(weight, expected_weight); - }); -} - -#[test] -fn test_swap_stake_success() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let stake_amount = 1000u64; - let mut weight = Weight::zero(); - - // Initialize Stake for old_hotkey - Stake::::insert(old_hotkey, coldkey, stake_amount); - - // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); - - // Verify the swap - assert_eq!(Stake::::get(new_hotkey, coldkey), stake_amount); - assert!(!Stake::::contains_key(old_hotkey, coldkey)); - }); -} - -#[test] -fn test_swap_stake_old_hotkey_not_exist() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let stake_amount = 1000u64; - let mut weight = Weight::zero(); - - // Initialize Stake for old_hotkey - Stake::::insert(old_hotkey, coldkey, stake_amount); - - // Ensure old_hotkey has a stake - assert!(Stake::::contains_key(old_hotkey, coldkey)); - - // Perform the swap - SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); - - // Verify that new_hotkey has the stake and old_hotkey does not - assert!(Stake::::contains_key(new_hotkey, coldkey)); - assert!(!Stake::::contains_key(old_hotkey, coldkey)); - }); -} - -#[test] -fn test_swap_total_hotkey_coldkey_stakes_this_interval_success() { - new_test_ext(1).execute_with(|| { - let old_hotkey = U256::from(1); - let new_hotkey = U256::from(2); - let coldkey = U256::from(3); - let stake = (1000u64, 42u64); // Example tuple value - let mut weight = Weight::zero(); - - // Initialize TotalHotkeyColdkeyStakesThisInterval for old_hotkey - TotalHotkeyColdkeyStakesThisInterval::::insert(old_hotkey, coldkey, stake); - - // Perform the swap - SubtensorModule::perform_hotkey_swap( - &old_hotkey, - &new_hotkey, - &coldkey, - &mut weight, - ); - - // Verify the swap - assert_eq!( - TotalHotkeyColdkeyStakesThisInterval::::get(new_hotkey, coldkey), - stake - ); - assert!(!TotalHotkeyColdkeyStakesThisInterval::::contains_key( - old_hotkey, coldkey - )); - }); -} #[test] fn test_do_swap_coldkey_success() { diff --git a/pallets/subtensor/tests/swap_hotkey.rs b/pallets/subtensor/tests/swap_hotkey.rs index 22e266efa..35227d3b1 100644 --- a/pallets/subtensor/tests/swap_hotkey.rs +++ b/pallets/subtensor/tests/swap_hotkey.rs @@ -488,6 +488,281 @@ fn test_swap_hotkey_with_multiple_coldkeys_and_subnets() { }); } +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_hotkey_tx_rate_limit_exceeded --exact --nocapture +#[test] +fn test_swap_hotkey_tx_rate_limit_exceeded() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + let tempo: u16 = 13; + let old_hotkey = U256::from(1); + let new_hotkey_1 = U256::from(2); + let new_hotkey_2 = U256::from(4); + let coldkey = U256::from(3); + let swap_cost = 1_000_000_000u64 * 2; + + let tx_rate_limit = 1; + + // Get the current transaction rate limit + let current_tx_rate_limit = SubtensorModule::get_tx_rate_limit(); + log::info!("current_tx_rate_limit: {:?}", current_tx_rate_limit); + + // Set the transaction rate limit + SubtensorModule::set_tx_rate_limit(tx_rate_limit); + // assert the rate limit is set to 1000 blocks + assert_eq!(SubtensorModule::get_tx_rate_limit(), tx_rate_limit); + + // Setup initial state + add_network(netuid, tempo, 0); + register_ok_neuron(netuid, old_hotkey, coldkey, 0); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, swap_cost); + + // Perform the first swap + assert_ok!(SubtensorModule::do_swap_hotkey( + <::RuntimeOrigin>::signed(coldkey), + &old_hotkey, + &new_hotkey_1 + )); + + // Attempt to perform another swap immediately, which should fail due to rate limit + assert_err!( + SubtensorModule::do_swap_hotkey( + <::RuntimeOrigin>::signed(coldkey), + &new_hotkey_1, + &new_hotkey_2 + ), + Error::::HotKeySetTxRateLimitExceeded + ); + + // move in time past the rate limit + step_block(1001); + assert_ok!(SubtensorModule::do_swap_hotkey( + <::RuntimeOrigin>::signed(coldkey), + &new_hotkey_1, + &new_hotkey_2 + )); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_do_swap_hotkey_err_not_owner --exact --nocapture +#[test] +fn test_do_swap_hotkey_err_not_owner() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + let tempo: u16 = 13; + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let not_owner_coldkey = U256::from(4); + let swap_cost = 1_000_000_000u64; + + // Setup initial state + add_network(netuid, tempo, 0); + register_ok_neuron(netuid, old_hotkey, coldkey, 0); + SubtensorModule::add_balance_to_coldkey_account(¬_owner_coldkey, swap_cost); + + // Attempt the swap with a non-owner coldkey + assert_err!( + SubtensorModule::do_swap_hotkey( + <::RuntimeOrigin>::signed(not_owner_coldkey), + &old_hotkey, + &new_hotkey + ), + Error::::NonAssociatedColdKey + ); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_owner_success --exact --nocapture +#[test] +fn test_swap_owner_success() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let mut weight = Weight::zero(); + + // Initialize Owner for old_hotkey + Owner::::insert(old_hotkey, coldkey); + + // Perform the swap + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + + // Verify the swap + assert_eq!(Owner::::get(new_hotkey), coldkey); + assert!(!Owner::::contains_key(old_hotkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_owner_old_hotkey_not_exist --exact --nocapture +#[test] +fn test_swap_owner_old_hotkey_not_exist() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let mut weight = Weight::zero(); + + // Ensure old_hotkey does not exist + assert!(!Owner::::contains_key(old_hotkey)); + + // Perform the swap + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + + // Verify the swap + assert_eq!(Owner::::get(new_hotkey), coldkey); + assert!(!Owner::::contains_key(old_hotkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_owner_new_hotkey_already_exists --exact --nocapture +#[test] +fn test_swap_owner_new_hotkey_already_exists() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let another_coldkey = U256::from(4); + let mut weight = Weight::zero(); + + // Initialize Owner for old_hotkey and new_hotkey + Owner::::insert(old_hotkey, coldkey); + Owner::::insert(new_hotkey, another_coldkey); + + // Perform the swap + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + + // Verify the swap + assert_eq!(Owner::::get(new_hotkey), coldkey); + assert!(!Owner::::contains_key(old_hotkey)); + }); +} + + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_total_hotkey_stake_success --exact --nocapture +#[test] +fn test_swap_total_hotkey_stake_success() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let total_stake = 1000u64; + let mut weight = Weight::zero(); + + // Initialize TotalHotkeyStake for old_hotkey + TotalHotkeyStake::::insert(old_hotkey, total_stake); + + // Perform the swap + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + + // Verify the swap + assert_eq!(TotalHotkeyStake::::get(new_hotkey), total_stake); + assert!(!TotalHotkeyStake::::contains_key(old_hotkey)); + }); +} + + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_delegates_success --exact --nocapture +#[test] +fn test_swap_delegates_success() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let delegate_take = 10u16; + let mut weight = Weight::zero(); + + // Initialize Delegates for old_hotkey + Delegates::::insert(old_hotkey, delegate_take); + + // Perform the swap + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + + // Verify the swap + assert_eq!(Delegates::::get(new_hotkey), delegate_take); + assert!(!Delegates::::contains_key(old_hotkey)); + }); +} + + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_stake_success --exact --nocapture +#[test] +fn test_swap_stake_success() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let stake_amount = 1000u64; + let mut weight = Weight::zero(); + + // Initialize Stake for old_hotkey + Stake::::insert(old_hotkey, coldkey, stake_amount); + + // Perform the swap + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + + // Verify the swap + assert_eq!(Stake::::get(new_hotkey, coldkey), stake_amount); + assert!(!Stake::::contains_key(old_hotkey, coldkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_stake_old_hotkey_not_exist --exact --nocapture +#[test] +fn test_swap_stake_old_hotkey_not_exist() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let stake_amount = 1000u64; + let mut weight = Weight::zero(); + + // Initialize Stake for old_hotkey + Stake::::insert(old_hotkey, coldkey, stake_amount); + + // Ensure old_hotkey has a stake + assert!(Stake::::contains_key(old_hotkey, coldkey)); + + // Perform the swap + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); + + // Verify that new_hotkey has the stake and old_hotkey does not + assert!(Stake::::contains_key(new_hotkey, coldkey)); + assert!(!Stake::::contains_key(old_hotkey, coldkey)); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_total_hotkey_coldkey_stakes_this_interval_success --exact --nocapture +#[test] +fn test_swap_total_hotkey_coldkey_stakes_this_interval_success() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let stake = (1000u64, 42u64); // Example tuple value + let mut weight = Weight::zero(); + + // Initialize TotalHotkeyColdkeyStakesThisInterval for old_hotkey + TotalHotkeyColdkeyStakesThisInterval::::insert(old_hotkey, coldkey, stake); + + // Perform the swap + SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight, + ); + + // Verify the swap + assert_eq!( + TotalHotkeyColdkeyStakesThisInterval::::get(new_hotkey, coldkey), + stake + ); + assert!(!TotalHotkeyColdkeyStakesThisInterval::::contains_key( + old_hotkey, coldkey + )); + }); +} + // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_hotkey_error_cases --exact --nocapture #[test] fn test_swap_hotkey_error_cases() { From 659b53c5319c53ae31d5a05aca37d72e67eadd32 Mon Sep 17 00:00:00 2001 From: const Date: Mon, 22 Jul 2024 13:42:23 -0500 Subject: [PATCH 49/51] clean the code --- pallets/commitments/src/lib.rs | 9 +++ pallets/subtensor/src/swap_hotkey.rs | 106 ++++++++++++++++++--------- 2 files changed, 82 insertions(+), 33 deletions(-) diff --git a/pallets/commitments/src/lib.rs b/pallets/commitments/src/lib.rs index d5d132034..4663b2647 100644 --- a/pallets/commitments/src/lib.rs +++ b/pallets/commitments/src/lib.rs @@ -173,6 +173,15 @@ pub mod pallet { Ok(()) } + + pub fn swap_commitment( netuid: u16, new_hotkey: T::AccountId, old_hotkey: T::AccountId ) { + if let Some(commitment) = >::take(netuid, &old_hotkey) { + >::insert(netuid, &new_hotkey, commitment); + } + if let Some(last_commit) = >::take(netuid, &old_hotkey) { + >::insert(netuid, &new_hotkey, last_commit); + } + } } } diff --git a/pallets/subtensor/src/swap_hotkey.rs b/pallets/subtensor/src/swap_hotkey.rs index a99e4b3dc..02052e4dd 100644 --- a/pallets/subtensor/src/swap_hotkey.rs +++ b/pallets/subtensor/src/swap_hotkey.rs @@ -27,79 +27,118 @@ impl Pallet { old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, ) -> DispatchResultWithPostInfo { - // Ensure the origin is signed and get the coldkey + // 1. Ensure the origin is signed and get the coldkey let coldkey = ensure_signed(origin)?; - // Check if the coldkey is in arbitration + // 2. Check if the coldkey is in arbitration ensure!( !Self::coldkey_in_arbitration(&coldkey), Error::::ColdkeyIsInArbitration ); - // Initialize the weight for this operation + // 3. Initialize the weight for this operation let mut weight = T::DbWeight::get().reads(2); - // Ensure the new hotkey is different from the old one + // 4. Ensure the new hotkey is different from the old one ensure!(old_hotkey != new_hotkey, Error::::NewHotKeyIsSameWithOld); - // Ensure the new hotkey is not already registered on any network + + // 5. Ensure the new hotkey is not already registered on any network ensure!( !Self::is_hotkey_registered_on_any_network(new_hotkey), Error::::HotKeyAlreadyRegisteredInSubNet ); - // Update the weight for the checks above + // 6. Update the weight for the checks above weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 0)); - // Ensure the coldkey owns the old hotkey + + // 7. Ensure the coldkey owns the old hotkey ensure!( Self::coldkey_owns_hotkey(&coldkey, old_hotkey), Error::::NonAssociatedColdKey ); - // Get the current block number + // 8. Get the current block number let block: u64 = Self::get_current_block_as_u64(); - // Ensure the transaction rate limit is not exceeded + + // 9. Ensure the transaction rate limit is not exceeded ensure!( !Self::exceeds_tx_rate_limit(Self::get_last_tx_block(&coldkey), block), Error::::HotKeySetTxRateLimitExceeded ); - // Update the weight for reading the total networks + // 10. Update the weight for reading the total networks weight.saturating_accrue( T::DbWeight::get().reads((TotalNetworks::::get().saturating_add(1u16)) as u64), ); - // Get the cost for swapping the key + // 11. Get the cost for swapping the key let swap_cost = Self::get_key_swap_cost(); log::debug!("Swap cost: {:?}", swap_cost); - // Ensure the coldkey has enough balance to pay for the swap + // 12. Ensure the coldkey has enough balance to pay for the swap ensure!( Self::can_remove_balance_from_coldkey_account(&coldkey, swap_cost), Error::::NotEnoughBalanceToPaySwapHotKey ); - // Remove the swap cost from the coldkey's account + + // 13. Remove the swap cost from the coldkey's account let actual_burn_amount = Self::remove_balance_from_coldkey_account(&coldkey, swap_cost)?; - // Burn the tokens + + // 14. Burn the tokens Self::burn_tokens(actual_burn_amount); - // Perform the hotkey swap + // 15. Perform the hotkey swap let _ = Self::perform_hotkey_swap(old_hotkey, new_hotkey, &coldkey, &mut weight); - // Update the last transaction block for the coldkey + // 16. Update the last transaction block for the coldkey Self::set_last_tx_block(&coldkey, block); weight.saturating_accrue(T::DbWeight::get().writes(1)); - // Emit an event for the hotkey swap + // 17. Emit an event for the hotkey swap Self::deposit_event(Event::HotkeySwapped { coldkey, old_hotkey: old_hotkey.clone(), new_hotkey: new_hotkey.clone(), }); - // Return the weight of the operation + // 18. Return the weight of the operation Ok(Some(weight).into()) } + /// Performs the hotkey swap operation, transferring all associated data and state from the old hotkey to the new hotkey. + /// + /// This function executes a series of steps to ensure a complete transfer of all relevant information: + /// 1. Swaps the owner of the hotkey. + /// 2. Updates the list of owned hotkeys for the coldkey. + /// 3. Transfers the total hotkey stake. + /// 4. Moves all stake-related data for the interval. + /// 5. Updates the last transaction block for the new hotkey. + /// 6. Transfers the delegate take information. + /// 7. Swaps Senate membership if applicable. + /// 8. Updates delegate information. + /// 9. For each subnet: + /// - Updates network membership status. + /// - Transfers UID and key information. + /// - Moves Prometheus data. + /// - Updates axon information. + /// - Transfers weight commits. + /// - Updates loaded emission data. + /// 10. Transfers all stake information, including updating staking hotkeys for each coldkey. + /// + /// Throughout the process, the function accumulates the computational weight of operations performed. + /// + /// # Arguments + /// * `old_hotkey` - The AccountId of the current hotkey to be replaced. + /// * `new_hotkey` - The AccountId of the new hotkey to replace the old one. + /// * `coldkey` - The AccountId of the coldkey that owns both hotkeys. + /// * `weight` - A mutable reference to the Weight, updated as operations are performed. + /// + /// # Returns + /// * `DispatchResult` - Ok(()) if the swap was successful, or an error if any operation failed. + /// + /// # Note + /// This function performs extensive storage reads and writes, which can be computationally expensive. + /// The accumulated weight should be carefully considered in the context of block limits. pub fn perform_hotkey_swap( old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, coldkey: &T::AccountId, weight: &mut Weight ) -> DispatchResult { // 1. Swap owner. @@ -128,7 +167,7 @@ impl Pallet { TotalHotkeyStake::::insert( new_hotkey, old_total_hotkey_stake.saturating_add( new_total_hotkey_stake ) ); // Insert the new total hotkey stake via the addition. weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2)); - // Swap total hotkey stakes. + // 4. Swap total hotkey stakes. // TotalHotkeyColdkeyStakesThisInterval( hotkey ) --> (u64: stakes, u64: block_number) let stake_tuples: Vec<(T::AccountId, (u64, u64))> = TotalHotkeyColdkeyStakesThisInterval::::iter_prefix(old_hotkey).collect(); for (coldkey, stake_tup) in stake_tuples { @@ -138,59 +177,59 @@ impl Pallet { weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); } - // Swap LastTxBlock + // 5. Swap LastTxBlock // LastTxBlock( hotkey ) --> u64 -- the last transaction block for the hotkey. LastTxBlock::::remove( old_hotkey ); LastTxBlock::::insert( new_hotkey, Self::get_current_block_as_u64() ); weight.saturating_accrue(T::DbWeight::get().reads_writes(0, 2)); - // Swap LastTxBlockDelegateTake + // 6. Swap LastTxBlockDelegateTake // LastTxBlockDelegateTake( hotkey ) --> u64 -- the last transaction block for the hotkey delegate take. LastTxBlockDelegateTake::::remove( old_hotkey ); LastTxBlockDelegateTake::::insert( new_hotkey, Self::get_current_block_as_u64() ); weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - // Swap Senate members. + // 7. Swap Senate members. // Senate( hotkey ) --> ? if T::SenateMembers::is_member(old_hotkey) { T::SenateMembers::swap_member(old_hotkey, new_hotkey).map_err(|e| e.error)?; weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); } - // 4. Swap delegates. + // 8. Swap delegates. // Delegates( hotkey ) -> take value -- the hotkey delegate take value. let old_delegate_take = Delegates::::get( old_hotkey ); Delegates::::remove( old_hotkey ); // Remove the old delegate take. Delegates::::insert( new_hotkey, old_delegate_take ); // Insert the new delegate take. weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - // Swap all subnet specific info. + // 9. Swap all subnet specific info. let all_netuids: Vec = Self::get_all_subnet_netuids(); for netuid in all_netuids { - // 7.1 Remove the previous hotkey and insert the new hotkey from membership. + // 9.1 Remove the previous hotkey and insert the new hotkey from membership. // IsNetworkMember( hotkey, netuid ) -> bool -- is the hotkey a subnet member. let is_network_member: bool = IsNetworkMember::::get( old_hotkey, netuid ); IsNetworkMember::::remove( old_hotkey, netuid ); IsNetworkMember::::insert( new_hotkey, netuid, is_network_member ); weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - // 7.2 Swap Uids + Keys. + // 9.2 Swap Uids + Keys. // Keys( netuid, hotkey ) -> uid -- the uid the hotkey has in the network if it is a member. // Uids( netuid, hotkey ) -> uid -- the uids that the hotkey has. if is_network_member { - // 7.2.1 Swap the UIDS + // 9.2.1 Swap the UIDS if let Ok(old_uid) = Uids::::try_get(netuid, old_hotkey) { Uids::::remove(netuid, old_hotkey); Uids::::insert(netuid, new_hotkey, old_uid); weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); - // 7.2.2 Swap the keys. + // 9.2.2 Swap the keys. Keys::::insert(netuid, old_uid, new_hotkey.clone()); weight.saturating_accrue(T::DbWeight::get().reads_writes(0, 1)); } } - // 7.3 Swap Prometheus. + // 9.3 Swap Prometheus. // Prometheus( netuid, hotkey ) -> prometheus -- the prometheus data that a hotkey has in the network. if is_network_member { if let Ok(old_prometheus_info) = Prometheus::::try_get(netuid, old_hotkey) { @@ -200,7 +239,7 @@ impl Pallet { } } - // 7.4. Swap axons. + // 9.4. Swap axons. // Axons( netuid, hotkey ) -> axon -- the axon that the hotkey has. if is_network_member { if let Ok(old_axon_info) = Axons::::try_get(netuid, old_hotkey) { @@ -210,7 +249,7 @@ impl Pallet { } } - // 7.5 Swap WeightCommits + // 9.5 Swap WeightCommits // WeightCommits( hotkey ) --> Vec -- the weight commits for the hotkey. if is_network_member { if let Ok(old_weight_commits) = WeightCommits::::try_get(netuid, old_hotkey) { @@ -220,7 +259,7 @@ impl Pallet { } } - // 7.5. Swap the subnet loaded emission. + // 9.6. Swap the subnet loaded emission. // LoadedEmission( netuid ) --> Vec<(hotkey, u64)> -- the loaded emission for the subnet. if is_network_member { if let Some(mut old_loaded_emission) = LoadedEmission::::get(netuid) { @@ -237,7 +276,7 @@ impl Pallet { } - // Swap Stake. + // 10. Swap Stake. // Stake( hotkey, coldkey ) -> stake -- the stake that the hotkey controls on behalf of the coldkey. let stakes: Vec<(T::AccountId, u64)> = Stake::::iter_prefix(old_hotkey).collect(); // Clear the entire old prefix here. @@ -263,6 +302,7 @@ impl Pallet { weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); } + // Return successful after swapping all the relevant terms. Ok(()) } From b8cfd6ce51967283b9610c81ef31bd9d2b6198e4 Mon Sep 17 00:00:00 2001 From: const Date: Mon, 22 Jul 2024 13:45:59 -0500 Subject: [PATCH 50/51] fix tests --- pallets/commitments/src/lib.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/pallets/commitments/src/lib.rs b/pallets/commitments/src/lib.rs index 4663b2647..d5d132034 100644 --- a/pallets/commitments/src/lib.rs +++ b/pallets/commitments/src/lib.rs @@ -173,15 +173,6 @@ pub mod pallet { Ok(()) } - - pub fn swap_commitment( netuid: u16, new_hotkey: T::AccountId, old_hotkey: T::AccountId ) { - if let Some(commitment) = >::take(netuid, &old_hotkey) { - >::insert(netuid, &new_hotkey, commitment); - } - if let Some(last_commit) = >::take(netuid, &old_hotkey) { - >::insert(netuid, &new_hotkey, last_commit); - } - } } } From 6b6460d4fc7864543af574d7390c53fa3556691d Mon Sep 17 00:00:00 2001 From: const Date: Mon, 22 Jul 2024 15:21:13 -0500 Subject: [PATCH 51/51] clippy and fmt --- pallets/subtensor/src/lib.rs | 6 +- pallets/subtensor/src/swap.rs | 4 - pallets/subtensor/src/swap_hotkey.rs | 57 +++--- pallets/subtensor/tests/swap.rs | 1 - pallets/subtensor/tests/swap_hotkey.rs | 248 ++++++++++++++++++++----- 5 files changed, 234 insertions(+), 82 deletions(-) diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index d492b5477..6a353eafb 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -1088,11 +1088,9 @@ pub mod pallet { pub type Active = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyBoolVec>; #[pallet::storage] // --- DMAP ( netuid ) --> rank - pub type Rank = - StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; + pub type Rank = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] // --- DMAP ( netuid ) --> trust - pub type Trust = - StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; + pub type Trust = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] // --- DMAP ( netuid ) --> consensus pub type Consensus = StorageMap<_, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; diff --git a/pallets/subtensor/src/swap.rs b/pallets/subtensor/src/swap.rs index 5d8f66c68..b6b0e9ba7 100644 --- a/pallets/subtensor/src/swap.rs +++ b/pallets/subtensor/src/swap.rs @@ -6,7 +6,6 @@ use frame_support::{storage::IterableStorageDoubleMap, weights::Weight}; use sp_core::{Get, U256}; impl Pallet { - /// Swaps the coldkey associated with a set of hotkeys from an old coldkey to a new coldkey. /// /// # Arguments @@ -378,7 +377,6 @@ impl Pallet { netuid_is_member } - /// Swaps the total stake associated with a coldkey from the old coldkey to the new coldkey. /// /// # Arguments @@ -635,6 +633,4 @@ impl Pallet { } weight.saturating_accrue(T::DbWeight::get().reads(TotalNetworks::::get() as u64)); } - - } diff --git a/pallets/subtensor/src/swap_hotkey.rs b/pallets/subtensor/src/swap_hotkey.rs index 02052e4dd..5c3fecbba 100644 --- a/pallets/subtensor/src/swap_hotkey.rs +++ b/pallets/subtensor/src/swap_hotkey.rs @@ -139,8 +139,12 @@ impl Pallet { /// # Note /// This function performs extensive storage reads and writes, which can be computationally expensive. /// The accumulated weight should be carefully considered in the context of block limits. - pub fn perform_hotkey_swap( old_hotkey: &T::AccountId, new_hotkey: &T::AccountId, coldkey: &T::AccountId, weight: &mut Weight ) -> DispatchResult { - + pub fn perform_hotkey_swap( + old_hotkey: &T::AccountId, + new_hotkey: &T::AccountId, + coldkey: &T::AccountId, + weight: &mut Weight, + ) -> DispatchResult { // 1. Swap owner. // Owner( hotkey ) -> coldkey -- the coldkey that owns the hotkey. Owner::::remove(old_hotkey); @@ -153,7 +157,7 @@ impl Pallet { // Add the new key if needed. if !hotkeys.contains(new_hotkey) { hotkeys.push(new_hotkey.clone()); - } + } // Remove the old key. hotkeys.retain(|hk| *hk != *old_hotkey); OwnedHotkeys::::insert(coldkey, hotkeys); @@ -161,15 +165,19 @@ impl Pallet { // 3. Swap total hotkey stake. // TotalHotkeyStake( hotkey ) -> stake -- the total stake that the hotkey has across all delegates. - let old_total_hotkey_stake = TotalHotkeyStake::::get( old_hotkey ); // Get the old total hotkey stake. - let new_total_hotkey_stake = TotalHotkeyStake::::get( new_hotkey ); // Get the new total hotkey stake. - TotalHotkeyStake::::remove( old_hotkey ); // Remove the old total hotkey stake. - TotalHotkeyStake::::insert( new_hotkey, old_total_hotkey_stake.saturating_add( new_total_hotkey_stake ) ); // Insert the new total hotkey stake via the addition. + let old_total_hotkey_stake = TotalHotkeyStake::::get(old_hotkey); // Get the old total hotkey stake. + let new_total_hotkey_stake = TotalHotkeyStake::::get(new_hotkey); // Get the new total hotkey stake. + TotalHotkeyStake::::remove(old_hotkey); // Remove the old total hotkey stake. + TotalHotkeyStake::::insert( + new_hotkey, + old_total_hotkey_stake.saturating_add(new_total_hotkey_stake), + ); // Insert the new total hotkey stake via the addition. weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2)); // 4. Swap total hotkey stakes. // TotalHotkeyColdkeyStakesThisInterval( hotkey ) --> (u64: stakes, u64: block_number) - let stake_tuples: Vec<(T::AccountId, (u64, u64))> = TotalHotkeyColdkeyStakesThisInterval::::iter_prefix(old_hotkey).collect(); + let stake_tuples: Vec<(T::AccountId, (u64, u64))> = + TotalHotkeyColdkeyStakesThisInterval::::iter_prefix(old_hotkey).collect(); for (coldkey, stake_tup) in stake_tuples { // NOTE: You could use this to increase your allowed stake operations but this would cost. TotalHotkeyColdkeyStakesThisInterval::::insert(new_hotkey, &coldkey, stake_tup); @@ -179,14 +187,14 @@ impl Pallet { // 5. Swap LastTxBlock // LastTxBlock( hotkey ) --> u64 -- the last transaction block for the hotkey. - LastTxBlock::::remove( old_hotkey ); - LastTxBlock::::insert( new_hotkey, Self::get_current_block_as_u64() ); + LastTxBlock::::remove(old_hotkey); + LastTxBlock::::insert(new_hotkey, Self::get_current_block_as_u64()); weight.saturating_accrue(T::DbWeight::get().reads_writes(0, 2)); // 6. Swap LastTxBlockDelegateTake // LastTxBlockDelegateTake( hotkey ) --> u64 -- the last transaction block for the hotkey delegate take. - LastTxBlockDelegateTake::::remove( old_hotkey ); - LastTxBlockDelegateTake::::insert( new_hotkey, Self::get_current_block_as_u64() ); + LastTxBlockDelegateTake::::remove(old_hotkey); + LastTxBlockDelegateTake::::insert(new_hotkey, Self::get_current_block_as_u64()); weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); // 7. Swap Senate members. @@ -198,19 +206,19 @@ impl Pallet { // 8. Swap delegates. // Delegates( hotkey ) -> take value -- the hotkey delegate take value. - let old_delegate_take = Delegates::::get( old_hotkey ); - Delegates::::remove( old_hotkey ); // Remove the old delegate take. - Delegates::::insert( new_hotkey, old_delegate_take ); // Insert the new delegate take. + let old_delegate_take = Delegates::::get(old_hotkey); + Delegates::::remove(old_hotkey); // Remove the old delegate take. + Delegates::::insert(new_hotkey, old_delegate_take); // Insert the new delegate take. weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); // 9. Swap all subnet specific info. let all_netuids: Vec = Self::get_all_subnet_netuids(); - for netuid in all_netuids { + for netuid in all_netuids { // 9.1 Remove the previous hotkey and insert the new hotkey from membership. // IsNetworkMember( hotkey, netuid ) -> bool -- is the hotkey a subnet member. - let is_network_member: bool = IsNetworkMember::::get( old_hotkey, netuid ); - IsNetworkMember::::remove( old_hotkey, netuid ); - IsNetworkMember::::insert( new_hotkey, netuid, is_network_member ); + let is_network_member: bool = IsNetworkMember::::get(old_hotkey, netuid); + IsNetworkMember::::remove(old_hotkey, netuid); + IsNetworkMember::::insert(new_hotkey, netuid, is_network_member); weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); // 9.2 Swap Uids + Keys. @@ -249,7 +257,7 @@ impl Pallet { } } - // 9.5 Swap WeightCommits + // 9.5 Swap WeightCommits // WeightCommits( hotkey ) --> Vec -- the weight commits for the hotkey. if is_network_member { if let Ok(old_weight_commits) = WeightCommits::::try_get(netuid, old_hotkey) { @@ -273,14 +281,13 @@ impl Pallet { weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2)); } } - } // 10. Swap Stake. // Stake( hotkey, coldkey ) -> stake -- the stake that the hotkey controls on behalf of the coldkey. let stakes: Vec<(T::AccountId, u64)> = Stake::::iter_prefix(old_hotkey).collect(); // Clear the entire old prefix here. - let _ = Stake::::clear_prefix( old_hotkey, stakes.len() as u32, None ); + let _ = Stake::::clear_prefix(old_hotkey, stakes.len() as u32, None); // Iterate over all the staking rows and insert them into the new hotkey. for (coldkey, old_stake_amount) in stakes { weight.saturating_accrue(T::DbWeight::get().reads(1)); @@ -290,7 +297,11 @@ impl Pallet { // Get the new stake value. let new_stake_value: u64 = Stake::::get(new_hotkey, &coldkey); // Insert the new stake value. - Stake::::insert(new_hotkey, &coldkey, new_stake_value.saturating_add(old_stake_amount)); + Stake::::insert( + new_hotkey, + &coldkey, + new_stake_value.saturating_add(old_stake_amount), + ); weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); // Swap StakingHotkeys. diff --git a/pallets/subtensor/tests/swap.rs b/pallets/subtensor/tests/swap.rs index f7f288cc2..0a3a85dff 100644 --- a/pallets/subtensor/tests/swap.rs +++ b/pallets/subtensor/tests/swap.rs @@ -9,7 +9,6 @@ use mock::*; use pallet_subtensor::*; use sp_core::U256; - #[test] fn test_do_swap_coldkey_success() { new_test_ext(1).execute_with(|| { diff --git a/pallets/subtensor/tests/swap_hotkey.rs b/pallets/subtensor/tests/swap_hotkey.rs index 35227d3b1..68f4ec49c 100644 --- a/pallets/subtensor/tests/swap_hotkey.rs +++ b/pallets/subtensor/tests/swap_hotkey.rs @@ -7,9 +7,8 @@ use frame_system::{Config, RawOrigin}; mod mock; use mock::*; use pallet_subtensor::*; -use sp_core::U256; use sp_core::H256; - +use sp_core::U256; // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_owner --exact --nocapture #[test] @@ -21,7 +20,12 @@ fn test_swap_owner() { let mut weight = Weight::zero(); Owner::::insert(&old_hotkey, &coldkey); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); assert!(!Owner::::contains_key(&old_hotkey)); assert_eq!(Owner::::get(&new_hotkey), coldkey); @@ -38,7 +42,12 @@ fn test_swap_owned_hotkeys() { let mut weight = Weight::zero(); OwnedHotkeys::::insert(&coldkey, vec![old_hotkey]); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); let hotkeys = OwnedHotkeys::::get(&coldkey); assert!(!hotkeys.contains(&old_hotkey)); @@ -57,7 +66,12 @@ fn test_swap_total_hotkey_stake() { TotalHotkeyStake::::insert(&old_hotkey, 100); TotalHotkeyStake::::insert(&new_hotkey, 50); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); assert!(!TotalHotkeyStake::::contains_key(&old_hotkey)); assert_eq!(TotalHotkeyStake::::get(&new_hotkey), 150); @@ -74,10 +88,21 @@ fn test_swap_total_hotkey_coldkey_stakes_this_interval() { let mut weight = Weight::zero(); TotalHotkeyColdkeyStakesThisInterval::::insert(&old_hotkey, &coldkey, (100, 1000)); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); - assert!(!TotalHotkeyColdkeyStakesThisInterval::::contains_key(&old_hotkey, &coldkey)); - assert_eq!(TotalHotkeyColdkeyStakesThisInterval::::get(&new_hotkey, &coldkey), (100, 1000)); + assert!(!TotalHotkeyColdkeyStakesThisInterval::::contains_key( + &old_hotkey, + &coldkey + )); + assert_eq!( + TotalHotkeyColdkeyStakesThisInterval::::get(&new_hotkey, &coldkey), + (100, 1000) + ); }); } @@ -91,10 +116,18 @@ fn test_swap_last_tx_block() { let mut weight = Weight::zero(); LastTxBlock::::insert(&old_hotkey, 1000); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); assert!(!LastTxBlock::::contains_key(&old_hotkey)); - assert_eq!(LastTxBlock::::get(&new_hotkey), SubtensorModule::get_current_block_as_u64()); + assert_eq!( + LastTxBlock::::get(&new_hotkey), + SubtensorModule::get_current_block_as_u64() + ); }); } @@ -108,10 +141,18 @@ fn test_swap_last_tx_block_delegate_take() { let mut weight = Weight::zero(); pallet_subtensor::LastTxBlockDelegateTake::::insert(&old_hotkey, 1000); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); assert!(!LastTxBlockDelegateTake::::contains_key(&old_hotkey)); - assert_eq!(LastTxBlockDelegateTake::::get(&new_hotkey), SubtensorModule::get_current_block_as_u64()); + assert_eq!( + LastTxBlockDelegateTake::::get(&new_hotkey), + SubtensorModule::get_current_block_as_u64() + ); }); } @@ -126,7 +167,12 @@ fn test_swap_senate_members() { // Assuming there's a way to add a member to the senate // SenateMembers::add_member(&old_hotkey); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); // Assert that the old_hotkey is no longer a member and new_hotkey is now a member // assert!(!SenateMembers::is_member(&old_hotkey)); @@ -144,7 +190,12 @@ fn test_swap_delegates() { let mut weight = Weight::zero(); Delegates::::insert(&old_hotkey, 100); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); assert!(!Delegates::::contains_key(&old_hotkey)); assert_eq!(Delegates::::get(&new_hotkey), 100); @@ -163,7 +214,12 @@ fn test_swap_subnet_membership() { add_network(netuid, 0, 1); IsNetworkMember::::insert(&old_hotkey, netuid, true); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); assert!(!IsNetworkMember::::contains_key(&old_hotkey, netuid)); assert!(IsNetworkMember::::get(&new_hotkey, netuid)); @@ -186,7 +242,12 @@ fn test_swap_uids_and_keys() { Uids::::insert(netuid, &old_hotkey, uid); Keys::::insert(netuid, uid, old_hotkey); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); assert_eq!(Uids::::get(netuid, &old_hotkey), None); assert_eq!(Uids::::get(netuid, &new_hotkey), Some(uid)); @@ -209,10 +270,18 @@ fn test_swap_prometheus() { IsNetworkMember::::insert(&old_hotkey, netuid, true); Prometheus::::insert(netuid, &old_hotkey, prometheus_info.clone()); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); assert!(!Prometheus::::contains_key(netuid, &old_hotkey)); - assert_eq!(Prometheus::::get(netuid, &new_hotkey), Some(prometheus_info)); + assert_eq!( + Prometheus::::get(netuid, &new_hotkey), + Some(prometheus_info) + ); }); } @@ -231,13 +300,18 @@ fn test_swap_axons() { IsNetworkMember::::insert(&old_hotkey, netuid, true); Axons::::insert(netuid, &old_hotkey, axon_info.clone()); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); assert!(!Axons::::contains_key(netuid, &old_hotkey)); assert_eq!(Axons::::get(netuid, &new_hotkey), Some(axon_info)); }); } - + // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_weight_commits --exact --nocapture #[test] fn test_swap_weight_commits() { @@ -253,10 +327,18 @@ fn test_swap_weight_commits() { IsNetworkMember::::insert(&old_hotkey, netuid, true); WeightCommits::::insert(netuid, &old_hotkey, weight_commits.clone()); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); assert!(!WeightCommits::::contains_key(netuid, &old_hotkey)); - assert_eq!(WeightCommits::::get(netuid, &new_hotkey), Some(weight_commits)); + assert_eq!( + WeightCommits::::get(netuid, &new_hotkey), + Some(weight_commits) + ); }); } @@ -274,12 +356,23 @@ fn test_swap_loaded_emission() { add_network(netuid, 0, 1); IsNetworkMember::::insert(&old_hotkey, netuid, true); - LoadedEmission::::insert(netuid, vec![(old_hotkey, server_emission, validator_emission)]); + LoadedEmission::::insert( + netuid, + vec![(old_hotkey, server_emission, validator_emission)], + ); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); let new_loaded_emission = LoadedEmission::::get(netuid); - assert_eq!(new_loaded_emission, Some(vec![(new_hotkey, server_emission, validator_emission)])); + assert_eq!( + new_loaded_emission, + Some(vec![(new_hotkey, server_emission, validator_emission)]) + ); }); } @@ -295,7 +388,12 @@ fn test_swap_stake() { Stake::::insert(&old_hotkey, &coldkey, stake_amount); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); assert!(!Stake::::contains_key(&old_hotkey, &coldkey)); assert_eq!(Stake::::get(&new_hotkey, &coldkey), stake_amount); @@ -314,7 +412,12 @@ fn test_swap_staking_hotkeys() { Stake::::insert(&old_hotkey, &coldkey, 100); StakingHotkeys::::insert(&coldkey, vec![old_hotkey]); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); let staking_hotkeys = StakingHotkeys::::get(&coldkey); assert!(!staking_hotkeys.contains(&old_hotkey)); @@ -337,7 +440,12 @@ fn test_swap_hotkey_with_multiple_coldkeys() { StakingHotkeys::::insert(&coldkey1, vec![old_hotkey]); StakingHotkeys::::insert(&coldkey2, vec![old_hotkey]); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey1, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey1, + &mut weight + )); assert_eq!(Stake::::get(&new_hotkey, &coldkey1), 100); assert_eq!(Stake::::get(&new_hotkey, &coldkey2), 200); @@ -358,7 +466,12 @@ fn test_swap_hotkey_with_existing_stake() { Stake::::insert(&old_hotkey, &coldkey, 100); Stake::::insert(&new_hotkey, &coldkey, 50); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); assert_eq!(Stake::::get(&new_hotkey, &coldkey), 150); }); @@ -380,7 +493,12 @@ fn test_swap_hotkey_with_multiple_subnets() { IsNetworkMember::::insert(&old_hotkey, netuid1, true); IsNetworkMember::::insert(&old_hotkey, netuid2, true); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); assert!(IsNetworkMember::::get(&new_hotkey, netuid1)); assert!(IsNetworkMember::::get(&new_hotkey, netuid2)); @@ -405,7 +523,12 @@ fn test_swap_staking_hotkeys_multiple_coldkeys() { StakingHotkeys::::insert(&coldkey1, vec![old_hotkey]); StakingHotkeys::::insert(&coldkey2, vec![old_hotkey, U256::from(5)]); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey1, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey1, + &mut weight + )); // Check if new_hotkey replaced old_hotkey in StakingHotkeys assert!(StakingHotkeys::::get(&coldkey1).contains(&new_hotkey)); @@ -414,7 +537,8 @@ fn test_swap_staking_hotkeys_multiple_coldkeys() { // Check if new_hotkey replaced old_hotkey for coldkey2 as well assert!(StakingHotkeys::::get(&coldkey2).contains(&new_hotkey)); assert!(!StakingHotkeys::::get(&coldkey2).contains(&old_hotkey)); - assert!(StakingHotkeys::::get(&coldkey2).contains(&U256::from(5))); // Other hotkeys should remain + assert!(StakingHotkeys::::get(&coldkey2).contains(&U256::from(5))); + // Other hotkeys should remain }); } @@ -430,7 +554,12 @@ fn test_swap_hotkey_with_no_stake() { // Set up initial state with no stake Owner::::insert(&old_hotkey, &coldkey); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight + )); // Check if ownership transferred assert!(!Owner::::contains_key(&old_hotkey)); @@ -464,7 +593,12 @@ fn test_swap_hotkey_with_multiple_coldkeys_and_subnets() { IsNetworkMember::::insert(&old_hotkey, netuid2, true); TotalHotkeyStake::::insert(&old_hotkey, 300); - assert_ok!(SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey1, &mut weight)); + assert_ok!(SubtensorModule::perform_hotkey_swap( + &old_hotkey, + &new_hotkey, + &coldkey1, + &mut weight + )); // Check ownership transfer assert!(!Owner::::contains_key(&old_hotkey)); @@ -637,7 +771,6 @@ fn test_swap_owner_new_hotkey_already_exists() { }); } - // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_total_hotkey_stake_success --exact --nocapture #[test] fn test_swap_total_hotkey_stake_success() { @@ -660,7 +793,6 @@ fn test_swap_total_hotkey_stake_success() { }); } - // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_delegates_success --exact --nocapture #[test] fn test_swap_delegates_success() { @@ -683,7 +815,6 @@ fn test_swap_delegates_success() { }); } - // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test swap_hotkey -- test_swap_stake_success --exact --nocapture #[test] fn test_swap_stake_success() { @@ -745,12 +876,7 @@ fn test_swap_total_hotkey_coldkey_stakes_this_interval_success() { TotalHotkeyColdkeyStakesThisInterval::::insert(old_hotkey, coldkey, stake); // Perform the swap - SubtensorModule::perform_hotkey_swap( - &old_hotkey, - &new_hotkey, - &coldkey, - &mut weight, - ); + SubtensorModule::perform_hotkey_swap(&old_hotkey, &new_hotkey, &coldkey, &mut weight); // Verify the swap assert_eq!( @@ -780,7 +906,11 @@ fn test_swap_hotkey_error_cases() { // Test not enough balance let swap_cost = SubtensorModule::get_key_swap_cost(); assert_noop!( - SubtensorModule::do_swap_hotkey(RuntimeOrigin::signed(coldkey), &old_hotkey, &new_hotkey), + SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey + ), Error::::NotEnoughBalanceToPaySwapHotKey ); @@ -789,29 +919,47 @@ fn test_swap_hotkey_error_cases() { // Test new hotkey same as old assert_noop!( - SubtensorModule::do_swap_hotkey(RuntimeOrigin::signed(coldkey), &old_hotkey, &old_hotkey), + SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &old_hotkey + ), Error::::NewHotKeyIsSameWithOld ); // Test new hotkey already registered IsNetworkMember::::insert(&new_hotkey, 0, true); assert_noop!( - SubtensorModule::do_swap_hotkey(RuntimeOrigin::signed(coldkey), &old_hotkey, &new_hotkey), + SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey + ), Error::::HotKeyAlreadyRegisteredInSubNet ); IsNetworkMember::::remove(&new_hotkey, 0); // Test non-associated coldkey assert_noop!( - SubtensorModule::do_swap_hotkey(RuntimeOrigin::signed(wrong_coldkey), &old_hotkey, &new_hotkey), + SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(wrong_coldkey), + &old_hotkey, + &new_hotkey + ), Error::::NonAssociatedColdKey ); - // Run the successful swap - assert_ok!(SubtensorModule::do_swap_hotkey(RuntimeOrigin::signed(coldkey), &old_hotkey, &new_hotkey)); + assert_ok!(SubtensorModule::do_swap_hotkey( + RuntimeOrigin::signed(coldkey), + &old_hotkey, + &new_hotkey + )); // Check balance after swap - assert_eq!(Balances::free_balance(&coldkey), initial_balance - swap_cost); + assert_eq!( + Balances::free_balance(&coldkey), + initial_balance - swap_cost + ); }); }