From c55b22642e48310d01f37ae88092e15c204be39a Mon Sep 17 00:00:00 2001 From: JohnReedV <87283488+JohnReedV@users.noreply.github.com> Date: Mon, 27 Jan 2025 17:58:53 -0800 Subject: [PATCH 01/34] add new fields to ChainIdentity and SubnetIdentity --- pallets/subtensor/rpc/src/lib.rs | 24 ++++ pallets/subtensor/runtime-api/src/lib.rs | 2 + pallets/subtensor/src/coinbase/root.rs | 6 +- pallets/subtensor/src/lib.rs | 65 ++++++++- pallets/subtensor/src/macros/dispatches.rs | 30 ++++- .../subtensor/src/migrations/migrate_rao.rs | 7 +- .../subtensor/src/rpc_info/dynamic_info.rs | 6 +- pallets/subtensor/src/rpc_info/metagraph.rs | 46 +++---- pallets/subtensor/src/rpc_info/subnet_info.rs | 97 ++++++++++++++ pallets/subtensor/src/subnets/subnet.rs | 4 +- pallets/subtensor/src/swap/swap_coldkey.rs | 4 +- pallets/subtensor/src/tests/serving.rs | 125 ++++++++++++++---- pallets/subtensor/src/tests/swap_coldkey.rs | 49 +++---- pallets/subtensor/src/utils/identity.rs | 31 +++-- runtime/src/lib.rs | 15 +++ 15 files changed, 410 insertions(+), 101 deletions(-) diff --git a/pallets/subtensor/rpc/src/lib.rs b/pallets/subtensor/rpc/src/lib.rs index cdbcebcacb..0df96eda65 100644 --- a/pallets/subtensor/rpc/src/lib.rs +++ b/pallets/subtensor/rpc/src/lib.rs @@ -49,6 +49,10 @@ pub trait SubtensorCustomApi { fn get_subnet_info_v2(&self, netuid: u16, at: Option) -> RpcResult>; #[method(name = "subnetInfo_getSubnetsInf_v2")] fn get_subnets_info_v2(&self, at: Option) -> RpcResult>; + #[method(name = "subnetInfo_getSubnetInfo_v3")] + fn get_subnet_info_v3(&self, netuid: u16, at: Option) -> RpcResult>; + #[method(name = "subnetInfo_getSubnetsInf_v3")] + fn get_subnets_info_v3(&self, at: Option) -> RpcResult>; #[method(name = "subnetInfo_getSubnetHyperparams")] fn get_subnet_hyperparams(&self, netuid: u16, at: Option) -> RpcResult>; #[method(name = "subnetInfo_getAllDynamicInfo")] @@ -298,6 +302,26 @@ where .map_err(|e| Error::RuntimeError(format!("Unable to get subnets info: {:?}", e)).into()) } + fn get_subnet_info_v3( + &self, + netuid: u16, + at: Option<::Hash>, + ) -> RpcResult> { + let api = self.client.runtime_api(); + let at = at.unwrap_or_else(|| self.client.info().best_hash); + + api.get_subnet_info_v3(at, netuid) + .map_err(|e| Error::RuntimeError(format!("Unable to get subnet info: {:?}", e)).into()) + } + + fn get_subnets_info_v3(&self, at: Option<::Hash>) -> RpcResult> { + let api = self.client.runtime_api(); + let at = at.unwrap_or_else(|| self.client.info().best_hash); + + api.get_subnets_info_v3(at) + .map_err(|e| Error::RuntimeError(format!("Unable to get subnets info: {:?}", e)).into()) + } + fn get_network_lock_cost(&self, at: Option<::Hash>) -> RpcResult { let api = self.client.runtime_api(); let at = at.unwrap_or_else(|| self.client.info().best_hash); diff --git a/pallets/subtensor/runtime-api/src/lib.rs b/pallets/subtensor/runtime-api/src/lib.rs index cdcd6ed390..8a3e8aba94 100644 --- a/pallets/subtensor/runtime-api/src/lib.rs +++ b/pallets/subtensor/runtime-api/src/lib.rs @@ -23,6 +23,8 @@ sp_api::decl_runtime_apis! { fn get_subnets_info() -> Vec; fn get_subnet_info_v2(netuid: u16) -> Vec; fn get_subnets_info_v2() -> Vec; + fn get_subnet_info_v3(netuid: u16) -> Vec; + fn get_subnets_info_v3()-> Vec; fn get_subnet_hyperparams(netuid: u16) -> Vec; fn get_all_dynamic_info() -> Vec; fn get_all_metagraphs() -> Vec; diff --git a/pallets/subtensor/src/coinbase/root.rs b/pallets/subtensor/src/coinbase/root.rs index 3f83f934f1..5968a73761 100644 --- a/pallets/subtensor/src/coinbase/root.rs +++ b/pallets/subtensor/src/coinbase/root.rs @@ -479,7 +479,7 @@ impl Pallet { ); // --- 4. Remove the subnet identity if it exists. - if SubnetIdentities::::take(netuid).is_some() { + if SubnetIdentitiesV2::::take(netuid).is_some() { Self::deposit_event(Event::SubnetIdentityRemoved(netuid)); } @@ -590,8 +590,8 @@ impl Pallet { SubnetOwner::::remove(netuid); // --- 13. Remove subnet identity if it exists. - if SubnetIdentities::::contains_key(netuid) { - SubnetIdentities::::remove(netuid); + if SubnetIdentitiesV2::::contains_key(netuid) { + SubnetIdentitiesV2::::remove(netuid); Self::deposit_event(Event::SubnetIdentityRemoved(netuid)); } } diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index 3fd67e0d8e..9f6844d8f5 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -189,10 +189,10 @@ pub mod pallet { pub ip_type: u8, } - /// Struct for ChainIdentities. + /// Struct for ChainIdentities. (DEPRECATED for V2) pub type ChainIdentityOf = ChainIdentity; - /// Data structure for Chain Identities. + /// Data structure for Chain Identities. (DEPRECATED for V2) #[crate::freeze_struct("bbfd00438dbe2b58")] #[derive(Encode, Decode, Default, TypeInfo, Clone, PartialEq, Eq, Debug)] pub struct ChainIdentity { @@ -210,9 +210,32 @@ pub mod pallet { pub additional: Vec, } - /// Struct for SubnetIdentities. + /// Struct for ChainIdentities. + pub type ChainIdentityOfV2 = ChainIdentityV2; + + /// Data structure for Chain Identities. + #[crate::freeze_struct("ad72a270be7b59d7")] + #[derive(Encode, Decode, Default, TypeInfo, Clone, PartialEq, Eq, Debug)] + pub struct ChainIdentityV2 { + /// The name of the chain identity + pub name: Vec, + /// The URL associated with the chain identity + pub url: Vec, + /// The github repository associated with the identity + pub github_repo: Vec, + /// The image representation of the chain identity + pub image: Vec, + /// The Discord information for the chain identity + pub discord: Vec, + /// A description of the chain identity + pub description: Vec, + /// Additional information about the chain identity + pub additional: Vec, + } + + /// Struct for SubnetIdentities. (DEPRECATED for V2) pub type SubnetIdentityOf = SubnetIdentity; - /// Data structure for Subnet Identities + /// Data structure for Subnet Identities. (DEPRECATED for V2) #[crate::freeze_struct("f448dc3dad763108")] #[derive(Encode, Decode, Default, TypeInfo, Clone, PartialEq, Eq, Debug)] pub struct SubnetIdentity { @@ -223,6 +246,28 @@ pub mod pallet { /// The subnet's contact pub subnet_contact: Vec, } + + /// Struct for SubnetIdentitiesV2. + pub type SubnetIdentityOfV2 = SubnetIdentityV2; + /// Data structure for Subnet Identities + #[crate::freeze_struct("e002be4cd05d7b3e")] + #[derive(Encode, Decode, Default, TypeInfo, Clone, PartialEq, Eq, Debug)] + pub struct SubnetIdentityV2 { + /// The name of the subnet + pub subnet_name: Vec, + /// The github repository associated with the subnet + pub github_repo: Vec, + /// The subnet's contact + pub subnet_contact: Vec, + /// The subnet's website + pub subnet_url: Vec, + /// The subnet's discord + pub discord: Vec, + /// The subnet's description + pub description: Vec, + /// Additional information about the subnet + pub additional: Vec, + } /// ============================ /// ==== Staking + Accounts ==== /// ============================ @@ -1398,14 +1443,22 @@ pub mod pallet { PrometheusInfoOf, OptionQuery, >; - #[pallet::storage] // --- MAP ( coldkey ) --> identity + #[pallet::storage] // --- MAP ( coldkey ) --> identity. (DEPRECATED for V2) pub type Identities = StorageMap<_, Blake2_128Concat, T::AccountId, ChainIdentityOf, OptionQuery>; - #[pallet::storage] // --- MAP ( netuid ) --> identity + #[pallet::storage] // --- MAP ( coldkey ) --> identity + pub type IdentitiesV2 = + StorageMap<_, Blake2_128Concat, T::AccountId, ChainIdentityOfV2, OptionQuery>; + + #[pallet::storage] // --- MAP ( netuid ) --> identity. (DEPRECATED for V2) pub type SubnetIdentities = StorageMap<_, Blake2_128Concat, u16, SubnetIdentityOf, OptionQuery>; + #[pallet::storage] // --- MAP ( netuid ) --> identityV2 + pub type SubnetIdentitiesV2 = + StorageMap<_, Blake2_128Concat, u16, SubnetIdentityOfV2, OptionQuery>; + /// ================================= /// ==== Axon / Promo Endpoints ===== /// ================================= diff --git a/pallets/subtensor/src/macros/dispatches.rs b/pallets/subtensor/src/macros/dispatches.rs index d9eafffa7a..b29db14c26 100644 --- a/pallets/subtensor/src/macros/dispatches.rs +++ b/pallets/subtensor/src/macros/dispatches.rs @@ -1453,12 +1453,22 @@ mod dispatches { origin: OriginFor, name: Vec, url: Vec, + github_repo: Vec, image: Vec, discord: Vec, description: Vec, additional: Vec, ) -> DispatchResult { - Self::do_set_identity(origin, name, url, image, discord, description, additional) + Self::do_set_identity( + origin, + name, + url, + github_repo, + image, + discord, + description, + additional, + ) } /// ---- Set the identity information for a subnet. @@ -1487,8 +1497,22 @@ mod dispatches { subnet_name: Vec, github_repo: Vec, subnet_contact: Vec, + subnet_url: Vec, + discord: Vec, + description: Vec, + additional: Vec, ) -> DispatchResult { - Self::do_set_subnet_identity(origin, netuid, subnet_name, github_repo, subnet_contact) + Self::do_set_subnet_identity( + origin, + netuid, + subnet_name, + github_repo, + subnet_contact, + subnet_url, + discord, + description, + additional, + ) } /// User register a new subnetwork @@ -1499,7 +1523,7 @@ mod dispatches { pub fn register_network_with_identity( origin: OriginFor, hotkey: T::AccountId, - identity: Option, + identity: Option, ) -> DispatchResult { Self::do_register_network(origin, &hotkey, 1, identity) } diff --git a/pallets/subtensor/src/migrations/migrate_rao.rs b/pallets/subtensor/src/migrations/migrate_rao.rs index 3c034b7dad..6273b06c80 100644 --- a/pallets/subtensor/src/migrations/migrate_rao.rs +++ b/pallets/subtensor/src/migrations/migrate_rao.rs @@ -105,19 +105,20 @@ pub fn migrate_rao() -> Weight { let _neuron_uid: u16 = Pallet::::register_neuron(*netuid, &owner_coldkey); } // Register the neuron immediately. - if !Identities::::contains_key(owner_coldkey.clone()) { + if !IdentitiesV2::::contains_key(owner_coldkey.clone()) { // Set the identitiy for the Owner coldkey if non existent. - let identity = ChainIdentityOf { + let identity = ChainIdentityOfV2 { name: format!("Owner{}", netuid).as_bytes().to_vec(), url: Vec::new(), image: Vec::new(), + github_repo: Vec::new(), discord: Vec::new(), description: Vec::new(), additional: Vec::new(), }; // Validate the created identity and set it. if Pallet::::is_valid_identity(&identity) { - Identities::::insert(owner_coldkey.clone(), identity.clone()); + IdentitiesV2::::insert(owner_coldkey.clone(), identity.clone()); } } } diff --git a/pallets/subtensor/src/rpc_info/dynamic_info.rs b/pallets/subtensor/src/rpc_info/dynamic_info.rs index a8ffd85495..1ec021988f 100644 --- a/pallets/subtensor/src/rpc_info/dynamic_info.rs +++ b/pallets/subtensor/src/rpc_info/dynamic_info.rs @@ -4,7 +4,7 @@ use codec::Compact; use frame_support::pallet_prelude::{Decode, Encode}; use subtensor_macros::freeze_struct; -#[freeze_struct("44fd17b240416875")] +#[freeze_struct("e425055e357d7a13")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug)] pub struct DynamicInfo { netuid: Compact, @@ -25,7 +25,7 @@ pub struct DynamicInfo { pending_alpha_emission: Compact, pending_root_emission: Compact, network_registered_at: Compact, - subnet_identity: Option, + subnet_identity: Option, } impl Pallet { @@ -61,7 +61,7 @@ impl Pallet { pending_alpha_emission: PendingEmission::::get(netuid).into(), pending_root_emission: PendingRootDivs::::get(netuid).into(), network_registered_at: NetworkRegisteredAt::::get(netuid).into(), - subnet_identity: SubnetIdentities::::get(netuid), + subnet_identity: SubnetIdentitiesV2::::get(netuid), }) } pub fn get_all_dynamic_info() -> Vec>> { diff --git a/pallets/subtensor/src/rpc_info/metagraph.rs b/pallets/subtensor/src/rpc_info/metagraph.rs index 1e77e5fe6a..9415d193e1 100644 --- a/pallets/subtensor/src/rpc_info/metagraph.rs +++ b/pallets/subtensor/src/rpc_info/metagraph.rs @@ -6,7 +6,7 @@ use frame_support::pallet_prelude::{Decode, Encode}; use substrate_fixed::types::I64F64; use subtensor_macros::freeze_struct; -#[freeze_struct("bce2310daa502e48")] +#[freeze_struct("b80fd826ead2df2f")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug)] pub struct Metagraph { // Subnet index @@ -15,7 +15,7 @@ pub struct Metagraph { // Name and symbol name: Vec>, // name symbol: Vec>, // token symbol - identity: Option, // identity information. + identity: Option, // identity information. network_registered_at: Compact, // block at registration // Keys for owner. @@ -80,24 +80,24 @@ pub struct Metagraph { bonds_moving_avg: Compact, // Bonds moving avg // Metagraph info. - hotkeys: Vec, // hotkey per UID - coldkeys: Vec, // coldkey per UID - identities: Vec>, // coldkeys identities - axons: Vec, // UID axons. - active: Vec, // Avtive per UID - validator_permit: Vec, // Val permit per UID - pruning_score: Vec>, // Pruning per UID - last_update: Vec>, // Last update per UID - emission: Vec>, // Emission per UID - dividends: Vec>, // Dividends per UID - incentives: Vec>, // Mining incentives per UID - consensus: Vec>, // Consensus per UID - trust: Vec>, // Trust per UID - rank: Vec>, // Rank per UID - block_at_registration: Vec>, // Reg block per UID - alpha_stake: Vec>, // Alpha staked per UID - tao_stake: Vec>, // TAO staked per UID - total_stake: Vec>, // Total stake per UID + hotkeys: Vec, // hotkey per UID + coldkeys: Vec, // coldkey per UID + identities: Vec>, // coldkeys identities + axons: Vec, // UID axons. + active: Vec, // Avtive per UID + validator_permit: Vec, // Val permit per UID + pruning_score: Vec>, // Pruning per UID + last_update: Vec>, // Last update per UID + emission: Vec>, // Emission per UID + dividends: Vec>, // Dividends per UID + incentives: Vec>, // Mining incentives per UID + consensus: Vec>, // Consensus per UID + trust: Vec>, // Trust per UID + rank: Vec>, // Rank per UID + block_at_registration: Vec>, // Reg block per UID + alpha_stake: Vec>, // Alpha staked per UID + tao_stake: Vec>, // TAO staked per UID + total_stake: Vec>, // Total stake per UID // Dividend break down. tao_dividends_per_hotkey: Vec<(T::AccountId, Compact)>, // List of dividend payouts in tao via root. @@ -114,7 +114,7 @@ impl Pallet { let mut hotkeys: Vec = vec![]; let mut coldkeys: Vec = vec![]; let mut block_at_registration: Vec> = vec![]; - let mut identities: Vec> = vec![]; + let mut identities: Vec> = vec![]; let mut axons: Vec = vec![]; for uid in 0..n { let hotkey = Keys::::get(netuid, uid); @@ -122,7 +122,7 @@ impl Pallet { hotkeys.push(hotkey.clone()); coldkeys.push(coldkey.clone()); block_at_registration.push(BlockAtRegistration::::get(netuid, uid).into()); - identities.push(Identities::::get(coldkey.clone())); + identities.push(IdentitiesV2::::get(coldkey.clone())); axons.push(Self::get_axon_info(netuid, &hotkey)); } let mut tao_dividends_per_hotkey: Vec<(T::AccountId, Compact)> = vec![]; @@ -154,7 +154,7 @@ impl Pallet { .into_iter() .map(Compact) .collect(), // Symbol. - identity: SubnetIdentities::::get(netuid), // identity information. + identity: SubnetIdentitiesV2::::get(netuid), // identity information. network_registered_at: NetworkRegisteredAt::::get(netuid).into(), // block at registration // Keys for owner. diff --git a/pallets/subtensor/src/rpc_info/subnet_info.rs b/pallets/subtensor/src/rpc_info/subnet_info.rs index bdd420821a..5003ec5f63 100644 --- a/pallets/subtensor/src/rpc_info/subnet_info.rs +++ b/pallets/subtensor/src/rpc_info/subnet_info.rs @@ -51,6 +51,30 @@ pub struct SubnetInfov2 { identity: Option, } +#[freeze_struct("dd91200554b75bc4")] +#[derive(Decode, Encode, PartialEq, Eq, Clone, Debug)] +pub struct SubnetInfov3 { + netuid: Compact, + rho: Compact, + kappa: Compact, + difficulty: Compact, + immunity_period: Compact, + max_allowed_validators: Compact, + min_allowed_weights: Compact, + max_weights_limit: Compact, + scaling_law_power: Compact, + subnetwork_n: Compact, + max_allowed_uids: Compact, + blocks_since_last_step: Compact, + tempo: Compact, + network_modality: Compact, + network_connect: Vec<[u16; 2]>, + emission_values: Compact, + burn: Compact, + owner: T::AccountId, + identity: Option, +} + #[freeze_struct("55b472510f10e76a")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug)] pub struct SubnetHyperparams { @@ -225,6 +249,79 @@ impl Pallet { subnets_info } + + pub fn get_subnet_info_v3(netuid: u16) -> Option> { + if !Self::if_subnet_exist(netuid) { + return None; + } + + let rho = Self::get_rho(netuid); + let kappa = Self::get_kappa(netuid); + let difficulty: Compact = Self::get_difficulty_as_u64(netuid).into(); + let immunity_period = Self::get_immunity_period(netuid); + let max_allowed_validators = Self::get_max_allowed_validators(netuid); + let min_allowed_weights = Self::get_min_allowed_weights(netuid); + let max_weights_limit = Self::get_max_weight_limit(netuid); + let scaling_law_power = Self::get_scaling_law_power(netuid); + let subnetwork_n = Self::get_subnetwork_n(netuid); + let max_allowed_uids = Self::get_max_allowed_uids(netuid); + let blocks_since_last_step = Self::get_blocks_since_last_step(netuid); + let tempo = Self::get_tempo(netuid); + let network_modality = >::get(netuid); + let emission_values = Self::get_emission_value(netuid); + let burn: Compact = Self::get_burn_as_u64(netuid).into(); + let identity: Option = SubnetIdentitiesV2::::get(netuid); + + // DEPRECATED + let network_connect: Vec<[u16; 2]> = Vec::<[u16; 2]>::new(); + // DEPRECATED for ( _netuid_, con_req) in < NetworkConnect as IterableStorageDoubleMap >::iter_prefix(netuid) { + // network_connect.push([_netuid_, con_req]); + // } + + Some(SubnetInfov3 { + rho: rho.into(), + kappa: kappa.into(), + difficulty, + immunity_period: immunity_period.into(), + netuid: netuid.into(), + max_allowed_validators: max_allowed_validators.into(), + min_allowed_weights: min_allowed_weights.into(), + max_weights_limit: max_weights_limit.into(), + scaling_law_power: scaling_law_power.into(), + subnetwork_n: subnetwork_n.into(), + max_allowed_uids: max_allowed_uids.into(), + blocks_since_last_step: blocks_since_last_step.into(), + tempo: tempo.into(), + network_modality: network_modality.into(), + network_connect, + emission_values: emission_values.into(), + burn, + owner: Self::get_subnet_owner(netuid), + identity, + }) + } + + pub fn get_subnets_info_v3() -> Vec>> { + let mut subnet_netuids = Vec::::new(); + let mut max_netuid: u16 = 0; + for (netuid, added) in as IterableStorageMap>::iter() { + if added { + subnet_netuids.push(netuid); + if netuid > max_netuid { + max_netuid = netuid; + } + } + } + + let mut subnets_info = Vec::>>::new(); + for netuid_ in 0..=max_netuid { + if subnet_netuids.contains(&netuid_) { + subnets_info.push(Self::get_subnet_info_v3(netuid_)); + } + } + + subnets_info + } pub fn get_subnet_hyperparams(netuid: u16) -> Option { if !Self::if_subnet_exist(netuid) { return None; diff --git a/pallets/subtensor/src/subnets/subnet.rs b/pallets/subtensor/src/subnets/subnet.rs index 942f6fe8ba..7a3b256327 100644 --- a/pallets/subtensor/src/subnets/subnet.rs +++ b/pallets/subtensor/src/subnets/subnet.rs @@ -160,7 +160,7 @@ impl Pallet { origin: T::RuntimeOrigin, hotkey: &T::AccountId, mechid: u16, - identity: Option, + identity: Option, ) -> DispatchResult { // --- 1. Ensure the caller is a signed user. let coldkey = ensure_signed(origin)?; @@ -260,7 +260,7 @@ impl Pallet { Error::::InvalidIdentity ); - SubnetIdentities::::insert(netuid_to_register, identity_value); + SubnetIdentitiesV2::::insert(netuid_to_register, identity_value); Self::deposit_event(Event::SubnetIdentitySet(netuid_to_register)); } diff --git a/pallets/subtensor/src/swap/swap_coldkey.rs b/pallets/subtensor/src/swap/swap_coldkey.rs index 075538421b..b505cd58e9 100644 --- a/pallets/subtensor/src/swap/swap_coldkey.rs +++ b/pallets/subtensor/src/swap/swap_coldkey.rs @@ -52,8 +52,8 @@ impl Pallet { weight = weight.saturating_add(T::DbWeight::get().reads(1)); // 5. Swap the identity if the old coldkey has one - if let Some(identity) = Identities::::take(old_coldkey) { - Identities::::insert(new_coldkey, identity); + if let Some(identity) = IdentitiesV2::::take(old_coldkey) { + IdentitiesV2::::insert(new_coldkey, identity); } // 6. Ensure sufficient balance for the swap cost diff --git a/pallets/subtensor/src/tests/serving.rs b/pallets/subtensor/src/tests/serving.rs index 32b604ba5a..f7ce4d6a2b 100644 --- a/pallets/subtensor/src/tests/serving.rs +++ b/pallets/subtensor/src/tests/serving.rs @@ -625,6 +625,7 @@ fn test_do_set_identity() { // Prepare identity data let name = b"Alice".to_vec(); let url = b"https://alice.com".to_vec(); + let git = b"https://github.com".to_vec(); let image = b"alice.jpg".to_vec(); let discord = b"alice#1234".to_vec(); let description = b"Alice's identity".to_vec(); @@ -635,6 +636,7 @@ fn test_do_set_identity() { <::RuntimeOrigin>::signed(coldkey), name.clone(), url.clone(), + git.clone(), image.clone(), discord.clone(), description.clone(), @@ -642,7 +644,7 @@ fn test_do_set_identity() { )); // Check if identity is set correctly - let stored_identity = Identities::::get(coldkey).expect("Identity should be set"); + let stored_identity = IdentitiesV2::::get(coldkey).expect("Identity should be set"); assert_eq!(stored_identity.name, name); assert_eq!(stored_identity.url, url); assert_eq!(stored_identity.image, image); @@ -657,6 +659,7 @@ fn test_do_set_identity() { <::RuntimeOrigin>::signed(coldkey_without_hotkey), name.clone(), url.clone(), + git.clone(), image.clone(), discord.clone(), description.clone(), @@ -672,6 +675,7 @@ fn test_do_set_identity() { <::RuntimeOrigin>::signed(coldkey), new_name.clone(), new_url.clone(), + git.clone(), image.clone(), discord.clone(), description.clone(), @@ -679,7 +683,7 @@ fn test_do_set_identity() { )); let updated_identity = - Identities::::get(coldkey).expect("Updated identity should be set"); + IdentitiesV2::::get(coldkey).expect("Updated identity should be set"); assert_eq!(updated_identity.name, new_name); assert_eq!(updated_identity.url, new_url); @@ -693,6 +697,7 @@ fn test_do_set_identity() { long_data.clone(), long_data.clone(), long_data.clone(), + long_data.clone(), long_data.clone() ), Error::::InvalidIdentity @@ -705,9 +710,10 @@ fn test_do_set_identity() { fn test_is_valid_identity() { new_test_ext(1).execute_with(|| { // Test valid identity - let valid_identity = ChainIdentity { + let valid_identity = ChainIdentityV2 { name: vec![0; 256], url: vec![0; 256], + github_repo: vec![0; 256], image: vec![0; 1024], discord: vec![0; 256], description: vec![0; 1024], @@ -716,9 +722,10 @@ fn test_is_valid_identity() { assert!(SubtensorModule::is_valid_identity(&valid_identity)); // Test identity with total length exactly at the maximum - let max_length_identity = ChainIdentity { + let max_length_identity = ChainIdentityV2 { name: vec![0; 256], url: vec![0; 256], + github_repo: vec![0; 256], image: vec![0; 1024], discord: vec![0; 256], description: vec![0; 1024], @@ -727,9 +734,10 @@ fn test_is_valid_identity() { assert!(SubtensorModule::is_valid_identity(&max_length_identity)); // Test identity with total length exceeding the maximum - let invalid_length_identity = ChainIdentity { + let invalid_length_identity = ChainIdentityV2 { name: vec![0; 257], url: vec![0; 256], + github_repo: vec![0; 256], image: vec![0; 1024], discord: vec![0; 256], description: vec![0; 1024], @@ -740,9 +748,10 @@ fn test_is_valid_identity() { )); // Test identity with one field exceeding its maximum - let invalid_field_identity = ChainIdentity { + let invalid_field_identity = ChainIdentityV2 { name: vec![0; 257], url: vec![0; 256], + github_repo: vec![0; 256], image: vec![0; 1024], discord: vec![0; 256], description: vec![0; 1024], @@ -751,9 +760,10 @@ fn test_is_valid_identity() { assert!(!SubtensorModule::is_valid_identity(&invalid_field_identity)); // Test identity with empty fields - let empty_identity = ChainIdentity { + let empty_identity = ChainIdentityV2 { name: vec![], url: vec![], + github_repo: vec![], image: vec![], discord: vec![], description: vec![], @@ -762,9 +772,10 @@ fn test_is_valid_identity() { assert!(SubtensorModule::is_valid_identity(&empty_identity)); // Test identity with some empty and some filled fields - let mixed_identity = ChainIdentity { + let mixed_identity = ChainIdentityV2 { name: b"Alice".to_vec(), url: b"https://alice.com".to_vec(), + github_repo: vec![], image: vec![], discord: b"alice#1234".to_vec(), description: vec![], @@ -773,9 +784,10 @@ fn test_is_valid_identity() { assert!(SubtensorModule::is_valid_identity(&mixed_identity)); // Test identity with all fields at maximum allowed length - let max_field_identity = ChainIdentity { + let max_field_identity = ChainIdentityV2 { name: vec![0; 256], url: vec![0; 256], + github_repo: vec![0; 256], image: vec![0; 1024], discord: vec![0; 256], description: vec![0; 1024], @@ -800,6 +812,7 @@ fn test_set_and_get_identity() { // Prepare identity data let name = b"Bob".to_vec(); let url = b"https://bob.com".to_vec(); + let git = b"https://github.com".to_vec(); let image = b"bob.jpg".to_vec(); let discord = b"bob#5678".to_vec(); let description = b"Bob's identity".to_vec(); @@ -810,6 +823,7 @@ fn test_set_and_get_identity() { <::RuntimeOrigin>::signed(coldkey), name.clone(), url.clone(), + git.clone(), image.clone(), discord.clone(), description.clone(), @@ -817,7 +831,7 @@ fn test_set_and_get_identity() { )); // Get and verify identity - let stored_identity = Identities::::get(coldkey).expect("Identity should be set"); + let stored_identity = IdentitiesV2::::get(coldkey).expect("Identity should be set"); assert_eq!(stored_identity.name, name); assert_eq!(stored_identity.url, url); assert_eq!(stored_identity.image, image); @@ -832,6 +846,7 @@ fn test_set_and_get_identity() { <::RuntimeOrigin>::signed(coldkey), new_name.clone(), new_url.clone(), + git.clone(), image.clone(), discord.clone(), description.clone(), @@ -840,7 +855,7 @@ fn test_set_and_get_identity() { // Get and verify updated identity let updated_identity = - Identities::::get(coldkey).expect("Updated identity should be set"); + IdentitiesV2::::get(coldkey).expect("Updated identity should be set"); assert_eq!(updated_identity.name, new_name); assert_eq!(updated_identity.url, new_url); assert_eq!(updated_identity.image, image); @@ -850,7 +865,7 @@ fn test_set_and_get_identity() { // Verify non-existent identity let non_existent_coldkey = U256::from(999); - assert!(Identities::::get(non_existent_coldkey).is_none()); + assert!(IdentitiesV2::::get(non_existent_coldkey).is_none()); }); } @@ -903,6 +918,10 @@ fn test_do_set_subnet_identity() { let subnet_name = b"Test Subnet".to_vec(); let github_repo = b"https://github.com/test/subnet".to_vec(); let subnet_contact = b"contact@testsubnet.com".to_vec(); + let subnet_url = b"subnet.com".to_vec(); + let discord = b"discord.com".to_vec(); + let description = b"I am the describer".to_vec(); + let additional = b"tao foreva".to_vec(); // Set subnet identity assert_ok!(SubtensorModule::do_set_subnet_identity( @@ -910,12 +929,16 @@ fn test_do_set_subnet_identity() { netuid, subnet_name.clone(), github_repo.clone(), - subnet_contact.clone() + subnet_contact.clone(), + subnet_url.clone(), + discord.clone(), + description.clone(), + additional.clone(), )); // Check if subnet identity is set correctly let stored_identity = - SubnetIdentities::::get(netuid).expect("Subnet identity should be set"); + SubnetIdentitiesV2::::get(netuid).expect("Subnet identity should be set"); assert_eq!(stored_identity.subnet_name, subnet_name); assert_eq!(stored_identity.github_repo, github_repo); assert_eq!(stored_identity.subnet_contact, subnet_contact); @@ -928,7 +951,11 @@ fn test_do_set_subnet_identity() { netuid, subnet_name.clone(), github_repo.clone(), - subnet_contact.clone() + subnet_contact.clone(), + subnet_url.clone(), + discord.clone(), + description.clone(), + additional.clone(), ), Error::::NotSubnetOwner ); @@ -941,11 +968,15 @@ fn test_do_set_subnet_identity() { netuid, new_subnet_name.clone(), new_github_repo.clone(), - subnet_contact.clone() + subnet_contact.clone(), + subnet_url.clone(), + discord.clone(), + description.clone(), + additional.clone(), )); let updated_identity = - SubnetIdentities::::get(netuid).expect("Updated subnet identity should be set"); + SubnetIdentitiesV2::::get(netuid).expect("Updated subnet identity should be set"); assert_eq!(updated_identity.subnet_name, new_subnet_name); assert_eq!(updated_identity.github_repo, new_github_repo); @@ -957,7 +988,11 @@ fn test_do_set_subnet_identity() { netuid, long_data.clone(), long_data.clone(), - long_data.clone() + long_data.clone(), + long_data.clone(), + long_data.clone(), + long_data.clone(), + long_data.clone(), ), Error::::InvalidIdentity ); @@ -969,56 +1004,80 @@ fn test_do_set_subnet_identity() { fn test_is_valid_subnet_identity() { new_test_ext(1).execute_with(|| { // Test valid subnet identity - let valid_identity = SubnetIdentity { + let valid_identity = SubnetIdentityV2 { subnet_name: vec![0; 256], github_repo: vec![0; 1024], subnet_contact: vec![0; 1024], + subnet_url: vec![0; 1024], + discord: vec![0; 256], + description: vec![0; 1024], + additional: vec![0; 1024], }; assert!(SubtensorModule::is_valid_subnet_identity(&valid_identity)); // Test subnet identity with total length exactly at the maximum - let max_length_identity = SubnetIdentity { + let max_length_identity = SubnetIdentityV2 { subnet_name: vec![0; 256], github_repo: vec![0; 1024], subnet_contact: vec![0; 1024], + subnet_url: vec![0; 1024], + discord: vec![0; 256], + description: vec![0; 1024], + additional: vec![0; 1024], }; assert!(SubtensorModule::is_valid_subnet_identity( &max_length_identity )); // Test subnet identity with total length exceeding the maximum - let invalid_length_identity = SubnetIdentity { + let invalid_length_identity = SubnetIdentityV2 { subnet_name: vec![0; 257], github_repo: vec![0; 1024], subnet_contact: vec![0; 1024], + subnet_url: vec![0; 1024], + discord: vec![0; 256], + description: vec![0; 1024], + additional: vec![0; 1024], }; assert!(!SubtensorModule::is_valid_subnet_identity( &invalid_length_identity )); // Test subnet identity with one field exceeding its maximum - let invalid_field_identity = SubnetIdentity { + let invalid_field_identity = SubnetIdentityV2 { subnet_name: vec![0; 257], github_repo: vec![0; 1024], subnet_contact: vec![0; 1024], + subnet_url: vec![0; 1024], + discord: vec![0; 256], + description: vec![0; 1024], + additional: vec![0; 1024], }; assert!(!SubtensorModule::is_valid_subnet_identity( &invalid_field_identity )); // Test subnet identity with empty fields - let empty_identity = SubnetIdentity { + let empty_identity = SubnetIdentityV2 { subnet_name: vec![], github_repo: vec![], subnet_contact: vec![], + subnet_url: vec![], + discord: vec![], + description: vec![], + additional: vec![], }; assert!(SubtensorModule::is_valid_subnet_identity(&empty_identity)); // Test subnet identity with some empty and some filled fields - let mixed_identity = SubnetIdentity { + let mixed_identity = SubnetIdentityV2 { subnet_name: b"Test Subnet".to_vec(), github_repo: vec![], subnet_contact: b"contact@testsubnet.com".to_vec(), + subnet_url: b"https://testsubnet.com".to_vec(), + discord: vec![], + description: b"A description".to_vec(), + additional: vec![], }; assert!(SubtensorModule::is_valid_subnet_identity(&mixed_identity)); }); @@ -1034,6 +1093,10 @@ fn test_set_identity_for_non_existent_subnet() { let subnet_name = b"Non-existent Subnet".to_vec(); let github_repo = b"https://github.com/test/nonexistent".to_vec(); let subnet_contact = b"contact@nonexistent.com".to_vec(); + let subnet_url = b"subnet.com".to_vec(); + let discord = b"discord.com".to_vec(); + let description = b"I am the describer".to_vec(); + let additional = b"tao foreva".to_vec(); // Attempt to set identity for a non-existent subnet assert_noop!( @@ -1042,7 +1105,11 @@ fn test_set_identity_for_non_existent_subnet() { netuid, subnet_name.clone(), github_repo.clone(), - subnet_contact.clone() + subnet_contact.clone(), + subnet_url.clone(), + discord.clone(), + description.clone(), + additional.clone(), ), Error::::NotSubnetOwner // Since there's no owner, it should fail ); @@ -1056,12 +1123,20 @@ fn test_set_subnet_identity_dispatch_info_ok() { let subnet_name: Vec = b"JesusSubnet".to_vec(); let github_repo: Vec = b"bible.com".to_vec(); let subnet_contact: Vec = b"https://www.vatican.va".to_vec(); + let subnet_url = b"subnet.com".to_vec(); + let discord = b"discord.com".to_vec(); + let description = b"I am the describer".to_vec(); + let additional = b"tao foreva".to_vec(); let call: RuntimeCall = RuntimeCall::SubtensorModule(SubtensorCall::set_subnet_identity { netuid, subnet_name, github_repo, subnet_contact, + subnet_url, + discord, + description, + additional, }); let dispatch_info: DispatchInfo = call.get_dispatch_info(); diff --git a/pallets/subtensor/src/tests/swap_coldkey.rs b/pallets/subtensor/src/tests/swap_coldkey.rs index f21af56cf9..7761005780 100644 --- a/pallets/subtensor/src/tests/swap_coldkey.rs +++ b/pallets/subtensor/src/tests/swap_coldkey.rs @@ -673,19 +673,20 @@ fn test_do_swap_coldkey_success() { // Insert an Identity let name: Vec = b"The fourth Coolest Identity".to_vec(); - let identity: ChainIdentity = ChainIdentity { + let identity: ChainIdentityV2 = ChainIdentityV2 { name: name.clone(), url: vec![], + github_repo: vec![], image: vec![], discord: vec![], description: vec![], additional: vec![], }; - Identities::::insert(old_coldkey, identity.clone()); + IdentitiesV2::::insert(old_coldkey, identity.clone()); - assert!(Identities::::get(old_coldkey).is_some()); - assert!(Identities::::get(new_coldkey).is_none()); + assert!(IdentitiesV2::::get(old_coldkey).is_some()); + assert!(IdentitiesV2::::get(new_coldkey).is_none()); // Log state after adding stake log::info!( @@ -774,10 +775,10 @@ fn test_do_swap_coldkey_success() { ); // Verify identities were swapped - assert!(Identities::::get(old_coldkey).is_none()); - assert!(Identities::::get(new_coldkey).is_some()); + assert!(IdentitiesV2::::get(old_coldkey).is_none()); + assert!(IdentitiesV2::::get(new_coldkey).is_some()); assert_eq!( - Identities::::get(new_coldkey).expect("Expected an Identity"), + IdentitiesV2::::get(new_coldkey).expect("Expected an Identity"), identity ); @@ -1887,19 +1888,20 @@ fn test_coldkey_swap_delegate_identity_updated() { )); let name: Vec = b"The Third Coolest Identity".to_vec(); - let identity: ChainIdentity = ChainIdentity { + let identity: ChainIdentityV2 = ChainIdentityV2 { name: name.clone(), url: vec![], image: vec![], + github_repo: vec![], discord: vec![], description: vec![], additional: vec![], }; - Identities::::insert(old_coldkey, identity.clone()); + IdentitiesV2::::insert(old_coldkey, identity.clone()); - assert!(Identities::::get(old_coldkey).is_some()); - assert!(Identities::::get(new_coldkey).is_none()); + assert!(IdentitiesV2::::get(old_coldkey).is_some()); + assert!(IdentitiesV2::::get(new_coldkey).is_none()); assert_ok!(SubtensorModule::do_swap_coldkey( &old_coldkey, @@ -1907,10 +1909,10 @@ fn test_coldkey_swap_delegate_identity_updated() { burn_cost )); - assert!(Identities::::get(old_coldkey).is_none()); - assert!(Identities::::get(new_coldkey).is_some()); + assert!(IdentitiesV2::::get(old_coldkey).is_none()); + assert!(IdentitiesV2::::get(new_coldkey).is_some()); assert_eq!( - Identities::::get(new_coldkey).expect("Expected an Identity"), + IdentitiesV2::::get(new_coldkey).expect("Expected an Identity"), identity ); }); @@ -1938,7 +1940,7 @@ fn test_coldkey_swap_no_identity_no_changes() { )); // Ensure the old coldkey does not have an identity before the swap - assert!(Identities::::get(old_coldkey).is_none()); + assert!(IdentitiesV2::::get(old_coldkey).is_none()); // Perform the coldkey swap assert_ok!(SubtensorModule::do_swap_coldkey( @@ -1948,8 +1950,8 @@ fn test_coldkey_swap_no_identity_no_changes() { )); // Ensure no identities have been changed - assert!(Identities::::get(old_coldkey).is_none()); - assert!(Identities::::get(new_coldkey).is_none()); + assert!(IdentitiesV2::::get(old_coldkey).is_none()); + assert!(IdentitiesV2::::get(new_coldkey).is_none()); }); } @@ -1974,19 +1976,20 @@ fn test_coldkey_swap_no_identity_no_changes_newcoldkey_exists() { )); let name: Vec = b"The Coolest Identity".to_vec(); - let identity: ChainIdentity = ChainIdentity { + let identity: ChainIdentityV2 = ChainIdentityV2 { name: name.clone(), url: vec![], + github_repo: vec![], image: vec![], discord: vec![], description: vec![], additional: vec![], }; - Identities::::insert(new_coldkey, identity.clone()); + IdentitiesV2::::insert(new_coldkey, identity.clone()); // Ensure the new coldkey does have an identity before the swap - assert!(Identities::::get(new_coldkey).is_some()); - assert!(Identities::::get(old_coldkey).is_none()); + assert!(IdentitiesV2::::get(new_coldkey).is_some()); + assert!(IdentitiesV2::::get(old_coldkey).is_none()); // Perform the coldkey swap assert_ok!(SubtensorModule::do_swap_coldkey( @@ -1996,8 +1999,8 @@ fn test_coldkey_swap_no_identity_no_changes_newcoldkey_exists() { )); // Ensure no identities have been changed - assert!(Identities::::get(old_coldkey).is_none()); - assert!(Identities::::get(new_coldkey).is_some()); + assert!(IdentitiesV2::::get(old_coldkey).is_none()); + assert!(IdentitiesV2::::get(new_coldkey).is_some()); }); } diff --git a/pallets/subtensor/src/utils/identity.rs b/pallets/subtensor/src/utils/identity.rs index 7babb04f4f..b721664f0f 100644 --- a/pallets/subtensor/src/utils/identity.rs +++ b/pallets/subtensor/src/utils/identity.rs @@ -27,6 +27,7 @@ impl Pallet { origin: T::RuntimeOrigin, name: Vec, url: Vec, + github_repo: Vec, image: Vec, discord: Vec, description: Vec, @@ -47,9 +48,10 @@ impl Pallet { ); // Create the identity struct with the provided information - let identity = ChainIdentityOf { + let identity = ChainIdentityOfV2 { name, url, + github_repo, image, discord, description, @@ -63,7 +65,7 @@ impl Pallet { ); // Store the validated identity in the blockchain state - Identities::::insert(coldkey.clone(), identity.clone()); + IdentitiesV2::::insert(coldkey.clone(), identity.clone()); // Log the identity set event log::debug!("ChainIdentitySet( coldkey:{:?} ) ", coldkey.clone()); @@ -98,6 +100,10 @@ impl Pallet { subnet_name: Vec, github_repo: Vec, subnet_contact: Vec, + subnet_url: Vec, + discord: Vec, + description: Vec, + additional: Vec, ) -> dispatch::DispatchResult { // Ensure the call is signed and get the signer's (coldkey) account let coldkey = ensure_signed(origin)?; @@ -109,10 +115,14 @@ impl Pallet { ); // Create the identity struct with the provided information - let identity: SubnetIdentityOf = SubnetIdentityOf { + let identity: SubnetIdentityOfV2 = SubnetIdentityOfV2 { subnet_name, github_repo, subnet_contact, + subnet_url, + discord, + description, + additional, }; // Validate the created identity @@ -122,7 +132,7 @@ impl Pallet { ); // Store the validated identity in the blockchain state - SubnetIdentities::::insert(netuid, identity.clone()); + SubnetIdentitiesV2::::insert(netuid, identity.clone()); // Log the identity set event log::info!("SubnetIdentitySet( netuid:{:?} ) ", netuid); @@ -147,7 +157,7 @@ impl Pallet { /// # Returns /// /// * `bool` - Returns true if the Identity is valid, false otherwise. - pub fn is_valid_identity(identity: &ChainIdentityOf) -> bool { + pub fn is_valid_identity(identity: &ChainIdentityOfV2) -> bool { let total_length = identity .name .len() @@ -157,9 +167,10 @@ impl Pallet { .saturating_add(identity.description.len()) .saturating_add(identity.additional.len()); - total_length <= 256 + 256 + 1024 + 256 + 1024 + 1024 + total_length <= 256 + 256 + 256 + 1024 + 256 + 1024 + 1024 && identity.name.len() <= 256 && identity.url.len() <= 256 + && identity.github_repo.len() <= 256 && identity.image.len() <= 1024 && identity.discord.len() <= 256 && identity.description.len() <= 1024 @@ -179,16 +190,20 @@ impl Pallet { /// # Returns /// /// * `bool` - Returns true if the SubnetIdentity is valid, false otherwise. - pub fn is_valid_subnet_identity(identity: &SubnetIdentityOf) -> bool { + pub fn is_valid_subnet_identity(identity: &SubnetIdentityOfV2) -> bool { let total_length = identity .subnet_name .len() .saturating_add(identity.github_repo.len()) .saturating_add(identity.subnet_contact.len()); - total_length <= 256 + 1024 + 1024 + total_length <= 256 + 1024 + 1024 + 1024 + 256 + 1024 + 1024 && identity.subnet_name.len() <= 256 && identity.github_repo.len() <= 1024 && identity.subnet_contact.len() <= 1024 + && identity.subnet_url.len() <= 1024 + && identity.discord.len() <= 256 + && identity.description.len() <= 1024 + && identity.additional.len() <= 1024 } } diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 372c9a9815..74524e2a96 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -2096,6 +2096,21 @@ impl_runtime_apis! { result.encode() } + fn get_subnet_info_v3(netuid: u16) -> Vec { + let _result = SubtensorModule::get_subnet_info_v3(netuid); + if _result.is_some() { + let result = _result.expect("Could not get SubnetInfo"); + result.encode() + } else { + vec![] + } + } + + fn get_subnets_info_v3() -> Vec { + let result = SubtensorModule::get_subnets_info_v3(); + result.encode() + } + fn get_subnet_hyperparams(netuid: u16) -> Vec { let _result = SubtensorModule::get_subnet_hyperparams(netuid); if _result.is_some() { From 0c5eaecf59f485a38b56bb9bb022da2dbe829729 Mon Sep 17 00:00:00 2001 From: JohnReedV <87283488+JohnReedV@users.noreply.github.com> Date: Tue, 28 Jan 2025 09:52:06 -0800 Subject: [PATCH 02/34] add migration and test --- pallets/subtensor/src/macros/hooks.rs | 4 +- .../src/migrations/migrate_identities_v2.rs | 91 ++++++++++++++ pallets/subtensor/src/migrations/mod.rs | 1 + pallets/subtensor/src/tests/serving.rs | 112 ++++++++++++++++++ 4 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 pallets/subtensor/src/migrations/migrate_identities_v2.rs diff --git a/pallets/subtensor/src/macros/hooks.rs b/pallets/subtensor/src/macros/hooks.rs index 2a43238ab3..d3b08c51ac 100644 --- a/pallets/subtensor/src/macros/hooks.rs +++ b/pallets/subtensor/src/macros/hooks.rs @@ -76,7 +76,9 @@ mod hooks { // Migrate to RAO .saturating_add(migrations::migrate_rao::migrate_rao::()) // Fix the IsNetworkMember map to be consistent with other storage maps - .saturating_add(migrations::migrate_fix_is_network_member::migrate_fix_is_network_member::()); + .saturating_add(migrations::migrate_fix_is_network_member::migrate_fix_is_network_member::()) + // Upgrade identities to V2 + .saturating_add(migrations::migrate_identities_v2::migrate_identities_to_v2::()); weight } diff --git a/pallets/subtensor/src/migrations/migrate_identities_v2.rs b/pallets/subtensor/src/migrations/migrate_identities_v2.rs new file mode 100644 index 0000000000..505b617b2f --- /dev/null +++ b/pallets/subtensor/src/migrations/migrate_identities_v2.rs @@ -0,0 +1,91 @@ +use super::*; +use frame_support::weights::Weight; +use log; +use scale_info::prelude::{string::String, vec::Vec}; + +pub fn migrate_identities_to_v2() -> Weight { + use frame_support::traits::Get; + let migration_name = b"migrate_identities_to_v2".to_vec(); + + // Start counting weight + let mut weight = T::DbWeight::get().reads(1); + + // Check if we already ran this migration + if HasMigrationRun::::get(&migration_name) { + log::info!( + target: "runtime", + "Migration '{:?}' has already run. Skipping.", + String::from_utf8_lossy(&migration_name) + ); + return weight; + } + + log::info!( + target: "runtime", + "Running migration '{}'", + String::from_utf8_lossy(&migration_name) + ); + + // ----------------------------- + // 1) Migrate Chain Identities + // ----------------------------- + let old_identities = Identities::::iter().collect::>(); + for (account_id, old_identity) in old_identities.clone() { + let new_identity = ChainIdentityV2 { + name: old_identity.name, + url: old_identity.url, + github_repo: Vec::new(), + image: old_identity.image, + discord: old_identity.discord, + description: old_identity.description, + additional: old_identity.additional, + }; + + // Insert into the new storage map + IdentitiesV2::::insert(&account_id, &new_identity); + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + + Identities::::remove(&account_id); + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + } + + weight = weight.saturating_add(T::DbWeight::get().reads(old_identities.len() as u64)); + + // ----------------------------- + // 2) Migrate Subnet Identities + // ----------------------------- + let old_subnet_identities = SubnetIdentities::::iter().collect::>(); + for (netuid, old_subnet_identity) in old_subnet_identities.clone() { + let new_subnet_identity = SubnetIdentityV2 { + subnet_name: old_subnet_identity.subnet_name, + github_repo: old_subnet_identity.github_repo, + subnet_contact: old_subnet_identity.subnet_contact, + subnet_url: Vec::new(), + discord: Vec::new(), + description: Vec::new(), + additional: Vec::new(), + }; + + // Insert into the new storage map + SubnetIdentitiesV2::::insert(netuid, &new_subnet_identity); + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + + SubnetIdentities::::remove(netuid); + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + } + weight = weight.saturating_add(T::DbWeight::get().reads(old_subnet_identities.len() as u64)); + + // ----------------------------- + // Mark the migration as done + // ----------------------------- + HasMigrationRun::::insert(&migration_name, true); + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + + log::info!( + target: "runtime", + "Migration '{}' completed successfully.", + String::from_utf8_lossy(&migration_name) + ); + + weight +} diff --git a/pallets/subtensor/src/migrations/mod.rs b/pallets/subtensor/src/migrations/mod.rs index 6cf358c4db..5af200d62f 100644 --- a/pallets/subtensor/src/migrations/mod.rs +++ b/pallets/subtensor/src/migrations/mod.rs @@ -6,6 +6,7 @@ pub mod migrate_delete_subnet_21; pub mod migrate_delete_subnet_3; pub mod migrate_fix_is_network_member; pub mod migrate_fix_total_coldkey_stake; +pub mod migrate_identities_v2; pub mod migrate_init_total_issuance; pub mod migrate_populate_owned_hotkeys; pub mod migrate_populate_staking_hotkeys; diff --git a/pallets/subtensor/src/tests/serving.rs b/pallets/subtensor/src/tests/serving.rs index f7ce4d6a2b..52b8f8b08f 100644 --- a/pallets/subtensor/src/tests/serving.rs +++ b/pallets/subtensor/src/tests/serving.rs @@ -899,6 +899,118 @@ fn test_migrate_set_hotkey_identities() { }); } +#[test] +fn test_migrate_identities_to_v2() { + new_test_ext(1).execute_with(|| { + let account_id_1 = U256::from(1); + let account_id_2 = U256::from(2); + + let chainone_name = b"ChainOne".to_vec(); + let chainone_url = b"https://chainone.example".to_vec(); + let chainone_image = b"some_image_data".to_vec(); + let chainone_discord = b"discord#1".to_vec(); + let chainone_description = b"Old chain identity".to_vec(); + let chainone_additional = b"extra-info".to_vec(); + + let chaintwo_name = b"ChainTwo".to_vec(); + let chaintwo_url = b"https://chaintwo.example".to_vec(); + let chaintwo_description = b"Another chain identity".to_vec(); + + Identities::::insert( + account_id_1, + ChainIdentity { + name: chainone_name.clone(), + url: chainone_url.clone(), + image: chainone_image.clone(), + discord: chainone_discord.clone(), + description: chainone_description.clone(), + additional: chainone_additional.clone(), + }, + ); + + Identities::::insert( + account_id_2, + ChainIdentity { + name: chaintwo_name.clone(), + url: chaintwo_url.clone(), + image: b"".to_vec(), + discord: b"".to_vec(), + description: chaintwo_description.clone(), + additional: b"".to_vec(), + }, + ); + + let old_subnet_name = b"SubnetExample".to_vec(); + let old_github_repo = b"https://github.com/org/repo".to_vec(); + let old_subnet_contact = b"subnet@example".to_vec(); + + SubnetIdentities::::insert( + 42u16, + SubnetIdentity { + subnet_name: old_subnet_name.clone(), + github_repo: old_github_repo.clone(), + subnet_contact: old_subnet_contact.clone(), + }, + ); + + assert!(Identities::::get(account_id_1).is_some()); + assert!(Identities::::get(account_id_2).is_some()); + assert!(SubnetIdentities::::get(42u16).is_some()); + assert!(!HasMigrationRun::::get( + b"migrate_identities_to_v2".to_vec() + )); + + let weight = crate::migrations::migrate_identities_v2::migrate_identities_to_v2::(); + + assert!( + HasMigrationRun::::get(b"migrate_identities_to_v2".to_vec()), + "Expected HasMigrationRun to be true after migration" + ); + assert!(Identities::::get(account_id_1).is_none()); + assert!(Identities::::get(account_id_2).is_none()); + assert!(SubnetIdentities::::get(42u16).is_none()); + + let new_identity_1 = IdentitiesV2::::get(account_id_1) + .expect("ChainOne should be migrated to IdentitiesV2"); + let expected_github_repo = b"".to_vec(); + + assert_eq!(new_identity_1.name, chainone_name); + assert_eq!(new_identity_1.url, chainone_url); + assert_eq!(new_identity_1.github_repo, expected_github_repo); + assert_eq!(new_identity_1.image, chainone_image); + assert_eq!(new_identity_1.discord, chainone_discord); + assert_eq!(new_identity_1.description, chainone_description); + assert_eq!(new_identity_1.additional, chainone_additional); + + let new_identity_2 = IdentitiesV2::::get(account_id_2) + .expect("ChainTwo should be migrated to IdentitiesV2"); + assert_eq!(new_identity_2.name, chaintwo_name); + assert_eq!(new_identity_2.url, chaintwo_url); + assert_eq!(new_identity_2.github_repo, b"".to_vec()); + + let new_subnet_identity = SubnetIdentitiesV2::::get(42u16) + .expect("SubnetExample should be migrated to SubnetIdentitiesV2"); + + let expected_subnet_url = b"".to_vec(); + let expected_discord = b"".to_vec(); + let expected_description = b"".to_vec(); + let expected_additional = b"".to_vec(); + + assert_eq!(new_subnet_identity.subnet_name, old_subnet_name); + assert_eq!(new_subnet_identity.github_repo, old_github_repo); + assert_eq!(new_subnet_identity.subnet_contact, old_subnet_contact); + assert_eq!(new_subnet_identity.subnet_url, expected_subnet_url); + assert_eq!(new_subnet_identity.discord, expected_discord); + assert_eq!(new_subnet_identity.description, expected_description); + assert_eq!(new_subnet_identity.additional, expected_additional); + + assert!( + weight != Weight::zero(), + "Migration weight should be non-zero" + ); + }); +} + // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test serving -- test_do_set_subnet_identity --exact --nocapture #[test] fn test_do_set_subnet_identity() { From ea96beca7a0c347f0b68835857df2598232b9e8d Mon Sep 17 00:00:00 2001 From: JohnReedV <87283488+JohnReedV@users.noreply.github.com> Date: Mon, 3 Feb 2025 09:22:48 -0800 Subject: [PATCH 03/34] address freeze_struct --- pallets/subtensor/src/rpc_info/dynamic_info.rs | 2 +- pallets/subtensor/src/rpc_info/metagraph.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pallets/subtensor/src/rpc_info/dynamic_info.rs b/pallets/subtensor/src/rpc_info/dynamic_info.rs index 213fc7654a..554e79eef8 100644 --- a/pallets/subtensor/src/rpc_info/dynamic_info.rs +++ b/pallets/subtensor/src/rpc_info/dynamic_info.rs @@ -4,7 +4,7 @@ use codec::Compact; use frame_support::pallet_prelude::{Decode, Encode}; use subtensor_macros::freeze_struct; -#[freeze_struct("e425055e357d7a13")] +#[freeze_struct("66f29110b41779af")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug)] pub struct DynamicInfo { netuid: Compact, diff --git a/pallets/subtensor/src/rpc_info/metagraph.rs b/pallets/subtensor/src/rpc_info/metagraph.rs index 33fde563c9..b4238f601f 100644 --- a/pallets/subtensor/src/rpc_info/metagraph.rs +++ b/pallets/subtensor/src/rpc_info/metagraph.rs @@ -6,7 +6,7 @@ use frame_support::pallet_prelude::{Decode, Encode}; use substrate_fixed::types::I64F64; use subtensor_macros::freeze_struct; -#[freeze_struct("b80fd826ead2df2f")] +#[freeze_struct("66f29110b41779af")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug)] pub struct Metagraph { // Subnet index From a7232b06fa624a5105cbf23584d5c185bfa121df Mon Sep 17 00:00:00 2001 From: JohnReedV <87283488+JohnReedV@users.noreply.github.com> Date: Mon, 3 Feb 2025 09:27:26 -0800 Subject: [PATCH 04/34] rename commit_reveal_period --- pallets/subtensor/src/rpc_info/subnet_info.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pallets/subtensor/src/rpc_info/subnet_info.rs b/pallets/subtensor/src/rpc_info/subnet_info.rs index 5003ec5f63..2ced07a1b5 100644 --- a/pallets/subtensor/src/rpc_info/subnet_info.rs +++ b/pallets/subtensor/src/rpc_info/subnet_info.rs @@ -75,7 +75,7 @@ pub struct SubnetInfov3 { identity: Option, } -#[freeze_struct("55b472510f10e76a")] +#[freeze_struct("a2dd2fcd6f4d4ff8")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug)] pub struct SubnetHyperparams { rho: Compact, @@ -100,7 +100,7 @@ pub struct SubnetHyperparams { max_validators: Compact, adjustment_alpha: Compact, difficulty: Compact, - commit_reveal_weights_interval: Compact, + commit_reveal_period: Compact, commit_reveal_weights_enabled: bool, alpha_high: Compact, alpha_low: Compact, @@ -377,7 +377,7 @@ impl Pallet { max_validators: max_validators.into(), adjustment_alpha: adjustment_alpha.into(), difficulty: difficulty.into(), - commit_reveal_weights_interval: commit_reveal_periods.into(), + commit_reveal_period: commit_reveal_periods.into(), commit_reveal_weights_enabled, alpha_high: alpha_high.into(), alpha_low: alpha_low.into(), From 12f483c2e7e7a00a5f84660ba769475c2e4b149b Mon Sep 17 00:00:00 2001 From: JohnReedV <87283488+JohnReedV@users.noreply.github.com> Date: Mon, 3 Feb 2025 10:01:33 -0800 Subject: [PATCH 05/34] remove subnet_info_v3 --- pallets/subtensor/rpc/src/lib.rs | 24 ------ pallets/subtensor/runtime-api/src/lib.rs | 2 - pallets/subtensor/src/rpc_info/subnet_info.rs | 78 +------------------ runtime/src/lib.rs | 15 ---- 4 files changed, 3 insertions(+), 116 deletions(-) diff --git a/pallets/subtensor/rpc/src/lib.rs b/pallets/subtensor/rpc/src/lib.rs index 0df96eda65..cdbcebcacb 100644 --- a/pallets/subtensor/rpc/src/lib.rs +++ b/pallets/subtensor/rpc/src/lib.rs @@ -49,10 +49,6 @@ pub trait SubtensorCustomApi { fn get_subnet_info_v2(&self, netuid: u16, at: Option) -> RpcResult>; #[method(name = "subnetInfo_getSubnetsInf_v2")] fn get_subnets_info_v2(&self, at: Option) -> RpcResult>; - #[method(name = "subnetInfo_getSubnetInfo_v3")] - fn get_subnet_info_v3(&self, netuid: u16, at: Option) -> RpcResult>; - #[method(name = "subnetInfo_getSubnetsInf_v3")] - fn get_subnets_info_v3(&self, at: Option) -> RpcResult>; #[method(name = "subnetInfo_getSubnetHyperparams")] fn get_subnet_hyperparams(&self, netuid: u16, at: Option) -> RpcResult>; #[method(name = "subnetInfo_getAllDynamicInfo")] @@ -302,26 +298,6 @@ where .map_err(|e| Error::RuntimeError(format!("Unable to get subnets info: {:?}", e)).into()) } - fn get_subnet_info_v3( - &self, - netuid: u16, - at: Option<::Hash>, - ) -> RpcResult> { - let api = self.client.runtime_api(); - let at = at.unwrap_or_else(|| self.client.info().best_hash); - - api.get_subnet_info_v3(at, netuid) - .map_err(|e| Error::RuntimeError(format!("Unable to get subnet info: {:?}", e)).into()) - } - - fn get_subnets_info_v3(&self, at: Option<::Hash>) -> RpcResult> { - let api = self.client.runtime_api(); - let at = at.unwrap_or_else(|| self.client.info().best_hash); - - api.get_subnets_info_v3(at) - .map_err(|e| Error::RuntimeError(format!("Unable to get subnets info: {:?}", e)).into()) - } - fn get_network_lock_cost(&self, at: Option<::Hash>) -> RpcResult { let api = self.client.runtime_api(); let at = at.unwrap_or_else(|| self.client.info().best_hash); diff --git a/pallets/subtensor/runtime-api/src/lib.rs b/pallets/subtensor/runtime-api/src/lib.rs index 75d0916dd0..31f351aeb6 100644 --- a/pallets/subtensor/runtime-api/src/lib.rs +++ b/pallets/subtensor/runtime-api/src/lib.rs @@ -23,8 +23,6 @@ sp_api::decl_runtime_apis! { fn get_subnets_info() -> Vec; fn get_subnet_info_v2(netuid: u16) -> Vec; fn get_subnets_info_v2() -> Vec; - fn get_subnet_info_v3(netuid: u16) -> Vec; - fn get_subnets_info_v3()-> Vec; fn get_subnet_hyperparams(netuid: u16) -> Vec; fn get_all_dynamic_info() -> Vec; fn get_all_metagraphs() -> Vec; diff --git a/pallets/subtensor/src/rpc_info/subnet_info.rs b/pallets/subtensor/src/rpc_info/subnet_info.rs index 2ced07a1b5..65851d36cf 100644 --- a/pallets/subtensor/src/rpc_info/subnet_info.rs +++ b/pallets/subtensor/src/rpc_info/subnet_info.rs @@ -27,7 +27,7 @@ pub struct SubnetInfo { owner: T::AccountId, } -#[freeze_struct("65f931972fa13222")] +#[freeze_struct("c46dc4e2d4d9f8a3")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug)] pub struct SubnetInfov2 { netuid: Compact, @@ -48,7 +48,7 @@ pub struct SubnetInfov2 { emission_values: Compact, burn: Compact, owner: T::AccountId, - identity: Option, + identity: Option, } #[freeze_struct("dd91200554b75bc4")] @@ -198,7 +198,7 @@ impl Pallet { let network_modality = >::get(netuid); let emission_values = Self::get_emission_value(netuid); let burn: Compact = Self::get_burn_as_u64(netuid).into(); - let identity: Option = SubnetIdentities::::get(netuid); + let identity: Option = SubnetIdentitiesV2::::get(netuid); // DEPRECATED let network_connect: Vec<[u16; 2]> = Vec::<[u16; 2]>::new(); @@ -250,78 +250,6 @@ impl Pallet { subnets_info } - pub fn get_subnet_info_v3(netuid: u16) -> Option> { - if !Self::if_subnet_exist(netuid) { - return None; - } - - let rho = Self::get_rho(netuid); - let kappa = Self::get_kappa(netuid); - let difficulty: Compact = Self::get_difficulty_as_u64(netuid).into(); - let immunity_period = Self::get_immunity_period(netuid); - let max_allowed_validators = Self::get_max_allowed_validators(netuid); - let min_allowed_weights = Self::get_min_allowed_weights(netuid); - let max_weights_limit = Self::get_max_weight_limit(netuid); - let scaling_law_power = Self::get_scaling_law_power(netuid); - let subnetwork_n = Self::get_subnetwork_n(netuid); - let max_allowed_uids = Self::get_max_allowed_uids(netuid); - let blocks_since_last_step = Self::get_blocks_since_last_step(netuid); - let tempo = Self::get_tempo(netuid); - let network_modality = >::get(netuid); - let emission_values = Self::get_emission_value(netuid); - let burn: Compact = Self::get_burn_as_u64(netuid).into(); - let identity: Option = SubnetIdentitiesV2::::get(netuid); - - // DEPRECATED - let network_connect: Vec<[u16; 2]> = Vec::<[u16; 2]>::new(); - // DEPRECATED for ( _netuid_, con_req) in < NetworkConnect as IterableStorageDoubleMap >::iter_prefix(netuid) { - // network_connect.push([_netuid_, con_req]); - // } - - Some(SubnetInfov3 { - rho: rho.into(), - kappa: kappa.into(), - difficulty, - immunity_period: immunity_period.into(), - netuid: netuid.into(), - max_allowed_validators: max_allowed_validators.into(), - min_allowed_weights: min_allowed_weights.into(), - max_weights_limit: max_weights_limit.into(), - scaling_law_power: scaling_law_power.into(), - subnetwork_n: subnetwork_n.into(), - max_allowed_uids: max_allowed_uids.into(), - blocks_since_last_step: blocks_since_last_step.into(), - tempo: tempo.into(), - network_modality: network_modality.into(), - network_connect, - emission_values: emission_values.into(), - burn, - owner: Self::get_subnet_owner(netuid), - identity, - }) - } - - pub fn get_subnets_info_v3() -> Vec>> { - let mut subnet_netuids = Vec::::new(); - let mut max_netuid: u16 = 0; - for (netuid, added) in as IterableStorageMap>::iter() { - if added { - subnet_netuids.push(netuid); - if netuid > max_netuid { - max_netuid = netuid; - } - } - } - - let mut subnets_info = Vec::>>::new(); - for netuid_ in 0..=max_netuid { - if subnet_netuids.contains(&netuid_) { - subnets_info.push(Self::get_subnet_info_v3(netuid_)); - } - } - - subnets_info - } pub fn get_subnet_hyperparams(netuid: u16) -> Option { if !Self::if_subnet_exist(netuid) { return None; diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 85aa209938..d9c4fcd99d 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -2096,21 +2096,6 @@ impl_runtime_apis! { result.encode() } - fn get_subnet_info_v3(netuid: u16) -> Vec { - let _result = SubtensorModule::get_subnet_info_v3(netuid); - if _result.is_some() { - let result = _result.expect("Could not get SubnetInfo"); - result.encode() - } else { - vec![] - } - } - - fn get_subnets_info_v3() -> Vec { - let result = SubtensorModule::get_subnets_info_v3(); - result.encode() - } - fn get_subnet_hyperparams(netuid: u16) -> Vec { let _result = SubtensorModule::get_subnet_hyperparams(netuid); if _result.is_some() { From ea136bb6ddb1d43b622a44888d0bb774d1161391 Mon Sep 17 00:00:00 2001 From: JohnReedV <87283488+JohnReedV@users.noreply.github.com> Date: Mon, 3 Feb 2025 10:10:30 -0800 Subject: [PATCH 06/34] address lint --- pallets/subtensor/src/rpc_info/dynamic_info.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/subtensor/src/rpc_info/dynamic_info.rs b/pallets/subtensor/src/rpc_info/dynamic_info.rs index 554e79eef8..4046246be6 100644 --- a/pallets/subtensor/src/rpc_info/dynamic_info.rs +++ b/pallets/subtensor/src/rpc_info/dynamic_info.rs @@ -4,7 +4,7 @@ use codec::Compact; use frame_support::pallet_prelude::{Decode, Encode}; use subtensor_macros::freeze_struct; -#[freeze_struct("66f29110b41779af")] +#[freeze_struct("6f2a966922016f51")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug)] pub struct DynamicInfo { netuid: Compact, From 2d32d96b3b2157d4ce11f55068ab95824e4b52e8 Mon Sep 17 00:00:00 2001 From: JohnReedV <87283488+JohnReedV@users.noreply.github.com> Date: Mon, 3 Feb 2025 10:32:22 -0800 Subject: [PATCH 07/34] update register_network with identity precompile --- runtime/src/precompiles/subnet.rs | 181 ++++++++++++++++++++++++++++-- 1 file changed, 172 insertions(+), 9 deletions(-) diff --git a/runtime/src/precompiles/subnet.rs b/runtime/src/precompiles/subnet.rs index 9944572c51..d62a0efd04 100644 --- a/runtime/src/precompiles/subnet.rs +++ b/runtime/src/precompiles/subnet.rs @@ -5,8 +5,8 @@ use pallet_evm::{ AddressMapping, ExitError, HashedAddressMapping, PrecompileFailure, PrecompileHandle, PrecompileResult, }; -use sp_runtime::traits::BlakeTwo256; use sp_runtime::AccountId32; +use sp_runtime::{traits::BlakeTwo256, Vec}; use sp_std::vec; pub const SUBNET_PRECOMPILE_INDEX: u64 = 2051; // bytes with max lenght 1K @@ -62,14 +62,26 @@ impl SubnetPrecompile { ) } 33.. => { - let (hotkey, subnet_name, github_repo, subnet_contact) = - Self::parse_register_network_parameters(data)?; + let ( + hotkey, + subnet_name, + github_repo, + subnet_contact, + subnet_url, + discord, + description, + additional, + ) = Self::parse_register_network_parameters(data)?; - let identity: pallet_subtensor::SubnetIdentityOf = - pallet_subtensor::SubnetIdentityOf { + let identity: pallet_subtensor::SubnetIdentityOfV2 = + pallet_subtensor::SubnetIdentityOfV2 { subnet_name, github_repo, subnet_contact, + subnet_url, + discord, + description, + additional, }; // Create the register_network callcle @@ -98,12 +110,24 @@ impl SubnetPrecompile { fn parse_register_network_parameters( data: &[u8], - ) -> Result<(AccountId32, vec::Vec, vec::Vec, vec::Vec), PrecompileFailure> { + ) -> Result< + ( + AccountId32, + Vec, + Vec, + Vec, + Vec, + Vec, + Vec, + Vec, + ), + PrecompileFailure, + > { let (pubkey, dynamic_params) = get_pubkey(data)?; let dynamic_data_len = dynamic_params.len(); let mut buf = [0_u8; 4]; - // get all start point for three data items: name, repo and contact + // get all start points for the data items: name, repo, contact, url, discord, description, additional buf.copy_from_slice(get_slice(data, 60, 64)?); let subnet_name_start: usize = u32::from_be_bytes(buf) as usize; if subnet_name_start > dynamic_data_len { @@ -140,6 +164,54 @@ impl SubnetPrecompile { }); } + buf.copy_from_slice(get_slice(data, 156, 160)?); + let subnet_url_start: usize = u32::from_be_bytes(buf) as usize; + if subnet_url_start > dynamic_data_len { + log::error!( + "the start position of subnet_url as {} is too big ", + subnet_url_start + ); + return Err(PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + }); + } + + buf.copy_from_slice(get_slice(data, 188, 192)?); + let discord_start: usize = u32::from_be_bytes(buf) as usize; + if discord_start > dynamic_data_len { + log::error!( + "the start position of discord as {} is too big ", + discord_start + ); + return Err(PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + }); + } + + buf.copy_from_slice(get_slice(data, 220, 224)?); + let description_start: usize = u32::from_be_bytes(buf) as usize; + if description_start > dynamic_data_len { + log::error!( + "the start position of description as {} is too big ", + description_start + ); + return Err(PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + }); + } + + buf.copy_from_slice(get_slice(data, 252, 256)?); + let additional_start: usize = u32::from_be_bytes(buf) as usize; + if additional_start > dynamic_data_len { + log::error!( + "the start position of additional as {} is too big ", + additional_start + ); + return Err(PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + }); + } + // get name buf.copy_from_slice(get_slice( data, @@ -149,7 +221,10 @@ impl SubnetPrecompile { let subnet_name_len: usize = u32::from_be_bytes(buf) as usize; if subnet_name_len > MAX_SINGLE_PARAMETER_SIZE { - log::error!("the length of subnet nae as {} is too big", subnet_name_len); + log::error!( + "the length of subnet name as {} is too big", + subnet_name_len + ); return Err(PrecompileFailure::Error { exit_status: ExitError::InvalidRange, }); @@ -210,6 +285,94 @@ impl SubnetPrecompile { subnet_contact_start + subnet_contact_len + 32, )?); - Ok((pubkey, name_vec, repo_vec, contact_vec)) + // get subnet_url + buf.copy_from_slice(get_slice( + data, + subnet_url_start + 28, + subnet_url_start + 32, + )?); + let subnet_url_len: usize = u32::from_be_bytes(buf) as usize; + if subnet_url_len > MAX_SINGLE_PARAMETER_SIZE { + log::error!("the length of subnet_url as {} is too big", subnet_url_len); + return Err(PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + }); + } + let mut url_vec = vec![0; subnet_url_len]; + url_vec.copy_from_slice(get_slice( + data, + subnet_url_start + 32, + subnet_url_start + subnet_url_len + 32, + )?); + + // get discord + buf.copy_from_slice(get_slice(data, discord_start + 28, discord_start + 32)?); + let discord_len: usize = u32::from_be_bytes(buf) as usize; + if discord_len > MAX_SINGLE_PARAMETER_SIZE { + log::error!("the length of discord as {} is too big", discord_len); + return Err(PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + }); + } + let mut discord_vec = vec![0; discord_len]; + discord_vec.copy_from_slice(get_slice( + data, + discord_start + 32, + discord_start + discord_len + 32, + )?); + + // get description + buf.copy_from_slice(get_slice( + data, + description_start + 28, + description_start + 32, + )?); + let description_len: usize = u32::from_be_bytes(buf) as usize; + if description_len > MAX_SINGLE_PARAMETER_SIZE { + log::error!( + "the length of description as {} is too big", + description_len + ); + return Err(PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + }); + } + let mut description_vec = vec![0; description_len]; + description_vec.copy_from_slice(get_slice( + data, + description_start + 32, + description_start + description_len + 32, + )?); + + // get additional + buf.copy_from_slice(get_slice( + data, + additional_start + 28, + additional_start + 32, + )?); + let additional_len: usize = u32::from_be_bytes(buf) as usize; + if additional_len > MAX_SINGLE_PARAMETER_SIZE { + log::error!("the length of additional as {} is too big", additional_len); + return Err(PrecompileFailure::Error { + exit_status: ExitError::InvalidRange, + }); + } + let mut additional_vec = vec![0; additional_len]; + additional_vec.copy_from_slice(get_slice( + data, + additional_start + 32, + additional_start + additional_len + 32, + )?); + + Ok(( + pubkey, + name_vec, + repo_vec, + contact_vec, + url_vec, + discord_vec, + description_vec, + additional_vec, + )) } } From 913fb1a4bac8ba8c6ae5f3130bde568c6477576e Mon Sep 17 00:00:00 2001 From: JohnReedV <87283488+JohnReedV@users.noreply.github.com> Date: Mon, 3 Feb 2025 12:00:21 -0800 Subject: [PATCH 08/34] remove SubnetInfov3 struct --- pallets/subtensor/src/rpc_info/subnet_info.rs | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/pallets/subtensor/src/rpc_info/subnet_info.rs b/pallets/subtensor/src/rpc_info/subnet_info.rs index 65851d36cf..ce59a4406b 100644 --- a/pallets/subtensor/src/rpc_info/subnet_info.rs +++ b/pallets/subtensor/src/rpc_info/subnet_info.rs @@ -51,30 +51,6 @@ pub struct SubnetInfov2 { identity: Option, } -#[freeze_struct("dd91200554b75bc4")] -#[derive(Decode, Encode, PartialEq, Eq, Clone, Debug)] -pub struct SubnetInfov3 { - netuid: Compact, - rho: Compact, - kappa: Compact, - difficulty: Compact, - immunity_period: Compact, - max_allowed_validators: Compact, - min_allowed_weights: Compact, - max_weights_limit: Compact, - scaling_law_power: Compact, - subnetwork_n: Compact, - max_allowed_uids: Compact, - blocks_since_last_step: Compact, - tempo: Compact, - network_modality: Compact, - network_connect: Vec<[u16; 2]>, - emission_values: Compact, - burn: Compact, - owner: T::AccountId, - identity: Option, -} - #[freeze_struct("a2dd2fcd6f4d4ff8")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug)] pub struct SubnetHyperparams { From 69d2b778e5185d9e99de429b142ecc3c72addcd0 Mon Sep 17 00:00:00 2001 From: JohnReedV <87283488+JohnReedV@users.noreply.github.com> Date: Mon, 3 Feb 2025 12:04:38 -0800 Subject: [PATCH 09/34] rename emission_values => emission_value --- pallets/subtensor/src/rpc_info/subnet_info.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pallets/subtensor/src/rpc_info/subnet_info.rs b/pallets/subtensor/src/rpc_info/subnet_info.rs index ce59a4406b..a72da1c0c6 100644 --- a/pallets/subtensor/src/rpc_info/subnet_info.rs +++ b/pallets/subtensor/src/rpc_info/subnet_info.rs @@ -27,7 +27,7 @@ pub struct SubnetInfo { owner: T::AccountId, } -#[freeze_struct("c46dc4e2d4d9f8a3")] +#[freeze_struct("da372105ad6aacb0")] #[derive(Decode, Encode, PartialEq, Eq, Clone, Debug)] pub struct SubnetInfov2 { netuid: Compact, @@ -45,7 +45,7 @@ pub struct SubnetInfov2 { tempo: Compact, network_modality: Compact, network_connect: Vec<[u16; 2]>, - emission_values: Compact, + emission_value: Compact, burn: Compact, owner: T::AccountId, identity: Option, @@ -172,7 +172,7 @@ impl Pallet { let blocks_since_last_step = Self::get_blocks_since_last_step(netuid); let tempo = Self::get_tempo(netuid); let network_modality = >::get(netuid); - let emission_values = Self::get_emission_value(netuid); + let emission_value = Self::get_emission_value(netuid); let burn: Compact = Self::get_burn_as_u64(netuid).into(); let identity: Option = SubnetIdentitiesV2::::get(netuid); @@ -198,7 +198,7 @@ impl Pallet { tempo: tempo.into(), network_modality: network_modality.into(), network_connect, - emission_values: emission_values.into(), + emission_value: emission_value.into(), burn, owner: Self::get_subnet_owner(netuid), identity, From 6766f1d4500113d898a27678870314332a3144ac Mon Sep 17 00:00:00 2001 From: JohnReedV <87283488+JohnReedV@users.noreply.github.com> Date: Mon, 3 Feb 2025 12:34:21 -0800 Subject: [PATCH 10/34] 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 63a03c1ad8..b3f617edd4 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -220,7 +220,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: 225, + spec_version: 226, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From 0213918c3716f9f99d1ee8bf30ff9334e6bec5d1 Mon Sep 17 00:00:00 2001 From: JohnReedV <87283488+JohnReedV@users.noreply.github.com> Date: Tue, 4 Feb 2025 12:06:08 -0800 Subject: [PATCH 11/34] use saturating math --- pallets/subtensor/src/utils/identity.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/pallets/subtensor/src/utils/identity.rs b/pallets/subtensor/src/utils/identity.rs index b721664f0f..0e83205cc0 100644 --- a/pallets/subtensor/src/utils/identity.rs +++ b/pallets/subtensor/src/utils/identity.rs @@ -167,7 +167,15 @@ impl Pallet { .saturating_add(identity.description.len()) .saturating_add(identity.additional.len()); - total_length <= 256 + 256 + 256 + 1024 + 256 + 1024 + 1024 + let max_length: usize = 256_usize + .saturating_add(256) + .saturating_add(256) + .saturating_add(1024) + .saturating_add(256) + .saturating_add(1024) + .saturating_add(1024); + + total_length <= max_length && identity.name.len() <= 256 && identity.url.len() <= 256 && identity.github_repo.len() <= 256 @@ -197,7 +205,15 @@ impl Pallet { .saturating_add(identity.github_repo.len()) .saturating_add(identity.subnet_contact.len()); - total_length <= 256 + 1024 + 1024 + 1024 + 256 + 1024 + 1024 + let max_length: usize = 256_usize + .saturating_add(1024) + .saturating_add(1024) + .saturating_add(1024) + .saturating_add(256) + .saturating_add(1024) + .saturating_add(1024); + + total_length <= max_length && identity.subnet_name.len() <= 256 && identity.github_repo.len() <= 1024 && identity.subnet_contact.len() <= 1024 From d479346b9a441c5eb653a2f8c479deedf2401e1e Mon Sep 17 00:00:00 2001 From: unconst Date: Tue, 4 Feb 2025 17:48:51 -0500 Subject: [PATCH 12/34] add cleaned coinbase --- .../subtensor/src/coinbase/block_emission.rs | 4 + pallets/subtensor/src/coinbase/block_step.rs | 7 +- .../subtensor/src/coinbase/run_coinbase.rs | 767 ++++++------------ pallets/subtensor/src/lib.rs | 4 +- pallets/subtensor/src/staking/helpers.rs | 5 + pallets/subtensor/src/tests/children.rs | 3 +- pallets/subtensor/src/tests/coinbase.rs | 526 ------------ 7 files changed, 273 insertions(+), 1043 deletions(-) diff --git a/pallets/subtensor/src/coinbase/block_emission.rs b/pallets/subtensor/src/coinbase/block_emission.rs index 6d2c57b742..3c3288c93b 100644 --- a/pallets/subtensor/src/coinbase/block_emission.rs +++ b/pallets/subtensor/src/coinbase/block_emission.rs @@ -30,6 +30,10 @@ impl Pallet { tao_emission: u64, alpha_block_emission: u64, ) -> (u64, u64, u64) { + + // Get the total_alpha_emission for the block + let alpha_block_emission: u64 = Self::get_block_emission_for_issuance(Self::get_alpha_issuance(netuid)).unwrap_or(0); + // Init terms. let mut tao_in_emission: I96F32 = I96F32::saturating_from_num(tao_emission); let float_alpha_block_emission: I96F32 = I96F32::saturating_from_num(alpha_block_emission); diff --git a/pallets/subtensor/src/coinbase/block_step.rs b/pallets/subtensor/src/coinbase/block_step.rs index bcfd1a37bc..5978892ecf 100644 --- a/pallets/subtensor/src/coinbase/block_step.rs +++ b/pallets/subtensor/src/coinbase/block_step.rs @@ -14,9 +14,10 @@ impl Pallet { let block_emission: I96F32 = I96F32::saturating_from_num(Self::get_block_emission().unwrap_or(0)); log::debug!("Block emission: {:?}", block_emission); - // --- 3. Run emission through network. - Self::run_coinbase(block_emission); - + // // --- 3. Run emission through network. + if !PauseCoinbase::::get() { + Self::run_coinbase(block_emission); + } // --- 4. Set pending children on the epoch; but only after the coinbase has been run. Self::try_set_pending_children(block_number); diff --git a/pallets/subtensor/src/coinbase/run_coinbase.rs b/pallets/subtensor/src/coinbase/run_coinbase.rs index b57a085034..a15ab587e6 100644 --- a/pallets/subtensor/src/coinbase/run_coinbase.rs +++ b/pallets/subtensor/src/coinbase/run_coinbase.rs @@ -18,6 +18,19 @@ pub struct WeightsTlockPayload { pub version_key: u64, } +// Distribute dividends to each hotkey +macro_rules! asfloat { + ($val:expr) => { + I96F32::saturating_from_num($val) + }; +} + +macro_rules! tou64 { + ($val:expr) => { + $val.saturating_to_num::() + }; +} + impl Pallet { pub fn get_root_divs_in_alpha( netuid: u16, @@ -25,16 +38,15 @@ impl Pallet { validator_proportion: I96F32, ) -> I96F32 { // Get total TAO on root. - let total_root_tao: I96F32 = I96F32::saturating_from_num(SubnetTAO::::get(0)); + let total_root_tao: I96F32 = asfloat!( SubnetTAO::::get(0) ); // Get total ALPHA on subnet. - let total_alpha_issuance: I96F32 = - I96F32::saturating_from_num(Self::get_alpha_issuance(netuid)); + let total_alpha_issuance: I96F32 = asfloat!( Self::get_alpha_issuance(netuid)) ; // Get tao_weight let tao_weight: I96F32 = total_root_tao.saturating_mul(Self::get_tao_weight()); // Get root proportional dividends. let root_proportion: I96F32 = tao_weight .checked_div(tao_weight.saturating_add(total_alpha_issuance)) - .unwrap_or(I96F32::saturating_from_num(0.0)); + .unwrap_or(asfloat!(0.0)); // Get root proportion of alpha_out dividends. let root_divs_in_alpha: I96F32 = root_proportion .saturating_mul(alpha_out_emission) @@ -45,229 +57,145 @@ impl Pallet { } pub fn run_coinbase(block_emission: I96F32) { + // --- 0. Get current block. let current_block: u64 = Self::get_current_block_as_u64(); log::debug!("Current block: {:?}", current_block); - // --- 1. Get all netuids. - let subnets: Vec = Self::get_all_subnet_netuids(); + // --- 1. Get all netuids (not root.) + let subnets: Vec = Self::get_all_subnet_netuids().into_iter().filter(|netuid| *netuid != 0).collect(); log::debug!("All subnet netuids: {:?}", subnets); - // --- 2. Sum all the SubnetTAO associated with the same mechanism. - // Mechanisms get emission based on the proportion of TAO across all their subnets - let mut total_active_tao: I96F32 = I96F32::saturating_from_num(0); - let mut mechanism_tao: BTreeMap = BTreeMap::new(); - for netuid in subnets.iter() { - if *netuid == 0 { - continue; - } // Skip root network - let mechid = SubnetMechanism::::get(*netuid); - let subnet_tao = I96F32::saturating_from_num(SubnetTAO::::get(*netuid)); - let new_subnet_tao = subnet_tao.saturating_add( - *mechanism_tao - .entry(mechid) - .or_insert(I96F32::saturating_from_num(0)), - ); - *mechanism_tao - .entry(mechid) - .or_insert(I96F32::saturating_from_num(0)) = new_subnet_tao; - total_active_tao = total_active_tao.saturating_add(subnet_tao); + // --- 2. Get sum of tao reserves. + let mut tao_sum: I96F32 = I96F32::from_num(0.0); + for netuid_i in subnets.iter() { + // Get and add subnet TAO in reserve. + tao_sum = tao_sum.saturating_add( asfloat!( SubnetTAO::::get(netuid_i)) ); } - log::debug!("Mechanism TAO sums: {:?}", mechanism_tao); - - // --- 3. Compute subnet emission values (amount of tao inflation this block). - let mut tao_in_map: BTreeMap = BTreeMap::new(); - for netuid in subnets.iter() { - // Do not emit into root network. - if *netuid == 0 { - continue; - } - // 3.1: Get subnet mechanism ID - let mechid: u16 = SubnetMechanism::::get(*netuid); - log::debug!("Netuid: {:?}, Mechanism ID: {:?}", netuid, mechid); - // 3.2: Get subnet TAO (T_s) - let subnet_tao: I96F32 = I96F32::saturating_from_num(SubnetTAO::::get(*netuid)); - log::debug!("Subnet TAO (T_s) for netuid {:?}: {:?}", netuid, subnet_tao); - // 3.3: Get the denominator as the sum of all TAO associated with a specific mechanism (T_m) - let mech_tao: I96F32 = *mechanism_tao - .get(&mechid) - .unwrap_or(&I96F32::saturating_from_num(0)); - log::debug!( - "Mechanism TAO (T_m) for mechanism ID {:?}: {:?}", - mechid, - mech_tao - ); - // 3.4: Compute the mechanism emission proportion: P_m = T_m / T_total - let mech_proportion: I96F32 = mech_tao - .checked_div(total_active_tao) - .unwrap_or(I96F32::saturating_from_num(0)); - log::debug!( - "Mechanism proportion (P_m) for mechanism ID {:?}: {:?}", - mechid, - mech_proportion - ); - // 3.5: Compute the mechanism emission: E_m = P_m * E_b - let mech_emission: I96F32 = mech_proportion.saturating_mul(block_emission); - log::debug!( - "Mechanism emission (E_m) for mechanism ID {:?}: {:?}", - mechid, - mech_emission - ); - // 3.6: Calculate subnet's proportion of mechanism TAO: P_s = T_s / T_m - let subnet_proportion: I96F32 = subnet_tao - .checked_div(mech_tao) - .unwrap_or(I96F32::saturating_from_num(0)); - log::debug!( - "Subnet proportion (P_s) for netuid {:?}: {:?}", - netuid, - subnet_proportion - ); - - // Only emit TAO if the subnetwork allows registration. - if Self::get_network_registration_allowed(*netuid) - || Self::get_network_pow_registration_allowed(*netuid) - { - // 3.7: Calculate subnet's TAO emission: E_s = P_s * E_m - let tao_in: u64 = mech_emission - .checked_mul(subnet_proportion) - .unwrap_or(I96F32::saturating_from_num(0)) - .saturating_to_num::(); - log::debug!( - "Subnet TAO emission (E_s) for netuid {:?}: {:?}", - netuid, - tao_in - ); - // 3.8: Store the subnet TAO emission. - *tao_in_map.entry(*netuid).or_insert(0) = tao_in; - // 3.9: Store the block emission for this subnet for chain storage. - EmissionValues::::insert(*netuid, tao_in); + log::debug!("tao_sum: {:?}", tao_sum); + + // --- 3. Get subnet terms (tao_in, alpha_in, and alpha_out) + let mut tao_in: BTreeMap = BTreeMap::new(); + let mut alpha_in: BTreeMap = BTreeMap::new(); + let mut alpha_out: BTreeMap = BTreeMap::new(); + for netuid_i in subnets.iter() { + // Get subnet price. + let price_i: I96F32 = Self::get_alpha_price(*netuid_i); + log::debug!("price_i: {:?}", price_i); + // Get subnet TAO. + let subnet_tao_i: I96F32 = asfloat!( SubnetTAO::::get(netuid_i) ); + log::debug!("subnet_tao_i: {:?}", subnet_tao_i); + // Emission is price over total. + let mut tao_in_i: I96F32 = block_emission.saturating_mul(subnet_tao_i).checked_div(tao_sum).unwrap_or(asfloat!(0.0)); + log::debug!("tao_in_i: {:?}", tao_in_i); + // Get alpha_emission total + let alpha_emission_i: I96F32 = asfloat!(Self::get_block_emission_for_issuance(Self::get_alpha_issuance(*netuid_i)).unwrap_or(0)); + log::debug!("alpha_emission_i: {:?}", alpha_emission_i); + // Get initial alpha_in + let mut alpha_in_i: I96F32 = tao_in_i.checked_div(price_i).unwrap_or(alpha_emission_i); + log::debug!("alpha_in_i: {:?}", alpha_in_i); + // Check if we are emitting too much alpha_in + if alpha_in_i >= alpha_emission_i { + // Scale down tao_in + tao_in_i = price_i.saturating_mul(alpha_emission_i); + log::debug!("change tao_in_i: {:?}", tao_in_i); + // Set to max alpha_block_emission + alpha_in_i = alpha_emission_i; + log::debug!("change alpha_in_i: {:?}", alpha_in_i); } + // Get alpha_out. + let alpha_out_i = alpha_emission_i; + // Insert values into maps + tao_in.insert(*netuid_i, tao_in_i); + alpha_in.insert(*netuid_i, alpha_in_i); + alpha_out.insert(*netuid_i, alpha_out_i); } - - // == We'll save the owner cuts for each subnet. - let mut owner_cuts: BTreeMap = BTreeMap::new(); - - // --- 4. Distribute subnet emission into subnets based on mechanism type. - for netuid in subnets.iter() { - // Do not emit into root network. - if *netuid == 0 { - continue; - } - // 4.1. Get subnet mechanism ID - let mechid: u16 = SubnetMechanism::::get(*netuid); - log::debug!("{:?} - mechid: {:?}", netuid, mechid); - // 4.2: Get the subnet emission TAO. - let subnet_emission: u64 = *tao_in_map.get(netuid).unwrap_or(&0); - log::debug!("{:?} subnet_emission: {:?}", netuid, subnet_emission); - if mechid == 0 { - // The mechanism is Stable (FOR TESTING PURPOSES ONLY) - // 4.2.1 Increase Tao in the subnet "reserves" unconditionally. - SubnetTAO::::mutate(*netuid, |total| { - *total = total.saturating_add(subnet_emission) - }); - // 4.2.2 Increase total stake across all subnets. - TotalStake::::mutate(|total| *total = total.saturating_add(subnet_emission)); - // 4.2.3 Increase total issuance of Tao. - TotalIssuance::::mutate(|total| *total = total.saturating_add(subnet_emission)); - // 4.2.4 Increase this subnet pending emission. - PendingEmission::::mutate(*netuid, |total| { - *total = total.saturating_add(subnet_emission) - }); - // 4.2.5 Go to next subnet. - continue; - } - // Get the total_alpha_emission for the block - let alpha_block_emission: u64 = - Self::get_block_emission_for_issuance(Self::get_alpha_issuance(*netuid)) - .unwrap_or(0); - - // Compute emission into pool. - let (tao_in_emission, alpha_in_emission, alpha_out_emission): (u64, u64, u64) = - Self::get_dynamic_tao_emission(*netuid, subnet_emission, alpha_block_emission); - - // Set state vars. - SubnetTaoInEmission::::insert(*netuid, tao_in_emission); - SubnetAlphaInEmission::::insert(*netuid, alpha_in_emission); - SubnetAlphaOutEmission::::insert(*netuid, alpha_out_emission); - - // Increase counters. - SubnetAlphaIn::::mutate(*netuid, |total| { - *total = total.saturating_add(alpha_in_emission); - log::debug!("Injected alpha_in into SubnetAlphaIn: {:?}", *total); + log::debug!("tao_in: {:?}", tao_in); + log::debug!("alpha_in: {:?}", alpha_in); + log::debug!("alpha_out: {:?}", alpha_out); + + // --- 4. Injection. + for netuid_i in subnets.iter() { + // Inject Alpha in. + let alpha_in_i: u64 = tou64!( *alpha_in.get(netuid_i).unwrap_or(&asfloat!(0)) ); + SubnetAlphaInEmission::::insert( *netuid_i, alpha_in_i ); + SubnetAlphaIn::::mutate( *netuid_i, |total| { + *total = total.saturating_add(alpha_in_i); }); - SubnetAlphaOut::::mutate(*netuid, |total| { - *total = total.saturating_add(alpha_out_emission); - log::debug!("Injected alpha_in into SubnetAlphaIn: {:?}", *total); + // Injection Alpha out. + let alpha_out_i: u64 = tou64!( *alpha_out.get(netuid_i).unwrap_or(&asfloat!(0)) ); + SubnetAlphaOutEmission::::insert( *netuid_i, alpha_out_i ); + SubnetAlphaOut::::mutate( *netuid_i, |total| { + *total = total.saturating_add( alpha_out_i ); }); - SubnetTAO::::mutate(*netuid, |total| { - *total = total.saturating_add(tao_in_emission); - log::debug!("Increased Tao in SubnetTAO: {:?}", *total); + // Inject TAO in. + let tao_in_i: u64 = tou64!( *tao_in.get(netuid_i).unwrap_or(&asfloat!(0)) ); + SubnetTaoInEmission::::insert( *netuid_i, tao_in_i ); + SubnetTAO::::mutate( *netuid_i, |total| { + *total = total.saturating_add( tao_in_i ); }); TotalStake::::mutate(|total| { - *total = total.saturating_add(tao_in_emission); - log::debug!("Increased TotalStake: {:?}", *total); + *total = total.saturating_add( tao_in_i ); }); TotalIssuance::::mutate(|total| { - *total = total.saturating_add(tao_in_emission); - log::debug!("Increased TotalIssuance: {:?}", *total); + *total = total.saturating_add( tao_in_i ); }); + } + // --- 5. Compute owner cuts and remove them from alpha_out remaining. + let cut_percent: I96F32 = Self::get_float_subnet_owner_cut(); + let mut owner_cuts: BTreeMap = BTreeMap::new(); + for netuid_i in subnets.iter() { + // Get alpha out. + let alpha_out_i: I96F32 = *alpha_out.get( netuid_i ).unwrap_or(&asfloat!(0)); // Calculate the owner cut. - let owner_cut: u64 = I96F32::saturating_from_num(alpha_out_emission) - .saturating_mul(Self::get_float_subnet_owner_cut()) - .saturating_to_num::(); - log::debug!("Owner cut for netuid {:?}: {:?}", netuid, owner_cut); - // Store the owner cut for this subnet. - *owner_cuts.entry(*netuid).or_insert(0) = owner_cut; - - let remaining_emission: u64 = alpha_out_emission.saturating_sub(owner_cut); - log::debug!( - "Remaining emission for netuid {:?}: {:?}", - netuid, - remaining_emission - ); + let owner_cut_i: I96F32 = alpha_out_i.saturating_mul( cut_percent ); + // Save owner cut. + *owner_cuts.entry( *netuid_i ).or_insert( asfloat!(0) ) = owner_cut_i; + // Save new alpha_out. + alpha_out.insert( *netuid_i, alpha_out_i.saturating_sub( owner_cut_i ) ); + // Accumulate the owner cut in pending. + PendingOwnerCut::::mutate(*netuid_i, |total| { + *total = total.saturating_add( tou64!( owner_cut_i ) ); + }); + } + // --- 6. Accumulate pending emission for root and alpha. + for netuid_i in subnets.iter() { + // Get remaining alpha out. + let alpha_out_i: I96F32 = *alpha_out.get( netuid_i ).unwrap_or(&asfloat!(0.0)); // Validators get 50% of remaining emission. - let validator_proportion: I96F32 = I96F32::saturating_from_num(0.5); + let val_prop: I96F32 = asfloat!(0.5); // Get proportion of alpha out emission as root divs. - let root_emission_in_alpha: I96F32 = Self::get_root_divs_in_alpha( - *netuid, - I96F32::saturating_from_num(remaining_emission), - validator_proportion, + let root_alpha: I96F32 = Self::get_root_divs_in_alpha( + *netuid_i, + alpha_out_i, + val_prop, ); - // Subtract root divs from alpha divs. - let pending_alpha_emission: I96F32 = I96F32::saturating_from_num(remaining_emission) - .saturating_sub(root_emission_in_alpha); + // Save pending alpha after root alpha removal. + let pending_alpha: I96F32 = alpha_out_i.saturating_sub( root_alpha ); // Sell root emission through the pool. - let root_emission_in_tao: u64 = Self::swap_alpha_for_tao( - *netuid, - root_emission_in_alpha.saturating_to_num::(), - ); - SubnetAlphaEmissionSell::::insert( - *netuid, - root_emission_in_alpha.saturating_to_num::(), + let root_tao: u64 = Self::swap_alpha_for_tao( + *netuid_i, + tou64!( root_alpha ), ); - // Accumulate root divs for subnet. - PendingRootDivs::::mutate(*netuid, |total| { - *total = total.saturating_add(root_emission_in_tao); - }); - // Accumulate alpha that was swapped for the pending root divs. - PendingAlphaSwapped::::mutate(*netuid, |total| { - *total = total.saturating_add(root_emission_in_alpha.saturating_to_num::()); + // Accumulate alpha emission in pending. + PendingAlphaSwapped::::mutate( *netuid_i, |total| { + *total = total.saturating_add( tou64!( root_alpha ) ); }); // Accumulate alpha emission in pending. - PendingEmission::::mutate(*netuid, |total| { - *total = total.saturating_add(pending_alpha_emission.saturating_to_num::()); + PendingEmission::::mutate( *netuid_i, |total| { + *total = total.saturating_add( tou64!( pending_alpha ) ); }); - // Accumulate the owner cut in pending. - PendingOwnerCut::::mutate(*netuid, |total| { - *total = total.saturating_add(owner_cut); + // Accumulate root divs for subnet. + PendingRootDivs::::mutate( *netuid_i, |total| { + *total = total.saturating_add(root_tao); }); } - // --- 5. Drain pending emission through the subnet based on tempo. + // --- 7. Drain pending emission through the subnet based on tempo. for &netuid in subnets.iter() { - // 5.1: Pass on subnets that have not reached their tempo. + // Pass on subnets that have not reached their tempo. if Self::should_run_epoch(netuid, current_block) { if let Err(e) = Self::reveal_crv3_commits(netuid) { log::warn!( @@ -281,28 +209,28 @@ impl Pallet { BlocksSinceLastStep::::insert(netuid, 0); LastMechansimStepBlock::::insert(netuid, current_block); - // 5.2.1 Get and drain the subnet pending emission. - let pending_emission: u64 = PendingEmission::::get(netuid); + // Get and drain the subnet pending emission. + let pending_alpha: u64 = PendingEmission::::get(netuid); PendingEmission::::insert(netuid, 0); - // 5.2.2a Get and drain the subnet pending root divs. - let pending_root_divs: u64 = PendingRootDivs::::get(netuid); + // Get and drain the subnet pending root divs. + let pending_tao: u64 = PendingRootDivs::::get(netuid); PendingRootDivs::::insert(netuid, 0); - // 5.2.2b Get this amount as alpha that was swapped for pending root divs. - let pending_alpha_swapped: u64 = PendingAlphaSwapped::::get(netuid); + // Get this amount as alpha that was swapped for pending root divs. + let pending_swapped: u64 = PendingAlphaSwapped::::get(netuid); PendingAlphaSwapped::::insert(netuid, 0); - // 5.2.3 Get owner cut and drain. + // Get owner cut and drain. let owner_cut: u64 = PendingOwnerCut::::get(netuid); PendingOwnerCut::::insert(netuid, 0); - // 5.2.4 Drain pending root divs, alpha emission, and owner cut. + // Drain pending root divs, alpha emission, and owner cut. Self::drain_pending_emission( netuid, - pending_emission, - pending_root_divs, - pending_alpha_swapped, + pending_alpha, + pending_tao, + pending_swapped, owner_cut, ); } else { @@ -314,360 +242,175 @@ impl Pallet { pub fn drain_pending_emission( netuid: u16, - pending_alpha_emission: u64, - pending_root_divs: u64, - pending_alpha_swapped: u64, + pending_alpha: u64, + pending_tao: u64, + pending_swapped: u64, owner_cut: u64, ) { log::debug!( - "Draining pending alpha emission for netuid {:?}: {:?}, with pending root divs {:?}, pending alpha swapped {:?}, and owner cut {:?}", + "Draining pending alpha emission for netuid {:?}, pending_alpha: {:?}, pending_tao: {:?}, pending_swapped: {:?}, owner_cut: {:?}", netuid, - pending_alpha_emission, - pending_root_divs, - pending_alpha_swapped, + pending_alpha, + pending_tao, + pending_swapped, owner_cut ); + // Setup. + let zero: I96F32 = asfloat!(0.0); - // === 1. Run the epoch() --> hotkey emission. - // Needs to run on the full emission to the subnet. + // Run the epoch. let hotkey_emission: Vec<(T::AccountId, u64, u64)> = Self::epoch( netuid, - pending_alpha_emission.saturating_add(pending_alpha_swapped), - ); - log::debug!( - "Hotkey emission for netuid {:?}: {:?}", - netuid, - hotkey_emission + pending_alpha.saturating_add(pending_swapped), ); - // === 2. Calculate the dividend distributions using the current stake. - // Clear maps - let _ = AlphaDividendsPerSubnet::::clear_prefix(netuid, u32::MAX, None); - let _ = TaoDividendsPerSubnet::::clear_prefix(netuid, u32::MAX, None); - - // Initialize maps for parent-child OR miner dividend distributions. - let mut dividends_to_distribute: Vec<(T::AccountId, Vec<(T::AccountId, u64)>)> = Vec::new(); - let mut mining_incentive_to_distribute: Vec<(T::AccountId, u64)> = Vec::new(); - - // 2.1 --- Get dividend distribution from parent-child and miner distributions. - for (hotkey, incentive, dividends) in hotkey_emission { - log::debug!( - "Processing hotkey {:?} with incentive {:?} and dividends {:?}", - hotkey, - incentive, + // Accumulate emission. + let mut incentives: BTreeMap = BTreeMap::new(); + let mut dividends: BTreeMap = BTreeMap::new(); + for (hotkey, incentive, dividend) in hotkey_emission { + // Accumulate incentives to miners. + incentives + .entry(hotkey.clone()) + .and_modify(|e| *e = e.saturating_add(incentive)) + .or_insert(incentive); + // Accumulate dividends to parents. + let div_tuples: Vec<(T::AccountId, u64)> = Self::get_dividends_distribution(&hotkey, netuid, dividend); + // Accumulate dividends per hotkey. + for (parent, parent_div) in div_tuples { dividends - ); - - // Record mining incentive - mining_incentive_to_distribute.push((hotkey.clone(), incentive)); + .entry(parent) + .and_modify(|e| *e = e.saturating_add( asfloat!(parent_div) ) ) + .or_insert( asfloat!(parent_div) ); + } + } - // Get dividend tuples for parents and self based on childkey relationships and child-take. - let dividend_tuples: Vec<(T::AccountId, u64)> = - Self::get_dividends_distribution(&hotkey, netuid, dividends); - log::debug!( - "Dividend tuples for hotkey {:?} on netuid {:?}: {:?}", - hotkey, - netuid, - dividend_tuples + // Accumulate root divs and alpha_divs + let mut total_root_divs: I96F32 = asfloat!( 0 ); + let mut root_dividends: BTreeMap = BTreeMap::new(); + let mut alpha_dividends: BTreeMap = BTreeMap::new(); + for (hotkey, dividend) in dividends { + // Get hotkey ALPHA on subnet. + let local_alpha = asfloat!( + Self::get_stake_for_hotkey_on_subnet( &hotkey, netuid) ); - - // Record dividends to distribute - dividends_to_distribute.push((hotkey.clone(), dividend_tuples)); + // Get hotkey TAO on root. + let root_tao: I96F32 = asfloat!( + Self::get_stake_for_hotkey_on_subnet( &hotkey, Self::get_root_netuid()) + ); + // Convert TAO to alpha with weight. + let root_alpha: I96F32 = root_tao.saturating_mul(Self::get_tao_weight()); + // Get total from root and local + let total_alpha: I96F32 = local_alpha.saturating_add( root_alpha ); + // Compute alpha prop. + let alpha_prop: I96F32 = local_alpha.checked_div(total_alpha).unwrap_or(zero); + // Copmute root prop. + let root_prop: I96F32 = root_alpha.checked_div(total_alpha).unwrap_or(zero); + // Compute alpha dividends + let alpha_divs: I96F32 = dividend.saturating_mul( alpha_prop ); + // Compute root dividends + let root_divs: I96F32 = dividend.saturating_mul( root_prop ); + // Record the root dividends. + alpha_dividends + .entry(hotkey.clone()) + .and_modify(|e| *e = e.saturating_add(alpha_divs)) + .or_insert(alpha_divs); + // Record the alpha_dividends. + root_dividends + .entry(hotkey.clone()) + .and_modify(|e| *e = e.saturating_add(root_divs)) + .or_insert(root_divs); + // Accumulate total root divs. + total_root_divs = total_root_divs.saturating_add( root_divs ); } - // Initialize maps for dividend calculations. - let mut root_alpha_divs: BTreeMap = BTreeMap::new(); - let mut alpha_divs: BTreeMap = BTreeMap::new(); - let mut validator_alpha_takes: BTreeMap = BTreeMap::new(); - let mut validator_root_alpha_takes: BTreeMap = BTreeMap::new(); - // 2.2 --- Calculate the validator_take, alpha_divs, and root_alpha_divs using above dividend tuples. - for (hotkey, dividend_tuples) in dividends_to_distribute.iter() { - // Calculate the proportion of root vs alpha divs for each hotkey using their stake. - for (hotkey_j, divs_j) in dividend_tuples.iter() { - log::debug!( - "Processing dividend for child-hotkey {:?} to parent-hotkey {:?}: {:?}", - hotkey, - hotkey_j, - *divs_j - ); - - // 2.1 --- Get the local alpha and root alpha. - let hotkey_tao: I96F32 = I96F32::saturating_from_num( - Self::get_stake_for_hotkey_on_subnet(hotkey_j, Self::get_root_netuid()), - ); - let hotkey_tao_as_alpha: I96F32 = hotkey_tao.saturating_mul(Self::get_tao_weight()); - let hotkey_alpha = I96F32::saturating_from_num( - Self::get_stake_for_hotkey_on_subnet(hotkey_j, netuid), - ); - log::debug!("Hotkey tao for hotkey {:?} on root netuid: {:?}, hotkey tao as alpha: {:?}, hotkey alpha: {:?}", hotkey_j, hotkey_tao, hotkey_tao_as_alpha, hotkey_alpha); - - // 2.2 --- Compute alpha and root proportions. - let alpha_prop: I96F32 = hotkey_alpha - .checked_div(hotkey_alpha.saturating_add(hotkey_tao_as_alpha)) - .unwrap_or(I96F32::saturating_from_num(0.0)); - let root_prop: I96F32 = hotkey_tao_as_alpha - .checked_div(hotkey_alpha.saturating_add(hotkey_tao_as_alpha)) - .unwrap_or(I96F32::saturating_from_num(0.0)); - log::debug!( - "Alpha proportion: {:?}, root proportion: {:?}", - alpha_prop, - root_prop - ); - - let divs_j: I96F32 = I96F32::saturating_from_num(*divs_j); - // 2.3.1 --- Compute root dividends - let root_alpha_divs_j: I96F32 = divs_j.saturating_mul(root_prop); - // 2.3.2 --- Compute alpha dividends - let alpha_divs_j: I96F32 = divs_j.saturating_sub(root_alpha_divs_j); - log::debug!( - "Alpha dividends: {:?}, Root alpha-dividends: {:?}", - alpha_divs_j, - root_alpha_divs_j - ); - - // 2.4.1 --- Remove the hotkey take from both alpha and root divs. - let take_prop: I96F32 = - I96F32::saturating_from_num(Self::get_hotkey_take(hotkey_j)) - .checked_div(I96F32::saturating_from_num(u16::MAX)) - .unwrap_or(I96F32::saturating_from_num(0.0)); - - let validator_alpha_take: I96F32 = take_prop.saturating_mul(alpha_divs_j); - let validator_root_alpha_take: I96F32 = take_prop.saturating_mul(root_alpha_divs_j); - - let rem_alpha_divs_j: I96F32 = alpha_divs_j.saturating_sub(validator_alpha_take); - let rem_root_alpha_divs_j: I96F32 = - root_alpha_divs_j.saturating_sub(validator_root_alpha_take); - log::debug!( - "Validator take for hotkey {:?}: alpha take: {:?}, remaining alpha: {:?}, root-alpha take: {:?}, remaining root-alpha: {:?}", - hotkey_j, - validator_alpha_take, - rem_alpha_divs_j, - validator_root_alpha_take, - rem_root_alpha_divs_j - ); - - // 2.4.2 --- Store the validator takes. - validator_alpha_takes - .entry(hotkey_j.clone()) - .and_modify(|e| { - *e = e.saturating_add(validator_alpha_take.saturating_to_num::()) - }) - .or_insert(validator_alpha_take.saturating_to_num::()); - validator_root_alpha_takes - .entry(hotkey_j.clone()) - .and_modify(|e| { - *e = e.saturating_add(validator_root_alpha_take.saturating_to_num::()) - }) - .or_insert(validator_root_alpha_take.saturating_to_num::()); - log::debug!( - "Stored validator take for hotkey {:?}: alpha take: {:?}, root-alpha take: {:?}", - hotkey_j, - validator_alpha_take.saturating_to_num::(), - validator_root_alpha_take.saturating_to_num::() - ); - - // 2.5.1 --- Store the root divs under hotkey_j - root_alpha_divs - .entry(hotkey_j.clone()) - .and_modify(|e| { - *e = e.saturating_add(rem_root_alpha_divs_j.saturating_to_num::()) - }) - .or_insert(rem_root_alpha_divs_j.saturating_to_num::()); - log::debug!( - "Stored root alpha dividends for hotkey {:?}: {:?}", - hotkey_j, - rem_root_alpha_divs_j.saturating_to_num::() - ); - - // 2.5.2 --- Store the alpha dividends - alpha_divs - .entry(hotkey_j.clone()) - .and_modify(|e| { - *e = e.saturating_add(rem_alpha_divs_j.saturating_to_num::()) - }) - .or_insert(rem_alpha_divs_j.saturating_to_num::()); - log::debug!( - "Stored alpha dividends for hotkey {:?}: {:?}", - hotkey_j, - rem_alpha_divs_j.saturating_to_num::() - ); - } + // Compute root divs as TAO. + let mut tao_dividends: BTreeMap = BTreeMap::new(); + for (hotkey, root_divs) in root_dividends { + // Root proportion. + let root_share: I96F32 = root_divs.checked_div( total_root_divs ).unwrap_or( zero ); + // Root proportion in TAO + let root_tao: I96F32 = asfloat!( pending_tao ).saturating_mul( root_share ); + // Record root dividends as TAO. + tao_dividends + .entry( hotkey ) + .and_modify(|e| *e = root_tao) + .or_insert(root_tao); } - let total_root_alpha_divs: u64 = root_alpha_divs - .values() - .sum::() - .saturating_add(validator_root_alpha_takes.values().sum::()); - - // === 3. Distribute the dividends to the hotkeys. - - // 3.1 --- Distribute owner cut. - // Check for existence of subnet owner cold/hot pair and distribute emission directly to them. + // Distribute the owner cut. if let Ok(owner_coldkey) = SubnetOwner::::try_get(netuid) { if let Ok(owner_hotkey) = SubnetOwnerHotkey::::try_get(netuid) { - // Increase stake for both coldkey and hotkey on the subnet + // Increase stake for owner hotkey and coldkey. Self::increase_stake_for_hotkey_and_coldkey_on_subnet( &owner_hotkey, &owner_coldkey, netuid, owner_cut, ); - log::debug!("Distributed owner cut for netuid {:?} to owner_hotkey {:?} and owner_coldkey {:?}", netuid, owner_hotkey, owner_coldkey); } } - // 3.2 --- Distribute mining incentive. - for (miner_j, incentive) in mining_incentive_to_distribute { - // Distribute mining incentive immediately. + // Distribute mining incentives. + for (hotkey, incentive) in incentives { + // Increase stake for miner. Self::increase_stake_for_hotkey_and_coldkey_on_subnet( - &miner_j.clone(), - &Owner::::get(miner_j.clone()), + &hotkey.clone(), + &Owner::::get(hotkey.clone()), netuid, incentive, ); - log::debug!( - "Distributed mining incentive for hotkey {:?} on netuid {:?}: {:?}", - miner_j, - netuid, - incentive - ); } - // 3.3.1 --- Distribute validator alpha takes - for (validator_j, validator_take) in validator_alpha_takes { - // 3.3.1a --- Distribute validator take to the validator. + // Distribute alpha divs. + let _ = AlphaDividendsPerSubnet::::clear_prefix(netuid, u32::MAX, None); + for (hotkey, mut alpha_divs) in alpha_dividends { + // Get take prop + let alpha_take: I96F32 = Self::get_hotkey_take_float( &hotkey ).saturating_mul( alpha_divs ); + // Remove take prop from alpha_divs + alpha_divs = alpha_divs.saturating_sub( alpha_take ); + // Give the validator their take. Self::increase_stake_for_hotkey_and_coldkey_on_subnet( - &validator_j.clone(), - &Owner::::get(validator_j.clone()), + &hotkey, + &Owner::::get(hotkey.clone()), netuid, - validator_take, + tou64!( alpha_take ), ); - log::debug!( - "Distributed validator take for hotkey {:?} on netuid {:?}: {:?}", - validator_j, - netuid, - validator_take + // Give all other nominators. + Self::increase_stake_for_hotkey_on_subnet( + &hotkey.clone(), + netuid, + tou64!( alpha_divs ) ); - - // 3.3.1b --- Record dividends for this validator on this subnet. - AlphaDividendsPerSubnet::::mutate(netuid, validator_j.clone(), |divs| { - *divs = divs.saturating_add(validator_take); + // Record dividends for this hotkey. + AlphaDividendsPerSubnet::::mutate(netuid, hotkey.clone(), |divs| { + *divs = divs.saturating_add( tou64!( alpha_divs ) ); }); - log::debug!( - "Recorded dividends for validator {:?} on netuid {:?}: {:?}", - validator_j, - netuid, - validator_take - ); } - // 3.3.2 --- Distribute validator root-alpha takes - for (validator_j, validator_take) in validator_root_alpha_takes { - // 3.3.2a --- Calculate the proportion of root divs to pay out to this validator's take. - let proportion: I96F32 = I96F32::saturating_from_num(validator_take) - .checked_div(I96F32::saturating_from_num(total_root_alpha_divs)) - .unwrap_or(I96F32::saturating_from_num(0)); - // 3.3.2b --- Get the proportion of root divs from the pending root divs. - let take_as_root_divs: u64 = proportion - .saturating_mul(I96F32::saturating_from_num(pending_root_divs)) - .saturating_to_num::(); - log::debug!( - "Root div proportion for validator take {:?}: {:?}, take_as_root_divs: {:?}", - validator_take, - proportion, - take_as_root_divs - ); - - // 3.3.2c --- Distribute validator take to the validator. + // Distribute root tao divs. + let _ = TaoDividendsPerSubnet::::clear_prefix(netuid, u32::MAX, None); + for (hotkey, mut root_tao) in tao_dividends { + // Get take prop + let tao_take: I96F32 = Self::get_hotkey_take_float(&hotkey).saturating_mul( root_tao ); + // Remove take prop from root_tao + root_tao = root_tao.saturating_sub( tao_take ); + // Give the validator their take. Self::increase_stake_for_hotkey_and_coldkey_on_subnet( - &validator_j.clone(), - &Owner::::get(validator_j.clone()), + &hotkey, + &Owner::::get(hotkey.clone()), Self::get_root_netuid(), - take_as_root_divs, + tou64!(tao_take), ); - log::debug!( - "Distributed validator take for hotkey {:?} on root netuid {:?}: {:?}", - validator_j, - Self::get_root_netuid(), - take_as_root_divs - ); - - // 3.3.2d --- Record dividends for this validator on this subnet. - TaoDividendsPerSubnet::::mutate(netuid, validator_j.clone(), |divs| { - *divs = divs.saturating_add(take_as_root_divs); - }); - log::debug!( - "Recorded dividends for validator {:?} on netuid {:?}: {:?}", - validator_j, - netuid, - take_as_root_divs - ); - } - - // 3.4 --- Distribute alpha divs - for (hotkey_j, alpha_divs_j) in alpha_divs { - // 3.4.1 --- Distribute alpha divs to the hotkey. - Self::increase_stake_for_hotkey_on_subnet(&hotkey_j.clone(), netuid, alpha_divs_j); - log::debug!( - "Distributed alpha dividends for hotkey {:?} on netuid {:?}: {:?}", - hotkey_j, - netuid, - alpha_divs_j - ); - - // 3.4.2 --- Record dividends for this hotkey on this subnet. - AlphaDividendsPerSubnet::::mutate(netuid, hotkey_j.clone(), |divs| { - *divs = divs.saturating_add(alpha_divs_j); - }); - log::debug!( - "Recorded dividends for hotkey {:?} on netuid {:?}: {:?}", - hotkey_j, - netuid, - alpha_divs_j - ); - } - - // 3.5 --- Distribute root divs - // For all the root-alpha divs give this proportion of the swapped tao to the root participants. - for (hotkey_j, root_alpha_divs_j) in root_alpha_divs.iter() { - // 3.5.1 --- Calculate the proportion of root divs to pay out to this hotkey. - let proportion: I96F32 = I96F32::saturating_from_num(*root_alpha_divs_j) - .checked_div(I96F32::saturating_from_num(total_root_alpha_divs)) - .unwrap_or(I96F32::saturating_from_num(0)); - // 3.5.2 --- Get the proportion of root divs from the pending root divs. - let root_divs_to_pay: u64 = proportion - .saturating_mul(I96F32::saturating_from_num(pending_root_divs)) - .saturating_to_num::(); - log::debug!( - "Proportion for hotkey {:?}: {:?}, root_divs_to_pay: {:?}", - hotkey_j, - proportion, - root_divs_to_pay - ); - - // 3.5.3 --- Distribute the root divs to the hotkey on the root subnet. + // Give rest to nominators. Self::increase_stake_for_hotkey_on_subnet( - hotkey_j, + &hotkey, Self::get_root_netuid(), - root_divs_to_pay, + tou64!(root_tao) ); - log::debug!( - "Paid tao to hotkey {:?} on root netuid from netuid {:?}: {:?}", - hotkey_j, - netuid, - root_divs_to_pay - ); - - // 3.5.4 --- Record dividends for this hotkey on this subnet. - TaoDividendsPerSubnet::::mutate(netuid, hotkey_j.clone(), |divs| { - *divs = divs.saturating_add(root_divs_to_pay); + // Record root dividends for this validator on this subnet. + TaoDividendsPerSubnet::::mutate(netuid, hotkey.clone(), |divs| { + *divs = divs.saturating_add(tou64!(root_tao)); }); - log::debug!( - "Recorded dividends for hotkey {:?} on netuid {:?}: {:?}", - hotkey_j, - netuid, - root_divs_to_pay - ); } } diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index 064bb5c6e4..36e6210fda 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -703,7 +703,7 @@ pub mod pallet { #[pallet::type_value] /// Default value for applying pending items (e.g. childkeys). pub fn DefaultPendingCooldown() -> u64 { - 7200 + 1 } #[pallet::type_value] @@ -904,6 +904,8 @@ pub mod pallet { /// /// Eventually, Bittensor should migrate to using Holds afterwhich time we will not require this /// separate accounting. + #[pallet::storage] // --- ITEM ( paused_coinbase ) + pub type PauseCoinbase = StorageValue<_, bool, ValueQuery, DefaultFalse>; #[pallet::storage] // --- ITEM ( total_issuance ) pub type TotalIssuance = StorageValue<_, u64, ValueQuery, DefaultTotalIssuance>; #[pallet::storage] // --- ITEM ( total_stake ) diff --git a/pallets/subtensor/src/staking/helpers.rs b/pallets/subtensor/src/staking/helpers.rs index 0cbe3bccf4..f4b2cef164 100644 --- a/pallets/subtensor/src/staking/helpers.rs +++ b/pallets/subtensor/src/staking/helpers.rs @@ -120,6 +120,11 @@ impl Pallet { pub fn get_hotkey_take(hotkey: &T::AccountId) -> u16 { Delegates::::get(hotkey) } + pub fn get_hotkey_take_float(hotkey: &T::AccountId) -> I96F32 { + I96F32::from_num( Self::get_hotkey_take(hotkey) ) + .checked_div( I96F32::from_num(u16::MAX) ) + .unwrap_or( I96F32::from_num(0.0) ) + } /// Returns true if the hotkey account has been created. /// diff --git a/pallets/subtensor/src/tests/children.rs b/pallets/subtensor/src/tests/children.rs index 7e30a22514..516713ddbb 100644 --- a/pallets/subtensor/src/tests/children.rs +++ b/pallets/subtensor/src/tests/children.rs @@ -2062,6 +2062,7 @@ fn test_get_stake_for_hotkey_on_subnet_complex_hierarchy() { let coldkey_grandchild = U256::from(8); add_network(netuid, 1, 0); + PauseCoinbase::::set(true); SubtensorModule::set_max_registrations_per_block(netuid, 1000); SubtensorModule::set_target_registrations_per_interval(netuid, 1000); register_ok_neuron(netuid, parent, coldkey_parent, 0); @@ -2699,7 +2700,7 @@ fn test_set_children_rate_limit_fail_then_succeed() { }); } -// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --test children -- test_childkey_set_weights_single_parent --exact --nocapture +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::children::test_childkey_set_weights_single_parent --exact --show-output --nocapture #[test] fn test_childkey_set_weights_single_parent() { new_test_ext(1).execute_with(|| { diff --git a/pallets/subtensor/src/tests/coinbase.rs b/pallets/subtensor/src/tests/coinbase.rs index fb7a927be8..b3042676d6 100644 --- a/pallets/subtensor/src/tests/coinbase.rs +++ b/pallets/subtensor/src/tests/coinbase.rs @@ -49,529 +49,3 @@ fn test_dynamic_function_various_values() { }); } -// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_dynamic_function_price_equal_emission --exact --show-output --nocapture -#[test] -fn test_dynamic_function_price_equal_emission() { - new_test_ext(1).execute_with(|| { - let netuid = 1; - let tao_subnet_emission: u64 = 100_000_000; - let tao_block_emission: u64 = 1_000_000_000; - let alpha_block_emission: u64 = 1_000_000_000; - SubnetTAO::::insert(netuid, 1_000_000_000); - SubnetAlphaIn::::insert(netuid, 1_000_000_000); - add_network(netuid, 110, 100); - let (tao_in, alpha_in, alpha_out): (u64, u64, u64) = - SubtensorModule::get_dynamic_tao_emission( - netuid, - tao_subnet_emission, - alpha_block_emission, - ); - assert_eq!(tao_in, tao_subnet_emission); // at price == tao_in == tao_subnet_emission - let expected_alpha_in: u64 = - (alpha_block_emission * tao_subnet_emission) / tao_block_emission; - close(alpha_in, expected_alpha_in, 10); - close(alpha_out, alpha_block_emission, 10); - }); -} - -// Verifies that the total stake after the coinbase is only increased by the coinbase emission. -// Avoids TAO weight. -// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_total_stake_after_coinbase_no_tao_weight --exact --show-output --nocapture -#[test] -fn test_total_stake_after_coinbase_no_tao_weight() { - new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; - add_network(netuid, 1, 0); - // Set TAO weight to 0 - SubtensorModule::set_tao_weight(0); - // Set owner cut to ~11.11% - SubtensorModule::set_subnet_owner_cut(u16::MAX / 9); - let total_coinbase_emission: I96F32 = I96F32::from_num(1_123_456_789); - let epsilon: u64 = 100; - - // Define hotkeys and coldkeys - let hotkey_a: U256 = U256::from(1); - let hotkey_b: U256 = U256::from(2); - let hotkey_c: U256 = U256::from(3); - let coldkey_a: U256 = U256::from(100); - let coldkey_b: U256 = U256::from(101); - let coldkey_c: U256 = U256::from(102); - - // Register neurons with decreasing stakes - register_ok_neuron(netuid, hotkey_a, coldkey_a, 0); - register_ok_neuron(netuid, hotkey_b, coldkey_b, 0); - register_ok_neuron(netuid, hotkey_c, coldkey_c, 0); - - // Add initial stakes - SubtensorModule::add_balance_to_coldkey_account(&coldkey_a, 1_000); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_b, 1_000); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_c, 1_000); - - // Swap to alpha - let total_tao: I96F32 = I96F32::from_num(300_000 + 100_000 + 50_000); - let total_alpha: I96F32 = I96F32::from_num(SubtensorModule::swap_tao_for_alpha( - netuid, - total_tao.saturating_to_num::(), - )); - - // Set the stakes directly - // This avoids needing to swap tao to alpha, impacting the initial stake distribution. - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_a, - &coldkey_a, - netuid, - (total_alpha * I96F32::from_num(300_000) / total_tao).saturating_to_num::(), - ); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_b, - &coldkey_b, - netuid, - (total_alpha * I96F32::from_num(100_000) / total_tao).saturating_to_num::(), - ); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_c, - &coldkey_c, - netuid, - (total_alpha * I96F32::from_num(50_000) / total_tao).saturating_to_num::(), - ); - - // Get the total stake on the network - let mut total_stake_before = 0; - for (hotkey, netuid_i, alpha) in TotalHotkeyAlpha::::iter() { - if netuid_i == netuid { - total_stake_before += alpha; - } else { - assert!( - alpha == 0, - "Alpha should be 0 for non-subnet hotkeys, but is {:?} on netuid {:?}", - alpha, - netuid_i - ); - } - } - - log::info!("total_stake_before: {:?}", total_stake_before); - - // Run the coinbase - SubtensorModule::run_coinbase(total_coinbase_emission); - - // Get the total stake on the network - let mut total_stake_after = 0; - for (hotkey, netuid_i, alpha) in TotalHotkeyAlpha::::iter() { - if netuid_i == netuid { - total_stake_after += alpha; - } else { - assert!( - alpha == 0, - "Alpha should be 0 for non-subnet hotkeys, but is {:?} on netuid {:?}", - alpha, - netuid_i - ); - } - } - assert_abs_diff_eq!( - total_stake_after, - total_stake_before + total_coinbase_emission.saturating_to_num::(), - epsilon = epsilon - ); - }); -} - -// Verifies that the total stake after the coinbase is only increased by the coinbase emission. -// Includes TAO weight. -// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_total_stake_after_coinbase --exact --show-output --nocapture -#[test] -fn test_total_stake_after_coinbase() { - new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; - add_network(netuid, 1, 0); - // Set TAO weight to 18% - SubtensorModule::set_tao_weight(I96F32::from_num(0.18).saturating_to_num::()); - // Set owner cut to ~11.11% - SubtensorModule::set_subnet_owner_cut(u16::MAX / 9); - let total_coinbase_emission: I96F32 = I96F32::from_num(1_123_456_789); - let epsilon: u64 = 100; - - // Define hotkeys and coldkeys - let hotkey_a: U256 = U256::from(1); - let hotkey_b: U256 = U256::from(2); - let hotkey_c: U256 = U256::from(3); - let coldkey_a: U256 = U256::from(100); - let coldkey_b: U256 = U256::from(101); - let coldkey_c: U256 = U256::from(102); - - // Register neurons with decreasing stakes - register_ok_neuron(netuid, hotkey_a, coldkey_a, 0); - register_ok_neuron(netuid, hotkey_b, coldkey_b, 0); - register_ok_neuron(netuid, hotkey_c, coldkey_c, 0); - - // Add initial stakes - SubtensorModule::add_balance_to_coldkey_account(&coldkey_a, 1_000); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_b, 1_000); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_c, 1_000); - - // Swap to alpha - let total_tao: I96F32 = I96F32::from_num(300_000 + 100_000 + 50_000); - let total_alpha: I96F32 = I96F32::from_num(SubtensorModule::swap_tao_for_alpha( - netuid, - total_tao.saturating_to_num::(), - )); - - // Set the stakes directly - // This avoids needing to swap tao to alpha, impacting the initial stake distribution. - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_a, - &coldkey_a, - netuid, - (total_alpha * I96F32::from_num(300_000) / total_tao).saturating_to_num::(), - ); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_b, - &coldkey_b, - netuid, - (total_alpha * I96F32::from_num(100_000) / total_tao).saturating_to_num::(), - ); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_c, - &coldkey_c, - netuid, - (total_alpha * I96F32::from_num(50_000) / total_tao).saturating_to_num::(), - ); - - // Stake some to root - let stake_to_root: u64 = 10_000_000; - SubtensorModule::add_balance_to_coldkey_account(&coldkey_a, stake_to_root); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_a, - &coldkey_a, - netuid, - stake_to_root, - ); - - let alpha_price = SubtensorModule::get_alpha_price(netuid); - log::info!("alpha_price: {:?}", alpha_price); - - // Get the total stake on the network - let mut total_stake_before = 0; - for (hotkey, netuid_i, alpha) in TotalHotkeyAlpha::::iter() { - if netuid_i == netuid { - total_stake_before += alpha; - } else if netuid == SubtensorModule::get_root_netuid() { - let as_alpha: I96F32 = I96F32::from_num(alpha) / alpha_price; - total_stake_before += as_alpha.saturating_to_num::(); - } else { - assert!( - alpha == 0, - "Alpha should be 0 for non-subnet hotkeys, but is {:?} on netuid {:?}", - alpha, - netuid_i - ); - } - } - - log::info!("total_stake_before: {:?}", total_stake_before); - - // Run the coinbase - SubtensorModule::run_coinbase(total_coinbase_emission); - - // Get the total stake on the network - let mut total_stake_after = 0; - for (hotkey, netuid_i, alpha) in TotalHotkeyAlpha::::iter() { - if netuid_i == netuid { - total_stake_after += alpha; - } else if netuid == SubtensorModule::get_root_netuid() { - let as_alpha: I96F32 = I96F32::from_num(alpha) / alpha_price; - total_stake_after += as_alpha.saturating_to_num::(); - } else { - assert!( - alpha == 0, - "Alpha should be 0 for non-subnet hotkeys, but is {:?} on netuid {:?}", - alpha, - netuid_i - ); - } - } - assert_abs_diff_eq!( - total_stake_after, - total_stake_before + total_coinbase_emission.saturating_to_num::(), - epsilon = epsilon - ); - }); -} - -// Verifies that the total issuance after the coinbase is only increased by the coinbase emission. -// Includes TAO weight. -// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_total_issuance_after_coinbase --exact --show-output --nocapture -#[test] -fn test_total_issuance_after_coinbase() { - new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; - add_network(netuid, 1, 0); - // Set TAO weight to 18% - SubtensorModule::set_tao_weight(I96F32::from_num(0.18).saturating_to_num::()); - // Set owner cut to ~11.11% - SubtensorModule::set_subnet_owner_cut(u16::MAX / 9); - let total_coinbase_emission: I96F32 = I96F32::from_num(1_123_456_789); - let epsilon: u64 = 100; - - // Define hotkeys and coldkeys - let hotkey_a: U256 = U256::from(1); - let hotkey_b: U256 = U256::from(2); - let hotkey_c: U256 = U256::from(3); - let coldkey_a: U256 = U256::from(100); - let coldkey_b: U256 = U256::from(101); - let coldkey_c: U256 = U256::from(102); - - // Register neurons with decreasing stakes - register_ok_neuron(netuid, hotkey_a, coldkey_a, 0); - register_ok_neuron(netuid, hotkey_b, coldkey_b, 0); - register_ok_neuron(netuid, hotkey_c, coldkey_c, 0); - - // Add initial stakes - SubtensorModule::add_balance_to_coldkey_account(&coldkey_a, 1_000); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_b, 1_000); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_c, 1_000); - - // Swap to alpha - let total_tao: I96F32 = I96F32::from_num(300_000 + 100_000 + 50_000); - let total_alpha: I96F32 = I96F32::from_num(SubtensorModule::swap_tao_for_alpha( - netuid, - total_tao.saturating_to_num::(), - )); - - // Set the stakes directly - // This avoids needing to swap tao to alpha, impacting the initial stake distribution. - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_a, - &coldkey_a, - netuid, - (total_alpha * I96F32::from_num(300_000) / total_tao).saturating_to_num::(), - ); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_b, - &coldkey_b, - netuid, - (total_alpha * I96F32::from_num(100_000) / total_tao).saturating_to_num::(), - ); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_c, - &coldkey_c, - netuid, - (total_alpha * I96F32::from_num(50_000) / total_tao).saturating_to_num::(), - ); - - // Stake some to root - let stake_to_root: u64 = 10_000_000; - SubtensorModule::add_balance_to_coldkey_account(&coldkey_a, stake_to_root); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_a, - &coldkey_a, - netuid, - stake_to_root, - ); - - let alpha_price = SubtensorModule::get_alpha_price(netuid); - log::info!("alpha_price: {:?}", alpha_price); - - // Get the total issuance - let mut total_issuance_before = TotalIssuance::::get(); - log::info!("total_issuance_before: {:?}", total_issuance_before); - - // Run the coinbase - SubtensorModule::run_coinbase(total_coinbase_emission); - - // Compare - let total_issuance_after = TotalIssuance::::get(); - assert_abs_diff_eq!( - total_issuance_after, - total_issuance_before + total_coinbase_emission.saturating_to_num::(), - epsilon = epsilon - ); - }); -} - -// Verifies that the total issuance after the coinbase is not changed when registration is disabled. -// Includes TAO weight. -// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_registration_disabled_total_issuance_same --exact --show-output --nocapture -#[test] -fn test_registration_disabled_total_issuance_same() { - new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; - add_network(netuid, 1, 0); - // Set TAO weight to 18% - SubtensorModule::set_tao_weight(I96F32::from_num(0.18).saturating_to_num::()); - // Set owner cut to ~11.11% - SubtensorModule::set_subnet_owner_cut(u16::MAX / 9); - let total_coinbase_emission: I96F32 = I96F32::from_num(1_123_456_789); - let epsilon: u64 = 100; - - // Define hotkeys and coldkeys - let hotkey_a: U256 = U256::from(1); - let hotkey_b: U256 = U256::from(2); - let hotkey_c: U256 = U256::from(3); - let coldkey_a: U256 = U256::from(100); - let coldkey_b: U256 = U256::from(101); - let coldkey_c: U256 = U256::from(102); - - // Register neurons with decreasing stakes - register_ok_neuron(netuid, hotkey_a, coldkey_a, 0); - register_ok_neuron(netuid, hotkey_b, coldkey_b, 0); - register_ok_neuron(netuid, hotkey_c, coldkey_c, 0); - - // Add initial stakes - SubtensorModule::add_balance_to_coldkey_account(&coldkey_a, 1_000); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_b, 1_000); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_c, 1_000); - - // Swap to alpha - let total_tao: I96F32 = I96F32::from_num(300_000 + 100_000 + 50_000); - let total_alpha: I96F32 = I96F32::from_num(SubtensorModule::swap_tao_for_alpha( - netuid, - total_tao.saturating_to_num::(), - )); - - // Set the stakes directly - // This avoids needing to swap tao to alpha, impacting the initial stake distribution. - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_a, - &coldkey_a, - netuid, - (total_alpha * I96F32::from_num(300_000) / total_tao).saturating_to_num::(), - ); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_b, - &coldkey_b, - netuid, - (total_alpha * I96F32::from_num(100_000) / total_tao).saturating_to_num::(), - ); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_c, - &coldkey_c, - netuid, - (total_alpha * I96F32::from_num(50_000) / total_tao).saturating_to_num::(), - ); - - // Stake some to root - let stake_to_root: u64 = 10_000_000; - SubtensorModule::add_balance_to_coldkey_account(&coldkey_a, stake_to_root); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_a, - &coldkey_a, - netuid, - stake_to_root, - ); - - let alpha_price = SubtensorModule::get_alpha_price(netuid); - log::info!("alpha_price: {:?}", alpha_price); - - // Get the total issuance - let mut total_issuance_before = TotalIssuance::::get(); - log::info!("total_issuance_before: {:?}", total_issuance_before); - - // Disable registration on the network - SubtensorModule::set_network_registration_allowed(netuid, false); - SubtensorModule::set_network_pow_registration_allowed(netuid, false); - - // Run the coinbase - SubtensorModule::run_coinbase(total_coinbase_emission); - - // Should be the same - let total_issuance_after = TotalIssuance::::get(); - assert_abs_diff_eq!( - total_issuance_after, - total_issuance_before, - epsilon = epsilon - ); - }); -} - -// Verifies that the TAO-in after the coinbase is not changed when registration is disabled. -// Includes TAO weight. -// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_registration_disabled_tao_in_same --exact --show-output --nocapture -#[test] -fn test_registration_disabled_tao_in_same() { - new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; - add_network(netuid, 1, 0); - // Set TAO weight to 18% - SubtensorModule::set_tao_weight(I96F32::from_num(0.18).saturating_to_num::()); - // Set owner cut to ~11.11% - SubtensorModule::set_subnet_owner_cut(u16::MAX / 9); - let total_coinbase_emission: I96F32 = I96F32::from_num(1_123_456_789); - let epsilon: u64 = 100; - - // Define hotkeys and coldkeys - let hotkey_a: U256 = U256::from(1); - let hotkey_b: U256 = U256::from(2); - let hotkey_c: U256 = U256::from(3); - let coldkey_a: U256 = U256::from(100); - let coldkey_b: U256 = U256::from(101); - let coldkey_c: U256 = U256::from(102); - - // Register neurons with decreasing stakes - register_ok_neuron(netuid, hotkey_a, coldkey_a, 0); - register_ok_neuron(netuid, hotkey_b, coldkey_b, 0); - register_ok_neuron(netuid, hotkey_c, coldkey_c, 0); - - // Add initial stakes - SubtensorModule::add_balance_to_coldkey_account(&coldkey_a, 1_000); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_b, 1_000); - SubtensorModule::add_balance_to_coldkey_account(&coldkey_c, 1_000); - - // Swap to alpha - let total_tao: I96F32 = I96F32::from_num(300_000 + 100_000 + 50_000); - let total_alpha: I96F32 = I96F32::from_num(SubtensorModule::swap_tao_for_alpha( - netuid, - total_tao.saturating_to_num::(), - )); - - // Set the stakes directly - // This avoids needing to swap tao to alpha, impacting the initial stake distribution. - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_a, - &coldkey_a, - netuid, - (total_alpha * I96F32::from_num(300_000) / total_tao).saturating_to_num::(), - ); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_b, - &coldkey_b, - netuid, - (total_alpha * I96F32::from_num(100_000) / total_tao).saturating_to_num::(), - ); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_c, - &coldkey_c, - netuid, - (total_alpha * I96F32::from_num(50_000) / total_tao).saturating_to_num::(), - ); - - // Stake some to root - let stake_to_root: u64 = 10_000_000; - SubtensorModule::add_balance_to_coldkey_account(&coldkey_a, stake_to_root); - SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &hotkey_a, - &coldkey_a, - netuid, - stake_to_root, - ); - - let alpha_price = SubtensorModule::get_alpha_price(netuid); - log::info!("alpha_price: {:?}", alpha_price); - - // Get the total issuance - let mut tao_in_before = SubnetTAO::::get(netuid); - log::info!("tao_in_before: {:?}", tao_in_before); - - // Disable registration on the network - SubtensorModule::set_network_registration_allowed(netuid, false); - SubtensorModule::set_network_pow_registration_allowed(netuid, false); - - // Run the coinbase - SubtensorModule::run_coinbase(total_coinbase_emission); - - // Should be the same - let tao_in_after = SubnetTAO::::get(netuid); - assert_abs_diff_eq!(tao_in_after, tao_in_before, epsilon = epsilon); - }); -} From 547ca2765183d4c6566b52318149b80ccf120e68 Mon Sep 17 00:00:00 2001 From: unconst Date: Tue, 4 Feb 2025 17:57:12 -0500 Subject: [PATCH 13/34] noclaim --- pallets/subtensor/src/coinbase/block_step.rs | 7 +++---- pallets/subtensor/src/coinbase/run_coinbase.rs | 12 +++++++++++- pallets/subtensor/src/lib.rs | 2 +- pallets/subtensor/src/tests/children.rs | 1 - 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/pallets/subtensor/src/coinbase/block_step.rs b/pallets/subtensor/src/coinbase/block_step.rs index 5978892ecf..bcfd1a37bc 100644 --- a/pallets/subtensor/src/coinbase/block_step.rs +++ b/pallets/subtensor/src/coinbase/block_step.rs @@ -14,10 +14,9 @@ impl Pallet { let block_emission: I96F32 = I96F32::saturating_from_num(Self::get_block_emission().unwrap_or(0)); log::debug!("Block emission: {:?}", block_emission); - // // --- 3. Run emission through network. - if !PauseCoinbase::::get() { - Self::run_coinbase(block_emission); - } + // --- 3. Run emission through network. + Self::run_coinbase(block_emission); + // --- 4. Set pending children on the epoch; but only after the coinbase has been run. Self::try_set_pending_children(block_number); diff --git a/pallets/subtensor/src/coinbase/run_coinbase.rs b/pallets/subtensor/src/coinbase/run_coinbase.rs index a15ab587e6..ca11a11129 100644 --- a/pallets/subtensor/src/coinbase/run_coinbase.rs +++ b/pallets/subtensor/src/coinbase/run_coinbase.rs @@ -58,6 +58,10 @@ impl Pallet { pub fn run_coinbase(block_emission: I96F32) { + // Increment emission by pending/ + let real_block_emission: I96F32 = block_emission + asfloat!( PendingBlockEmission::::get() ); + PendingBlockEmission::::set( 0 ); + // --- 0. Get current block. let current_block: u64 = Self::get_current_block_as_u64(); log::debug!("Current block: {:?}", current_block); @@ -75,6 +79,7 @@ impl Pallet { log::debug!("tao_sum: {:?}", tao_sum); // --- 3. Get subnet terms (tao_in, alpha_in, and alpha_out) + let mut sum_tao_in: I96F32 = asfloat!( 0 ); let mut tao_in: BTreeMap = BTreeMap::new(); let mut alpha_in: BTreeMap = BTreeMap::new(); let mut alpha_out: BTreeMap = BTreeMap::new(); @@ -86,7 +91,7 @@ impl Pallet { let subnet_tao_i: I96F32 = asfloat!( SubnetTAO::::get(netuid_i) ); log::debug!("subnet_tao_i: {:?}", subnet_tao_i); // Emission is price over total. - let mut tao_in_i: I96F32 = block_emission.saturating_mul(subnet_tao_i).checked_div(tao_sum).unwrap_or(asfloat!(0.0)); + let mut tao_in_i: I96F32 = real_block_emission.saturating_mul(subnet_tao_i).checked_div(tao_sum).unwrap_or(asfloat!(0.0)); log::debug!("tao_in_i: {:?}", tao_in_i); // Get alpha_emission total let alpha_emission_i: I96F32 = asfloat!(Self::get_block_emission_for_issuance(Self::get_alpha_issuance(*netuid_i)).unwrap_or(0)); @@ -109,11 +114,16 @@ impl Pallet { tao_in.insert(*netuid_i, tao_in_i); alpha_in.insert(*netuid_i, alpha_in_i); alpha_out.insert(*netuid_i, alpha_out_i); + sum_tao_in = sum_tao_in.saturating_add(tao_in_i); } log::debug!("tao_in: {:?}", tao_in); log::debug!("alpha_in: {:?}", alpha_in); log::debug!("alpha_out: {:?}", alpha_out); + // Add missed emission into pending. + let missing_emission: I96F32 = real_block_emission.saturating_sub( sum_tao_in ); + PendingBlockEmission::::set( tou64!( missing_emission ) ); + // --- 4. Injection. for netuid_i in subnets.iter() { // Inject Alpha in. diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index 36e6210fda..87f5ac8fe4 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -905,7 +905,7 @@ pub mod pallet { /// Eventually, Bittensor should migrate to using Holds afterwhich time we will not require this /// separate accounting. #[pallet::storage] // --- ITEM ( paused_coinbase ) - pub type PauseCoinbase = StorageValue<_, bool, ValueQuery, DefaultFalse>; + pub type PendingBlockEmission = StorageValue<_, u64, ValueQuery, DefaultZeroU64>; #[pallet::storage] // --- ITEM ( total_issuance ) pub type TotalIssuance = StorageValue<_, u64, ValueQuery, DefaultTotalIssuance>; #[pallet::storage] // --- ITEM ( total_stake ) diff --git a/pallets/subtensor/src/tests/children.rs b/pallets/subtensor/src/tests/children.rs index 516713ddbb..d8ff6ffb4f 100644 --- a/pallets/subtensor/src/tests/children.rs +++ b/pallets/subtensor/src/tests/children.rs @@ -2062,7 +2062,6 @@ fn test_get_stake_for_hotkey_on_subnet_complex_hierarchy() { let coldkey_grandchild = U256::from(8); add_network(netuid, 1, 0); - PauseCoinbase::::set(true); SubtensorModule::set_max_registrations_per_block(netuid, 1000); SubtensorModule::set_target_registrations_per_interval(netuid, 1000); register_ok_neuron(netuid, parent, coldkey_parent, 0); From 1a2ec64fb50c2e34494a6e7198b7cefc0c5b9cb4 Mon Sep 17 00:00:00 2001 From: unconst Date: Tue, 4 Feb 2025 18:20:23 -0500 Subject: [PATCH 14/34] remove complexity --- .../subtensor/src/coinbase/run_coinbase.rs | 21 ++----------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/pallets/subtensor/src/coinbase/run_coinbase.rs b/pallets/subtensor/src/coinbase/run_coinbase.rs index ca11a11129..8eb7256c60 100644 --- a/pallets/subtensor/src/coinbase/run_coinbase.rs +++ b/pallets/subtensor/src/coinbase/run_coinbase.rs @@ -58,10 +58,6 @@ impl Pallet { pub fn run_coinbase(block_emission: I96F32) { - // Increment emission by pending/ - let real_block_emission: I96F32 = block_emission + asfloat!( PendingBlockEmission::::get() ); - PendingBlockEmission::::set( 0 ); - // --- 0. Get current block. let current_block: u64 = Self::get_current_block_as_u64(); log::debug!("Current block: {:?}", current_block); @@ -91,23 +87,14 @@ impl Pallet { let subnet_tao_i: I96F32 = asfloat!( SubnetTAO::::get(netuid_i) ); log::debug!("subnet_tao_i: {:?}", subnet_tao_i); // Emission is price over total. - let mut tao_in_i: I96F32 = real_block_emission.saturating_mul(subnet_tao_i).checked_div(tao_sum).unwrap_or(asfloat!(0.0)); + let tao_in_i: I96F32 = block_emission.saturating_mul(subnet_tao_i).checked_div(tao_sum).unwrap_or(asfloat!(0.0)); log::debug!("tao_in_i: {:?}", tao_in_i); // Get alpha_emission total let alpha_emission_i: I96F32 = asfloat!(Self::get_block_emission_for_issuance(Self::get_alpha_issuance(*netuid_i)).unwrap_or(0)); log::debug!("alpha_emission_i: {:?}", alpha_emission_i); // Get initial alpha_in - let mut alpha_in_i: I96F32 = tao_in_i.checked_div(price_i).unwrap_or(alpha_emission_i); + let alpha_in_i: I96F32 = tao_in_i.checked_div(price_i).unwrap_or(alpha_emission_i).min(alpha_emission_i); log::debug!("alpha_in_i: {:?}", alpha_in_i); - // Check if we are emitting too much alpha_in - if alpha_in_i >= alpha_emission_i { - // Scale down tao_in - tao_in_i = price_i.saturating_mul(alpha_emission_i); - log::debug!("change tao_in_i: {:?}", tao_in_i); - // Set to max alpha_block_emission - alpha_in_i = alpha_emission_i; - log::debug!("change alpha_in_i: {:?}", alpha_in_i); - } // Get alpha_out. let alpha_out_i = alpha_emission_i; // Insert values into maps @@ -120,10 +107,6 @@ impl Pallet { log::debug!("alpha_in: {:?}", alpha_in); log::debug!("alpha_out: {:?}", alpha_out); - // Add missed emission into pending. - let missing_emission: I96F32 = real_block_emission.saturating_sub( sum_tao_in ); - PendingBlockEmission::::set( tou64!( missing_emission ) ); - // --- 4. Injection. for netuid_i in subnets.iter() { // Inject Alpha in. From d81238a0a88976b25a2c78d6751372faef90f424 Mon Sep 17 00:00:00 2001 From: unconst Date: Wed, 5 Feb 2025 09:49:14 -0500 Subject: [PATCH 15/34] clean coinbase --- .../subtensor/src/coinbase/run_coinbase.rs | 78 ++++++++----------- 1 file changed, 33 insertions(+), 45 deletions(-) diff --git a/pallets/subtensor/src/coinbase/run_coinbase.rs b/pallets/subtensor/src/coinbase/run_coinbase.rs index 8eb7256c60..2489f57732 100644 --- a/pallets/subtensor/src/coinbase/run_coinbase.rs +++ b/pallets/subtensor/src/coinbase/run_coinbase.rs @@ -32,29 +32,6 @@ macro_rules! tou64 { } impl Pallet { - pub fn get_root_divs_in_alpha( - netuid: u16, - alpha_out_emission: I96F32, - validator_proportion: I96F32, - ) -> I96F32 { - // Get total TAO on root. - let total_root_tao: I96F32 = asfloat!( SubnetTAO::::get(0) ); - // Get total ALPHA on subnet. - let total_alpha_issuance: I96F32 = asfloat!( Self::get_alpha_issuance(netuid)) ; - // Get tao_weight - let tao_weight: I96F32 = total_root_tao.saturating_mul(Self::get_tao_weight()); - // Get root proportional dividends. - let root_proportion: I96F32 = tao_weight - .checked_div(tao_weight.saturating_add(total_alpha_issuance)) - .unwrap_or(asfloat!(0.0)); - // Get root proportion of alpha_out dividends. - let root_divs_in_alpha: I96F32 = root_proportion - .saturating_mul(alpha_out_emission) - .saturating_mul(validator_proportion); // % of emission that goes to *all* validators. - - // Return - root_divs_in_alpha - } pub fn run_coinbase(block_emission: I96F32) { @@ -62,11 +39,11 @@ impl Pallet { let current_block: u64 = Self::get_current_block_as_u64(); log::debug!("Current block: {:?}", current_block); - // --- 1. Get all netuids (not root.) + // --- 1. Get all netuids (filter out root.) let subnets: Vec = Self::get_all_subnet_netuids().into_iter().filter(|netuid| *netuid != 0).collect(); log::debug!("All subnet netuids: {:?}", subnets); - // --- 2. Get sum of tao reserves. + // --- 2. Get sum of tao reserves ( in a later version we will switch to prices. ) let mut tao_sum: I96F32 = I96F32::from_num(0.0); for netuid_i in subnets.iter() { // Get and add subnet TAO in reserve. @@ -75,7 +52,7 @@ impl Pallet { log::debug!("tao_sum: {:?}", tao_sum); // --- 3. Get subnet terms (tao_in, alpha_in, and alpha_out) - let mut sum_tao_in: I96F32 = asfloat!( 0 ); + // Computation is described in detail in the dtao whitepaper. let mut tao_in: BTreeMap = BTreeMap::new(); let mut alpha_in: BTreeMap = BTreeMap::new(); let mut alpha_out: BTreeMap = BTreeMap::new(); @@ -101,13 +78,14 @@ impl Pallet { tao_in.insert(*netuid_i, tao_in_i); alpha_in.insert(*netuid_i, alpha_in_i); alpha_out.insert(*netuid_i, alpha_out_i); - sum_tao_in = sum_tao_in.saturating_add(tao_in_i); } log::debug!("tao_in: {:?}", tao_in); log::debug!("alpha_in: {:?}", alpha_in); log::debug!("alpha_out: {:?}", alpha_out); // --- 4. Injection. + // Actually perform the injection of alpha_in, alpha_out and tao_in into the subnet pool. + // This operation changes the pool liquidity each block. for netuid_i in subnets.iter() { // Inject Alpha in. let alpha_in_i: u64 = tou64!( *alpha_in.get(netuid_i).unwrap_or(&asfloat!(0)) ); @@ -136,6 +114,8 @@ impl Pallet { } // --- 5. Compute owner cuts and remove them from alpha_out remaining. + // Remove owner cuts here so that we can properly seperate root dividends in the next step. + // Owner cuts are accumulated and then fed to the drain at the end of this func. let cut_percent: I96F32 = Self::get_float_subnet_owner_cut(); let mut owner_cuts: BTreeMap = BTreeMap::new(); for netuid_i in subnets.iter() { @@ -153,19 +133,26 @@ impl Pallet { }); } - // --- 6. Accumulate pending emission for root and alpha. + // --- 6. Seperate out root dividends in alpha and sell them into tao. + // Then accumulate those dividends for later. for netuid_i in subnets.iter() { // Get remaining alpha out. let alpha_out_i: I96F32 = *alpha_out.get( netuid_i ).unwrap_or(&asfloat!(0.0)); - // Validators get 50% of remaining emission. - let val_prop: I96F32 = asfloat!(0.5); - // Get proportion of alpha out emission as root divs. - let root_alpha: I96F32 = Self::get_root_divs_in_alpha( - *netuid_i, - alpha_out_i, - val_prop, - ); - // Save pending alpha after root alpha removal. + // Get total TAO on root. + let root_tao: I96F32 = asfloat!( SubnetTAO::::get(0) ); + // Get total ALPHA on subnet. + let alpha_issuance: I96F32 = asfloat!( Self::get_alpha_issuance(netuid)) ; + // Get tao_weight + let tao_weight: I96F32 = root_tao.saturating_mul(Self::get_tao_weight()); + // Get root proportional dividends. + let root_proportion: I96F32 = tao_weight + .checked_div(tao_weight.saturating_add(alpha_issuance)) + .unwrap_or(asfloat!(0.0)); + // Get root proportion of alpha_out dividends. + let root_alpha: I96F32 = root_proportion + .saturating_mul(alpha_out_i) // Total alpha emission per block remaining. + .saturating_mul(asfloat!(0.5)); // 50% to validators. + // Remove root alpha from alpha_out. let pending_alpha: I96F32 = alpha_out_i.saturating_sub( root_alpha ); // Sell root emission through the pool. let root_tao: u64 = Self::swap_alpha_for_tao( @@ -257,7 +244,7 @@ impl Pallet { pending_alpha.saturating_add(pending_swapped), ); - // Accumulate emission. + // Accumulate emission of dividends and incentive per hotkey. let mut incentives: BTreeMap = BTreeMap::new(); let mut dividends: BTreeMap = BTreeMap::new(); for (hotkey, incentive, dividend) in hotkey_emission { @@ -277,25 +264,26 @@ impl Pallet { } } - // Accumulate root divs and alpha_divs + // Accumulate root divs and alpha_divs. For each hotkye we compute their + // local and root dividend proportion based on their alpha_stake/root_stake let mut total_root_divs: I96F32 = asfloat!( 0 ); let mut root_dividends: BTreeMap = BTreeMap::new(); let mut alpha_dividends: BTreeMap = BTreeMap::new(); for (hotkey, dividend) in dividends { // Get hotkey ALPHA on subnet. - let local_alpha = asfloat!( + let alpha_stake = asfloat!( Self::get_stake_for_hotkey_on_subnet( &hotkey, netuid) ); // Get hotkey TAO on root. - let root_tao: I96F32 = asfloat!( + let root_stake: I96F32 = asfloat!( Self::get_stake_for_hotkey_on_subnet( &hotkey, Self::get_root_netuid()) ); // Convert TAO to alpha with weight. - let root_alpha: I96F32 = root_tao.saturating_mul(Self::get_tao_weight()); + let root_alpha: I96F32 = root_stake.saturating_mul(Self::get_tao_weight()); // Get total from root and local - let total_alpha: I96F32 = local_alpha.saturating_add( root_alpha ); + let total_alpha: I96F32 = alpha_stake.saturating_add( root_alpha ); // Compute alpha prop. - let alpha_prop: I96F32 = local_alpha.checked_div(total_alpha).unwrap_or(zero); + let alpha_prop: I96F32 = alpha_stake.checked_div(total_alpha).unwrap_or(zero); // Copmute root prop. let root_prop: I96F32 = root_alpha.checked_div(total_alpha).unwrap_or(zero); // Compute alpha dividends @@ -316,7 +304,7 @@ impl Pallet { total_root_divs = total_root_divs.saturating_add( root_divs ); } - // Compute root divs as TAO. + // Compute root divs as TAO. Here we take let mut tao_dividends: BTreeMap = BTreeMap::new(); for (hotkey, root_divs) in root_dividends { // Root proportion. From b144f210a45613f03487fd279d13fdda04f04341 Mon Sep 17 00:00:00 2001 From: unconst Date: Wed, 5 Feb 2025 10:11:22 -0500 Subject: [PATCH 16/34] pre merge --- .../subtensor/src/coinbase/block_emission.rs | 7 +- .../subtensor/src/coinbase/run_coinbase.rs | 2 +- pallets/subtensor/src/tests/children.rs | 222 ------------------ pallets/subtensor/src/tests/coinbase.rs | 6 +- 4 files changed, 6 insertions(+), 231 deletions(-) diff --git a/pallets/subtensor/src/coinbase/block_emission.rs b/pallets/subtensor/src/coinbase/block_emission.rs index 3c3288c93b..f0f2394e94 100644 --- a/pallets/subtensor/src/coinbase/block_emission.rs +++ b/pallets/subtensor/src/coinbase/block_emission.rs @@ -30,9 +30,6 @@ impl Pallet { tao_emission: u64, alpha_block_emission: u64, ) -> (u64, u64, u64) { - - // Get the total_alpha_emission for the block - let alpha_block_emission: u64 = Self::get_block_emission_for_issuance(Self::get_alpha_issuance(netuid)).unwrap_or(0); // Init terms. let mut tao_in_emission: I96F32 = I96F32::saturating_from_num(tao_emission); @@ -56,8 +53,8 @@ impl Pallet { float_alpha_block_emission ); - // Scale down tao_in - tao_in_emission = alpha_price.saturating_mul(float_alpha_block_emission); + // // Scale down tao_in + // tao_in_emission = alpha_price.saturating_mul(float_alpha_block_emission); // Set to max alpha_block_emission alpha_in_emission = float_alpha_block_emission; diff --git a/pallets/subtensor/src/coinbase/run_coinbase.rs b/pallets/subtensor/src/coinbase/run_coinbase.rs index 2489f57732..ba9555a71c 100644 --- a/pallets/subtensor/src/coinbase/run_coinbase.rs +++ b/pallets/subtensor/src/coinbase/run_coinbase.rs @@ -141,7 +141,7 @@ impl Pallet { // Get total TAO on root. let root_tao: I96F32 = asfloat!( SubnetTAO::::get(0) ); // Get total ALPHA on subnet. - let alpha_issuance: I96F32 = asfloat!( Self::get_alpha_issuance(netuid)) ; + let alpha_issuance: I96F32 = asfloat!( Self::get_alpha_issuance( *netuid_i )) ; // Get tao_weight let tao_weight: I96F32 = root_tao.saturating_mul(Self::get_tao_weight()); // Get root proportional dividends. diff --git a/pallets/subtensor/src/tests/children.rs b/pallets/subtensor/src/tests/children.rs index d8ff6ffb4f..a7791688ff 100644 --- a/pallets/subtensor/src/tests/children.rs +++ b/pallets/subtensor/src/tests/children.rs @@ -3096,228 +3096,6 @@ fn test_childkey_take_drain_validator_take() { }); } -// 43: Test emission distribution between a childkey and multiple parents -// This test verifies the correct distribution of emissions between a child and multiple parents: -// - Sets up a network with two parents, a child, and a weight setter -// - Establishes parent-child relationships with different stake proportions -// - Sets weights on the child and one parent -// - Runs an epoch -// - Checks the emission distribution among parents, child, and weight setter -// - Verifies that all parties received emissions and the total stake increased correctly -// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::children::test_childkey_multiple_parents_emission --exact --nocapture -#[test] -fn test_childkey_multiple_parents_emission() { - new_test_ext(1).execute_with(|| { - let subnet_owner_coldkey = U256::from(1001); - let subnet_owner_hotkey: U256 = U256::from(1002); - let netuid = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); - Tempo::::insert(netuid, 10); // run epoch every 10 blocks - // Set subnet owner cut to 0 - SubtensorModule::set_subnet_owner_cut(0); - SubtensorModule::set_tao_weight(0); // No TAO weight - - // Set registration parameters and emission tempo - SubtensorModule::set_max_registrations_per_block(netuid, 1000); - SubtensorModule::set_target_registrations_per_interval(netuid, 1000); - - // Define hotkeys and coldkeys - let parent1: U256 = U256::from(1); - let parent2: U256 = U256::from(2); - let child: U256 = U256::from(3); - let weight_setter: U256 = U256::from(4); - let coldkey_parent1: U256 = U256::from(100); - let coldkey_parent2: U256 = U256::from(101); - let coldkey_child: U256 = U256::from(102); - let coldkey_weight_setter: U256 = U256::from(103); - - // Register neurons and add initial stakes - let initial_stakes: Vec<(bool, U256, U256, u64)> = vec![ - (false, coldkey_parent1, parent1, 200_000_000), - (true, coldkey_parent2, parent2, 150_000_000), - (true, coldkey_child, child, 20_000_000), - (true, coldkey_weight_setter, weight_setter, 100_000_000), - ]; - - initial_stakes - .iter() - .for_each(|(register, coldkey, hotkey, stake)| { - SubtensorModule::add_balance_to_coldkey_account(coldkey, *stake); - if *register { - // Register a neuron - register_ok_neuron(netuid, *hotkey, *coldkey, 0); - } else { - // Just create hotkey account - SubtensorModule::create_account_if_non_existent(coldkey, hotkey); - } - assert_ok!(SubtensorModule::add_stake( - RuntimeOrigin::signed(*coldkey), - *hotkey, - netuid, - *stake - )); - }); - - SubtensorModule::set_weights_set_rate_limit(netuid, 0); - step_block(2); - - // Set parent-child relationships - mock_schedule_children(&coldkey_parent1, &parent1, netuid, &[(u64::MAX, child)]); - mock_schedule_children(&coldkey_parent2, &parent2, netuid, &[(u64::MAX / 2, child)]); - wait_and_set_pending_children(netuid); - ChildkeyTake::::insert(child, netuid, u16::MAX / 5); - - // Set pending emission to 0 - PendingEmission::::insert(netuid, 0); - - let initial_actual_stakes: Vec = initial_stakes - .iter() - .map(|(_register, coldkey, hotkey, _stake)| { - // Return actual stake - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(hotkey, coldkey, netuid) - }) - .collect(); - - // Set weights (subnet owner is uid 0, ignore him) - let uids: Vec = vec![1, 2]; - let values: Vec = vec![65354, 65354]; - let version_key = SubtensorModule::get_weights_version_key(netuid); - ValidatorPermit::::insert(netuid, vec![true, true, true, true]); - assert_ok!(SubtensorModule::set_weights( - RuntimeOrigin::signed(weight_setter), - netuid, - uids, - values, - version_key - )); - log::info!("Running an epoch"); - // Wait until epoch - let start_block = SubtensorModule::get_current_block_as_u64(); - loop { - let current_block = SubtensorModule::get_current_block_as_u64(); - if SubtensorModule::should_run_epoch(netuid, current_block) { - step_block(1); - break; - } - step_block(1); - } - // We substract one because we are running it *after* the epoch, so we don't expect it to effect the emission. - let blocks_passed = SubtensorModule::get_current_block_as_u64() - start_block - 1; - log::info!("blocks_passed: {:?}", blocks_passed); - let alpha_block_emission: u64 = SubtensorModule::get_block_emission_for_issuance( - SubtensorModule::get_alpha_issuance(netuid), - ) - .unwrap_or(0); - let (_, _, per_block_emission) = SubtensorModule::get_dynamic_tao_emission( - netuid, - SubtensorModule::get_block_emission().unwrap_or(0), - alpha_block_emission, - ); - let total_emission = per_block_emission * blocks_passed; - - // Check emission distribution - let stakes: Vec<(U256, U256, &str)> = vec![ - (coldkey_parent1, parent1, "Parent1"), - (coldkey_parent2, parent2, "Parent2"), - (coldkey_child, child, "Child"), - (coldkey_weight_setter, weight_setter, "Weight setter"), - ]; - - for (coldkey, hotkey, name) in stakes.iter() { - let stake_on_subnet = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( - hotkey, coldkey, netuid, - ); - log::debug!("{} stake on subnet: {:?}", name, stake_on_subnet); - } - - let parent1_stake = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( - &parent1, - &coldkey_parent1, - netuid, - ); - let parent2_stake = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( - &parent2, - &coldkey_parent2, - netuid, - ); - let child_stake = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( - &child, - &coldkey_child, - netuid, - ); - let weight_setter_stake = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( - &weight_setter, - &coldkey_weight_setter, - netuid, - ); - - assert!( - parent1_stake > initial_actual_stakes[0], - "Parent1 should have received emission" - ); - assert!( - parent2_stake > initial_actual_stakes[1], - "Parent2 should have received emission" - ); - assert!( - child_stake > initial_actual_stakes[2], - "Child should have received emission" - ); - assert!( - weight_setter_stake > initial_actual_stakes[3], - "Weight setter should have received emission" - ); - - // Check individual stake increases - let parent1_stake_increase = parent1_stake - initial_actual_stakes[0]; - let parent2_stake_increase = parent2_stake - initial_actual_stakes[1]; - let child_stake_increase = child_stake - initial_actual_stakes[2]; - - log::debug!( - "Stake increases - Parent1: {}, Parent2: {}, Child: {}", - parent1_stake_increase, - parent2_stake_increase, - child_stake_increase - ); - - // Assert that all neurons received some emission - assert!( - parent1_stake_increase > 0, - "Parent1 should have received some emission" - ); - assert!( - parent2_stake_increase > 0, - "Parent2 should have received some emission" - ); - assert!( - child_stake_increase > 0, - "Child should have received some emission" - ); - - let mut total_stake_on_subnet = 0; - let hks = [parent1, parent2, child, weight_setter]; - for (hk, net, alpha) in TotalHotkeyAlpha::::iter() { - if hks.contains(&hk) && net == netuid { - total_stake_on_subnet += alpha; - } else { - log::info!("hk: {:?}, net: {:?}, alpha: {:?}", hk, net, alpha); - } - } - - log::info!("total_stake_on_subnet: {:?}", total_stake_on_subnet); - log::info!("total_stake: {:?}", TotalStake::::get()); - log::info!("total_emission: {:?}", total_emission); - // Check that the total stake has increased by the emission amount - // Allow 1% slippage - let total_stake = parent1_stake + parent2_stake + child_stake + weight_setter_stake; - let initial_total_stake: u64 = initial_actual_stakes.iter().sum::(); - assert_abs_diff_eq!( - total_stake, - initial_total_stake + total_emission, - epsilon = total_emission / 100, - ); - }); -} - // 44: Test with a chain of parent-child relationships (e.g., A -> B -> C) // This test verifies the correct distribution of emissions in a chain of parent-child relationships: // - Sets up a network with three neurons A, B, and C in a chain (A -> B -> C) diff --git a/pallets/subtensor/src/tests/coinbase.rs b/pallets/subtensor/src/tests/coinbase.rs index b3042676d6..f34cf3c761 100644 --- a/pallets/subtensor/src/tests/coinbase.rs +++ b/pallets/subtensor/src/tests/coinbase.rs @@ -40,9 +40,9 @@ fn test_dynamic_function_various_values() { assert!(alpha_out_emission <= 2 * alpha_emission, "alpha_out_emission is greater than 2 * alpha_emission"); assert!((alpha_in_emission + alpha_out_emission) <= 2 * alpha_emission, "Sum of alpha_in_emission and alpha_out_emission is less than or equal to. 2 * alpha_emission"); close( alpha_in_emission + alpha_out_emission, alpha_in_emission + alpha_emission, 10 ); - if alpha_in_emission > 0 || tao_in_emission > 0 { - assert!((tao_in_emission as f64 / alpha_in_emission as f64 - price).abs() < 1e-1, "Ratio of tao_in_emission to alpha_in_emission is not equal to price"); - } + // if alpha_in_emission > 0 || tao_in_emission > 0 { + // assert!((tao_in_emission as f64 / alpha_in_emission as f64 - price).abs() < 1e-1, "Ratio of tao_in_emission to alpha_in_emission is not equal to price"); + // } } } } From f29c7366765add2db14a35907c70ea884b57d371 Mon Sep 17 00:00:00 2001 From: unconst Date: Wed, 5 Feb 2025 11:22:12 -0500 Subject: [PATCH 17/34] no tao in for non registration --- pallets/subtensor/src/coinbase/run_coinbase.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pallets/subtensor/src/coinbase/run_coinbase.rs b/pallets/subtensor/src/coinbase/run_coinbase.rs index ba9555a71c..c61d52e3e0 100644 --- a/pallets/subtensor/src/coinbase/run_coinbase.rs +++ b/pallets/subtensor/src/coinbase/run_coinbase.rs @@ -74,6 +74,12 @@ impl Pallet { log::debug!("alpha_in_i: {:?}", alpha_in_i); // Get alpha_out. let alpha_out_i = alpha_emission_i; + // Only emit TAO if the subnetwork allows registration. + if !Self::get_network_registration_allowed(*netuid) + && Self::get_network_pow_registration_allowed(*netuid) + { + tao_in_i = asfloat!( 0.0 ); + } // Insert values into maps tao_in.insert(*netuid_i, tao_in_i); alpha_in.insert(*netuid_i, alpha_in_i); From ee37f6d7a56927c65366c8ad7282e5565e9f05cd Mon Sep 17 00:00:00 2001 From: unconst Date: Wed, 5 Feb 2025 11:50:37 -0500 Subject: [PATCH 18/34] move to moving prices rather than tao reserves --- .../subtensor/src/coinbase/run_coinbase.rs | 19 ++++++++++--------- pallets/subtensor/src/lib.rs | 16 ++++++++++++++-- pallets/subtensor/src/staking/stake_utils.rs | 19 +++++++++++++++++++ 3 files changed, 43 insertions(+), 11 deletions(-) diff --git a/pallets/subtensor/src/coinbase/run_coinbase.rs b/pallets/subtensor/src/coinbase/run_coinbase.rs index c61d52e3e0..886250eca4 100644 --- a/pallets/subtensor/src/coinbase/run_coinbase.rs +++ b/pallets/subtensor/src/coinbase/run_coinbase.rs @@ -44,12 +44,13 @@ impl Pallet { log::debug!("All subnet netuids: {:?}", subnets); // --- 2. Get sum of tao reserves ( in a later version we will switch to prices. ) - let mut tao_sum: I96F32 = I96F32::from_num(0.0); + let mut total_moving_prices: I96F32 = I96F32::from_num(0.0); for netuid_i in subnets.iter() { - // Get and add subnet TAO in reserve. - tao_sum = tao_sum.saturating_add( asfloat!( SubnetTAO::::get(netuid_i)) ); + // Get and update the moving price of each subnet adding the total together. + Self::update_moving_price( *netuid_i ); + total_moving_prices = total_moving_prices.saturating_add( Self::get_moving_alpha_price( *netuid_i ) ); } - log::debug!("tao_sum: {:?}", tao_sum); + log::debug!("total_moving_prices: {:?}", total_moving_prices); // --- 3. Get subnet terms (tao_in, alpha_in, and alpha_out) // Computation is described in detail in the dtao whitepaper. @@ -61,10 +62,10 @@ impl Pallet { let price_i: I96F32 = Self::get_alpha_price(*netuid_i); log::debug!("price_i: {:?}", price_i); // Get subnet TAO. - let subnet_tao_i: I96F32 = asfloat!( SubnetTAO::::get(netuid_i) ); - log::debug!("subnet_tao_i: {:?}", subnet_tao_i); + let moving_price_i: I96F32 = Self::get_moving_alpha_price( *netuid_i ); + log::debug!("moving_price_i: {:?}", moving_price_i); // Emission is price over total. - let tao_in_i: I96F32 = block_emission.saturating_mul(subnet_tao_i).checked_div(tao_sum).unwrap_or(asfloat!(0.0)); + let mut tao_in_i: I96F32 = block_emission.saturating_mul(moving_price_i).checked_div(total_moving_prices).unwrap_or(asfloat!(0.0)); log::debug!("tao_in_i: {:?}", tao_in_i); // Get alpha_emission total let alpha_emission_i: I96F32 = asfloat!(Self::get_block_emission_for_issuance(Self::get_alpha_issuance(*netuid_i)).unwrap_or(0)); @@ -75,8 +76,8 @@ impl Pallet { // Get alpha_out. let alpha_out_i = alpha_emission_i; // Only emit TAO if the subnetwork allows registration. - if !Self::get_network_registration_allowed(*netuid) - && Self::get_network_pow_registration_allowed(*netuid) + if !Self::get_network_registration_allowed(*netuid_i) + && Self::get_network_pow_registration_allowed(*netuid_i) { tao_in_i = asfloat!( 0.0 ); } diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index 87f5ac8fe4..16c4039f20 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -732,6 +732,16 @@ pub mod pallet { T::InitialDissolveNetworkScheduleDuration::get() } + #[pallet::type_value] + /// Default moving alpha for the moving price. + pub fn DefaultMovingAlpha() -> I96F32 { + I96F32::saturating_from_num(0.0001) + } + #[pallet::type_value] + /// Default subnet moving price. + pub fn DefaultMovingPrice() -> I96F32 { + I96F32::saturating_from_num(0.0) + } #[pallet::type_value] /// Default value for Share Pool variables pub fn DefaultSharePoolZero() -> U64F64 { @@ -904,14 +914,16 @@ pub mod pallet { /// /// Eventually, Bittensor should migrate to using Holds afterwhich time we will not require this /// separate accounting. - #[pallet::storage] // --- ITEM ( paused_coinbase ) - pub type PendingBlockEmission = StorageValue<_, u64, ValueQuery, DefaultZeroU64>; #[pallet::storage] // --- ITEM ( total_issuance ) pub type TotalIssuance = StorageValue<_, u64, ValueQuery, DefaultTotalIssuance>; #[pallet::storage] // --- ITEM ( total_stake ) pub type TotalStake = StorageValue<_, u64, ValueQuery>; #[pallet::storage] // --- ITEM ( dynamic_block ) -- block when dynamic was turned on. pub type DynamicBlock = StorageValue<_, u64, ValueQuery>; + #[pallet::storage] // --- ITEM ( moving_alpha ) -- subnet moving alpha. + pub type SubnetMovingAlpha = StorageValue<_, I96F32, ValueQuery, DefaultMovingAlpha>; + #[pallet::storage] // --- MAP ( netuid ) --> moving_price | The subnet moving price. + pub type SubnetMovingPrice = StorageMap<_, Identity, u16, I96F32, ValueQuery, DefaultMovingPrice>; #[pallet::storage] // --- MAP ( netuid ) --> total_volume | The total amount of TAO bought and sold since the start of the network. pub type SubnetVolume = StorageMap<_, Identity, u16, u128, ValueQuery, DefaultZeroU128>; diff --git a/pallets/subtensor/src/staking/stake_utils.rs b/pallets/subtensor/src/staking/stake_utils.rs index b4b650804a..1db6f390a5 100644 --- a/pallets/subtensor/src/staking/stake_utils.rs +++ b/pallets/subtensor/src/staking/stake_utils.rs @@ -45,6 +45,25 @@ impl Pallet { .unwrap_or(I96F32::saturating_from_num(0)) } } + pub fn get_moving_alpha_price(netuid: u16) -> I96F32 { + if netuid == Self::get_root_netuid() { + return I96F32::saturating_from_num(1.0); // Root. + } + else if SubnetMechanism::::get(netuid) == 0 { + return I96F32::saturating_from_num(1.0); // Stable + } + else { + return SubnetMovingPrice::::get( netuid ); + } + } + pub fn update_moving_price( netuid: u16 ) { + let alpha: I96F32 = SubnetMovingAlpha::::get(); + let minus_alpha: I96F32 = I96F32::saturating_from_num(1.0).saturating_sub(alpha); + let current_price: I96F32 = alpha.saturating_mul( Self::get_alpha_price(netuid) ); + let current_moving: I96F32 = minus_alpha.saturating_mul( Self::get_moving_alpha_price(netuid) ); + let new_moving: I96F32 = current_price.saturating_add( current_moving ); + SubnetMovingPrice::::insert( netuid, new_moving); + } /// Retrieves the global global weight as a normalized value between 0 and 1. /// From e252e902c45088a2308fcd4ac54ac7cd0a77ee17 Mon Sep 17 00:00:00 2001 From: unconst Date: Wed, 5 Feb 2025 12:12:35 -0500 Subject: [PATCH 19/34] price --- pallets/subtensor/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index 16c4039f20..4f7ee2ee5d 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -735,7 +735,7 @@ pub mod pallet { #[pallet::type_value] /// Default moving alpha for the moving price. pub fn DefaultMovingAlpha() -> I96F32 { - I96F32::saturating_from_num(0.0001) + I96F32::saturating_from_num(0.00001) } #[pallet::type_value] /// Default subnet moving price. From b2639e752e8f1c15cb656cbe98fab8e78fdc932b Mon Sep 17 00:00:00 2001 From: unconst Date: Wed, 5 Feb 2025 12:26:11 -0500 Subject: [PATCH 20/34] moving alpha --- pallets/subtensor/src/lib.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index 4f7ee2ee5d..b858b5914e 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -735,17 +735,19 @@ pub mod pallet { #[pallet::type_value] /// Default moving alpha for the moving price. pub fn DefaultMovingAlpha() -> I96F32 { - I96F32::saturating_from_num(0.00001) + // Moving average take 30 days to reach 50% of the price + // and 3.5 months to reach 90%. + I96F32::saturating_from_num( 0.000003 ) } #[pallet::type_value] /// Default subnet moving price. pub fn DefaultMovingPrice() -> I96F32 { - I96F32::saturating_from_num(0.0) + I96F32::saturating_from_num( 0.0 ) } #[pallet::type_value] /// Default value for Share Pool variables pub fn DefaultSharePoolZero() -> U64F64 { - U64F64::saturating_from_num(0) + U64F64::saturating_from_num( 0 ) } #[pallet::type_value] From 6c946db3a919b13c43c987e5df16fed7c4b548f4 Mon Sep 17 00:00:00 2001 From: JohnReedV <87283488+JohnReedV@users.noreply.github.com> Date: Wed, 5 Feb 2025 09:46:36 -0800 Subject: [PATCH 21/34] 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 a9a4bd2ca8..25f01692a8 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -229,7 +229,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: 226, + spec_version: 227, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From ea355f280539bd99a8c829e277130b0c45473c46 Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Wed, 5 Feb 2025 13:04:11 -0500 Subject: [PATCH 22/34] Fix tests --- pallets/subtensor/src/tests/children.rs | 131 ++++++++++++++---------- pallets/subtensor/src/tests/mock.rs | 9 ++ 2 files changed, 86 insertions(+), 54 deletions(-) diff --git a/pallets/subtensor/src/tests/children.rs b/pallets/subtensor/src/tests/children.rs index a7791688ff..036a33696c 100644 --- a/pallets/subtensor/src/tests/children.rs +++ b/pallets/subtensor/src/tests/children.rs @@ -1554,18 +1554,20 @@ fn test_set_network_max_stake_update() { #[test] fn test_children_stake_values() { new_test_ext(1).execute_with(|| { + let subnet_owner_coldkey = U256::from(1001); + let subnet_owner_hotkey = U256::from(1002); + let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let coldkey = U256::from(1); let hotkey = U256::from(2); let child1 = U256::from(3); let child2 = U256::from(4); let child3 = U256::from(5); - let netuid: u16 = 1; let proportion1: u64 = u64::MAX / 4; let proportion2: u64 = u64::MAX / 4; let proportion3: u64 = u64::MAX / 4; // Add network and register hotkey - add_network(netuid, 13, 0); SubtensorModule::set_max_registrations_per_block(netuid, 4); SubtensorModule::set_target_registrations_per_interval(netuid, 4); register_ok_neuron(netuid, hotkey, coldkey, 0); @@ -1580,10 +1582,9 @@ fn test_children_stake_values() { ); // Set multiple children with proportions. - mock_set_children( - &coldkey, - &hotkey, + mock_set_children_no_epochs( netuid, + &hotkey, &[ (proportion1, child1), (proportion2, child2), @@ -1830,20 +1831,20 @@ fn test_get_stake_for_hotkey_on_subnet_multiple_coldkeys() { #[test] fn test_get_stake_for_hotkey_on_subnet_single_parent_child() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let subnet_owner_coldkey = U256::from(1001); + let subnet_owner_hotkey = U256::from(1002); let parent = U256::from(1); let child = U256::from(2); let coldkey = U256::from(3); - - add_network(netuid, 1, 0); + let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); register_ok_neuron(netuid, parent, coldkey, 0); register_ok_neuron(netuid, child, coldkey, 0); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &parent, &coldkey, netuid, 1000, + &parent, &coldkey, netuid, 1_000_000_000, ); - mock_set_children(&coldkey, &parent, netuid, &[(u64::MAX, child)]); + mock_set_children_no_epochs(netuid, &parent, &[(u64::MAX, child)]); assert_eq!( SubtensorModule::get_inherited_for_hotkey_on_subnet(&parent, netuid), @@ -1851,7 +1852,7 @@ fn test_get_stake_for_hotkey_on_subnet_single_parent_child() { ); assert_eq!( SubtensorModule::get_inherited_for_hotkey_on_subnet(&child, netuid), - 1000 + 1_000_000_000 ); }); } @@ -1867,13 +1868,15 @@ fn test_get_stake_for_hotkey_on_subnet_single_parent_child() { #[test] fn test_get_stake_for_hotkey_on_subnet_multiple_parents_single_child() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let subnet_owner_coldkey = U256::from(1001); + let subnet_owner_hotkey = U256::from(1002); + let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let parent1 = U256::from(1); let parent2 = U256::from(2); let child = U256::from(3); let coldkey = U256::from(4); - add_network(netuid, 1, 0); register_ok_neuron(netuid, parent1, coldkey, 0); register_ok_neuron(netuid, parent2, coldkey, 0); register_ok_neuron(netuid, child, coldkey, 0); @@ -1885,8 +1888,8 @@ fn test_get_stake_for_hotkey_on_subnet_multiple_parents_single_child() { &parent2, &coldkey, netuid, 2000, ); - mock_set_children(&coldkey, &parent1, netuid, &[(u64::MAX / 2, child)]); - mock_set_children(&coldkey, &parent2, netuid, &[(u64::MAX / 2, child)]); + mock_set_children_no_epochs(netuid, &parent1, &[(u64::MAX / 2, child)]); + mock_set_children_no_epochs(netuid, &parent2, &[(u64::MAX / 2, child)]); close( SubtensorModule::get_inherited_for_hotkey_on_subnet(&parent1, netuid), @@ -1920,13 +1923,15 @@ fn test_get_stake_for_hotkey_on_subnet_multiple_parents_single_child() { #[test] fn test_get_stake_for_hotkey_on_subnet_single_parent_multiple_children() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let subnet_owner_coldkey = U256::from(1001); + let subnet_owner_hotkey = U256::from(1002); + let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let parent = U256::from(1); let child1 = U256::from(2); let child2 = U256::from(3); let coldkey = U256::from(4); - add_network(netuid, 1, 0); register_ok_neuron(netuid, parent, coldkey, 0); register_ok_neuron(netuid, child1, coldkey, 0); register_ok_neuron(netuid, child2, coldkey, 0); @@ -1939,10 +1944,9 @@ fn test_get_stake_for_hotkey_on_subnet_single_parent_multiple_children() { total_stake, ); - mock_set_children( - &coldkey, - &parent, + mock_set_children_no_epochs( netuid, + &parent, &[(u64::MAX / 3, child1), (u64::MAX / 3, child2)], ); @@ -1983,13 +1987,15 @@ fn test_get_stake_for_hotkey_on_subnet_single_parent_multiple_children() { #[test] fn test_get_stake_for_hotkey_on_subnet_edge_cases() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let subnet_owner_coldkey = U256::from(1001); + let subnet_owner_hotkey = U256::from(1002); + let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let parent = U256::from(1); let child1 = U256::from(2); let child2 = U256::from(3); let coldkey = U256::from(4); - add_network(netuid, 1, 0); register_ok_neuron(netuid, parent, coldkey, 0); register_ok_neuron(netuid, child1, coldkey, 0); register_ok_neuron(netuid, child2, coldkey, 0); @@ -2007,10 +2013,9 @@ fn test_get_stake_for_hotkey_on_subnet_edge_cases() { ); // Test with 0% and 100% stake allocation - mock_set_children( - &coldkey, - &parent, + mock_set_children_no_epochs( netuid, + &parent, &[(0, child1), (u64::MAX, child2)], ); @@ -2051,7 +2056,10 @@ fn test_get_stake_for_hotkey_on_subnet_edge_cases() { #[test] fn test_get_stake_for_hotkey_on_subnet_complex_hierarchy() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; + let subnet_owner_coldkey = U256::from(1001); + let subnet_owner_hotkey = U256::from(1002); + let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let parent = U256::from(1); let child1 = U256::from(2); let child2 = U256::from(3); @@ -2061,7 +2069,6 @@ fn test_get_stake_for_hotkey_on_subnet_complex_hierarchy() { let coldkey_child2 = U256::from(7); let coldkey_grandchild = U256::from(8); - add_network(netuid, 1, 0); SubtensorModule::set_max_registrations_per_block(netuid, 1000); SubtensorModule::set_target_registrations_per_interval(netuid, 1000); register_ok_neuron(netuid, parent, coldkey_parent, 0); @@ -2096,10 +2103,9 @@ fn test_get_stake_for_hotkey_on_subnet_complex_hierarchy() { ); // Step 1: Set children for parent - mock_set_children( - &coldkey_parent, - &parent, + mock_set_children_no_epochs( netuid, + &parent, &[(u64::MAX / 2, child1), (u64::MAX / 2, child2)], ); @@ -2133,7 +2139,7 @@ fn test_get_stake_for_hotkey_on_subnet_complex_hierarchy() { close(child2_stake_1, 499, 10, "Child2 should have 499 stake"); // Step 2: Set children for child1 - mock_set_children(&coldkey_child1, &child1, netuid, &[(u64::MAX, grandchild)]); + mock_set_children_no_epochs(netuid, &child1, &[(u64::MAX, grandchild)]); log::info!("After setting child1's children:"); log::info!( @@ -2810,8 +2816,9 @@ fn test_childkey_set_weights_single_parent() { fn test_set_weights_no_parent() { // Verify that a regular key without a parent delegation is effected by the minimum stake requirements new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; - add_network(netuid, 1, 0); + let subnet_owner_coldkey = U256::from(1001); + let subnet_owner_hotkey = U256::from(1002); + let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); let hotkey: U256 = U256::from(2); let spare_hk: U256 = U256::from(3); @@ -3108,8 +3115,15 @@ fn test_childkey_take_drain_validator_take() { #[test] fn test_parent_child_chain_emission() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; - add_network(netuid, 1, 0); + let subnet_owner_coldkey = U256::from(1001); + let subnet_owner_hotkey = U256::from(1002); + let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + Tempo::::insert(netuid, 1); + + // Setup large LPs to prevent slippage + SubnetTAO::::insert(netuid, 1_000_000_000_000_000); + SubnetAlphaIn::::insert(netuid, 1_000_000_000_000_000); + // Set owner cut to 0 SubtensorModule::set_subnet_owner_cut(0_u16); @@ -3132,7 +3146,10 @@ fn test_parent_child_chain_emission() { SubtensorModule::add_balance_to_coldkey_account(&coldkey_c, 1_000); // Swap to alpha - let total_tao: I96F32 = I96F32::from_num(300_000 + 100_000 + 50_000); + let stake_a = 300_000_000_000_u64; + let stake_b = 100_000_000_000_u64; + let stake_c = 50_000_000_000_u64; + let total_tao: I96F32 = I96F32::from_num(stake_a + stake_b + stake_c); let total_alpha: I96F32 = I96F32::from_num(SubtensorModule::swap_tao_for_alpha( netuid, total_tao.to_num::(), @@ -3144,19 +3161,19 @@ fn test_parent_child_chain_emission() { &hotkey_a, &coldkey_a, netuid, - (total_alpha * I96F32::from_num(300_000) / total_tao).saturating_to_num::(), + (total_alpha * I96F32::from_num(stake_a) / total_tao).saturating_to_num::(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey_b, &coldkey_b, netuid, - (total_alpha * I96F32::from_num(100_000) / total_tao).saturating_to_num::(), + (total_alpha * I96F32::from_num(stake_b) / total_tao).saturating_to_num::(), ); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey_c, &coldkey_c, netuid, - (total_alpha * I96F32::from_num(50_000) / total_tao).saturating_to_num::(), + (total_alpha * I96F32::from_num(stake_c) / total_tao).saturating_to_num::(), ); // Get old stakes @@ -3174,17 +3191,22 @@ fn test_parent_child_chain_emission() { log::info!("rel_stake_a: {:?}", rel_stake_a); // 0.6666 -> 2/3 log::info!("rel_stake_b: {:?}", rel_stake_b); // 0.2222 -> 2/9 log::info!("rel_stake_c: {:?}", rel_stake_c); // 0.1111 -> 1/9 - assert_eq!(rel_stake_a, I96F32::from_num(300_000) / total_tao); - assert_eq!(rel_stake_b, I96F32::from_num(100_000) / total_tao); - assert_eq!(rel_stake_c, I96F32::from_num(50_000) / total_tao); + assert!( + (rel_stake_a - I96F32::from_num(stake_a) / total_tao).abs() < 0.001 + ); + assert!( + (rel_stake_b - I96F32::from_num(stake_b) / total_tao).abs() < 0.001 + ); + assert!( + (rel_stake_c - I96F32::from_num(stake_c) / total_tao).abs() < 0.001 + ); // Set parent-child relationships // A -> B (50% of A's stake) - mock_schedule_children(&coldkey_a, &hotkey_a, netuid, &[(u64::MAX / 2, hotkey_b)]); + mock_set_children_no_epochs(netuid, &hotkey_a, &[(u64::MAX / 2, hotkey_b)]); // B -> C (50% of B's stake) - mock_schedule_children(&coldkey_b, &hotkey_b, netuid, &[(u64::MAX / 2, hotkey_c)]); - wait_and_set_pending_children(netuid); // Don't want to run blocks before both children are scheduled + mock_set_children_no_epochs(netuid, &hotkey_b, &[(u64::MAX / 2, hotkey_c)]); // Get old stakes after children are scheduled let stake_a_old: u64 = SubtensorModule::get_total_stake_for_hotkey(&hotkey_a); @@ -3192,6 +3214,10 @@ fn test_parent_child_chain_emission() { let stake_c_old: u64 = SubtensorModule::get_total_stake_for_hotkey(&hotkey_c); let total_stake_old: I96F32 = I96F32::from_num(stake_a_old + stake_b_old + stake_c_old); + log::info!("Old stake for hotkey A: {:?}", stake_a_old); + log::info!("Old stake for hotkey B: {:?}", stake_b_old); + log::info!("Old stake for hotkey C: {:?}", stake_c_old); + log::info!("Total old stake: {:?}", total_stake_old); // Set CHK take rate to 1/9 let chk_take: I96F32 = I96F32::from_num(1_f64 / 9_f64); @@ -3203,8 +3229,6 @@ fn test_parent_child_chain_emission() { SubtensorModule::set_tao_weight(0); let hardcoded_emission: I96F32 = I96F32::from_num(1_000_000); // 1 million (adjust as needed) - let emission_as_alpha = - I96F32::from_num(hardcoded_emission) / SubtensorModule::get_alpha_price(netuid); // Set pending emission to 0 PendingEmission::::insert(netuid, 0); @@ -3238,8 +3262,8 @@ fn test_parent_child_chain_emission() { // Verify the final stake distribution let stake_inc_eps: I96F32 = I96F32::from_num(1e-4); // 4 decimal places - // Each child has chk_take take - + + // Each child has chk_take take let expected_a = I96F32::from_num(2_f64 / 3_f64) * (I96F32::from_num(1_f64) - (I96F32::from_num(1_f64 / 2_f64) * chk_take)); assert!( @@ -3289,11 +3313,10 @@ fn test_parent_child_chain_emission() { total_stake_new ); - let eps: I96F32 = I96F32::from_num(10_000); - assert!( - (total_stake_new - (total_stake_old + emission_as_alpha)).abs() <= eps, - "Total stake should have increased by the hardcoded emission amount {:?}", - total_stake_new - (total_stake_old + emission_as_alpha) + assert_abs_diff_eq!( + total_stake_inc.to_num::(), + hardcoded_emission.to_num::(), + epsilon = 10_000, ); }); } diff --git a/pallets/subtensor/src/tests/mock.rs b/pallets/subtensor/src/tests/mock.rs index b0d7c461ad..be22926239 100644 --- a/pallets/subtensor/src/tests/mock.rs +++ b/pallets/subtensor/src/tests/mock.rs @@ -727,6 +727,15 @@ pub fn mock_set_children(coldkey: &U256, parent: &U256, netuid: u16, child_vec: wait_and_set_pending_children(netuid); } +#[allow(dead_code)] +pub fn mock_set_children_no_epochs(netuid: u16, parent: &U256, child_vec: &[(u64, U256)]) { + let backup_block = SubtensorModule::get_current_block_as_u64(); + PendingChildKeys::::insert(netuid, parent, (child_vec, 0)); + System::set_block_number(1); + SubtensorModule::do_set_pending_children(netuid); + System::set_block_number(backup_block); +} + // Helper function to wait for the rate limit #[allow(dead_code)] pub fn step_rate_limit(transaction_type: &TransactionType, netuid: u16) { From f91e7ca441806cab3d67128ccb5d57729cd2b0d6 Mon Sep 17 00:00:00 2001 From: unconst Date: Wed, 5 Feb 2025 13:10:38 -0500 Subject: [PATCH 23/34] add moving price tests --- .../subtensor/src/coinbase/run_coinbase.rs | 7 +- pallets/subtensor/src/tests/coinbase.rs | 134 ++++++++++++++++++ 2 files changed, 140 insertions(+), 1 deletion(-) diff --git a/pallets/subtensor/src/coinbase/run_coinbase.rs b/pallets/subtensor/src/coinbase/run_coinbase.rs index 886250eca4..9add02e932 100644 --- a/pallets/subtensor/src/coinbase/run_coinbase.rs +++ b/pallets/subtensor/src/coinbase/run_coinbase.rs @@ -47,7 +47,6 @@ impl Pallet { let mut total_moving_prices: I96F32 = I96F32::from_num(0.0); for netuid_i in subnets.iter() { // Get and update the moving price of each subnet adding the total together. - Self::update_moving_price( *netuid_i ); total_moving_prices = total_moving_prices.saturating_add( Self::get_moving_alpha_price( *netuid_i ) ); } log::debug!("total_moving_prices: {:?}", total_moving_prices); @@ -180,6 +179,12 @@ impl Pallet { }); } + // --- 7 Update moving prices after using them in the emission calculation. + for netuid_i in subnets.iter() { + // Update moving prices after using them above. + Self::update_moving_price( *netuid_i ); + } + // --- 7. Drain pending emission through the subnet based on tempo. for &netuid in subnets.iter() { // Pass on subnets that have not reached their tempo. diff --git a/pallets/subtensor/src/tests/coinbase.rs b/pallets/subtensor/src/tests/coinbase.rs index f34cf3c761..82ab6b1b3e 100644 --- a/pallets/subtensor/src/tests/coinbase.rs +++ b/pallets/subtensor/src/tests/coinbase.rs @@ -49,3 +49,137 @@ fn test_dynamic_function_various_values() { }); } + +// Test the base case of running coinbase with zero emission. +// This test verifies that the coinbase mechanism can handle the edge case +// of zero emission without errors or unexpected behavior. +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_coinbase_basecase --exact --show-output --nocapture +#[test] +fn test_coinbase_basecase() { + new_test_ext(1).execute_with(|| { + SubtensorModule::run_coinbase( I96F32::from_num(0.0) ); + }); +} + +// Test the emission distribution for a single subnet. +// This test verifies that: +// - A single subnet receives the full emission amount +// - The emission is correctly reflected in SubnetTAO +// - Total issuance and total stake are updated appropriately +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_coinbase_tao_issuance_base --exact --show-output --nocapture +#[test] +fn test_coinbase_tao_issuance_base() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + let emission: u64 = 1_234_567; + add_network(netuid, 1, 0); + assert_eq!( SubnetTAO::::get( netuid ), 0); + SubtensorModule::run_coinbase( I96F32::from_num( emission ) ); + assert_eq!( SubnetTAO::::get( netuid ), emission); + assert_eq!( TotalIssuance::::get(), emission); + assert_eq!( TotalStake::::get(), emission); + }); +} + +// Test emission distribution across multiple subnets. +// This test verifies that: +// - Multiple subnets receive equal portions of the total emission +// - Each subnet's TAO balance is updated correctly +// - Total issuance and total stake reflect the full emission amount +// - The emission is split evenly between all subnets +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_coinbase_tao_issuance_multiple --exact --show-output --nocapture +#[test] +fn test_coinbase_tao_issuance_multiple() { + new_test_ext(1).execute_with(|| { + let netuid1: u16 = 1; + let netuid2: u16 = 2; + let netuid3: u16 = 3; + let emission: u64 = 3_333_333; + add_network(netuid1, 1, 0); + add_network(netuid2, 1, 0); + add_network(netuid3, 1, 0); + assert_eq!( SubnetTAO::::get( netuid1 ), 0); + assert_eq!( SubnetTAO::::get( netuid2 ), 0); + assert_eq!( SubnetTAO::::get( netuid3 ), 0); + SubtensorModule::run_coinbase( I96F32::from_num( emission ) ); + assert_eq!( SubnetTAO::::get( netuid1 ), emission/3); + assert_eq!( SubnetTAO::::get( netuid2 ), emission/3); + assert_eq!( SubnetTAO::::get( netuid3 ), emission/3); + assert_eq!( TotalIssuance::::get(), emission); + assert_eq!( TotalStake::::get(), emission); + }); +} + +// Test emission distribution with different subnet prices. +// This test verifies that: +// - Subnets with different prices receive proportional emission shares +// - A subnet with double the price receives double the emission +// - Total issuance and total stake reflect the full emission amount +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_coinbase_tao_issuance_different_prices --exact --show-output --nocapture +#[test] +fn test_coinbase_tao_issuance_different_prices() { + new_test_ext(1).execute_with(|| { + let netuid1: u16 = 1; + let netuid2: u16 = 2; + let emission: u64 = 100_000_000; + add_network(netuid1, 1, 0); + add_network(netuid2, 1, 0); + // Make subnets dynamic. + SubnetMechanism::::insert(netuid1, 1); + SubnetMechanism::::insert(netuid2, 1); + // Set subnet prices. + SubnetMovingPrice::::insert( netuid1, I96F32::from_num(1) ); + SubnetMovingPrice::::insert( netuid2, I96F32::from_num(2) ); + // Assert initial TAO reserves. + assert_eq!( SubnetTAO::::get( netuid1 ), 0); + assert_eq!( SubnetTAO::::get( netuid2 ), 0); + // Run the coinbase with the emission amount. + SubtensorModule::run_coinbase( I96F32::from_num( emission ) ); + // Assert tao emission is split evenly. + assert_eq!( SubnetTAO::::get( netuid1 ), emission/3 ); + assert_eq!( SubnetTAO::::get( netuid2 ), emission/3 + emission/3); + close( TotalIssuance::::get(), emission, 2); + close( TotalStake::::get(), emission, 2); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_coinbase_moving_prices --exact --show-output --nocapture +#[test] +fn test_coinbase_moving_prices() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + add_network(netuid, 1, 0); + // Set price to 1.0 + SubnetTAO::::insert(netuid, 1_000_000); + SubnetAlphaIn::::insert(netuid, 1_000_000); + SubnetMechanism::::insert(netuid, 1); + SubnetMovingPrice::::insert( netuid, I96F32::from_num(1) ); + // Updating the moving price keeps it the same. + assert_eq!( SubtensorModule::get_moving_alpha_price(netuid), I96F32::from_num(1) ); + SubtensorModule::update_moving_price( netuid ); + assert_eq!( SubtensorModule::get_moving_alpha_price(netuid), I96F32::from_num(1) ); + // Check alpha of 1. + // Set price to zero. + SubnetMovingPrice::::insert( netuid, I96F32::from_num(0) ); + SubnetMovingAlpha::::set( I96F32::from_num(1.0) ); + // Run moving 1 times. + SubtensorModule::update_moving_price( netuid ); + // Assert price is == 100% of the real price. + assert_eq!( SubtensorModule::get_moving_alpha_price(netuid), I96F32::from_num(1.0) ); + // Set price to zero. + SubnetMovingPrice::::insert( netuid, I96F32::from_num(0) ); + SubnetMovingAlpha::::set( I96F32::from_num(0.1) ); + // Run moving 6 times. + SubtensorModule::update_moving_price( netuid ); + SubtensorModule::update_moving_price( netuid ); + SubtensorModule::update_moving_price( netuid ); + SubtensorModule::update_moving_price( netuid ); + SubtensorModule::update_moving_price( netuid ); + SubtensorModule::update_moving_price( netuid ); + // Assert price is > 50% of the real price. + assert_eq!( SubtensorModule::get_moving_alpha_price(netuid), I96F32::from_num(0.468559) ); + }); +} + + + From e4ccdfa71cfc3e9e7cd856ce037e2827611fb40c Mon Sep 17 00:00:00 2001 From: unconst Date: Wed, 5 Feb 2025 13:21:30 -0500 Subject: [PATCH 24/34] add alpha in tests --- pallets/subtensor/src/tests/coinbase.rs | 66 +++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/pallets/subtensor/src/tests/coinbase.rs b/pallets/subtensor/src/tests/coinbase.rs index 82ab6b1b3e..a4fc7edd03 100644 --- a/pallets/subtensor/src/tests/coinbase.rs +++ b/pallets/subtensor/src/tests/coinbase.rs @@ -143,6 +143,11 @@ fn test_coinbase_tao_issuance_different_prices() { }); } +// Test moving price updates with different alpha values. +// This test verifies that: +// - Moving price stays constant when alpha is 1.0 +// - Moving price converges to real price at expected rate with alpha 0.1 +// - Moving price updates correctly over multiple iterations // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_coinbase_moving_prices --exact --show-output --nocapture #[test] fn test_coinbase_moving_prices() { @@ -181,5 +186,66 @@ fn test_coinbase_moving_prices() { }); } +// Test basic alpha issuance in coinbase mechanism. +// This test verifies that: +// - Alpha issuance is initialized to 0 for new subnets +// - Alpha issuance is split evenly between subnets during coinbase +// - Each subnet receives the expected fraction of total emission +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_coinbase_alpha_issuance --exact --show-output --nocapture +#[test] +fn test_coinbase_alpha_issuance_base() { + new_test_ext(1).execute_with(|| { + let netuid1: u16 = 1; + let netuid2: u16 = 2; + let emission: u64 = 1_000_000; + add_network(netuid1, 1, 0); + add_network(netuid2, 1, 0); + // Set up prices 1 and 1 + SubnetTAO::::insert(netuid1, 1_000_000); + SubnetAlphaIn::::insert(netuid1, 1_000_000); + SubnetTAO::::insert(netuid2, 1_000_000); + SubnetAlphaIn::::insert(netuid2, 1_000_000); + // Check initial + assert_eq!( SubnetAlphaIn::::get( netuid1 ), 0); + assert_eq!( SubnetAlphaIn::::get( netuid2 ), 0); + SubtensorModule::run_coinbase( I96F32::from_num( emission ) ); + // tao_in = 500_000 + // alpha_in = 500_000/price = 500_000 + assert_eq!( SubnetAlphaIn::::get( netuid1 ), emission/2); + assert_eq!( SubnetAlphaIn::::get( netuid2 ), emission/2); + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_coinbase_alpha_issuance_different --exact --show-output --nocapture +#[test] +fn test_coinbase_alpha_issuance_different() { + new_test_ext(1).execute_with(|| { + let netuid1: u16 = 1; + let netuid2: u16 = 2; + let emission: u64 = 1_000_000; + add_network(netuid1, 1, 0); + add_network(netuid2, 1, 0); + // Make subnets dynamic. + SubnetMechanism::::insert(netuid1, 1); + SubnetMechanism::::insert(netuid2, 1); + // Setup prices 1 and 1 + let initial: u64 = 1_000_000; + SubnetTAO::::insert(netuid1, initial); + SubnetAlphaIn::::insert(netuid1, initial); + SubnetTAO::::insert(netuid2, initial); + SubnetAlphaIn::::insert(netuid2, initial); + // Set subnet prices. + SubnetMovingPrice::::insert( netuid1, I96F32::from_num(1) ); + SubnetMovingPrice::::insert( netuid2, I96F32::from_num(2) ); + // Run coinbase + SubtensorModule::run_coinbase( I96F32::from_num( emission ) ); + // tao_in = 333_333 + // alpha_in = 333_333/price = 333_333 + initial + assert_eq!( SubnetAlphaIn::::get( netuid1 ), initial + emission/3); + // tao_in = 666_666 + // alpha_in = 666_666/price = 666_666 + initial + assert_eq!( SubnetAlphaIn::::get( netuid2 ), initial + emission/3 + emission/3); + }); +} From ba80bbbdcd67ba56dd33bb53572dbc3884f8c0bb Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Wed, 5 Feb 2025 13:59:35 -0500 Subject: [PATCH 25/34] Fix all tests --- .../subtensor/src/coinbase/block_emission.rs | 1 - .../subtensor/src/coinbase/run_coinbase.rs | 163 +++++++++--------- pallets/subtensor/src/lib.rs | 11 +- pallets/subtensor/src/staking/helpers.rs | 6 +- pallets/subtensor/src/staking/stake_utils.rs | 25 +-- pallets/subtensor/src/tests/children.rs | 45 +++-- pallets/subtensor/src/tests/coinbase.rs | 1 - 7 files changed, 125 insertions(+), 127 deletions(-) diff --git a/pallets/subtensor/src/coinbase/block_emission.rs b/pallets/subtensor/src/coinbase/block_emission.rs index f0f2394e94..f372e41b6d 100644 --- a/pallets/subtensor/src/coinbase/block_emission.rs +++ b/pallets/subtensor/src/coinbase/block_emission.rs @@ -30,7 +30,6 @@ impl Pallet { tao_emission: u64, alpha_block_emission: u64, ) -> (u64, u64, u64) { - // Init terms. let mut tao_in_emission: I96F32 = I96F32::saturating_from_num(tao_emission); let float_alpha_block_emission: I96F32 = I96F32::saturating_from_num(alpha_block_emission); diff --git a/pallets/subtensor/src/coinbase/run_coinbase.rs b/pallets/subtensor/src/coinbase/run_coinbase.rs index 886250eca4..8dd9458689 100644 --- a/pallets/subtensor/src/coinbase/run_coinbase.rs +++ b/pallets/subtensor/src/coinbase/run_coinbase.rs @@ -32,23 +32,25 @@ macro_rules! tou64 { } impl Pallet { - pub fn run_coinbase(block_emission: I96F32) { - // --- 0. Get current block. let current_block: u64 = Self::get_current_block_as_u64(); log::debug!("Current block: {:?}", current_block); // --- 1. Get all netuids (filter out root.) - let subnets: Vec = Self::get_all_subnet_netuids().into_iter().filter(|netuid| *netuid != 0).collect(); + let subnets: Vec = Self::get_all_subnet_netuids() + .into_iter() + .filter(|netuid| *netuid != 0) + .collect(); log::debug!("All subnet netuids: {:?}", subnets); // --- 2. Get sum of tao reserves ( in a later version we will switch to prices. ) let mut total_moving_prices: I96F32 = I96F32::from_num(0.0); for netuid_i in subnets.iter() { // Get and update the moving price of each subnet adding the total together. - Self::update_moving_price( *netuid_i ); - total_moving_prices = total_moving_prices.saturating_add( Self::get_moving_alpha_price( *netuid_i ) ); + Self::update_moving_price(*netuid_i); + total_moving_prices = + total_moving_prices.saturating_add(Self::get_moving_alpha_price(*netuid_i)); } log::debug!("total_moving_prices: {:?}", total_moving_prices); @@ -62,16 +64,25 @@ impl Pallet { let price_i: I96F32 = Self::get_alpha_price(*netuid_i); log::debug!("price_i: {:?}", price_i); // Get subnet TAO. - let moving_price_i: I96F32 = Self::get_moving_alpha_price( *netuid_i ); + let moving_price_i: I96F32 = Self::get_moving_alpha_price(*netuid_i); log::debug!("moving_price_i: {:?}", moving_price_i); // Emission is price over total. - let mut tao_in_i: I96F32 = block_emission.saturating_mul(moving_price_i).checked_div(total_moving_prices).unwrap_or(asfloat!(0.0)); + let mut tao_in_i: I96F32 = block_emission + .saturating_mul(moving_price_i) + .checked_div(total_moving_prices) + .unwrap_or(asfloat!(0.0)); log::debug!("tao_in_i: {:?}", tao_in_i); // Get alpha_emission total - let alpha_emission_i: I96F32 = asfloat!(Self::get_block_emission_for_issuance(Self::get_alpha_issuance(*netuid_i)).unwrap_or(0)); + let alpha_emission_i: I96F32 = asfloat!(Self::get_block_emission_for_issuance( + Self::get_alpha_issuance(*netuid_i) + ) + .unwrap_or(0)); log::debug!("alpha_emission_i: {:?}", alpha_emission_i); // Get initial alpha_in - let alpha_in_i: I96F32 = tao_in_i.checked_div(price_i).unwrap_or(alpha_emission_i).min(alpha_emission_i); + let alpha_in_i: I96F32 = tao_in_i + .checked_div(price_i) + .unwrap_or(alpha_emission_i) + .min(alpha_emission_i); log::debug!("alpha_in_i: {:?}", alpha_in_i); // Get alpha_out. let alpha_out_i = alpha_emission_i; @@ -79,7 +90,7 @@ impl Pallet { if !Self::get_network_registration_allowed(*netuid_i) && Self::get_network_pow_registration_allowed(*netuid_i) { - tao_in_i = asfloat!( 0.0 ); + tao_in_i = asfloat!(0.0); } // Insert values into maps tao_in.insert(*netuid_i, tao_in_i); @@ -95,28 +106,28 @@ impl Pallet { // This operation changes the pool liquidity each block. for netuid_i in subnets.iter() { // Inject Alpha in. - let alpha_in_i: u64 = tou64!( *alpha_in.get(netuid_i).unwrap_or(&asfloat!(0)) ); - SubnetAlphaInEmission::::insert( *netuid_i, alpha_in_i ); - SubnetAlphaIn::::mutate( *netuid_i, |total| { + let alpha_in_i: u64 = tou64!(*alpha_in.get(netuid_i).unwrap_or(&asfloat!(0))); + SubnetAlphaInEmission::::insert(*netuid_i, alpha_in_i); + SubnetAlphaIn::::mutate(*netuid_i, |total| { *total = total.saturating_add(alpha_in_i); }); // Injection Alpha out. - let alpha_out_i: u64 = tou64!( *alpha_out.get(netuid_i).unwrap_or(&asfloat!(0)) ); - SubnetAlphaOutEmission::::insert( *netuid_i, alpha_out_i ); - SubnetAlphaOut::::mutate( *netuid_i, |total| { - *total = total.saturating_add( alpha_out_i ); + let alpha_out_i: u64 = tou64!(*alpha_out.get(netuid_i).unwrap_or(&asfloat!(0))); + SubnetAlphaOutEmission::::insert(*netuid_i, alpha_out_i); + SubnetAlphaOut::::mutate(*netuid_i, |total| { + *total = total.saturating_add(alpha_out_i); }); // Inject TAO in. - let tao_in_i: u64 = tou64!( *tao_in.get(netuid_i).unwrap_or(&asfloat!(0)) ); - SubnetTaoInEmission::::insert( *netuid_i, tao_in_i ); - SubnetTAO::::mutate( *netuid_i, |total| { - *total = total.saturating_add( tao_in_i ); + let tao_in_i: u64 = tou64!(*tao_in.get(netuid_i).unwrap_or(&asfloat!(0))); + SubnetTaoInEmission::::insert(*netuid_i, tao_in_i); + SubnetTAO::::mutate(*netuid_i, |total| { + *total = total.saturating_add(tao_in_i); }); TotalStake::::mutate(|total| { - *total = total.saturating_add( tao_in_i ); + *total = total.saturating_add(tao_in_i); }); TotalIssuance::::mutate(|total| { - *total = total.saturating_add( tao_in_i ); + *total = total.saturating_add(tao_in_i); }); } @@ -127,28 +138,28 @@ impl Pallet { let mut owner_cuts: BTreeMap = BTreeMap::new(); for netuid_i in subnets.iter() { // Get alpha out. - let alpha_out_i: I96F32 = *alpha_out.get( netuid_i ).unwrap_or(&asfloat!(0)); + let alpha_out_i: I96F32 = *alpha_out.get(netuid_i).unwrap_or(&asfloat!(0)); // Calculate the owner cut. - let owner_cut_i: I96F32 = alpha_out_i.saturating_mul( cut_percent ); + let owner_cut_i: I96F32 = alpha_out_i.saturating_mul(cut_percent); // Save owner cut. - *owner_cuts.entry( *netuid_i ).or_insert( asfloat!(0) ) = owner_cut_i; + *owner_cuts.entry(*netuid_i).or_insert(asfloat!(0)) = owner_cut_i; // Save new alpha_out. - alpha_out.insert( *netuid_i, alpha_out_i.saturating_sub( owner_cut_i ) ); + alpha_out.insert(*netuid_i, alpha_out_i.saturating_sub(owner_cut_i)); // Accumulate the owner cut in pending. PendingOwnerCut::::mutate(*netuid_i, |total| { - *total = total.saturating_add( tou64!( owner_cut_i ) ); + *total = total.saturating_add(tou64!(owner_cut_i)); }); } - // --- 6. Seperate out root dividends in alpha and sell them into tao. + // --- 6. Seperate out root dividends in alpha and sell them into tao. // Then accumulate those dividends for later. for netuid_i in subnets.iter() { // Get remaining alpha out. - let alpha_out_i: I96F32 = *alpha_out.get( netuid_i ).unwrap_or(&asfloat!(0.0)); + let alpha_out_i: I96F32 = *alpha_out.get(netuid_i).unwrap_or(&asfloat!(0.0)); // Get total TAO on root. - let root_tao: I96F32 = asfloat!( SubnetTAO::::get(0) ); + let root_tao: I96F32 = asfloat!(SubnetTAO::::get(0)); // Get total ALPHA on subnet. - let alpha_issuance: I96F32 = asfloat!( Self::get_alpha_issuance( *netuid_i )) ; + let alpha_issuance: I96F32 = asfloat!(Self::get_alpha_issuance(*netuid_i)); // Get tao_weight let tao_weight: I96F32 = root_tao.saturating_mul(Self::get_tao_weight()); // Get root proportional dividends. @@ -159,23 +170,20 @@ impl Pallet { let root_alpha: I96F32 = root_proportion .saturating_mul(alpha_out_i) // Total alpha emission per block remaining. .saturating_mul(asfloat!(0.5)); // 50% to validators. - // Remove root alpha from alpha_out. - let pending_alpha: I96F32 = alpha_out_i.saturating_sub( root_alpha ); + // Remove root alpha from alpha_out. + let pending_alpha: I96F32 = alpha_out_i.saturating_sub(root_alpha); // Sell root emission through the pool. - let root_tao: u64 = Self::swap_alpha_for_tao( - *netuid_i, - tou64!( root_alpha ), - ); + let root_tao: u64 = Self::swap_alpha_for_tao(*netuid_i, tou64!(root_alpha)); // Accumulate alpha emission in pending. - PendingAlphaSwapped::::mutate( *netuid_i, |total| { - *total = total.saturating_add( tou64!( root_alpha ) ); + PendingAlphaSwapped::::mutate(*netuid_i, |total| { + *total = total.saturating_add(tou64!(root_alpha)); }); // Accumulate alpha emission in pending. - PendingEmission::::mutate( *netuid_i, |total| { - *total = total.saturating_add( tou64!( pending_alpha ) ); + PendingEmission::::mutate(*netuid_i, |total| { + *total = total.saturating_add(tou64!(pending_alpha)); }); // Accumulate root divs for subnet. - PendingRootDivs::::mutate( *netuid_i, |total| { + PendingRootDivs::::mutate(*netuid_i, |total| { *total = total.saturating_add(root_tao); }); } @@ -246,10 +254,8 @@ impl Pallet { let zero: I96F32 = asfloat!(0.0); // Run the epoch. - let hotkey_emission: Vec<(T::AccountId, u64, u64)> = Self::epoch( - netuid, - pending_alpha.saturating_add(pending_swapped), - ); + let hotkey_emission: Vec<(T::AccountId, u64, u64)> = + Self::epoch(netuid, pending_alpha.saturating_add(pending_swapped)); // Accumulate emission of dividends and incentive per hotkey. let mut incentives: BTreeMap = BTreeMap::new(); @@ -261,42 +267,42 @@ impl Pallet { .and_modify(|e| *e = e.saturating_add(incentive)) .or_insert(incentive); // Accumulate dividends to parents. - let div_tuples: Vec<(T::AccountId, u64)> = Self::get_dividends_distribution(&hotkey, netuid, dividend); + let div_tuples: Vec<(T::AccountId, u64)> = + Self::get_dividends_distribution(&hotkey, netuid, dividend); // Accumulate dividends per hotkey. for (parent, parent_div) in div_tuples { dividends .entry(parent) - .and_modify(|e| *e = e.saturating_add( asfloat!(parent_div) ) ) - .or_insert( asfloat!(parent_div) ); + .and_modify(|e| *e = e.saturating_add(asfloat!(parent_div))) + .or_insert(asfloat!(parent_div)); } } - // Accumulate root divs and alpha_divs. For each hotkye we compute their + // Accumulate root divs and alpha_divs. For each hotkye we compute their // local and root dividend proportion based on their alpha_stake/root_stake - let mut total_root_divs: I96F32 = asfloat!( 0 ); + let mut total_root_divs: I96F32 = asfloat!(0); let mut root_dividends: BTreeMap = BTreeMap::new(); let mut alpha_dividends: BTreeMap = BTreeMap::new(); for (hotkey, dividend) in dividends { // Get hotkey ALPHA on subnet. - let alpha_stake = asfloat!( - Self::get_stake_for_hotkey_on_subnet( &hotkey, netuid) - ); + let alpha_stake = asfloat!(Self::get_stake_for_hotkey_on_subnet(&hotkey, netuid)); // Get hotkey TAO on root. - let root_stake: I96F32 = asfloat!( - Self::get_stake_for_hotkey_on_subnet( &hotkey, Self::get_root_netuid()) - ); + let root_stake: I96F32 = asfloat!(Self::get_stake_for_hotkey_on_subnet( + &hotkey, + Self::get_root_netuid() + )); // Convert TAO to alpha with weight. let root_alpha: I96F32 = root_stake.saturating_mul(Self::get_tao_weight()); // Get total from root and local - let total_alpha: I96F32 = alpha_stake.saturating_add( root_alpha ); + let total_alpha: I96F32 = alpha_stake.saturating_add(root_alpha); // Compute alpha prop. let alpha_prop: I96F32 = alpha_stake.checked_div(total_alpha).unwrap_or(zero); // Copmute root prop. let root_prop: I96F32 = root_alpha.checked_div(total_alpha).unwrap_or(zero); // Compute alpha dividends - let alpha_divs: I96F32 = dividend.saturating_mul( alpha_prop ); + let alpha_divs: I96F32 = dividend.saturating_mul(alpha_prop); // Compute root dividends - let root_divs: I96F32 = dividend.saturating_mul( root_prop ); + let root_divs: I96F32 = dividend.saturating_mul(root_prop); // Record the root dividends. alpha_dividends .entry(hotkey.clone()) @@ -306,21 +312,21 @@ impl Pallet { root_dividends .entry(hotkey.clone()) .and_modify(|e| *e = e.saturating_add(root_divs)) - .or_insert(root_divs); + .or_insert(root_divs); // Accumulate total root divs. - total_root_divs = total_root_divs.saturating_add( root_divs ); + total_root_divs = total_root_divs.saturating_add(root_divs); } - // Compute root divs as TAO. Here we take + // Compute root divs as TAO. Here we take let mut tao_dividends: BTreeMap = BTreeMap::new(); for (hotkey, root_divs) in root_dividends { // Root proportion. - let root_share: I96F32 = root_divs.checked_div( total_root_divs ).unwrap_or( zero ); + let root_share: I96F32 = root_divs.checked_div(total_root_divs).unwrap_or(zero); // Root proportion in TAO - let root_tao: I96F32 = asfloat!( pending_tao ).saturating_mul( root_share ); + let root_tao: I96F32 = asfloat!(pending_tao).saturating_mul(root_share); // Record root dividends as TAO. tao_dividends - .entry( hotkey ) + .entry(hotkey) .and_modify(|e| *e = root_tao) .or_insert(root_tao); } @@ -353,25 +359,22 @@ impl Pallet { let _ = AlphaDividendsPerSubnet::::clear_prefix(netuid, u32::MAX, None); for (hotkey, mut alpha_divs) in alpha_dividends { // Get take prop - let alpha_take: I96F32 = Self::get_hotkey_take_float( &hotkey ).saturating_mul( alpha_divs ); + let alpha_take: I96F32 = + Self::get_hotkey_take_float(&hotkey).saturating_mul(alpha_divs); // Remove take prop from alpha_divs - alpha_divs = alpha_divs.saturating_sub( alpha_take ); + alpha_divs = alpha_divs.saturating_sub(alpha_take); // Give the validator their take. Self::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, &Owner::::get(hotkey.clone()), netuid, - tou64!( alpha_take ), + tou64!(alpha_take), ); // Give all other nominators. - Self::increase_stake_for_hotkey_on_subnet( - &hotkey.clone(), - netuid, - tou64!( alpha_divs ) - ); + Self::increase_stake_for_hotkey_on_subnet(&hotkey.clone(), netuid, tou64!(alpha_divs)); // Record dividends for this hotkey. AlphaDividendsPerSubnet::::mutate(netuid, hotkey.clone(), |divs| { - *divs = divs.saturating_add( tou64!( alpha_divs ) ); + *divs = divs.saturating_add(tou64!(alpha_divs)); }); } @@ -379,9 +382,9 @@ impl Pallet { let _ = TaoDividendsPerSubnet::::clear_prefix(netuid, u32::MAX, None); for (hotkey, mut root_tao) in tao_dividends { // Get take prop - let tao_take: I96F32 = Self::get_hotkey_take_float(&hotkey).saturating_mul( root_tao ); - // Remove take prop from root_tao - root_tao = root_tao.saturating_sub( tao_take ); + let tao_take: I96F32 = Self::get_hotkey_take_float(&hotkey).saturating_mul(root_tao); + // Remove take prop from root_tao + root_tao = root_tao.saturating_sub(tao_take); // Give the validator their take. Self::increase_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, @@ -393,7 +396,7 @@ impl Pallet { Self::increase_stake_for_hotkey_on_subnet( &hotkey, Self::get_root_netuid(), - tou64!(root_tao) + tou64!(root_tao), ); // Record root dividends for this validator on this subnet. TaoDividendsPerSubnet::::mutate(netuid, hotkey.clone(), |divs| { diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index b858b5914e..033cd02576 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -736,18 +736,18 @@ pub mod pallet { /// Default moving alpha for the moving price. pub fn DefaultMovingAlpha() -> I96F32 { // Moving average take 30 days to reach 50% of the price - // and 3.5 months to reach 90%. - I96F32::saturating_from_num( 0.000003 ) + // and 3.5 months to reach 90%. + I96F32::saturating_from_num(0.000003) } #[pallet::type_value] /// Default subnet moving price. pub fn DefaultMovingPrice() -> I96F32 { - I96F32::saturating_from_num( 0.0 ) + I96F32::saturating_from_num(0.0) } #[pallet::type_value] /// Default value for Share Pool variables pub fn DefaultSharePoolZero() -> U64F64 { - U64F64::saturating_from_num( 0 ) + U64F64::saturating_from_num(0) } #[pallet::type_value] @@ -925,7 +925,8 @@ pub mod pallet { #[pallet::storage] // --- ITEM ( moving_alpha ) -- subnet moving alpha. pub type SubnetMovingAlpha = StorageValue<_, I96F32, ValueQuery, DefaultMovingAlpha>; #[pallet::storage] // --- MAP ( netuid ) --> moving_price | The subnet moving price. - pub type SubnetMovingPrice = StorageMap<_, Identity, u16, I96F32, ValueQuery, DefaultMovingPrice>; + pub type SubnetMovingPrice = + StorageMap<_, Identity, u16, I96F32, ValueQuery, DefaultMovingPrice>; #[pallet::storage] // --- MAP ( netuid ) --> total_volume | The total amount of TAO bought and sold since the start of the network. pub type SubnetVolume = StorageMap<_, Identity, u16, u128, ValueQuery, DefaultZeroU128>; diff --git a/pallets/subtensor/src/staking/helpers.rs b/pallets/subtensor/src/staking/helpers.rs index f4b2cef164..b5ca9c98d9 100644 --- a/pallets/subtensor/src/staking/helpers.rs +++ b/pallets/subtensor/src/staking/helpers.rs @@ -121,9 +121,9 @@ impl Pallet { Delegates::::get(hotkey) } pub fn get_hotkey_take_float(hotkey: &T::AccountId) -> I96F32 { - I96F32::from_num( Self::get_hotkey_take(hotkey) ) - .checked_div( I96F32::from_num(u16::MAX) ) - .unwrap_or( I96F32::from_num(0.0) ) + I96F32::from_num(Self::get_hotkey_take(hotkey)) + .checked_div(I96F32::from_num(u16::MAX)) + .unwrap_or(I96F32::from_num(0.0)) } /// Returns true if the hotkey account has been created. diff --git a/pallets/subtensor/src/staking/stake_utils.rs b/pallets/subtensor/src/staking/stake_utils.rs index 1db6f390a5..4db9bebeb5 100644 --- a/pallets/subtensor/src/staking/stake_utils.rs +++ b/pallets/subtensor/src/staking/stake_utils.rs @@ -47,22 +47,23 @@ impl Pallet { } pub fn get_moving_alpha_price(netuid: u16) -> I96F32 { if netuid == Self::get_root_netuid() { - return I96F32::saturating_from_num(1.0); // Root. - } - else if SubnetMechanism::::get(netuid) == 0 { - return I96F32::saturating_from_num(1.0); // Stable - } - else { - return SubnetMovingPrice::::get( netuid ); + // Root. + I96F32::saturating_from_num(1.0) + } else if SubnetMechanism::::get(netuid) == 0 { + // Stable + I96F32::saturating_from_num(1.0) + } else { + SubnetMovingPrice::::get(netuid) } } - pub fn update_moving_price( netuid: u16 ) { + pub fn update_moving_price(netuid: u16) { let alpha: I96F32 = SubnetMovingAlpha::::get(); let minus_alpha: I96F32 = I96F32::saturating_from_num(1.0).saturating_sub(alpha); - let current_price: I96F32 = alpha.saturating_mul( Self::get_alpha_price(netuid) ); - let current_moving: I96F32 = minus_alpha.saturating_mul( Self::get_moving_alpha_price(netuid) ); - let new_moving: I96F32 = current_price.saturating_add( current_moving ); - SubnetMovingPrice::::insert( netuid, new_moving); + let current_price: I96F32 = alpha.saturating_mul(Self::get_alpha_price(netuid)); + let current_moving: I96F32 = + minus_alpha.saturating_mul(Self::get_moving_alpha_price(netuid)); + let new_moving: I96F32 = current_price.saturating_add(current_moving); + SubnetMovingPrice::::insert(netuid, new_moving); } /// Retrieves the global global weight as a normalized value between 0 and 1. diff --git a/pallets/subtensor/src/tests/children.rs b/pallets/subtensor/src/tests/children.rs index 036a33696c..b6181e03cd 100644 --- a/pallets/subtensor/src/tests/children.rs +++ b/pallets/subtensor/src/tests/children.rs @@ -1841,7 +1841,10 @@ fn test_get_stake_for_hotkey_on_subnet_single_parent_child() { register_ok_neuron(netuid, child, coldkey, 0); SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( - &parent, &coldkey, netuid, 1_000_000_000, + &parent, + &coldkey, + netuid, + 1_000_000_000, ); mock_set_children_no_epochs(netuid, &parent, &[(u64::MAX, child)]); @@ -2013,11 +2016,7 @@ fn test_get_stake_for_hotkey_on_subnet_edge_cases() { ); // Test with 0% and 100% stake allocation - mock_set_children_no_epochs( - netuid, - &parent, - &[(0, child1), (u64::MAX, child2)], - ); + mock_set_children_no_epochs(netuid, &parent, &[(0, child1), (u64::MAX, child2)]); let parent_stake = SubtensorModule::get_inherited_for_hotkey_on_subnet(&parent, netuid); let child1_stake = SubtensorModule::get_inherited_for_hotkey_on_subnet(&child1, netuid); @@ -2709,8 +2708,10 @@ fn test_set_children_rate_limit_fail_then_succeed() { #[test] fn test_childkey_set_weights_single_parent() { new_test_ext(1).execute_with(|| { - let netuid: u16 = 1; - add_network(netuid, 1, 0); + let subnet_owner_coldkey = U256::from(1001); + let subnet_owner_hotkey = U256::from(1002); + let netuid: u16 = add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + Tempo::::insert(netuid, 1); // Define hotkeys let parent: U256 = U256::from(1); @@ -2750,14 +2751,14 @@ fn test_childkey_set_weights_single_parent() { SubtensorModule::set_weights_set_rate_limit(netuid, 0); // Set parent-child relationship - mock_set_children(&coldkey_parent, &parent, netuid, &[(u64::MAX, child)]); + mock_set_children_no_epochs(netuid, &parent, &[(u64::MAX, child)]); - step_block(7200 + 1); // Set weights on the child using the weight_setter account let origin = RuntimeOrigin::signed(weight_setter); let uids: Vec = vec![1]; // Only set weight for the child (UID 1) let values: Vec = vec![u16::MAX]; // Use maximum value for u16 let version_key = SubtensorModule::get_weights_version_key(netuid); + ValidatorPermit::::insert(netuid, vec![true, true, true, true]); assert_ok!(SubtensorModule::set_weights( origin, netuid, @@ -3191,15 +3192,9 @@ fn test_parent_child_chain_emission() { log::info!("rel_stake_a: {:?}", rel_stake_a); // 0.6666 -> 2/3 log::info!("rel_stake_b: {:?}", rel_stake_b); // 0.2222 -> 2/9 log::info!("rel_stake_c: {:?}", rel_stake_c); // 0.1111 -> 1/9 - assert!( - (rel_stake_a - I96F32::from_num(stake_a) / total_tao).abs() < 0.001 - ); - assert!( - (rel_stake_b - I96F32::from_num(stake_b) / total_tao).abs() < 0.001 - ); - assert!( - (rel_stake_c - I96F32::from_num(stake_c) / total_tao).abs() < 0.001 - ); + assert!((rel_stake_a - I96F32::from_num(stake_a) / total_tao).abs() < 0.001); + assert!((rel_stake_b - I96F32::from_num(stake_b) / total_tao).abs() < 0.001); + assert!((rel_stake_c - I96F32::from_num(stake_c) / total_tao).abs() < 0.001); // Set parent-child relationships // A -> B (50% of A's stake) @@ -3228,13 +3223,13 @@ fn test_parent_child_chain_emission() { // Set the weight of root TAO to be 0%, so only alpha is effective. SubtensorModule::set_tao_weight(0); - let hardcoded_emission: I96F32 = I96F32::from_num(1_000_000); // 1 million (adjust as needed) + let emission: I96F32 = I96F32::from_num(SubtensorModule::get_block_emission().unwrap_or(0)); // Set pending emission to 0 PendingEmission::::insert(netuid, 0); - // Run epoch with a hardcoded emission value - SubtensorModule::run_coinbase(hardcoded_emission); + // Run epoch with emission value + SubtensorModule::run_coinbase(emission); // Log new stake let stake_a_new: u64 = SubtensorModule::get_total_stake_for_hotkey(&hotkey_a); @@ -3262,7 +3257,7 @@ fn test_parent_child_chain_emission() { // Verify the final stake distribution let stake_inc_eps: I96F32 = I96F32::from_num(1e-4); // 4 decimal places - + // Each child has chk_take take let expected_a = I96F32::from_num(2_f64 / 3_f64) * (I96F32::from_num(1_f64) - (I96F32::from_num(1_f64 / 2_f64) * chk_take)); @@ -3315,8 +3310,8 @@ fn test_parent_child_chain_emission() { assert_abs_diff_eq!( total_stake_inc.to_num::(), - hardcoded_emission.to_num::(), - epsilon = 10_000, + emission.to_num::(), + epsilon = emission.to_num::() / 1000, ); }); } diff --git a/pallets/subtensor/src/tests/coinbase.rs b/pallets/subtensor/src/tests/coinbase.rs index f34cf3c761..3c0e1cadbf 100644 --- a/pallets/subtensor/src/tests/coinbase.rs +++ b/pallets/subtensor/src/tests/coinbase.rs @@ -48,4 +48,3 @@ fn test_dynamic_function_various_values() { } }); } - From 3eca45ffc3cf64ef4b2e08783e8e55dfaf1a3188 Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Wed, 5 Feb 2025 14:01:04 -0500 Subject: [PATCH 26/34] Format --- .../subtensor/src/coinbase/run_coinbase.rs | 5 +- pallets/subtensor/src/tests/coinbase.rs | 120 ++++++++++-------- 2 files changed, 69 insertions(+), 56 deletions(-) diff --git a/pallets/subtensor/src/coinbase/run_coinbase.rs b/pallets/subtensor/src/coinbase/run_coinbase.rs index 916a5a27ac..6e6490b17e 100644 --- a/pallets/subtensor/src/coinbase/run_coinbase.rs +++ b/pallets/subtensor/src/coinbase/run_coinbase.rs @@ -48,7 +48,8 @@ impl Pallet { let mut total_moving_prices: I96F32 = I96F32::from_num(0.0); for netuid_i in subnets.iter() { // Get and update the moving price of each subnet adding the total together. - total_moving_prices = total_moving_prices.saturating_add( Self::get_moving_alpha_price( *netuid_i ) ); + total_moving_prices = + total_moving_prices.saturating_add(Self::get_moving_alpha_price(*netuid_i)); } log::debug!("total_moving_prices: {:?}", total_moving_prices); @@ -189,7 +190,7 @@ impl Pallet { // --- 7 Update moving prices after using them in the emission calculation. for netuid_i in subnets.iter() { // Update moving prices after using them above. - Self::update_moving_price( *netuid_i ); + Self::update_moving_price(*netuid_i); } // --- 7. Drain pending emission through the subnet based on tempo. diff --git a/pallets/subtensor/src/tests/coinbase.rs b/pallets/subtensor/src/tests/coinbase.rs index a4fc7edd03..c501f31d2d 100644 --- a/pallets/subtensor/src/tests/coinbase.rs +++ b/pallets/subtensor/src/tests/coinbase.rs @@ -49,7 +49,6 @@ fn test_dynamic_function_various_values() { }); } - // Test the base case of running coinbase with zero emission. // This test verifies that the coinbase mechanism can handle the edge case // of zero emission without errors or unexpected behavior. @@ -57,7 +56,7 @@ fn test_dynamic_function_various_values() { #[test] fn test_coinbase_basecase() { new_test_ext(1).execute_with(|| { - SubtensorModule::run_coinbase( I96F32::from_num(0.0) ); + SubtensorModule::run_coinbase(I96F32::from_num(0.0)); }); } @@ -73,11 +72,11 @@ fn test_coinbase_tao_issuance_base() { let netuid: u16 = 1; let emission: u64 = 1_234_567; add_network(netuid, 1, 0); - assert_eq!( SubnetTAO::::get( netuid ), 0); - SubtensorModule::run_coinbase( I96F32::from_num( emission ) ); - assert_eq!( SubnetTAO::::get( netuid ), emission); - assert_eq!( TotalIssuance::::get(), emission); - assert_eq!( TotalStake::::get(), emission); + assert_eq!(SubnetTAO::::get(netuid), 0); + SubtensorModule::run_coinbase(I96F32::from_num(emission)); + assert_eq!(SubnetTAO::::get(netuid), emission); + assert_eq!(TotalIssuance::::get(), emission); + assert_eq!(TotalStake::::get(), emission); }); } @@ -98,15 +97,15 @@ fn test_coinbase_tao_issuance_multiple() { add_network(netuid1, 1, 0); add_network(netuid2, 1, 0); add_network(netuid3, 1, 0); - assert_eq!( SubnetTAO::::get( netuid1 ), 0); - assert_eq!( SubnetTAO::::get( netuid2 ), 0); - assert_eq!( SubnetTAO::::get( netuid3 ), 0); - SubtensorModule::run_coinbase( I96F32::from_num( emission ) ); - assert_eq!( SubnetTAO::::get( netuid1 ), emission/3); - assert_eq!( SubnetTAO::::get( netuid2 ), emission/3); - assert_eq!( SubnetTAO::::get( netuid3 ), emission/3); - assert_eq!( TotalIssuance::::get(), emission); - assert_eq!( TotalStake::::get(), emission); + assert_eq!(SubnetTAO::::get(netuid1), 0); + assert_eq!(SubnetTAO::::get(netuid2), 0); + assert_eq!(SubnetTAO::::get(netuid3), 0); + SubtensorModule::run_coinbase(I96F32::from_num(emission)); + assert_eq!(SubnetTAO::::get(netuid1), emission / 3); + assert_eq!(SubnetTAO::::get(netuid2), emission / 3); + assert_eq!(SubnetTAO::::get(netuid3), emission / 3); + assert_eq!(TotalIssuance::::get(), emission); + assert_eq!(TotalStake::::get(), emission); }); } @@ -128,18 +127,18 @@ fn test_coinbase_tao_issuance_different_prices() { SubnetMechanism::::insert(netuid1, 1); SubnetMechanism::::insert(netuid2, 1); // Set subnet prices. - SubnetMovingPrice::::insert( netuid1, I96F32::from_num(1) ); - SubnetMovingPrice::::insert( netuid2, I96F32::from_num(2) ); + SubnetMovingPrice::::insert(netuid1, I96F32::from_num(1)); + SubnetMovingPrice::::insert(netuid2, I96F32::from_num(2)); // Assert initial TAO reserves. - assert_eq!( SubnetTAO::::get( netuid1 ), 0); - assert_eq!( SubnetTAO::::get( netuid2 ), 0); + assert_eq!(SubnetTAO::::get(netuid1), 0); + assert_eq!(SubnetTAO::::get(netuid2), 0); // Run the coinbase with the emission amount. - SubtensorModule::run_coinbase( I96F32::from_num( emission ) ); + SubtensorModule::run_coinbase(I96F32::from_num(emission)); // Assert tao emission is split evenly. - assert_eq!( SubnetTAO::::get( netuid1 ), emission/3 ); - assert_eq!( SubnetTAO::::get( netuid2 ), emission/3 + emission/3); - close( TotalIssuance::::get(), emission, 2); - close( TotalStake::::get(), emission, 2); + assert_eq!(SubnetTAO::::get(netuid1), emission / 3); + assert_eq!(SubnetTAO::::get(netuid2), emission / 3 + emission / 3); + close(TotalIssuance::::get(), emission, 2); + close(TotalStake::::get(), emission, 2); }); } @@ -158,31 +157,43 @@ fn test_coinbase_moving_prices() { SubnetTAO::::insert(netuid, 1_000_000); SubnetAlphaIn::::insert(netuid, 1_000_000); SubnetMechanism::::insert(netuid, 1); - SubnetMovingPrice::::insert( netuid, I96F32::from_num(1) ); + SubnetMovingPrice::::insert(netuid, I96F32::from_num(1)); // Updating the moving price keeps it the same. - assert_eq!( SubtensorModule::get_moving_alpha_price(netuid), I96F32::from_num(1) ); - SubtensorModule::update_moving_price( netuid ); - assert_eq!( SubtensorModule::get_moving_alpha_price(netuid), I96F32::from_num(1) ); + assert_eq!( + SubtensorModule::get_moving_alpha_price(netuid), + I96F32::from_num(1) + ); + SubtensorModule::update_moving_price(netuid); + assert_eq!( + SubtensorModule::get_moving_alpha_price(netuid), + I96F32::from_num(1) + ); // Check alpha of 1. // Set price to zero. - SubnetMovingPrice::::insert( netuid, I96F32::from_num(0) ); - SubnetMovingAlpha::::set( I96F32::from_num(1.0) ); + SubnetMovingPrice::::insert(netuid, I96F32::from_num(0)); + SubnetMovingAlpha::::set(I96F32::from_num(1.0)); // Run moving 1 times. - SubtensorModule::update_moving_price( netuid ); + SubtensorModule::update_moving_price(netuid); // Assert price is == 100% of the real price. - assert_eq!( SubtensorModule::get_moving_alpha_price(netuid), I96F32::from_num(1.0) ); + assert_eq!( + SubtensorModule::get_moving_alpha_price(netuid), + I96F32::from_num(1.0) + ); // Set price to zero. - SubnetMovingPrice::::insert( netuid, I96F32::from_num(0) ); - SubnetMovingAlpha::::set( I96F32::from_num(0.1) ); + SubnetMovingPrice::::insert(netuid, I96F32::from_num(0)); + SubnetMovingAlpha::::set(I96F32::from_num(0.1)); // Run moving 6 times. - SubtensorModule::update_moving_price( netuid ); - SubtensorModule::update_moving_price( netuid ); - SubtensorModule::update_moving_price( netuid ); - SubtensorModule::update_moving_price( netuid ); - SubtensorModule::update_moving_price( netuid ); - SubtensorModule::update_moving_price( netuid ); + SubtensorModule::update_moving_price(netuid); + SubtensorModule::update_moving_price(netuid); + SubtensorModule::update_moving_price(netuid); + SubtensorModule::update_moving_price(netuid); + SubtensorModule::update_moving_price(netuid); + SubtensorModule::update_moving_price(netuid); // Assert price is > 50% of the real price. - assert_eq!( SubtensorModule::get_moving_alpha_price(netuid), I96F32::from_num(0.468559) ); + assert_eq!( + SubtensorModule::get_moving_alpha_price(netuid), + I96F32::from_num(0.468559) + ); }); } @@ -206,13 +217,13 @@ fn test_coinbase_alpha_issuance_base() { SubnetTAO::::insert(netuid2, 1_000_000); SubnetAlphaIn::::insert(netuid2, 1_000_000); // Check initial - assert_eq!( SubnetAlphaIn::::get( netuid1 ), 0); - assert_eq!( SubnetAlphaIn::::get( netuid2 ), 0); - SubtensorModule::run_coinbase( I96F32::from_num( emission ) ); + assert_eq!(SubnetAlphaIn::::get(netuid1), 0); + assert_eq!(SubnetAlphaIn::::get(netuid2), 0); + SubtensorModule::run_coinbase(I96F32::from_num(emission)); // tao_in = 500_000 // alpha_in = 500_000/price = 500_000 - assert_eq!( SubnetAlphaIn::::get( netuid1 ), emission/2); - assert_eq!( SubnetAlphaIn::::get( netuid2 ), emission/2); + assert_eq!(SubnetAlphaIn::::get(netuid1), emission / 2); + assert_eq!(SubnetAlphaIn::::get(netuid2), emission / 2); }); } @@ -235,17 +246,18 @@ fn test_coinbase_alpha_issuance_different() { SubnetTAO::::insert(netuid2, initial); SubnetAlphaIn::::insert(netuid2, initial); // Set subnet prices. - SubnetMovingPrice::::insert( netuid1, I96F32::from_num(1) ); - SubnetMovingPrice::::insert( netuid2, I96F32::from_num(2) ); + SubnetMovingPrice::::insert(netuid1, I96F32::from_num(1)); + SubnetMovingPrice::::insert(netuid2, I96F32::from_num(2)); // Run coinbase - SubtensorModule::run_coinbase( I96F32::from_num( emission ) ); + SubtensorModule::run_coinbase(I96F32::from_num(emission)); // tao_in = 333_333 // alpha_in = 333_333/price = 333_333 + initial - assert_eq!( SubnetAlphaIn::::get( netuid1 ), initial + emission/3); + assert_eq!(SubnetAlphaIn::::get(netuid1), initial + emission / 3); // tao_in = 666_666 // alpha_in = 666_666/price = 666_666 + initial - assert_eq!( SubnetAlphaIn::::get( netuid2 ), initial + emission/3 + emission/3); + assert_eq!( + SubnetAlphaIn::::get(netuid2), + initial + emission / 3 + emission / 3 + ); }); } - - From 1ffefe1f3e59956ac16bb7383ca8c506b333694c Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Wed, 5 Feb 2025 14:08:49 -0500 Subject: [PATCH 27/34] Fix unsafe math --- pallets/subtensor/src/coinbase/run_coinbase.rs | 2 +- pallets/subtensor/src/staking/helpers.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pallets/subtensor/src/coinbase/run_coinbase.rs b/pallets/subtensor/src/coinbase/run_coinbase.rs index 6e6490b17e..bb463e556f 100644 --- a/pallets/subtensor/src/coinbase/run_coinbase.rs +++ b/pallets/subtensor/src/coinbase/run_coinbase.rs @@ -45,7 +45,7 @@ impl Pallet { log::debug!("All subnet netuids: {:?}", subnets); // --- 2. Get sum of tao reserves ( in a later version we will switch to prices. ) - let mut total_moving_prices: I96F32 = I96F32::from_num(0.0); + let mut total_moving_prices: I96F32 = I96F32::saturating_from_num(0.0); for netuid_i in subnets.iter() { // Get and update the moving price of each subnet adding the total together. total_moving_prices = diff --git a/pallets/subtensor/src/staking/helpers.rs b/pallets/subtensor/src/staking/helpers.rs index b5ca9c98d9..c83e303c74 100644 --- a/pallets/subtensor/src/staking/helpers.rs +++ b/pallets/subtensor/src/staking/helpers.rs @@ -121,9 +121,9 @@ impl Pallet { Delegates::::get(hotkey) } pub fn get_hotkey_take_float(hotkey: &T::AccountId) -> I96F32 { - I96F32::from_num(Self::get_hotkey_take(hotkey)) - .checked_div(I96F32::from_num(u16::MAX)) - .unwrap_or(I96F32::from_num(0.0)) + I96F32::saturating_from_num(Self::get_hotkey_take(hotkey)) + .checked_div(I96F32::saturating_from_num(u16::MAX)) + .unwrap_or(I96F32::saturating_from_num(0.0)) } /// Returns true if the hotkey account has been created. From 8af65dfc37be22ee8e7686daca7011560b34016f Mon Sep 17 00:00:00 2001 From: unconst Date: Wed, 5 Feb 2025 14:17:49 -0500 Subject: [PATCH 28/34] alpha tests --- pallets/subtensor/src/coinbase/block_step.rs | 2 - pallets/subtensor/src/tests/coinbase.rs | 78 ++++++++++++++++++++ 2 files changed, 78 insertions(+), 2 deletions(-) diff --git a/pallets/subtensor/src/coinbase/block_step.rs b/pallets/subtensor/src/coinbase/block_step.rs index bcfd1a37bc..f9dc0022d8 100644 --- a/pallets/subtensor/src/coinbase/block_step.rs +++ b/pallets/subtensor/src/coinbase/block_step.rs @@ -16,10 +16,8 @@ impl Pallet { log::debug!("Block emission: {:?}", block_emission); // --- 3. Run emission through network. Self::run_coinbase(block_emission); - // --- 4. Set pending children on the epoch; but only after the coinbase has been run. Self::try_set_pending_children(block_number); - // Return ok. Ok(()) } diff --git a/pallets/subtensor/src/tests/coinbase.rs b/pallets/subtensor/src/tests/coinbase.rs index a4fc7edd03..17305ac3ca 100644 --- a/pallets/subtensor/src/tests/coinbase.rs +++ b/pallets/subtensor/src/tests/coinbase.rs @@ -216,6 +216,11 @@ fn test_coinbase_alpha_issuance_base() { }); } +// Test alpha issuance with different subnet prices. +// This test verifies that: +// - Alpha issuance is proportional to subnet prices +// - Higher priced subnets receive more TAO emission +// - Alpha issuance is correctly calculated based on price ratios // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_coinbase_alpha_issuance_different --exact --show-output --nocapture #[test] fn test_coinbase_alpha_issuance_different() { @@ -249,3 +254,76 @@ fn test_coinbase_alpha_issuance_different() { } +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_coinbase_alpha_issuance_with_cap_trigger --exact --show-output --nocapture +#[test] +fn test_coinbase_alpha_issuance_with_cap_trigger() { + new_test_ext(1).execute_with(|| { + let netuid1: u16 = 1; + let netuid2: u16 = 2; + let emission: u64 = 1_000_000; + add_network(netuid1, 1, 0); + add_network(netuid2, 1, 0); + // Make subnets dynamic. + SubnetMechanism::::insert(netuid1, 1); + SubnetMechanism::::insert(netuid2, 1); + // Setup prices 1000000 + let initial: u64 = 1_000; + let initial_alpha: u64 = initial * 1000000; + SubnetTAO::::insert(netuid1, initial); + SubnetAlphaIn::::insert(netuid1, initial_alpha); // Make price extremely low. + SubnetTAO::::insert(netuid2, initial); + SubnetAlphaIn::::insert(netuid2, initial_alpha); // Make price extremely low. + // Set subnet prices. + SubnetMovingPrice::::insert( netuid1, I96F32::from_num(1) ); + SubnetMovingPrice::::insert( netuid2, I96F32::from_num(2) ); + // Run coinbase + SubtensorModule::run_coinbase( I96F32::from_num( emission ) ); + // tao_in = 333_333 + // alpha_in = 333_333/price > 1_000_000_000 --> 1_000_000_000 + initial_alpha + assert_eq!( SubnetAlphaIn::::get( netuid1 ), initial_alpha + 1_000_000_000 ); + assert_eq!( SubnetAlphaOut::::get( netuid2 ), 1_000_000_000 ); + // tao_in = 666_666 + // alpha_in = 666_666/price > 1_000_000_000 --> 1_000_000_000 + initial_alpha + assert_eq!( SubnetAlphaIn::::get( netuid2 ), initial_alpha + 1_000_000_000 ); + assert_eq!( SubnetAlphaOut::::get( netuid2 ), 1_000_000_000 ); // Gets full block emission. + }); +} + +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_coinbase_alpha_issuance_with_cap_trigger_and_block_emission --exact --show-output --nocapture +#[test] +fn test_coinbase_alpha_issuance_with_cap_trigger_and_block_emission() { + new_test_ext(1).execute_with(|| { + let netuid1: u16 = 1; + let netuid2: u16 = 2; + let emission: u64 = 1_000_000; + add_network(netuid1, 1, 0); + add_network(netuid2, 1, 0); + // Make subnets dynamic. + SubnetMechanism::::insert(netuid1, 1); + SubnetMechanism::::insert(netuid2, 1); + // Setup prices 1000000 + let initial: u64 = 1_000; + let initial_alpha: u64 = initial * 1000000; + SubnetTAO::::insert(netuid1, initial); + SubnetAlphaIn::::insert(netuid1, initial_alpha); // Make price extremely low. + SubnetTAO::::insert(netuid2, initial); + SubnetAlphaIn::::insert(netuid2, initial_alpha); // Make price extremely low. + // Set issuance to greater than 21M + SubnetAlphaOut::::insert(netuid1, 22_000_000_000_000_000 ); // Set issuance above 21M + SubnetAlphaOut::::insert(netuid2, 22_000_000_000_000_000 ); // Set issuance above 21M + // Set subnet prices. + SubnetMovingPrice::::insert( netuid1, I96F32::from_num(1) ); + SubnetMovingPrice::::insert( netuid2, I96F32::from_num(2) ); + // Run coinbase + SubtensorModule::run_coinbase( I96F32::from_num( emission ) ); + // tao_in = 333_333 + // alpha_in = 333_333/price > 1_000_000_000 --> 0 + initial_alpha + assert_eq!( SubnetAlphaIn::::get( netuid1 ), initial_alpha ); + assert_eq!( SubnetAlphaOut::::get( netuid2 ), 22_000_000_000_000_000 ); + // tao_in = 666_666 + // alpha_in = 666_666/price > 1_000_000_000 --> 0 + initial_alpha + assert_eq!( SubnetAlphaIn::::get( netuid2 ), initial_alpha ); + assert_eq!( SubnetAlphaOut::::get( netuid2 ), 22_000_000_000_000_000 ); // No emission. + }); +} + From 0e367f75a79316fe79c969c00008f6c3b5fa6f87 Mon Sep 17 00:00:00 2001 From: unconst Date: Wed, 5 Feb 2025 14:25:04 -0500 Subject: [PATCH 29/34] set tao weight --- pallets/subtensor/src/tests/coinbase.rs | 15 +++++++++++++++ runtime/src/lib.rs | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/pallets/subtensor/src/tests/coinbase.rs b/pallets/subtensor/src/tests/coinbase.rs index cb4781ec61..4296e91ff3 100644 --- a/pallets/subtensor/src/tests/coinbase.rs +++ b/pallets/subtensor/src/tests/coinbase.rs @@ -80,6 +80,21 @@ fn test_coinbase_tao_issuance_base() { }); } +// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_coinbase_tao_issuance_base_low --exact --show-output --nocapture +#[test] +fn test_coinbase_tao_issuance_base_low() { + new_test_ext(1).execute_with(|| { + let netuid: u16 = 1; + let emission: u64 = 1; + add_network(netuid, 1, 0); + assert_eq!(SubnetTAO::::get(netuid), 0); + SubtensorModule::run_coinbase(I96F32::from_num(emission)); + assert_eq!(SubnetTAO::::get(netuid), emission); + assert_eq!(TotalIssuance::::get(), emission); + assert_eq!(TotalStake::::get(), emission); + }); +} + // Test emission distribution across multiple subnets. // This test verifies that: // - Multiple subnets receive equal portions of the total emission diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index a9a4bd2ca8..8f02556a5c 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -1052,7 +1052,7 @@ parameter_types! { pub const SubtensorInitialNetworkMaxStake: u64 = u64::MAX; // Maximum possible value for u64, this make the make stake infinity pub const InitialColdkeySwapScheduleDuration: BlockNumber = 5 * 24 * 60 * 60 / 12; // 5 days pub const InitialDissolveNetworkScheduleDuration: BlockNumber = 5 * 24 * 60 * 60 / 12; // 5 days - pub const SubtensorInitialTaoWeight: u64 = 332_041_393_326_771_929; // 18% global weigh. + pub const SubtensorInitialTaoWeight: u64 = 971_718_665_099_567_868; // 0.05267697438728329% tao weight. } impl pallet_subtensor::Config for Runtime { From 290498e726cf76a41f95c7e79d838a537b6b8c62 Mon Sep 17 00:00:00 2001 From: unconst Date: Wed, 5 Feb 2025 14:25:43 -0500 Subject: [PATCH 30/34] reset default staking fee --- pallets/subtensor/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index 033cd02576..1c482ad328 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -717,7 +717,7 @@ pub mod pallet { /// Default staking fee. /// 500k rao matches $0.25 at $500/TAO pub fn DefaultStakingFee() -> u64 { - 500_000 + 50_000 } #[pallet::type_value] From ab105c756b2e60d43e9458e11278cbde5a4d16a5 Mon Sep 17 00:00:00 2001 From: unconst Date: Wed, 5 Feb 2025 14:29:02 -0500 Subject: [PATCH 31/34] fix names --- pallets/subtensor/src/subnets/symbols.rs | 204 ++++++++++++++++++++++- 1 file changed, 201 insertions(+), 3 deletions(-) diff --git a/pallets/subtensor/src/subnets/symbols.rs b/pallets/subtensor/src/subnets/symbols.rs index 24b28720fc..fc7fb57a12 100644 --- a/pallets/subtensor/src/subnets/symbols.rs +++ b/pallets/subtensor/src/subnets/symbols.rs @@ -126,9 +126,207 @@ impl Pallet { 116 => b"dze".to_vec(), 117 => b"alfa".to_vec(), 118 => b"alfas".to_vec(), - 119 => b"vidac".to_vec(), - // Skipping lines 120-318 for brevity as they were omitted in context - 319 => b"kana_a".to_vec(), + 119 => b"vida".to_vec(), // Ⲃ (Vida, 119) + 120 => b"vida_small".to_vec(), // ⲃ (Small Vida, 120) + 121 => b"gamma".to_vec(), // Ⲅ (Gamma, 121) + 122 => b"gamma_small".to_vec(), // ⲅ (Small Gamma, 122) + 123 => b"brahmi_a".to_vec(), // 𑀀 (A, 123) + 124 => b"brahmi_aa".to_vec(), // 𑀁 (Aa, 124) + 125 => b"brahmi_i".to_vec(), // 𑀂 (I, 125) + 126 => b"brahmi_ii".to_vec(), // 𑀃 (Ii, 126) + 127 => b"brahmi_u".to_vec(), // 𑀅 (U, 127) + 128 => b"tifinagh_ya".to_vec(), // ⴰ (Ya, 128) + 129 => b"tifinagh_yab".to_vec(), // ⴱ (Yab, 129) + 130 => b"tifinagh_yabh".to_vec(), // ⴲ (Yabh, 130) + 131 => b"tifinagh_yag".to_vec(), // ⴳ (Yag, 131) + 132 => b"tifinagh_yagh".to_vec(), // ⴴ (Yagh, 132) + 133 => b"tifinagh_yaj".to_vec(), // ⴵ (Yaj, 133) + 134 => b"glagolitic_az".to_vec(), // Ⰰ (Az, 134) + 135 => b"glagolitic_buky".to_vec(), // Ⰱ (Buky, 135) + 136 => b"glagolitic_vede".to_vec(), // Ⰲ (Vede, 136) + 137 => b"glagolitic_glagoli".to_vec(), // Ⰳ (Glagoli, 137) + 138 => b"glagolitic_dobro".to_vec(), // Ⰴ (Dobro, 138) + 139 => b"glagolitic_yest".to_vec(), // Ⰵ (Yest, 139) + 140 => b"glagolitic_zhivete".to_vec(), // Ⰶ (Zhivete, 140) + 141 => b"glagolitic_zemlja".to_vec(), // Ⰷ (Zemlja, 141) + 142 => b"glagolitic_izhe".to_vec(), // Ⰸ (Izhe, 142) + 143 => b"glagolitic_initial_izhe".to_vec(), // Ⰹ (Initial Izhe, 143) + 144 => b"glagolitic_i".to_vec(), // Ⰺ (I, 144) + 145 => b"glagolitic_djerv".to_vec(), // Ⰻ (Djerv, 145) + 146 => b"glagolitic_kako".to_vec(), // Ⰼ (Kako, 146) + 147 => b"glagolitic_ljudije".to_vec(), // Ⰽ (Ljudije, 147) + 148 => b"glagolitic_myse".to_vec(), // Ⰾ (Myse, 148) + 149 => b"glagolitic_nash".to_vec(), // Ⰿ (Nash, 149) + 150 => b"glagolitic_on".to_vec(), // Ⱀ (On, 150) + 151 => b"glagolitic_pokoj".to_vec(), // Ⱁ (Pokoj, 151) + 152 => b"glagolitic_rtsy".to_vec(), // Ⱂ (Rtsy, 152) + 153 => b"glagolitic_slovo".to_vec(), // Ⱃ (Slovo, 153) + 154 => b"glagolitic_tvrido".to_vec(), // Ⱄ (Tvrido, 154) + 155 => b"glagolitic_uku".to_vec(), // Ⱅ (Uku, 155) + 156 => b"glagolitic_fert".to_vec(), // Ⱆ (Fert, 156) + 157 => b"glagolitic_xrivi".to_vec(), // Ⱇ (Xrivi, 157) + 158 => b"glagolitic_ot".to_vec(), // Ⱈ (Ot, 158) + 159 => b"glagolitic_cy".to_vec(), // Ⱉ (Cy, 159) + 160 => b"glagolitic_shcha".to_vec(), // Ⱊ (Shcha, 160) + 161 => b"glagolitic_er".to_vec(), // Ⱋ (Er, 161) + 162 => b"glagolitic_yeru".to_vec(), // Ⱌ (Yeru, 162) + 163 => b"glagolitic_small_yer".to_vec(), // Ⱍ (Small Yer, 163) + 164 => b"glagolitic_yo".to_vec(), // Ⱎ (Yo, 164) + 165 => b"glagolitic_yu".to_vec(), // Ⱏ (Yu, 165) + 166 => b"glagolitic_ja".to_vec(), // Ⱐ (Ja, 166) + 167 => b"thai_ko_kai".to_vec(), // ก (Ko Kai, 167) + 168 => b"thai_kho_khai".to_vec(), // ข (Kho Khai, 168) + 169 => b"thai_kho_khuat".to_vec(), // ฃ (Kho Khuat, 169) + 170 => b"thai_kho_khon".to_vec(), // ค (Kho Khon, 170) + 171 => b"thai_kho_rakhang".to_vec(), // ฅ (Kho Rakhang, 171) + 172 => b"thai_kho_khwai".to_vec(), // ฆ (Kho Khwai, 172) + 173 => b"thai_ngo_ngu".to_vec(), // ง (Ngo Ngu, 173) + 174 => b"thai_cho_chan".to_vec(), // จ (Cho Chan, 174) + 175 => b"thai_cho_ching".to_vec(), // ฉ (Cho Ching, 175) + 176 => b"thai_cho_chang".to_vec(), // ช (Cho Chang, 176) + 177 => b"thai_so_so".to_vec(), // ซ (So So, 177) + 178 => b"thai_cho_choe".to_vec(), // ฌ (Cho Choe, 178) + 179 => b"thai_yo_ying".to_vec(), // ญ (Yo Ying, 179) + 180 => b"thai_do_chada".to_vec(), // ฎ (Do Chada, 180) + 181 => b"thai_to_patak".to_vec(), // ฏ (To Patak, 181) + 182 => b"thai_tho_than".to_vec(), // ฐ (Tho Than, 182) + 183 => b"thai_tho_nangmontho".to_vec(), // ฑ (Tho Nangmontho, 183) + 184 => b"thai_tho_phuthao".to_vec(), // ฒ (Tho Phuthao, 184) + 185 => b"thai_no_nen".to_vec(), // ณ (No Nen, 185) + 186 => b"thai_do_dek".to_vec(), // ด (Do Dek, 186) + 187 => b"thai_to_tao".to_vec(), // ต (To Tao, 187) + 188 => b"thai_tho_thung".to_vec(), // ถ (Tho Thung, 188) + 189 => b"thai_tho_thahan".to_vec(), // ท (Tho Thahan, 189) + 190 => b"thai_tho_thong".to_vec(), // ธ (Tho Thong, 190) + 191 => b"thai_no_nu".to_vec(), // น (No Nu, 191) + 192 => b"thai_bo_baimai".to_vec(), // บ (Bo Baimai, 192) + 193 => b"thai_po_pla".to_vec(), // ป (Po Pla, 193) + 194 => b"thai_pho_phung".to_vec(), // ผ (Pho Phung, 194) + 195 => b"thai_fo_fa".to_vec(), // ฝ (Fo Fa, 195) + 196 => b"thai_pho_phan".to_vec(), // พ (Pho Phan, 196) + 197 => b"thai_fo_fan".to_vec(), // ฟ (Fo Fan, 197) + 198 => b"thai_pho_samphao".to_vec(), // ภ (Pho Samphao, 198) + 199 => b"thai_mo_ma".to_vec(), // ม (Mo Ma, 199) + 200 => b"thai_yo_yak".to_vec(), // ย (Yo Yak, 200) + 201 => b"thai_ro_rua".to_vec(), // ร (Ro Rua, 201) + 202 => b"thai_lo_ling".to_vec(), // ล (Lo Ling, 202) + 203 => b"thai_wo_waen".to_vec(), // ว (Wo Waen, 203) + 204 => b"thai_so_sala".to_vec(), // ศ (So Sala, 204) + 205 => b"thai_so_rusi".to_vec(), // ษ (So Rusi, 205) + 206 => b"thai_so_sua".to_vec(), // ส (So Sua, 206) + 207 => b"thai_ho_hip".to_vec(), // ห (Ho Hip, 207) + 208 => b"thai_lo_chula".to_vec(), // ฬ (Lo Chula, 208) + 209 => b"thai_o_ang".to_vec(), // อ (O Ang, 209) + 210 => b"thai_ho_nokhuk".to_vec(), // ฮ (Ho Nokhuk, 210) + 211 => b"hangul_giyeok".to_vec(), // ㄱ (Giyeok, 211) + 212 => b"hangul_nieun".to_vec(), // ㄴ (Nieun, 212) + 213 => b"hangul_digeut".to_vec(), // ㄷ (Digeut, 213) + 214 => b"hangul_rieul".to_vec(), // ㄹ (Rieul, 214) + 215 => b"hangul_mieum".to_vec(), // ㅁ (Mieum, 215) + 216 => b"hangul_bieup".to_vec(), // ㅂ (Bieup, 216) + 217 => b"hangul_siot".to_vec(), // ㅅ (Siot, 217) + 218 => b"hangul_ieung".to_vec(), // ㅇ (Ieung, 218) + 219 => b"hangul_jieut".to_vec(), // ㅈ (Jieut, 219) + 220 => b"hangul_chieut".to_vec(), // ㅊ (Chieut, 220) + 221 => b"hangul_kieuk".to_vec(), // ㅋ (Kieuk, 221) + 222 => b"hangul_tieut".to_vec(), // ㅌ (Tieut, 222) + 223 => b"hangul_pieup".to_vec(), // ㅍ (Pieup, 223) + 224 => b"hangul_hieut".to_vec(), // ㅎ (Hieut, 224) + 225 => b"hangul_a".to_vec(), // ㅏ (A, 225) + 226 => b"hangul_ae".to_vec(), // ㅐ (Ae, 226) + 227 => b"hangul_ya".to_vec(), // ㅑ (Ya, 227) + 228 => b"hangul_yae".to_vec(), // ㅒ (Yae, 228) + 229 => b"hangul_eo".to_vec(), // ㅓ (Eo, 229) + 230 => b"hangul_e".to_vec(), // ㅔ (E, 230) + 231 => b"hangul_yeo".to_vec(), // ㅕ (Yeo, 231) + 232 => b"hangul_ye".to_vec(), // ㅖ (Ye, 232) + 233 => b"hangul_o".to_vec(), // ㅗ (O, 233) + 234 => b"hangul_wa".to_vec(), // ㅘ (Wa, 234) + 235 => b"hangul_wae".to_vec(), // ㅙ (Wae, 235) + 236 => b"hangul_oe".to_vec(), // ㅚ (Oe, 236) + 237 => b"hangul_yo".to_vec(), // ㅛ (Yo, 237) + 238 => b"hangul_u".to_vec(), // ㅜ (U, 238) + 239 => b"hangul_weo".to_vec(), // ㅝ (Weo, 239) + 240 => b"hangul_we".to_vec(), // ㅞ (We, 240) + 241 => b"hangul_wi".to_vec(), // ㅟ (Wi, 241) + 242 => b"hangul_yu".to_vec(), // ㅠ (Yu, 242) + 243 => b"hangul_eu".to_vec(), // ㅡ (Eu, 243) + 244 => b"hangul_ui".to_vec(), // ㅢ (Ui, 244) + 245 => b"hangul_i".to_vec(), // ㅣ (I, 245) + 246 => b"ethiopic_glottal_a".to_vec(), // አ (Glottal A, 246) + 247 => b"ethiopic_glottal_u".to_vec(), // ኡ (Glottal U, 247) + 248 => b"ethiopic_glottal_i".to_vec(), // ኢ (Glottal I, 248) + 249 => b"ethiopic_glottal_aa".to_vec(), // ኣ (Glottal Aa, 249) + 250 => b"ethiopic_glottal_e".to_vec(), // ኤ (Glottal E, 250) + 251 => b"ethiopic_glottal_ie".to_vec(), // እ (Glottal Ie, 251) + 252 => b"ethiopic_glottal_o".to_vec(), // ኦ (Glottal O, 252) + 253 => b"ethiopic_glottal_wa".to_vec(), // ኧ (Glottal Wa, 253) + 254 => b"ethiopic_wa".to_vec(), // ወ (Wa, 254) + 255 => b"ethiopic_wu".to_vec(), // ዉ (Wu, 255) + 256 => b"ethiopic_wi".to_vec(), // ዊ (Wi, 256) + 257 => b"ethiopic_waa".to_vec(), // ዋ (Waa, 257) + 258 => b"ethiopic_we".to_vec(), // ዌ (We, 258) + 259 => b"ethiopic_wye".to_vec(), // ው (Wye, 259) + 260 => b"ethiopic_wo".to_vec(), // ዎ (Wo, 260) + 261 => b"ethiopic_ko".to_vec(), // ኰ (Ko, 261) + 262 => b"ethiopic_ku".to_vec(), // ኱ (Ku, 262) + 263 => b"ethiopic_ki".to_vec(), // ኲ (Ki, 263) + 264 => b"ethiopic_kua".to_vec(), // ኳ (Kua, 264) + 265 => b"ethiopic_ke".to_vec(), // ኴ (Ke, 265) + 266 => b"ethiopic_kwe".to_vec(), // ኵ (Kwe, 266) + 267 => b"ethiopic_ko_alt".to_vec(), // ኶ (Ko, 267) + 268 => b"ethiopic_go".to_vec(), // ጐ (Go, 268) + 269 => b"ethiopic_gu".to_vec(), // ጑ (Gu, 269) + 270 => b"ethiopic_gi".to_vec(), // ጒ (Gi, 270) + 271 => b"ethiopic_gua".to_vec(), // መ (Gua, 271) + 272 => b"ethiopic_ge".to_vec(), // ጔ (Ge, 272) + 273 => b"ethiopic_gwe".to_vec(), // ጕ (Gwe, 273) + 274 => b"ethiopic_go_alt".to_vec(), // ጖ (Go, 274) + 275 => b"devanagari_a".to_vec(), // अ (A, 275) + 276 => b"devanagari_aa".to_vec(), // आ (Aa, 276) + 277 => b"devanagari_i".to_vec(), // इ (I, 277) + 278 => b"devanagari_ii".to_vec(), // ई (Ii, 278) + 279 => b"devanagari_u".to_vec(), // उ (U, 279) + 280 => b"devanagari_uu".to_vec(), // ऊ (Uu, 280) + 281 => b"devanagari_r".to_vec(), // ऋ (R, 281) + 282 => b"devanagari_e".to_vec(), // ए (E, 282) + 283 => b"devanagari_ai".to_vec(), // ऐ (Ai, 283) + 284 => b"devanagari_o".to_vec(), // ओ (O, 284) + 285 => b"devanagari_au".to_vec(), // औ (Au, 285) + 286 => b"devanagari_ka".to_vec(), // क (Ka, 286) + 287 => b"devanagari_kha".to_vec(), // ख (Kha, 287) + 288 => b"devanagari_ga".to_vec(), // ग (Ga, 288) + 289 => b"devanagari_gha".to_vec(), // घ (Gha, 289) + 290 => b"devanagari_nga".to_vec(), // ङ (Nga, 290) + 291 => b"devanagari_cha".to_vec(), // च (Cha, 291) + 292 => b"devanagari_chha".to_vec(), // छ (Chha, 292) + 293 => b"devanagari_ja".to_vec(), // ज (Ja, 293) + 294 => b"devanagari_jha".to_vec(), // झ (Jha, 294) + 295 => b"devanagari_nya".to_vec(), // ञ (Nya, 295) + 296 => b"devanagari_ta".to_vec(), // ट (Ta, 296) + 297 => b"devanagari_tha".to_vec(), // ठ (Tha, 297) + 298 => b"devanagari_da".to_vec(), // ड (Da, 298) + 299 => b"devanagari_dha".to_vec(), // ढ (Dha, 299) + 300 => b"devanagari_na".to_vec(), // ण (Na, 300) + 301 => b"devanagari_ta_alt".to_vec(), // त (Ta, 301) + 302 => b"devanagari_tha_alt".to_vec(), // थ (Tha, 302) + 303 => b"devanagari_da_alt".to_vec(), // द (Da, 303) + 304 => b"devanagari_dha_alt".to_vec(), // ध (Dha, 304) + 305 => b"devanagari_na_alt".to_vec(), // न (Na, 305) + 306 => b"devanagari_pa".to_vec(), // प (Pa, 306) + 307 => b"devanagari_pha".to_vec(), // फ (Pha, 307) + 308 => b"devanagari_ba".to_vec(), // ब (Ba, 308) + 309 => b"devanagari_bha".to_vec(), // भ (Bha, 309) + 310 => b"devanagari_ma".to_vec(), // म (Ma, 310) + 311 => b"devanagari_ya".to_vec(), // य (Ya, 311) + 312 => b"devanagari_ra".to_vec(), // र (Ra, 312) + 313 => b"devanagari_la".to_vec(), // ल (La, 313) + 314 => b"devanagari_va".to_vec(), // व (Va, 314) + 315 => b"devanagari_sha".to_vec(), // श (Sha, 315) + 316 => b"devanagari_ssa".to_vec(), // ष (Ssa, 316) + 317 => b"devanagari_sa".to_vec(), // स (Sa, 317) + 318 => b"devanagari_ha".to_vec(), // ह (Ha, 318) + 319 => b"katakana_a".to_vec(), // ア (A, 319) 320 => b"kana_i".to_vec(), 321 => b"kana_u".to_vec(), 322 => b"kana_e".to_vec(), From 452dbacd6fdd817448f2d52fcbd7470f0c36f21f Mon Sep 17 00:00:00 2001 From: unconst Date: Wed, 5 Feb 2025 14:30:17 -0500 Subject: [PATCH 32/34] add mainnet names --- pallets/subtensor/src/subnets/symbols.rs | 130 +++++++++++------------ 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/pallets/subtensor/src/subnets/symbols.rs b/pallets/subtensor/src/subnets/symbols.rs index fc7fb57a12..d9cc20fb72 100644 --- a/pallets/subtensor/src/subnets/symbols.rs +++ b/pallets/subtensor/src/subnets/symbols.rs @@ -7,71 +7,71 @@ impl Pallet { SubnetName::::get(netuid) } else { match netuid { - 0 => b"tau".to_vec(), - 1 => b"alpha".to_vec(), - 2 => b"beta".to_vec(), - 3 => b"gamma".to_vec(), - 4 => b"delta".to_vec(), - 5 => b"epsilon".to_vec(), - 6 => b"zeta".to_vec(), - 7 => b"eta".to_vec(), - 8 => b"theta".to_vec(), - 9 => b"iota".to_vec(), - 10 => b"kappa".to_vec(), - 11 => b"lambda".to_vec(), - 12 => b"mu".to_vec(), - 13 => b"nu".to_vec(), - 14 => b"xi".to_vec(), - 15 => b"omicron".to_vec(), - 16 => b"pi".to_vec(), - 17 => b"rho".to_vec(), - 18 => b"sigma".to_vec(), - 19 => b"tau".to_vec(), - 20 => b"upsilon".to_vec(), - 21 => b"phi".to_vec(), - 22 => b"chi".to_vec(), - 23 => b"psi".to_vec(), - 24 => b"omega".to_vec(), - 25 => b"aleph".to_vec(), - 26 => b"bet".to_vec(), - 27 => b"gimel".to_vec(), - 28 => b"dalet".to_vec(), - 29 => b"he".to_vec(), - 30 => b"vav".to_vec(), - 31 => b"zayin".to_vec(), - 32 => b"het".to_vec(), - 33 => b"tet".to_vec(), - 34 => b"yod".to_vec(), - 35 => b"kafso".to_vec(), - 36 => b"kaf".to_vec(), - 37 => b"lamed".to_vec(), - 38 => b"mem".to_vec(), - 39 => b"mem".to_vec(), - 40 => b"nunso".to_vec(), - 41 => b"nun".to_vec(), - 42 => b"samekh".to_vec(), - 43 => b"ayin".to_vec(), - 44 => b"peso".to_vec(), - 45 => b"pe".to_vec(), - 46 => b"tsadiso".to_vec(), - 47 => b"tsadi".to_vec(), - 48 => b"qof".to_vec(), - 49 => b"resh".to_vec(), - 50 => b"shin".to_vec(), - 51 => b"tav".to_vec(), - 52 => b"alif".to_vec(), - 53 => b"ba".to_vec(), - 54 => b"ta".to_vec(), - 55 => b"tha".to_vec(), - 56 => b"jim".to_vec(), - 57 => b"ha".to_vec(), - 58 => b"kha".to_vec(), - 59 => b"dal".to_vec(), - 60 => b"dhal".to_vec(), - 61 => b"ra".to_vec(), - 62 => b"zay".to_vec(), - 63 => b"sin".to_vec(), - 64 => b"shin".to_vec(), + 0 => b"root".to_vec(), // Τ (Upper case Tau) + 1 => b"apex".to_vec(), // α (Alpha) + 2 => b"omron".to_vec(), // β (Beta) + 3 => b"templar".to_vec(), // γ (Gamma) + 4 => b"targon".to_vec(), // δ (Delta) + 5 => b"kaito".to_vec(), // ε (Epsilon) + 6 => b"infinite".to_vec(), // ζ (Zeta) + 7 => b"subvortex".to_vec(), // η (Eta) + 8 => b"ptn".to_vec(), // θ (Theta) + 9 => b"pretrain".to_vec(), // ι (Iota) + 10 => b"sturdy".to_vec(), // κ (Kappa) + 11 => b"dippy".to_vec(), // λ (Lambda) + 12 => b"horde".to_vec(), // μ (Mu) + 13 => b"dataverse".to_vec(), // ν (Nu) + 14 => b"palaidn".to_vec(), // ξ (Xi) + 15 => b"deval".to_vec(), // ο (Omicron) + 16 => b"bitads".to_vec(), // π (Pi) + 17 => b"3gen".to_vec(), // ρ (Rho) + 18 => b"cortex".to_vec(), // σ (Sigma) + 19 => b"inference".to_vec(), // t (Tau) + 20 => b"bitagent".to_vec(), // υ (Upsilon) + 21 => b"any-any".to_vec(), // φ (Phi) + 22 => b"meta".to_vec(), // χ (Chi) + 23 => b"social".to_vec(), // ψ (Psi) + 24 => b"omega".to_vec(), // ω (Omega) + 25 => b"protein".to_vec(), // א (Aleph) + 26 => b"alchemy".to_vec(), // ב (Bet) + 27 => b"compute".to_vec(), // ג (Gimel) + 28 => b"oracle".to_vec(), // ד (Dalet) + 29 => b"coldint".to_vec(), // ה (He) + 30 => b"bet".to_vec(), // ו (Vav) + 31 => b"naschain".to_vec(), // ז (Zayin) + 32 => b"itsai".to_vec(), // ח (Het) + 33 => b"ready".to_vec(), // ט (Tet) + 34 => b"mind".to_vec(), // י (Yod) + 35 => b"logic".to_vec(), // ך (Final Kaf) + 36 => b"automata".to_vec(), // כ (Kaf) + 37 => b"tuning".to_vec(), // ל (Lamed) + 38 => b"distributed".to_vec(), // ם (Final Mem) + 39 => b"edge".to_vec(), // מ (Mem) + 40 => b"chunk".to_vec(), // ן (Final Nun) + 41 => b"sportsensor".to_vec(), // נ (Nun) + 42 => b"masa".to_vec(), // ס (Samekh) + 43 => b"graphite".to_vec(), // ע (Ayin) + 44 => b"score".to_vec(), // ף (Final Pe) + 45 => b"gen42".to_vec(), // פ (Pe) + 46 => b"neural".to_vec(), // ץ (Final Tsadi) + 47 => b"condense".to_vec(), // צ (Tsadi) + 48 => b"nextplace".to_vec(), // ק (Qof) + 49 => b"automl".to_vec(), // ר (Resh) + 50 => b"audio".to_vec(), // ש (Shin) + 51 => b"celium".to_vec(), // ת (Tav) + 52 => b"dojo".to_vec(), // ا (Alif) + 53 => b"frontier".to_vec(), // ب (Ba) + 54 => b"safescan".to_vec(), // ت (Ta) + 55 => b"unknown".to_vec(), // ث (Tha) + 56 => b"gradients".to_vec(), // ج (Jim) + 57 => b"gaia".to_vec(), // ح (Ha) + 58 => b"dippy-speach".to_vec(), // خ (Kha) + 59 => b"agent-arena".to_vec(), // د (Dal) + 60 => b"unknown".to_vec(), // ذ (Dhal) + 61 => b"red team".to_vec(), // ر (Ra) + 62 => b"agentao".to_vec(), // ز (Zay) + 63 => b"lean-in".to_vec(), // س (Sin) + 64 => b"chutes".to_vec(), // ش (Shin) 65 => b"sad".to_vec(), 66 => b"dad".to_vec(), 67 => b"ta".to_vec(), From 5c96afd095681697875230e9fe41bd66b02494c7 Mon Sep 17 00:00:00 2001 From: unconst Date: Wed, 5 Feb 2025 14:31:58 -0500 Subject: [PATCH 33/34] cargo clippy --- 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 8f02556a5c..84283b0343 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -229,7 +229,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: 226, + spec_version: 227, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From bce7cc695cf62921431ddb11259a8e700fa5913d Mon Sep 17 00:00:00 2001 From: unconst Date: Wed, 5 Feb 2025 14:32:43 -0500 Subject: [PATCH 34/34] cargo fmt --- pallets/subtensor/src/subnets/symbols.rs | 528 +++++++++++------------ pallets/subtensor/src/tests/coinbase.rs | 46 +- 2 files changed, 290 insertions(+), 284 deletions(-) diff --git a/pallets/subtensor/src/subnets/symbols.rs b/pallets/subtensor/src/subnets/symbols.rs index d9cc20fb72..6350c303e5 100644 --- a/pallets/subtensor/src/subnets/symbols.rs +++ b/pallets/subtensor/src/subnets/symbols.rs @@ -7,71 +7,71 @@ impl Pallet { SubnetName::::get(netuid) } else { match netuid { - 0 => b"root".to_vec(), // Τ (Upper case Tau) - 1 => b"apex".to_vec(), // α (Alpha) - 2 => b"omron".to_vec(), // β (Beta) - 3 => b"templar".to_vec(), // γ (Gamma) - 4 => b"targon".to_vec(), // δ (Delta) - 5 => b"kaito".to_vec(), // ε (Epsilon) - 6 => b"infinite".to_vec(), // ζ (Zeta) - 7 => b"subvortex".to_vec(), // η (Eta) - 8 => b"ptn".to_vec(), // θ (Theta) - 9 => b"pretrain".to_vec(), // ι (Iota) - 10 => b"sturdy".to_vec(), // κ (Kappa) - 11 => b"dippy".to_vec(), // λ (Lambda) - 12 => b"horde".to_vec(), // μ (Mu) - 13 => b"dataverse".to_vec(), // ν (Nu) - 14 => b"palaidn".to_vec(), // ξ (Xi) - 15 => b"deval".to_vec(), // ο (Omicron) - 16 => b"bitads".to_vec(), // π (Pi) - 17 => b"3gen".to_vec(), // ρ (Rho) - 18 => b"cortex".to_vec(), // σ (Sigma) - 19 => b"inference".to_vec(), // t (Tau) - 20 => b"bitagent".to_vec(), // υ (Upsilon) - 21 => b"any-any".to_vec(), // φ (Phi) - 22 => b"meta".to_vec(), // χ (Chi) - 23 => b"social".to_vec(), // ψ (Psi) - 24 => b"omega".to_vec(), // ω (Omega) - 25 => b"protein".to_vec(), // א (Aleph) - 26 => b"alchemy".to_vec(), // ב (Bet) - 27 => b"compute".to_vec(), // ג (Gimel) - 28 => b"oracle".to_vec(), // ד (Dalet) - 29 => b"coldint".to_vec(), // ה (He) - 30 => b"bet".to_vec(), // ו (Vav) - 31 => b"naschain".to_vec(), // ז (Zayin) - 32 => b"itsai".to_vec(), // ח (Het) - 33 => b"ready".to_vec(), // ט (Tet) - 34 => b"mind".to_vec(), // י (Yod) - 35 => b"logic".to_vec(), // ך (Final Kaf) - 36 => b"automata".to_vec(), // כ (Kaf) - 37 => b"tuning".to_vec(), // ל (Lamed) - 38 => b"distributed".to_vec(), // ם (Final Mem) - 39 => b"edge".to_vec(), // מ (Mem) - 40 => b"chunk".to_vec(), // ן (Final Nun) - 41 => b"sportsensor".to_vec(), // נ (Nun) - 42 => b"masa".to_vec(), // ס (Samekh) - 43 => b"graphite".to_vec(), // ע (Ayin) - 44 => b"score".to_vec(), // ף (Final Pe) - 45 => b"gen42".to_vec(), // פ (Pe) - 46 => b"neural".to_vec(), // ץ (Final Tsadi) - 47 => b"condense".to_vec(), // צ (Tsadi) - 48 => b"nextplace".to_vec(), // ק (Qof) - 49 => b"automl".to_vec(), // ר (Resh) - 50 => b"audio".to_vec(), // ש (Shin) - 51 => b"celium".to_vec(), // ת (Tav) - 52 => b"dojo".to_vec(), // ا (Alif) - 53 => b"frontier".to_vec(), // ب (Ba) - 54 => b"safescan".to_vec(), // ت (Ta) - 55 => b"unknown".to_vec(), // ث (Tha) - 56 => b"gradients".to_vec(), // ج (Jim) - 57 => b"gaia".to_vec(), // ح (Ha) + 0 => b"root".to_vec(), // Τ (Upper case Tau) + 1 => b"apex".to_vec(), // α (Alpha) + 2 => b"omron".to_vec(), // β (Beta) + 3 => b"templar".to_vec(), // γ (Gamma) + 4 => b"targon".to_vec(), // δ (Delta) + 5 => b"kaito".to_vec(), // ε (Epsilon) + 6 => b"infinite".to_vec(), // ζ (Zeta) + 7 => b"subvortex".to_vec(), // η (Eta) + 8 => b"ptn".to_vec(), // θ (Theta) + 9 => b"pretrain".to_vec(), // ι (Iota) + 10 => b"sturdy".to_vec(), // κ (Kappa) + 11 => b"dippy".to_vec(), // λ (Lambda) + 12 => b"horde".to_vec(), // μ (Mu) + 13 => b"dataverse".to_vec(), // ν (Nu) + 14 => b"palaidn".to_vec(), // ξ (Xi) + 15 => b"deval".to_vec(), // ο (Omicron) + 16 => b"bitads".to_vec(), // π (Pi) + 17 => b"3gen".to_vec(), // ρ (Rho) + 18 => b"cortex".to_vec(), // σ (Sigma) + 19 => b"inference".to_vec(), // t (Tau) + 20 => b"bitagent".to_vec(), // υ (Upsilon) + 21 => b"any-any".to_vec(), // φ (Phi) + 22 => b"meta".to_vec(), // χ (Chi) + 23 => b"social".to_vec(), // ψ (Psi) + 24 => b"omega".to_vec(), // ω (Omega) + 25 => b"protein".to_vec(), // א (Aleph) + 26 => b"alchemy".to_vec(), // ב (Bet) + 27 => b"compute".to_vec(), // ג (Gimel) + 28 => b"oracle".to_vec(), // ד (Dalet) + 29 => b"coldint".to_vec(), // ה (He) + 30 => b"bet".to_vec(), // ו (Vav) + 31 => b"naschain".to_vec(), // ז (Zayin) + 32 => b"itsai".to_vec(), // ח (Het) + 33 => b"ready".to_vec(), // ט (Tet) + 34 => b"mind".to_vec(), // י (Yod) + 35 => b"logic".to_vec(), // ך (Final Kaf) + 36 => b"automata".to_vec(), // כ (Kaf) + 37 => b"tuning".to_vec(), // ל (Lamed) + 38 => b"distributed".to_vec(), // ם (Final Mem) + 39 => b"edge".to_vec(), // מ (Mem) + 40 => b"chunk".to_vec(), // ן (Final Nun) + 41 => b"sportsensor".to_vec(), // נ (Nun) + 42 => b"masa".to_vec(), // ס (Samekh) + 43 => b"graphite".to_vec(), // ע (Ayin) + 44 => b"score".to_vec(), // ף (Final Pe) + 45 => b"gen42".to_vec(), // פ (Pe) + 46 => b"neural".to_vec(), // ץ (Final Tsadi) + 47 => b"condense".to_vec(), // צ (Tsadi) + 48 => b"nextplace".to_vec(), // ק (Qof) + 49 => b"automl".to_vec(), // ר (Resh) + 50 => b"audio".to_vec(), // ש (Shin) + 51 => b"celium".to_vec(), // ת (Tav) + 52 => b"dojo".to_vec(), // ا (Alif) + 53 => b"frontier".to_vec(), // ب (Ba) + 54 => b"safescan".to_vec(), // ت (Ta) + 55 => b"unknown".to_vec(), // ث (Tha) + 56 => b"gradients".to_vec(), // ج (Jim) + 57 => b"gaia".to_vec(), // ح (Ha) 58 => b"dippy-speach".to_vec(), // خ (Kha) - 59 => b"agent-arena".to_vec(), // د (Dal) - 60 => b"unknown".to_vec(), // ذ (Dhal) - 61 => b"red team".to_vec(), // ر (Ra) - 62 => b"agentao".to_vec(), // ز (Zay) - 63 => b"lean-in".to_vec(), // س (Sin) - 64 => b"chutes".to_vec(), // ش (Shin) + 59 => b"agent-arena".to_vec(), // د (Dal) + 60 => b"unknown".to_vec(), // ذ (Dhal) + 61 => b"red team".to_vec(), // ر (Ra) + 62 => b"agentao".to_vec(), // ز (Zay) + 63 => b"lean-in".to_vec(), // س (Sin) + 64 => b"chutes".to_vec(), // ش (Shin) 65 => b"sad".to_vec(), 66 => b"dad".to_vec(), 67 => b"ta".to_vec(), @@ -126,207 +126,207 @@ impl Pallet { 116 => b"dze".to_vec(), 117 => b"alfa".to_vec(), 118 => b"alfas".to_vec(), - 119 => b"vida".to_vec(), // Ⲃ (Vida, 119) - 120 => b"vida_small".to_vec(), // ⲃ (Small Vida, 120) - 121 => b"gamma".to_vec(), // Ⲅ (Gamma, 121) - 122 => b"gamma_small".to_vec(), // ⲅ (Small Gamma, 122) - 123 => b"brahmi_a".to_vec(), // 𑀀 (A, 123) - 124 => b"brahmi_aa".to_vec(), // 𑀁 (Aa, 124) - 125 => b"brahmi_i".to_vec(), // 𑀂 (I, 125) - 126 => b"brahmi_ii".to_vec(), // 𑀃 (Ii, 126) - 127 => b"brahmi_u".to_vec(), // 𑀅 (U, 127) - 128 => b"tifinagh_ya".to_vec(), // ⴰ (Ya, 128) - 129 => b"tifinagh_yab".to_vec(), // ⴱ (Yab, 129) - 130 => b"tifinagh_yabh".to_vec(), // ⴲ (Yabh, 130) - 131 => b"tifinagh_yag".to_vec(), // ⴳ (Yag, 131) - 132 => b"tifinagh_yagh".to_vec(), // ⴴ (Yagh, 132) - 133 => b"tifinagh_yaj".to_vec(), // ⴵ (Yaj, 133) - 134 => b"glagolitic_az".to_vec(), // Ⰰ (Az, 134) - 135 => b"glagolitic_buky".to_vec(), // Ⰱ (Buky, 135) - 136 => b"glagolitic_vede".to_vec(), // Ⰲ (Vede, 136) - 137 => b"glagolitic_glagoli".to_vec(), // Ⰳ (Glagoli, 137) - 138 => b"glagolitic_dobro".to_vec(), // Ⰴ (Dobro, 138) - 139 => b"glagolitic_yest".to_vec(), // Ⰵ (Yest, 139) - 140 => b"glagolitic_zhivete".to_vec(), // Ⰶ (Zhivete, 140) - 141 => b"glagolitic_zemlja".to_vec(), // Ⰷ (Zemlja, 141) - 142 => b"glagolitic_izhe".to_vec(), // Ⰸ (Izhe, 142) + 119 => b"vida".to_vec(), // Ⲃ (Vida, 119) + 120 => b"vida_small".to_vec(), // ⲃ (Small Vida, 120) + 121 => b"gamma".to_vec(), // Ⲅ (Gamma, 121) + 122 => b"gamma_small".to_vec(), // ⲅ (Small Gamma, 122) + 123 => b"brahmi_a".to_vec(), // 𑀀 (A, 123) + 124 => b"brahmi_aa".to_vec(), // 𑀁 (Aa, 124) + 125 => b"brahmi_i".to_vec(), // 𑀂 (I, 125) + 126 => b"brahmi_ii".to_vec(), // 𑀃 (Ii, 126) + 127 => b"brahmi_u".to_vec(), // 𑀅 (U, 127) + 128 => b"tifinagh_ya".to_vec(), // ⴰ (Ya, 128) + 129 => b"tifinagh_yab".to_vec(), // ⴱ (Yab, 129) + 130 => b"tifinagh_yabh".to_vec(), // ⴲ (Yabh, 130) + 131 => b"tifinagh_yag".to_vec(), // ⴳ (Yag, 131) + 132 => b"tifinagh_yagh".to_vec(), // ⴴ (Yagh, 132) + 133 => b"tifinagh_yaj".to_vec(), // ⴵ (Yaj, 133) + 134 => b"glagolitic_az".to_vec(), // Ⰰ (Az, 134) + 135 => b"glagolitic_buky".to_vec(), // Ⰱ (Buky, 135) + 136 => b"glagolitic_vede".to_vec(), // Ⰲ (Vede, 136) + 137 => b"glagolitic_glagoli".to_vec(), // Ⰳ (Glagoli, 137) + 138 => b"glagolitic_dobro".to_vec(), // Ⰴ (Dobro, 138) + 139 => b"glagolitic_yest".to_vec(), // Ⰵ (Yest, 139) + 140 => b"glagolitic_zhivete".to_vec(), // Ⰶ (Zhivete, 140) + 141 => b"glagolitic_zemlja".to_vec(), // Ⰷ (Zemlja, 141) + 142 => b"glagolitic_izhe".to_vec(), // Ⰸ (Izhe, 142) 143 => b"glagolitic_initial_izhe".to_vec(), // Ⰹ (Initial Izhe, 143) - 144 => b"glagolitic_i".to_vec(), // Ⰺ (I, 144) - 145 => b"glagolitic_djerv".to_vec(), // Ⰻ (Djerv, 145) - 146 => b"glagolitic_kako".to_vec(), // Ⰼ (Kako, 146) - 147 => b"glagolitic_ljudije".to_vec(), // Ⰽ (Ljudije, 147) - 148 => b"glagolitic_myse".to_vec(), // Ⰾ (Myse, 148) - 149 => b"glagolitic_nash".to_vec(), // Ⰿ (Nash, 149) - 150 => b"glagolitic_on".to_vec(), // Ⱀ (On, 150) - 151 => b"glagolitic_pokoj".to_vec(), // Ⱁ (Pokoj, 151) - 152 => b"glagolitic_rtsy".to_vec(), // Ⱂ (Rtsy, 152) - 153 => b"glagolitic_slovo".to_vec(), // Ⱃ (Slovo, 153) - 154 => b"glagolitic_tvrido".to_vec(), // Ⱄ (Tvrido, 154) - 155 => b"glagolitic_uku".to_vec(), // Ⱅ (Uku, 155) - 156 => b"glagolitic_fert".to_vec(), // Ⱆ (Fert, 156) - 157 => b"glagolitic_xrivi".to_vec(), // Ⱇ (Xrivi, 157) - 158 => b"glagolitic_ot".to_vec(), // Ⱈ (Ot, 158) - 159 => b"glagolitic_cy".to_vec(), // Ⱉ (Cy, 159) - 160 => b"glagolitic_shcha".to_vec(), // Ⱊ (Shcha, 160) - 161 => b"glagolitic_er".to_vec(), // Ⱋ (Er, 161) - 162 => b"glagolitic_yeru".to_vec(), // Ⱌ (Yeru, 162) - 163 => b"glagolitic_small_yer".to_vec(), // Ⱍ (Small Yer, 163) - 164 => b"glagolitic_yo".to_vec(), // Ⱎ (Yo, 164) - 165 => b"glagolitic_yu".to_vec(), // Ⱏ (Yu, 165) - 166 => b"glagolitic_ja".to_vec(), // Ⱐ (Ja, 166) - 167 => b"thai_ko_kai".to_vec(), // ก (Ko Kai, 167) - 168 => b"thai_kho_khai".to_vec(), // ข (Kho Khai, 168) - 169 => b"thai_kho_khuat".to_vec(), // ฃ (Kho Khuat, 169) - 170 => b"thai_kho_khon".to_vec(), // ค (Kho Khon, 170) - 171 => b"thai_kho_rakhang".to_vec(), // ฅ (Kho Rakhang, 171) - 172 => b"thai_kho_khwai".to_vec(), // ฆ (Kho Khwai, 172) - 173 => b"thai_ngo_ngu".to_vec(), // ง (Ngo Ngu, 173) - 174 => b"thai_cho_chan".to_vec(), // จ (Cho Chan, 174) - 175 => b"thai_cho_ching".to_vec(), // ฉ (Cho Ching, 175) - 176 => b"thai_cho_chang".to_vec(), // ช (Cho Chang, 176) - 177 => b"thai_so_so".to_vec(), // ซ (So So, 177) - 178 => b"thai_cho_choe".to_vec(), // ฌ (Cho Choe, 178) - 179 => b"thai_yo_ying".to_vec(), // ญ (Yo Ying, 179) - 180 => b"thai_do_chada".to_vec(), // ฎ (Do Chada, 180) - 181 => b"thai_to_patak".to_vec(), // ฏ (To Patak, 181) - 182 => b"thai_tho_than".to_vec(), // ฐ (Tho Than, 182) - 183 => b"thai_tho_nangmontho".to_vec(), // ฑ (Tho Nangmontho, 183) - 184 => b"thai_tho_phuthao".to_vec(), // ฒ (Tho Phuthao, 184) - 185 => b"thai_no_nen".to_vec(), // ณ (No Nen, 185) - 186 => b"thai_do_dek".to_vec(), // ด (Do Dek, 186) - 187 => b"thai_to_tao".to_vec(), // ต (To Tao, 187) - 188 => b"thai_tho_thung".to_vec(), // ถ (Tho Thung, 188) - 189 => b"thai_tho_thahan".to_vec(), // ท (Tho Thahan, 189) - 190 => b"thai_tho_thong".to_vec(), // ธ (Tho Thong, 190) - 191 => b"thai_no_nu".to_vec(), // น (No Nu, 191) - 192 => b"thai_bo_baimai".to_vec(), // บ (Bo Baimai, 192) - 193 => b"thai_po_pla".to_vec(), // ป (Po Pla, 193) - 194 => b"thai_pho_phung".to_vec(), // ผ (Pho Phung, 194) - 195 => b"thai_fo_fa".to_vec(), // ฝ (Fo Fa, 195) - 196 => b"thai_pho_phan".to_vec(), // พ (Pho Phan, 196) - 197 => b"thai_fo_fan".to_vec(), // ฟ (Fo Fan, 197) - 198 => b"thai_pho_samphao".to_vec(), // ภ (Pho Samphao, 198) - 199 => b"thai_mo_ma".to_vec(), // ม (Mo Ma, 199) - 200 => b"thai_yo_yak".to_vec(), // ย (Yo Yak, 200) - 201 => b"thai_ro_rua".to_vec(), // ร (Ro Rua, 201) - 202 => b"thai_lo_ling".to_vec(), // ล (Lo Ling, 202) - 203 => b"thai_wo_waen".to_vec(), // ว (Wo Waen, 203) - 204 => b"thai_so_sala".to_vec(), // ศ (So Sala, 204) - 205 => b"thai_so_rusi".to_vec(), // ษ (So Rusi, 205) - 206 => b"thai_so_sua".to_vec(), // ส (So Sua, 206) - 207 => b"thai_ho_hip".to_vec(), // ห (Ho Hip, 207) - 208 => b"thai_lo_chula".to_vec(), // ฬ (Lo Chula, 208) - 209 => b"thai_o_ang".to_vec(), // อ (O Ang, 209) - 210 => b"thai_ho_nokhuk".to_vec(), // ฮ (Ho Nokhuk, 210) - 211 => b"hangul_giyeok".to_vec(), // ㄱ (Giyeok, 211) - 212 => b"hangul_nieun".to_vec(), // ㄴ (Nieun, 212) - 213 => b"hangul_digeut".to_vec(), // ㄷ (Digeut, 213) - 214 => b"hangul_rieul".to_vec(), // ㄹ (Rieul, 214) - 215 => b"hangul_mieum".to_vec(), // ㅁ (Mieum, 215) - 216 => b"hangul_bieup".to_vec(), // ㅂ (Bieup, 216) - 217 => b"hangul_siot".to_vec(), // ㅅ (Siot, 217) - 218 => b"hangul_ieung".to_vec(), // ㅇ (Ieung, 218) - 219 => b"hangul_jieut".to_vec(), // ㅈ (Jieut, 219) - 220 => b"hangul_chieut".to_vec(), // ㅊ (Chieut, 220) - 221 => b"hangul_kieuk".to_vec(), // ㅋ (Kieuk, 221) - 222 => b"hangul_tieut".to_vec(), // ㅌ (Tieut, 222) - 223 => b"hangul_pieup".to_vec(), // ㅍ (Pieup, 223) - 224 => b"hangul_hieut".to_vec(), // ㅎ (Hieut, 224) - 225 => b"hangul_a".to_vec(), // ㅏ (A, 225) - 226 => b"hangul_ae".to_vec(), // ㅐ (Ae, 226) - 227 => b"hangul_ya".to_vec(), // ㅑ (Ya, 227) - 228 => b"hangul_yae".to_vec(), // ㅒ (Yae, 228) - 229 => b"hangul_eo".to_vec(), // ㅓ (Eo, 229) - 230 => b"hangul_e".to_vec(), // ㅔ (E, 230) - 231 => b"hangul_yeo".to_vec(), // ㅕ (Yeo, 231) - 232 => b"hangul_ye".to_vec(), // ㅖ (Ye, 232) - 233 => b"hangul_o".to_vec(), // ㅗ (O, 233) - 234 => b"hangul_wa".to_vec(), // ㅘ (Wa, 234) - 235 => b"hangul_wae".to_vec(), // ㅙ (Wae, 235) - 236 => b"hangul_oe".to_vec(), // ㅚ (Oe, 236) - 237 => b"hangul_yo".to_vec(), // ㅛ (Yo, 237) - 238 => b"hangul_u".to_vec(), // ㅜ (U, 238) - 239 => b"hangul_weo".to_vec(), // ㅝ (Weo, 239) - 240 => b"hangul_we".to_vec(), // ㅞ (We, 240) - 241 => b"hangul_wi".to_vec(), // ㅟ (Wi, 241) - 242 => b"hangul_yu".to_vec(), // ㅠ (Yu, 242) - 243 => b"hangul_eu".to_vec(), // ㅡ (Eu, 243) - 244 => b"hangul_ui".to_vec(), // ㅢ (Ui, 244) - 245 => b"hangul_i".to_vec(), // ㅣ (I, 245) - 246 => b"ethiopic_glottal_a".to_vec(), // አ (Glottal A, 246) - 247 => b"ethiopic_glottal_u".to_vec(), // ኡ (Glottal U, 247) - 248 => b"ethiopic_glottal_i".to_vec(), // ኢ (Glottal I, 248) - 249 => b"ethiopic_glottal_aa".to_vec(), // ኣ (Glottal Aa, 249) - 250 => b"ethiopic_glottal_e".to_vec(), // ኤ (Glottal E, 250) - 251 => b"ethiopic_glottal_ie".to_vec(), // እ (Glottal Ie, 251) - 252 => b"ethiopic_glottal_o".to_vec(), // ኦ (Glottal O, 252) - 253 => b"ethiopic_glottal_wa".to_vec(), // ኧ (Glottal Wa, 253) - 254 => b"ethiopic_wa".to_vec(), // ወ (Wa, 254) - 255 => b"ethiopic_wu".to_vec(), // ዉ (Wu, 255) - 256 => b"ethiopic_wi".to_vec(), // ዊ (Wi, 256) - 257 => b"ethiopic_waa".to_vec(), // ዋ (Waa, 257) - 258 => b"ethiopic_we".to_vec(), // ዌ (We, 258) - 259 => b"ethiopic_wye".to_vec(), // ው (Wye, 259) - 260 => b"ethiopic_wo".to_vec(), // ዎ (Wo, 260) - 261 => b"ethiopic_ko".to_vec(), // ኰ (Ko, 261) - 262 => b"ethiopic_ku".to_vec(), // ኱ (Ku, 262) - 263 => b"ethiopic_ki".to_vec(), // ኲ (Ki, 263) - 264 => b"ethiopic_kua".to_vec(), // ኳ (Kua, 264) - 265 => b"ethiopic_ke".to_vec(), // ኴ (Ke, 265) - 266 => b"ethiopic_kwe".to_vec(), // ኵ (Kwe, 266) - 267 => b"ethiopic_ko_alt".to_vec(), // ኶ (Ko, 267) - 268 => b"ethiopic_go".to_vec(), // ጐ (Go, 268) - 269 => b"ethiopic_gu".to_vec(), // ጑ (Gu, 269) - 270 => b"ethiopic_gi".to_vec(), // ጒ (Gi, 270) - 271 => b"ethiopic_gua".to_vec(), // መ (Gua, 271) - 272 => b"ethiopic_ge".to_vec(), // ጔ (Ge, 272) - 273 => b"ethiopic_gwe".to_vec(), // ጕ (Gwe, 273) - 274 => b"ethiopic_go_alt".to_vec(), // ጖ (Go, 274) - 275 => b"devanagari_a".to_vec(), // अ (A, 275) - 276 => b"devanagari_aa".to_vec(), // आ (Aa, 276) - 277 => b"devanagari_i".to_vec(), // इ (I, 277) - 278 => b"devanagari_ii".to_vec(), // ई (Ii, 278) - 279 => b"devanagari_u".to_vec(), // उ (U, 279) - 280 => b"devanagari_uu".to_vec(), // ऊ (Uu, 280) - 281 => b"devanagari_r".to_vec(), // ऋ (R, 281) - 282 => b"devanagari_e".to_vec(), // ए (E, 282) - 283 => b"devanagari_ai".to_vec(), // ऐ (Ai, 283) - 284 => b"devanagari_o".to_vec(), // ओ (O, 284) - 285 => b"devanagari_au".to_vec(), // औ (Au, 285) - 286 => b"devanagari_ka".to_vec(), // क (Ka, 286) - 287 => b"devanagari_kha".to_vec(), // ख (Kha, 287) - 288 => b"devanagari_ga".to_vec(), // ग (Ga, 288) - 289 => b"devanagari_gha".to_vec(), // घ (Gha, 289) - 290 => b"devanagari_nga".to_vec(), // ङ (Nga, 290) - 291 => b"devanagari_cha".to_vec(), // च (Cha, 291) - 292 => b"devanagari_chha".to_vec(), // छ (Chha, 292) - 293 => b"devanagari_ja".to_vec(), // ज (Ja, 293) - 294 => b"devanagari_jha".to_vec(), // झ (Jha, 294) - 295 => b"devanagari_nya".to_vec(), // ञ (Nya, 295) - 296 => b"devanagari_ta".to_vec(), // ट (Ta, 296) - 297 => b"devanagari_tha".to_vec(), // ठ (Tha, 297) - 298 => b"devanagari_da".to_vec(), // ड (Da, 298) - 299 => b"devanagari_dha".to_vec(), // ढ (Dha, 299) - 300 => b"devanagari_na".to_vec(), // ण (Na, 300) - 301 => b"devanagari_ta_alt".to_vec(), // त (Ta, 301) - 302 => b"devanagari_tha_alt".to_vec(), // थ (Tha, 302) - 303 => b"devanagari_da_alt".to_vec(), // द (Da, 303) - 304 => b"devanagari_dha_alt".to_vec(), // ध (Dha, 304) - 305 => b"devanagari_na_alt".to_vec(), // न (Na, 305) - 306 => b"devanagari_pa".to_vec(), // प (Pa, 306) - 307 => b"devanagari_pha".to_vec(), // फ (Pha, 307) - 308 => b"devanagari_ba".to_vec(), // ब (Ba, 308) - 309 => b"devanagari_bha".to_vec(), // भ (Bha, 309) - 310 => b"devanagari_ma".to_vec(), // म (Ma, 310) - 311 => b"devanagari_ya".to_vec(), // य (Ya, 311) - 312 => b"devanagari_ra".to_vec(), // र (Ra, 312) - 313 => b"devanagari_la".to_vec(), // ल (La, 313) - 314 => b"devanagari_va".to_vec(), // व (Va, 314) - 315 => b"devanagari_sha".to_vec(), // श (Sha, 315) - 316 => b"devanagari_ssa".to_vec(), // ष (Ssa, 316) - 317 => b"devanagari_sa".to_vec(), // स (Sa, 317) - 318 => b"devanagari_ha".to_vec(), // ह (Ha, 318) - 319 => b"katakana_a".to_vec(), // ア (A, 319) + 144 => b"glagolitic_i".to_vec(), // Ⰺ (I, 144) + 145 => b"glagolitic_djerv".to_vec(), // Ⰻ (Djerv, 145) + 146 => b"glagolitic_kako".to_vec(), // Ⰼ (Kako, 146) + 147 => b"glagolitic_ljudije".to_vec(), // Ⰽ (Ljudije, 147) + 148 => b"glagolitic_myse".to_vec(), // Ⰾ (Myse, 148) + 149 => b"glagolitic_nash".to_vec(), // Ⰿ (Nash, 149) + 150 => b"glagolitic_on".to_vec(), // Ⱀ (On, 150) + 151 => b"glagolitic_pokoj".to_vec(), // Ⱁ (Pokoj, 151) + 152 => b"glagolitic_rtsy".to_vec(), // Ⱂ (Rtsy, 152) + 153 => b"glagolitic_slovo".to_vec(), // Ⱃ (Slovo, 153) + 154 => b"glagolitic_tvrido".to_vec(), // Ⱄ (Tvrido, 154) + 155 => b"glagolitic_uku".to_vec(), // Ⱅ (Uku, 155) + 156 => b"glagolitic_fert".to_vec(), // Ⱆ (Fert, 156) + 157 => b"glagolitic_xrivi".to_vec(), // Ⱇ (Xrivi, 157) + 158 => b"glagolitic_ot".to_vec(), // Ⱈ (Ot, 158) + 159 => b"glagolitic_cy".to_vec(), // Ⱉ (Cy, 159) + 160 => b"glagolitic_shcha".to_vec(), // Ⱊ (Shcha, 160) + 161 => b"glagolitic_er".to_vec(), // Ⱋ (Er, 161) + 162 => b"glagolitic_yeru".to_vec(), // Ⱌ (Yeru, 162) + 163 => b"glagolitic_small_yer".to_vec(), // Ⱍ (Small Yer, 163) + 164 => b"glagolitic_yo".to_vec(), // Ⱎ (Yo, 164) + 165 => b"glagolitic_yu".to_vec(), // Ⱏ (Yu, 165) + 166 => b"glagolitic_ja".to_vec(), // Ⱐ (Ja, 166) + 167 => b"thai_ko_kai".to_vec(), // ก (Ko Kai, 167) + 168 => b"thai_kho_khai".to_vec(), // ข (Kho Khai, 168) + 169 => b"thai_kho_khuat".to_vec(), // ฃ (Kho Khuat, 169) + 170 => b"thai_kho_khon".to_vec(), // ค (Kho Khon, 170) + 171 => b"thai_kho_rakhang".to_vec(), // ฅ (Kho Rakhang, 171) + 172 => b"thai_kho_khwai".to_vec(), // ฆ (Kho Khwai, 172) + 173 => b"thai_ngo_ngu".to_vec(), // ง (Ngo Ngu, 173) + 174 => b"thai_cho_chan".to_vec(), // จ (Cho Chan, 174) + 175 => b"thai_cho_ching".to_vec(), // ฉ (Cho Ching, 175) + 176 => b"thai_cho_chang".to_vec(), // ช (Cho Chang, 176) + 177 => b"thai_so_so".to_vec(), // ซ (So So, 177) + 178 => b"thai_cho_choe".to_vec(), // ฌ (Cho Choe, 178) + 179 => b"thai_yo_ying".to_vec(), // ญ (Yo Ying, 179) + 180 => b"thai_do_chada".to_vec(), // ฎ (Do Chada, 180) + 181 => b"thai_to_patak".to_vec(), // ฏ (To Patak, 181) + 182 => b"thai_tho_than".to_vec(), // ฐ (Tho Than, 182) + 183 => b"thai_tho_nangmontho".to_vec(), // ฑ (Tho Nangmontho, 183) + 184 => b"thai_tho_phuthao".to_vec(), // ฒ (Tho Phuthao, 184) + 185 => b"thai_no_nen".to_vec(), // ณ (No Nen, 185) + 186 => b"thai_do_dek".to_vec(), // ด (Do Dek, 186) + 187 => b"thai_to_tao".to_vec(), // ต (To Tao, 187) + 188 => b"thai_tho_thung".to_vec(), // ถ (Tho Thung, 188) + 189 => b"thai_tho_thahan".to_vec(), // ท (Tho Thahan, 189) + 190 => b"thai_tho_thong".to_vec(), // ธ (Tho Thong, 190) + 191 => b"thai_no_nu".to_vec(), // น (No Nu, 191) + 192 => b"thai_bo_baimai".to_vec(), // บ (Bo Baimai, 192) + 193 => b"thai_po_pla".to_vec(), // ป (Po Pla, 193) + 194 => b"thai_pho_phung".to_vec(), // ผ (Pho Phung, 194) + 195 => b"thai_fo_fa".to_vec(), // ฝ (Fo Fa, 195) + 196 => b"thai_pho_phan".to_vec(), // พ (Pho Phan, 196) + 197 => b"thai_fo_fan".to_vec(), // ฟ (Fo Fan, 197) + 198 => b"thai_pho_samphao".to_vec(), // ภ (Pho Samphao, 198) + 199 => b"thai_mo_ma".to_vec(), // ม (Mo Ma, 199) + 200 => b"thai_yo_yak".to_vec(), // ย (Yo Yak, 200) + 201 => b"thai_ro_rua".to_vec(), // ร (Ro Rua, 201) + 202 => b"thai_lo_ling".to_vec(), // ล (Lo Ling, 202) + 203 => b"thai_wo_waen".to_vec(), // ว (Wo Waen, 203) + 204 => b"thai_so_sala".to_vec(), // ศ (So Sala, 204) + 205 => b"thai_so_rusi".to_vec(), // ษ (So Rusi, 205) + 206 => b"thai_so_sua".to_vec(), // ส (So Sua, 206) + 207 => b"thai_ho_hip".to_vec(), // ห (Ho Hip, 207) + 208 => b"thai_lo_chula".to_vec(), // ฬ (Lo Chula, 208) + 209 => b"thai_o_ang".to_vec(), // อ (O Ang, 209) + 210 => b"thai_ho_nokhuk".to_vec(), // ฮ (Ho Nokhuk, 210) + 211 => b"hangul_giyeok".to_vec(), // ㄱ (Giyeok, 211) + 212 => b"hangul_nieun".to_vec(), // ㄴ (Nieun, 212) + 213 => b"hangul_digeut".to_vec(), // ㄷ (Digeut, 213) + 214 => b"hangul_rieul".to_vec(), // ㄹ (Rieul, 214) + 215 => b"hangul_mieum".to_vec(), // ㅁ (Mieum, 215) + 216 => b"hangul_bieup".to_vec(), // ㅂ (Bieup, 216) + 217 => b"hangul_siot".to_vec(), // ㅅ (Siot, 217) + 218 => b"hangul_ieung".to_vec(), // ㅇ (Ieung, 218) + 219 => b"hangul_jieut".to_vec(), // ㅈ (Jieut, 219) + 220 => b"hangul_chieut".to_vec(), // ㅊ (Chieut, 220) + 221 => b"hangul_kieuk".to_vec(), // ㅋ (Kieuk, 221) + 222 => b"hangul_tieut".to_vec(), // ㅌ (Tieut, 222) + 223 => b"hangul_pieup".to_vec(), // ㅍ (Pieup, 223) + 224 => b"hangul_hieut".to_vec(), // ㅎ (Hieut, 224) + 225 => b"hangul_a".to_vec(), // ㅏ (A, 225) + 226 => b"hangul_ae".to_vec(), // ㅐ (Ae, 226) + 227 => b"hangul_ya".to_vec(), // ㅑ (Ya, 227) + 228 => b"hangul_yae".to_vec(), // ㅒ (Yae, 228) + 229 => b"hangul_eo".to_vec(), // ㅓ (Eo, 229) + 230 => b"hangul_e".to_vec(), // ㅔ (E, 230) + 231 => b"hangul_yeo".to_vec(), // ㅕ (Yeo, 231) + 232 => b"hangul_ye".to_vec(), // ㅖ (Ye, 232) + 233 => b"hangul_o".to_vec(), // ㅗ (O, 233) + 234 => b"hangul_wa".to_vec(), // ㅘ (Wa, 234) + 235 => b"hangul_wae".to_vec(), // ㅙ (Wae, 235) + 236 => b"hangul_oe".to_vec(), // ㅚ (Oe, 236) + 237 => b"hangul_yo".to_vec(), // ㅛ (Yo, 237) + 238 => b"hangul_u".to_vec(), // ㅜ (U, 238) + 239 => b"hangul_weo".to_vec(), // ㅝ (Weo, 239) + 240 => b"hangul_we".to_vec(), // ㅞ (We, 240) + 241 => b"hangul_wi".to_vec(), // ㅟ (Wi, 241) + 242 => b"hangul_yu".to_vec(), // ㅠ (Yu, 242) + 243 => b"hangul_eu".to_vec(), // ㅡ (Eu, 243) + 244 => b"hangul_ui".to_vec(), // ㅢ (Ui, 244) + 245 => b"hangul_i".to_vec(), // ㅣ (I, 245) + 246 => b"ethiopic_glottal_a".to_vec(), // አ (Glottal A, 246) + 247 => b"ethiopic_glottal_u".to_vec(), // ኡ (Glottal U, 247) + 248 => b"ethiopic_glottal_i".to_vec(), // ኢ (Glottal I, 248) + 249 => b"ethiopic_glottal_aa".to_vec(), // ኣ (Glottal Aa, 249) + 250 => b"ethiopic_glottal_e".to_vec(), // ኤ (Glottal E, 250) + 251 => b"ethiopic_glottal_ie".to_vec(), // እ (Glottal Ie, 251) + 252 => b"ethiopic_glottal_o".to_vec(), // ኦ (Glottal O, 252) + 253 => b"ethiopic_glottal_wa".to_vec(), // ኧ (Glottal Wa, 253) + 254 => b"ethiopic_wa".to_vec(), // ወ (Wa, 254) + 255 => b"ethiopic_wu".to_vec(), // ዉ (Wu, 255) + 256 => b"ethiopic_wi".to_vec(), // ዊ (Wi, 256) + 257 => b"ethiopic_waa".to_vec(), // ዋ (Waa, 257) + 258 => b"ethiopic_we".to_vec(), // ዌ (We, 258) + 259 => b"ethiopic_wye".to_vec(), // ው (Wye, 259) + 260 => b"ethiopic_wo".to_vec(), // ዎ (Wo, 260) + 261 => b"ethiopic_ko".to_vec(), // ኰ (Ko, 261) + 262 => b"ethiopic_ku".to_vec(), // ኱ (Ku, 262) + 263 => b"ethiopic_ki".to_vec(), // ኲ (Ki, 263) + 264 => b"ethiopic_kua".to_vec(), // ኳ (Kua, 264) + 265 => b"ethiopic_ke".to_vec(), // ኴ (Ke, 265) + 266 => b"ethiopic_kwe".to_vec(), // ኵ (Kwe, 266) + 267 => b"ethiopic_ko_alt".to_vec(), // ኶ (Ko, 267) + 268 => b"ethiopic_go".to_vec(), // ጐ (Go, 268) + 269 => b"ethiopic_gu".to_vec(), // ጑ (Gu, 269) + 270 => b"ethiopic_gi".to_vec(), // ጒ (Gi, 270) + 271 => b"ethiopic_gua".to_vec(), // መ (Gua, 271) + 272 => b"ethiopic_ge".to_vec(), // ጔ (Ge, 272) + 273 => b"ethiopic_gwe".to_vec(), // ጕ (Gwe, 273) + 274 => b"ethiopic_go_alt".to_vec(), // ጖ (Go, 274) + 275 => b"devanagari_a".to_vec(), // अ (A, 275) + 276 => b"devanagari_aa".to_vec(), // आ (Aa, 276) + 277 => b"devanagari_i".to_vec(), // इ (I, 277) + 278 => b"devanagari_ii".to_vec(), // ई (Ii, 278) + 279 => b"devanagari_u".to_vec(), // उ (U, 279) + 280 => b"devanagari_uu".to_vec(), // ऊ (Uu, 280) + 281 => b"devanagari_r".to_vec(), // ऋ (R, 281) + 282 => b"devanagari_e".to_vec(), // ए (E, 282) + 283 => b"devanagari_ai".to_vec(), // ऐ (Ai, 283) + 284 => b"devanagari_o".to_vec(), // ओ (O, 284) + 285 => b"devanagari_au".to_vec(), // औ (Au, 285) + 286 => b"devanagari_ka".to_vec(), // क (Ka, 286) + 287 => b"devanagari_kha".to_vec(), // ख (Kha, 287) + 288 => b"devanagari_ga".to_vec(), // ग (Ga, 288) + 289 => b"devanagari_gha".to_vec(), // घ (Gha, 289) + 290 => b"devanagari_nga".to_vec(), // ङ (Nga, 290) + 291 => b"devanagari_cha".to_vec(), // च (Cha, 291) + 292 => b"devanagari_chha".to_vec(), // छ (Chha, 292) + 293 => b"devanagari_ja".to_vec(), // ज (Ja, 293) + 294 => b"devanagari_jha".to_vec(), // झ (Jha, 294) + 295 => b"devanagari_nya".to_vec(), // ञ (Nya, 295) + 296 => b"devanagari_ta".to_vec(), // ट (Ta, 296) + 297 => b"devanagari_tha".to_vec(), // ठ (Tha, 297) + 298 => b"devanagari_da".to_vec(), // ड (Da, 298) + 299 => b"devanagari_dha".to_vec(), // ढ (Dha, 299) + 300 => b"devanagari_na".to_vec(), // ण (Na, 300) + 301 => b"devanagari_ta_alt".to_vec(), // त (Ta, 301) + 302 => b"devanagari_tha_alt".to_vec(), // थ (Tha, 302) + 303 => b"devanagari_da_alt".to_vec(), // द (Da, 303) + 304 => b"devanagari_dha_alt".to_vec(), // ध (Dha, 304) + 305 => b"devanagari_na_alt".to_vec(), // न (Na, 305) + 306 => b"devanagari_pa".to_vec(), // प (Pa, 306) + 307 => b"devanagari_pha".to_vec(), // फ (Pha, 307) + 308 => b"devanagari_ba".to_vec(), // ब (Ba, 308) + 309 => b"devanagari_bha".to_vec(), // भ (Bha, 309) + 310 => b"devanagari_ma".to_vec(), // म (Ma, 310) + 311 => b"devanagari_ya".to_vec(), // य (Ya, 311) + 312 => b"devanagari_ra".to_vec(), // र (Ra, 312) + 313 => b"devanagari_la".to_vec(), // ल (La, 313) + 314 => b"devanagari_va".to_vec(), // व (Va, 314) + 315 => b"devanagari_sha".to_vec(), // श (Sha, 315) + 316 => b"devanagari_ssa".to_vec(), // ष (Ssa, 316) + 317 => b"devanagari_sa".to_vec(), // स (Sa, 317) + 318 => b"devanagari_ha".to_vec(), // ह (Ha, 318) + 319 => b"katakana_a".to_vec(), // ア (A, 319) 320 => b"kana_i".to_vec(), 321 => b"kana_u".to_vec(), 322 => b"kana_e".to_vec(), diff --git a/pallets/subtensor/src/tests/coinbase.rs b/pallets/subtensor/src/tests/coinbase.rs index 4296e91ff3..2ddb73bb85 100644 --- a/pallets/subtensor/src/tests/coinbase.rs +++ b/pallets/subtensor/src/tests/coinbase.rs @@ -300,19 +300,25 @@ fn test_coinbase_alpha_issuance_with_cap_trigger() { SubnetAlphaIn::::insert(netuid1, initial_alpha); // Make price extremely low. SubnetTAO::::insert(netuid2, initial); SubnetAlphaIn::::insert(netuid2, initial_alpha); // Make price extremely low. - // Set subnet prices. - SubnetMovingPrice::::insert( netuid1, I96F32::from_num(1) ); - SubnetMovingPrice::::insert( netuid2, I96F32::from_num(2) ); + // Set subnet prices. + SubnetMovingPrice::::insert(netuid1, I96F32::from_num(1)); + SubnetMovingPrice::::insert(netuid2, I96F32::from_num(2)); // Run coinbase - SubtensorModule::run_coinbase( I96F32::from_num( emission ) ); + SubtensorModule::run_coinbase(I96F32::from_num(emission)); // tao_in = 333_333 // alpha_in = 333_333/price > 1_000_000_000 --> 1_000_000_000 + initial_alpha - assert_eq!( SubnetAlphaIn::::get( netuid1 ), initial_alpha + 1_000_000_000 ); - assert_eq!( SubnetAlphaOut::::get( netuid2 ), 1_000_000_000 ); + assert_eq!( + SubnetAlphaIn::::get(netuid1), + initial_alpha + 1_000_000_000 + ); + assert_eq!(SubnetAlphaOut::::get(netuid2), 1_000_000_000); // tao_in = 666_666 // alpha_in = 666_666/price > 1_000_000_000 --> 1_000_000_000 + initial_alpha - assert_eq!( SubnetAlphaIn::::get( netuid2 ), initial_alpha + 1_000_000_000 ); - assert_eq!( SubnetAlphaOut::::get( netuid2 ), 1_000_000_000 ); // Gets full block emission. + assert_eq!( + SubnetAlphaIn::::get(netuid2), + initial_alpha + 1_000_000_000 + ); + assert_eq!(SubnetAlphaOut::::get(netuid2), 1_000_000_000); // Gets full block emission. }); } @@ -335,22 +341,22 @@ fn test_coinbase_alpha_issuance_with_cap_trigger_and_block_emission() { SubnetAlphaIn::::insert(netuid1, initial_alpha); // Make price extremely low. SubnetTAO::::insert(netuid2, initial); SubnetAlphaIn::::insert(netuid2, initial_alpha); // Make price extremely low. - // Set issuance to greater than 21M - SubnetAlphaOut::::insert(netuid1, 22_000_000_000_000_000 ); // Set issuance above 21M - SubnetAlphaOut::::insert(netuid2, 22_000_000_000_000_000 ); // Set issuance above 21M - // Set subnet prices. - SubnetMovingPrice::::insert( netuid1, I96F32::from_num(1) ); - SubnetMovingPrice::::insert( netuid2, I96F32::from_num(2) ); + // Set issuance to greater than 21M + SubnetAlphaOut::::insert(netuid1, 22_000_000_000_000_000); // Set issuance above 21M + SubnetAlphaOut::::insert(netuid2, 22_000_000_000_000_000); // Set issuance above 21M + // Set subnet prices. + SubnetMovingPrice::::insert(netuid1, I96F32::from_num(1)); + SubnetMovingPrice::::insert(netuid2, I96F32::from_num(2)); // Run coinbase - SubtensorModule::run_coinbase( I96F32::from_num( emission ) ); + SubtensorModule::run_coinbase(I96F32::from_num(emission)); // tao_in = 333_333 // alpha_in = 333_333/price > 1_000_000_000 --> 0 + initial_alpha - assert_eq!( SubnetAlphaIn::::get( netuid1 ), initial_alpha ); - assert_eq!( SubnetAlphaOut::::get( netuid2 ), 22_000_000_000_000_000 ); + assert_eq!(SubnetAlphaIn::::get(netuid1), initial_alpha); + assert_eq!(SubnetAlphaOut::::get(netuid2), 22_000_000_000_000_000); // tao_in = 666_666 // alpha_in = 666_666/price > 1_000_000_000 --> 0 + initial_alpha - assert_eq!( SubnetAlphaIn::::get( netuid2 ), initial_alpha ); - assert_eq!( SubnetAlphaOut::::get( netuid2 ), 22_000_000_000_000_000 ); // No emission. + assert_eq!(SubnetAlphaIn::::get(netuid2), initial_alpha); + assert_eq!(SubnetAlphaOut::::get(netuid2), 22_000_000_000_000_000); + // No emission. }); } -