From 05c8c693d7f2b423abe86270981b5851b35ad1ea Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Tue, 4 Nov 2025 18:36:25 -0500 Subject: [PATCH 1/8] Re-init tao flows --- pallets/subtensor/src/macros/hooks.rs | 4 +- .../src/migrations/migrate_init_tao_flow.rs | 57 +++++++++++++++++++ pallets/subtensor/src/migrations/mod.rs | 1 + 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 pallets/subtensor/src/migrations/migrate_init_tao_flow.rs diff --git a/pallets/subtensor/src/macros/hooks.rs b/pallets/subtensor/src/macros/hooks.rs index 87a87e911c..2369b25275 100644 --- a/pallets/subtensor/src/macros/hooks.rs +++ b/pallets/subtensor/src/macros/hooks.rs @@ -159,7 +159,9 @@ mod hooks { // Migrate Kappa to default (0.5) .saturating_add(migrations::migrate_kappa_map_to_default::migrate_kappa_map_to_default::()) // Remove obsolete map entries - .saturating_add(migrations::migrate_remove_tao_dividends::migrate_remove_tao_dividends::()); + .saturating_add(migrations::migrate_remove_tao_dividends::migrate_remove_tao_dividends::()) + // Re-init tao flows + .saturating_add(migrations::migrate_init_tao_flows::migrate_init_tao_flows::()); weight } diff --git a/pallets/subtensor/src/migrations/migrate_init_tao_flow.rs b/pallets/subtensor/src/migrations/migrate_init_tao_flow.rs new file mode 100644 index 0000000000..c0cdb87336 --- /dev/null +++ b/pallets/subtensor/src/migrations/migrate_init_tao_flow.rs @@ -0,0 +1,57 @@ +use alloc::string::String; + +use frame_support::IterableStorageMap; +use frame_support::{traits::Get, weights::Weight}; +use subtensor_runtime_common::NetUid; + +use super::*; + +pub fn migrate_init_tao_flows() -> Weight { + let migration_name = b"migrate_init_tao_flow".to_vec(); + + // Initialize the weight with one read operation. + let mut weight = T::DbWeight::get().reads(1); + + // Check if the migration has already run + if HasMigrationRun::::get(&migration_name) { + log::info!( + "Migration '{:?}' has already run. Skipping.", + String::from_utf8_lossy(&migration_name) + ); + return weight; + } + log::info!( + "Running migration '{}'", + String::from_utf8_lossy(&migration_name) + ); + + let netuids: Vec = as IterableStorageMap>::iter() + .map(|(netuid, _)| netuid) + .collect(); + weight = weight.saturating_add(T::DbWeight::get().reads(netuids.len() as u64)); + + for netuid in netuids.iter() { + if netuid.is_root() { + continue; + } + // Set SubnetEmaTaoFlow + SubnetEmaTaoFlow::::insert(*netuid, I64F64::saturating_from_num(0)); + + + + + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + } + + // Mark the migration as completed + HasMigrationRun::::insert(&migration_name, true); + weight = weight.saturating_add(T::DbWeight::get().writes(1)); + + log::info!( + "Migration '{:?}' completed.", + String::from_utf8_lossy(&migration_name) + ); + + // Return the migration weight. + weight +} diff --git a/pallets/subtensor/src/migrations/mod.rs b/pallets/subtensor/src/migrations/mod.rs index d95e4c7bac..dc14de151f 100644 --- a/pallets/subtensor/src/migrations/mod.rs +++ b/pallets/subtensor/src/migrations/mod.rs @@ -20,6 +20,7 @@ pub mod migrate_fix_is_network_member; pub mod migrate_fix_root_subnet_tao; pub mod migrate_fix_root_tao_and_alpha_in; pub mod migrate_identities_v2; +pub mod migrate_init_tao_flows; pub mod migrate_init_total_issuance; pub mod migrate_kappa_map_to_default; pub mod migrate_network_immunity_period; From 60c4a5c5803a8bb9ac9d298ac2a08df239c7ddc0 Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Tue, 4 Nov 2025 18:54:07 -0500 Subject: [PATCH 2/8] Revert back to ema-prices --- .../src/coinbase/subnet_emissions.rs | 34 +- pallets/subtensor/src/tests/coinbase.rs | 200 +++--- .../subtensor/src/tests/subnet_emissions.rs | 654 +++++++++--------- runtime/src/lib.rs | 2 +- 4 files changed, 461 insertions(+), 429 deletions(-) diff --git a/pallets/subtensor/src/coinbase/subnet_emissions.rs b/pallets/subtensor/src/coinbase/subnet_emissions.rs index 80ecf85a42..4f3911e3ae 100644 --- a/pallets/subtensor/src/coinbase/subnet_emissions.rs +++ b/pallets/subtensor/src/coinbase/subnet_emissions.rs @@ -51,6 +51,7 @@ impl Pallet { // Update SubnetEmaTaoFlow if needed and return its value for // the current block + #[allow(dead_code)] fn get_ema_flow(netuid: NetUid) -> I64F64 { let current_block: u64 = Self::get_current_block_as_u64(); @@ -87,6 +88,7 @@ impl Pallet { // Either the minimal EMA flow L = min{Si}, or an artificial // cut off at some higher value A (TaoFlowCutoff) // L = max {A, min{min{S[i], 0}}} + #[allow(dead_code)] fn get_lower_limit(ema_flows: &BTreeMap) -> I64F64 { let zero = I64F64::saturating_from_num(0); let min_flow = ema_flows @@ -178,6 +180,7 @@ impl Pallet { } // Implementation of shares that uses TAO flow + #[allow(dead_code)] fn get_shares_flow(subnets_to_emit_to: &[NetUid]) -> BTreeMap { // Get raw flows let ema_flows = subnets_to_emit_to @@ -210,8 +213,37 @@ impl Pallet { offset_flows } + // DEPRECATED: Implementation of shares that uses EMA prices will be gradually deprecated + fn get_shares_price_ema(subnets_to_emit_to: &[NetUid]) -> BTreeMap { + // Get sum of alpha moving prices + let total_moving_prices = subnets_to_emit_to + .iter() + .map(|netuid| U64F64::saturating_from_num(Self::get_moving_alpha_price(*netuid))) + .fold(U64F64::saturating_from_num(0.0), |acc, ema| { + acc.saturating_add(ema) + }); + log::debug!("total_moving_prices: {total_moving_prices:?}"); + + // Calculate shares. + subnets_to_emit_to + .iter() + .map(|netuid| { + let moving_price = + U64F64::saturating_from_num(Self::get_moving_alpha_price(*netuid)); + log::debug!("moving_price_i: {moving_price:?}"); + + let share = moving_price + .checked_div(total_moving_prices) + .unwrap_or(U64F64::saturating_from_num(0)); + + (*netuid, share) + }) + .collect::>() + } + // Combines ema price method and tao flow method linearly over FlowHalfLife blocks pub(crate) fn get_shares(subnets_to_emit_to: &[NetUid]) -> BTreeMap { - Self::get_shares_flow(subnets_to_emit_to) + // Self::get_shares_flow(subnets_to_emit_to) + Self::get_shares_price_ema(subnets_to_emit_to) } } diff --git a/pallets/subtensor/src/tests/coinbase.rs b/pallets/subtensor/src/tests/coinbase.rs index 2d0376c896..60644b2a28 100644 --- a/pallets/subtensor/src/tests/coinbase.rs +++ b/pallets/subtensor/src/tests/coinbase.rs @@ -115,28 +115,28 @@ fn test_coinbase_tao_issuance_base_low() { } // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_coinbase_tao_issuance_base_low_flow --exact --show-output --nocapture -#[test] -fn test_coinbase_tao_issuance_base_low_flow() { - new_test_ext(1).execute_with(|| { - let emission = TaoCurrency::from(1_234_567); - let subnet_owner_ck = U256::from(1001); - let subnet_owner_hk = U256::from(1002); - let netuid = add_dynamic_network(&subnet_owner_hk, &subnet_owner_ck); - let emission = TaoCurrency::from(1); - - // 100% tao flow method - let block_num = FlowHalfLife::::get(); - SubnetEmaTaoFlow::::insert(netuid, (block_num, I64F64::from_num(1_000_000_000))); - System::set_block_number(block_num); - - let tao_in_before = SubnetTAO::::get(netuid); - let total_stake_before = TotalStake::::get(); - SubtensorModule::run_coinbase(U96F32::from_num(emission)); - assert_eq!(SubnetTAO::::get(netuid), tao_in_before + emission); - assert_eq!(TotalIssuance::::get(), emission); - assert_eq!(TotalStake::::get(), total_stake_before + emission); - }); -} +// #[test] +// fn test_coinbase_tao_issuance_base_low_flow() { +// new_test_ext(1).execute_with(|| { +// let emission = TaoCurrency::from(1_234_567); +// let subnet_owner_ck = U256::from(1001); +// let subnet_owner_hk = U256::from(1002); +// let netuid = add_dynamic_network(&subnet_owner_hk, &subnet_owner_ck); +// let emission = TaoCurrency::from(1); + +// // 100% tao flow method +// let block_num = FlowHalfLife::::get(); +// SubnetEmaTaoFlow::::insert(netuid, (block_num, I64F64::from_num(1_000_000_000))); +// System::set_block_number(block_num); + +// let tao_in_before = SubnetTAO::::get(netuid); +// let total_stake_before = TotalStake::::get(); +// SubtensorModule::run_coinbase(U96F32::from_num(emission)); +// assert_eq!(SubnetTAO::::get(netuid), tao_in_before + emission); +// assert_eq!(TotalIssuance::::get(), emission); +// assert_eq!(TotalStake::::get(), total_stake_before + emission); +// }); +// } // Test emission distribution across multiple subnets. // This test verifies that: @@ -260,85 +260,85 @@ fn test_coinbase_tao_issuance_different_prices() { } // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::coinbase::test_coinbase_tao_issuance_different_flows --exact --show-output --nocapture -#[test] -fn test_coinbase_tao_issuance_different_flows() { - new_test_ext(1).execute_with(|| { - let subnet_owner_ck = U256::from(1001); - let subnet_owner_hk = U256::from(1002); - let netuid1 = add_dynamic_network(&subnet_owner_hk, &subnet_owner_ck); - let netuid2 = add_dynamic_network(&subnet_owner_hk, &subnet_owner_ck); - let emission = 100_000_000; - - // Setup prices 0.1 and 0.2 - let initial_tao: u64 = 100_000_u64; - let initial_alpha1: u64 = initial_tao * 10; - let initial_alpha2: u64 = initial_tao * 5; - mock::setup_reserves(netuid1, initial_tao.into(), initial_alpha1.into()); - mock::setup_reserves(netuid2, initial_tao.into(), initial_alpha2.into()); - - // Force the swap to initialize - SubtensorModule::swap_tao_for_alpha( - netuid1, - TaoCurrency::ZERO, - 1_000_000_000_000.into(), - false, - ) - .unwrap(); - SubtensorModule::swap_tao_for_alpha( - netuid2, - TaoCurrency::ZERO, - 1_000_000_000_000.into(), - false, - ) - .unwrap(); - - // Set subnet prices to reversed proportion to ensure they don't affect emissions. - SubnetMovingPrice::::insert(netuid1, I96F32::from_num(2)); - SubnetMovingPrice::::insert(netuid2, I96F32::from_num(1)); - - // Set subnet tao flow ema. - let block_num = FlowHalfLife::::get(); - SubnetEmaTaoFlow::::insert(netuid1, (block_num, I64F64::from_num(1))); - SubnetEmaTaoFlow::::insert(netuid2, (block_num, I64F64::from_num(2))); - System::set_block_number(block_num); - - // Set normalization exponent to 1 for simplicity - FlowNormExponent::::set(U64F64::from(1_u64)); - - // Assert initial TAO reserves. - assert_eq!(SubnetTAO::::get(netuid1), initial_tao.into()); - assert_eq!(SubnetTAO::::get(netuid2), initial_tao.into()); - let total_stake_before = TotalStake::::get(); - - // Run the coinbase with the emission amount. - SubtensorModule::run_coinbase(U96F32::from_num(emission)); - - // Assert tao emission is split evenly. - assert_abs_diff_eq!( - SubnetTAO::::get(netuid1), - TaoCurrency::from(initial_tao + emission / 3), - epsilon = 10.into(), - ); - assert_abs_diff_eq!( - SubnetTAO::::get(netuid2), - TaoCurrency::from(initial_tao + 2 * emission / 3), - epsilon = 10.into(), - ); +// #[test] +// fn test_coinbase_tao_issuance_different_flows() { +// new_test_ext(1).execute_with(|| { +// let subnet_owner_ck = U256::from(1001); +// let subnet_owner_hk = U256::from(1002); +// let netuid1 = add_dynamic_network(&subnet_owner_hk, &subnet_owner_ck); +// let netuid2 = add_dynamic_network(&subnet_owner_hk, &subnet_owner_ck); +// let emission = 100_000_000; + +// // Setup prices 0.1 and 0.2 +// let initial_tao: u64 = 100_000_u64; +// let initial_alpha1: u64 = initial_tao * 10; +// let initial_alpha2: u64 = initial_tao * 5; +// mock::setup_reserves(netuid1, initial_tao.into(), initial_alpha1.into()); +// mock::setup_reserves(netuid2, initial_tao.into(), initial_alpha2.into()); + +// // Force the swap to initialize +// SubtensorModule::swap_tao_for_alpha( +// netuid1, +// TaoCurrency::ZERO, +// 1_000_000_000_000.into(), +// false, +// ) +// .unwrap(); +// SubtensorModule::swap_tao_for_alpha( +// netuid2, +// TaoCurrency::ZERO, +// 1_000_000_000_000.into(), +// false, +// ) +// .unwrap(); + +// // Set subnet prices to reversed proportion to ensure they don't affect emissions. +// SubnetMovingPrice::::insert(netuid1, I96F32::from_num(2)); +// SubnetMovingPrice::::insert(netuid2, I96F32::from_num(1)); + +// // Set subnet tao flow ema. +// let block_num = FlowHalfLife::::get(); +// SubnetEmaTaoFlow::::insert(netuid1, (block_num, I64F64::from_num(1))); +// SubnetEmaTaoFlow::::insert(netuid2, (block_num, I64F64::from_num(2))); +// System::set_block_number(block_num); + +// // Set normalization exponent to 1 for simplicity +// FlowNormExponent::::set(U64F64::from(1_u64)); + +// // Assert initial TAO reserves. +// assert_eq!(SubnetTAO::::get(netuid1), initial_tao.into()); +// assert_eq!(SubnetTAO::::get(netuid2), initial_tao.into()); +// let total_stake_before = TotalStake::::get(); + +// // Run the coinbase with the emission amount. +// SubtensorModule::run_coinbase(U96F32::from_num(emission)); + +// // Assert tao emission is split evenly. +// assert_abs_diff_eq!( +// SubnetTAO::::get(netuid1), +// TaoCurrency::from(initial_tao + emission / 3), +// epsilon = 10.into(), +// ); +// assert_abs_diff_eq!( +// SubnetTAO::::get(netuid2), +// TaoCurrency::from(initial_tao + 2 * emission / 3), +// epsilon = 10.into(), +// ); - // Prices are low => we limit tao issued (buy alpha with it) - let tao_issued = TaoCurrency::from(((0.1 + 0.2) * emission as f64) as u64); - assert_abs_diff_eq!( - TotalIssuance::::get(), - tao_issued, - epsilon = 10.into() - ); - assert_abs_diff_eq!( - TotalStake::::get(), - total_stake_before + emission.into(), - epsilon = 10.into() - ); - }); -} +// // Prices are low => we limit tao issued (buy alpha with it) +// let tao_issued = TaoCurrency::from(((0.1 + 0.2) * emission as f64) as u64); +// assert_abs_diff_eq!( +// TotalIssuance::::get(), +// tao_issued, +// epsilon = 10.into() +// ); +// assert_abs_diff_eq!( +// TotalStake::::get(), +// total_stake_before + emission.into(), +// epsilon = 10.into() +// ); +// }); +// } // Test moving price updates with different alpha values. // This test verifies that: diff --git a/pallets/subtensor/src/tests/subnet_emissions.rs b/pallets/subtensor/src/tests/subnet_emissions.rs index 9f29b3fee2..311a930647 100644 --- a/pallets/subtensor/src/tests/subnet_emissions.rs +++ b/pallets/subtensor/src/tests/subnet_emissions.rs @@ -151,137 +151,137 @@ fn inplace_pow_normalize_fractional_exponent() { }) } -/// Normal (moderate, non-zero) EMA flows across 3 subnets. -/// Expect: shares sum to ~1 and are monotonic with flows. -#[test] -fn get_shares_normal_flows_three_subnets() { - new_test_ext(1).execute_with(|| { - let owner_hotkey = U256::from(10); - let owner_coldkey = U256::from(20); - - let n1 = add_dynamic_network(&owner_hotkey, &owner_coldkey); - let n2 = add_dynamic_network(&owner_hotkey, &owner_coldkey); - let n3 = add_dynamic_network(&owner_hotkey, &owner_coldkey); - - let block_num = FlowHalfLife::::get(); - System::set_block_number(block_num); - - // Set (block_number, flow) with reasonable positive flows - SubnetEmaTaoFlow::::insert(n1, (block_num, i64f64(1_000.0))); - SubnetEmaTaoFlow::::insert(n2, (block_num, i64f64(3_000.0))); - SubnetEmaTaoFlow::::insert(n3, (block_num, i64f64(6_000.0))); - - let subnets = vec![n1, n2, n3]; - let shares = SubtensorModule::get_shares(&subnets); - - // Sum ≈ 1 - let sum: f64 = shares.values().map(|v| v.to_num::()).sum(); - assert_abs_diff_eq!(sum, 1.0_f64, epsilon = 1e-9); - - // Each share in [0,1] and finite - for (k, v) in &shares { - let f = v.to_num::(); - assert!(f.is_finite(), "share for {k:?} not finite"); - assert!( - (0.0..=1.0).contains(&f), - "share for {k:?} out of [0,1]: {f}" - ); - } - - // Monotonicity with the flows: share(n3) > share(n2) > share(n1) - let s1 = shares.get(&n1).unwrap().to_num::(); - let s2 = shares.get(&n2).unwrap().to_num::(); - let s3 = shares.get(&n3).unwrap().to_num::(); - assert!( - s3 > s2 && s2 > s1, - "expected s3 > s2 > s1; got {s1}, {s2}, {s3}" - ); - }); -} - -/// Very low (but non-zero) EMA flows across 2 subnets. -/// Expect: shares sum to ~1 and higher-flow subnet gets higher share. -#[test] -fn get_shares_low_flows_sum_one_and_ordering() { - new_test_ext(1).execute_with(|| { - let owner_hotkey = U256::from(11); - let owner_coldkey = U256::from(21); - - let n1 = add_dynamic_network(&owner_hotkey, &owner_coldkey); - let n2 = add_dynamic_network(&owner_hotkey, &owner_coldkey); - - let block_num = FlowHalfLife::::get(); - System::set_block_number(block_num); - - // Tiny flows to exercise precision/scaling path - SubnetEmaTaoFlow::::insert(n1, (block_num, i64f64(1e-9))); - SubnetEmaTaoFlow::::insert(n2, (block_num, i64f64(2e-9))); - - let subnets = vec![n1, n2]; - let shares = SubtensorModule::get_shares(&subnets); - - let sum: f64 = shares.values().map(|v| v.to_num::()).sum(); - assert_abs_diff_eq!(sum, 1.0_f64, epsilon = 1e-8); - - for (k, v) in &shares { - let f = v.to_num::(); - assert!(f.is_finite(), "share for {k:?} not finite"); - assert!( - (0.0..=1.0).contains(&f), - "share for {k:?} out of [0,1]: {f}" - ); - } - - let s1 = shares.get(&n1).unwrap().to_num::(); - let s2 = shares.get(&n2).unwrap().to_num::(); - assert!( - s2 > s1, - "expected s2 > s1 with higher flow; got s1={s1}, s2={s2}" - ); - }); -} - -/// High EMA flows across 2 subnets. -/// Expect: no overflow, shares sum to ~1, and ordering follows flows. -#[test] -fn get_shares_high_flows_sum_one_and_ordering() { - new_test_ext(1).execute_with(|| { - let owner_hotkey = U256::from(12); - let owner_coldkey = U256::from(22); - - let n1 = add_dynamic_network(&owner_hotkey, &owner_coldkey); - let n2 = add_dynamic_network(&owner_hotkey, &owner_coldkey); - - let block_num = FlowHalfLife::::get(); - System::set_block_number(block_num); - - // Large but safe flows for I64F64 - SubnetEmaTaoFlow::::insert(n1, (block_num, i64f64(9.0e11))); - SubnetEmaTaoFlow::::insert(n2, (block_num, i64f64(1.8e12))); - - let subnets = vec![n1, n2]; - let shares = SubtensorModule::get_shares(&subnets); - - let sum: f64 = shares.values().map(|v| v.to_num::()).sum(); - assert_abs_diff_eq!(sum, 1.0_f64, epsilon = 1e-9); - - for (k, v) in &shares { - let f = v.to_num::(); - assert!(f.is_finite(), "share for {k:?} not finite"); - assert!( - (0.0..=1.0).contains(&f), - "share for {k:?} out of [0,1]: {f}" - ); - } - - let s1 = shares.get(&n1).unwrap().to_num::(); - let s2 = shares.get(&n2).unwrap().to_num::(); - assert!( - s2 > s1, - "expected s2 > s1 with higher flow; got s1={s1}, s2={s2}" - ); - }); -} +// /// Normal (moderate, non-zero) EMA flows across 3 subnets. +// /// Expect: shares sum to ~1 and are monotonic with flows. +// #[test] +// fn get_shares_normal_flows_three_subnets() { +// new_test_ext(1).execute_with(|| { +// let owner_hotkey = U256::from(10); +// let owner_coldkey = U256::from(20); + +// let n1 = add_dynamic_network(&owner_hotkey, &owner_coldkey); +// let n2 = add_dynamic_network(&owner_hotkey, &owner_coldkey); +// let n3 = add_dynamic_network(&owner_hotkey, &owner_coldkey); + +// let block_num = FlowHalfLife::::get(); +// System::set_block_number(block_num); + +// // Set (block_number, flow) with reasonable positive flows +// SubnetEmaTaoFlow::::insert(n1, (block_num, i64f64(1_000.0))); +// SubnetEmaTaoFlow::::insert(n2, (block_num, i64f64(3_000.0))); +// SubnetEmaTaoFlow::::insert(n3, (block_num, i64f64(6_000.0))); + +// let subnets = vec![n1, n2, n3]; +// let shares = SubtensorModule::get_shares(&subnets); + +// // Sum ≈ 1 +// let sum: f64 = shares.values().map(|v| v.to_num::()).sum(); +// assert_abs_diff_eq!(sum, 1.0_f64, epsilon = 1e-9); + +// // Each share in [0,1] and finite +// for (k, v) in &shares { +// let f = v.to_num::(); +// assert!(f.is_finite(), "share for {k:?} not finite"); +// assert!( +// (0.0..=1.0).contains(&f), +// "share for {k:?} out of [0,1]: {f}" +// ); +// } + +// // Monotonicity with the flows: share(n3) > share(n2) > share(n1) +// let s1 = shares.get(&n1).unwrap().to_num::(); +// let s2 = shares.get(&n2).unwrap().to_num::(); +// let s3 = shares.get(&n3).unwrap().to_num::(); +// assert!( +// s3 > s2 && s2 > s1, +// "expected s3 > s2 > s1; got {s1}, {s2}, {s3}" +// ); +// }); +// } + +// /// Very low (but non-zero) EMA flows across 2 subnets. +// /// Expect: shares sum to ~1 and higher-flow subnet gets higher share. +// #[test] +// fn get_shares_low_flows_sum_one_and_ordering() { +// new_test_ext(1).execute_with(|| { +// let owner_hotkey = U256::from(11); +// let owner_coldkey = U256::from(21); + +// let n1 = add_dynamic_network(&owner_hotkey, &owner_coldkey); +// let n2 = add_dynamic_network(&owner_hotkey, &owner_coldkey); + +// let block_num = FlowHalfLife::::get(); +// System::set_block_number(block_num); + +// // Tiny flows to exercise precision/scaling path +// SubnetEmaTaoFlow::::insert(n1, (block_num, i64f64(1e-9))); +// SubnetEmaTaoFlow::::insert(n2, (block_num, i64f64(2e-9))); + +// let subnets = vec![n1, n2]; +// let shares = SubtensorModule::get_shares(&subnets); + +// let sum: f64 = shares.values().map(|v| v.to_num::()).sum(); +// assert_abs_diff_eq!(sum, 1.0_f64, epsilon = 1e-8); + +// for (k, v) in &shares { +// let f = v.to_num::(); +// assert!(f.is_finite(), "share for {k:?} not finite"); +// assert!( +// (0.0..=1.0).contains(&f), +// "share for {k:?} out of [0,1]: {f}" +// ); +// } + +// let s1 = shares.get(&n1).unwrap().to_num::(); +// let s2 = shares.get(&n2).unwrap().to_num::(); +// assert!( +// s2 > s1, +// "expected s2 > s1 with higher flow; got s1={s1}, s2={s2}" +// ); +// }); +// } + +// /// High EMA flows across 2 subnets. +// /// Expect: no overflow, shares sum to ~1, and ordering follows flows. +// #[test] +// fn get_shares_high_flows_sum_one_and_ordering() { +// new_test_ext(1).execute_with(|| { +// let owner_hotkey = U256::from(12); +// let owner_coldkey = U256::from(22); + +// let n1 = add_dynamic_network(&owner_hotkey, &owner_coldkey); +// let n2 = add_dynamic_network(&owner_hotkey, &owner_coldkey); + +// let block_num = FlowHalfLife::::get(); +// System::set_block_number(block_num); + +// // Large but safe flows for I64F64 +// SubnetEmaTaoFlow::::insert(n1, (block_num, i64f64(9.0e11))); +// SubnetEmaTaoFlow::::insert(n2, (block_num, i64f64(1.8e12))); + +// let subnets = vec![n1, n2]; +// let shares = SubtensorModule::get_shares(&subnets); + +// let sum: f64 = shares.values().map(|v| v.to_num::()).sum(); +// assert_abs_diff_eq!(sum, 1.0_f64, epsilon = 1e-9); + +// for (k, v) in &shares { +// let f = v.to_num::(); +// assert!(f.is_finite(), "share for {k:?} not finite"); +// assert!( +// (0.0..=1.0).contains(&f), +// "share for {k:?} out of [0,1]: {f}" +// ); +// } + +// let s1 = shares.get(&n1).unwrap().to_num::(); +// let s2 = shares.get(&n2).unwrap().to_num::(); +// assert!( +// s2 > s1, +// "expected s2 > s1 with higher flow; got s1={s1}, s2={s2}" +// ); +// }); +// } /// Helper to (re)seed EMA price & flow at the *current* block. fn seed_price_and_flow(n1: NetUid, n2: NetUid, price1: f64, price2: f64, flow1: f64, flow2: f64) { @@ -292,199 +292,199 @@ fn seed_price_and_flow(n1: NetUid, n2: NetUid, price1: f64, price2: f64, flow1: SubnetEmaTaoFlow::::insert(n2, (now, i64f64(flow2))); } -/// If one subnet has a negative EMA flow and the other positive, -/// the negative one should contribute no weight (treated as zero), -/// so the positive-flow subnet gets the full share. -#[test] -fn get_shares_negative_vs_positive_flow() { - new_test_ext(1).execute_with(|| { - // 2 subnets - let owner_hotkey = U256::from(60); - let owner_coldkey = U256::from(61); - let n1 = add_dynamic_network(&owner_hotkey, &owner_coldkey); - let n2 = add_dynamic_network(&owner_hotkey, &owner_coldkey); - - // Configure blending window and current block - let half_life: u64 = FlowHalfLife::::get(); - FlowNormExponent::::set(u64f64(1.0)); - frame_system::Pallet::::set_block_number(half_life); - TaoFlowCutoff::::set(I64F64::from_num(0)); - - // Equal EMA prices so price side doesn't bias - SubnetMovingPrice::::insert(n1, i96f32(1.0)); - SubnetMovingPrice::::insert(n2, i96f32(1.0)); - - // Set flows: n1 negative, n2 positive - let now = frame_system::Pallet::::block_number(); - SubnetEmaTaoFlow::::insert(n1, (now, i64f64(-100.0))); - SubnetEmaTaoFlow::::insert(n2, (now, i64f64(500.0))); - - let shares = SubtensorModule::get_shares(&[n1, n2]); - let s1 = shares.get(&n1).unwrap().to_num::(); - let s2 = shares.get(&n2).unwrap().to_num::(); - - // Sum ~ 1 - assert_abs_diff_eq!(s1 + s2, 1.0_f64, epsilon = 1e-9); - // Negative flow subnet should not get weight from flow; with equal prices mid-window, - // positive-flow subnet should dominate and get all the allocation. - assert!( - s2 > 0.999_999 && s1 < 1e-6, - "expected s2≈1, s1≈0; got s1={s1}, s2={s2}" - ); - }); -} - -/// If both subnets have negative EMA flows, flows should contribute zero weight -#[test] -fn get_shares_both_negative_flows_zero_emission() { - new_test_ext(1).execute_with(|| { - // 2 subnets - let owner_hotkey = U256::from(60); - let owner_coldkey = U256::from(61); - let n1 = add_dynamic_network(&owner_hotkey, &owner_coldkey); - let n2 = add_dynamic_network(&owner_hotkey, &owner_coldkey); - - // Configure blending window and current block - let half_life: u64 = FlowHalfLife::::get(); - FlowNormExponent::::set(u64f64(1.0)); - frame_system::Pallet::::set_block_number(half_life); - TaoFlowCutoff::::set(I64F64::from_num(0)); - - // Equal EMA prices so price side doesn't bias - SubnetMovingPrice::::insert(n1, i96f32(1.0)); - SubnetMovingPrice::::insert(n2, i96f32(1.0)); - - // Set flows - let now = frame_system::Pallet::::block_number(); - SubnetEmaTaoFlow::::insert(n1, (now, i64f64(-100.0))); - SubnetEmaTaoFlow::::insert(n2, (now, i64f64(-200.0))); - - let shares = SubtensorModule::get_shares(&[n1, n2]); - let s1 = shares.get(&n1).unwrap().to_num::(); - let s2 = shares.get(&n2).unwrap().to_num::(); - - assert!( - s1 < 1e-20 && s2 < 1e-20, - "expected s2≈0, s1≈0; got s1={s1}, s2={s2}" - ); - }); -} - -/// If both subnets have positive EMA flows lower than or equal to cutoff, flows should contribute zero weight -#[test] -fn get_shares_both_below_cutoff_zero_emission() { - new_test_ext(1).execute_with(|| { - // 2 subnets - let owner_hotkey = U256::from(60); - let owner_coldkey = U256::from(61); - let n1 = add_dynamic_network(&owner_hotkey, &owner_coldkey); - let n2 = add_dynamic_network(&owner_hotkey, &owner_coldkey); - - // Configure blending window and current block - let half_life: u64 = FlowHalfLife::::get(); - FlowNormExponent::::set(u64f64(1.0)); - frame_system::Pallet::::set_block_number(half_life); - TaoFlowCutoff::::set(I64F64::from_num(2_000)); - - // Equal EMA prices so price side doesn't bias - SubnetMovingPrice::::insert(n1, i96f32(1.0)); - SubnetMovingPrice::::insert(n2, i96f32(1.0)); - - // Set flows - let now = frame_system::Pallet::::block_number(); - SubnetEmaTaoFlow::::insert(n1, (now, i64f64(1000.0))); - SubnetEmaTaoFlow::::insert(n2, (now, i64f64(2000.0))); - - let shares = SubtensorModule::get_shares(&[n1, n2]); - let s1 = shares.get(&n1).unwrap().to_num::(); - let s2 = shares.get(&n2).unwrap().to_num::(); - - assert!( - s1 < 1e-20 && s2 < 1e-20, - "expected s2≈0, s1≈0; got s1={s1}, s2={s2}" - ); - }); -} - -/// If one subnet has positive EMA flow lower than cutoff, the other gets full emission -#[test] -fn get_shares_one_below_cutoff_other_full_emission() { - new_test_ext(1).execute_with(|| { - [(1000.0, 2000.00001), (1000.0, 2000.001), (1000.0, 5000.0)] - .into_iter() - .for_each(|(flow1, flow2)| { - // 2 subnets - let owner_hotkey = U256::from(60); - let owner_coldkey = U256::from(61); - let n1 = add_dynamic_network(&owner_hotkey, &owner_coldkey); - let n2 = add_dynamic_network(&owner_hotkey, &owner_coldkey); - - // Configure blending window and current block - let half_life: u64 = FlowHalfLife::::get(); - FlowNormExponent::::set(u64f64(1.0)); - frame_system::Pallet::::set_block_number(half_life); - TaoFlowCutoff::::set(I64F64::from_num(2_000)); - - // Equal EMA prices (price side doesn't bias) - SubnetMovingPrice::::insert(n1, i96f32(1.0)); - SubnetMovingPrice::::insert(n2, i96f32(1.0)); - - // Set flows - let now = frame_system::Pallet::::block_number(); - SubnetEmaTaoFlow::::insert(n1, (now, i64f64(flow1))); - SubnetEmaTaoFlow::::insert(n2, (now, i64f64(flow2))); - - let shares = SubtensorModule::get_shares(&[n1, n2]); - let s1 = shares.get(&n1).unwrap().to_num::(); - let s2 = shares.get(&n2).unwrap().to_num::(); - - // Sum ~ 1 - assert_abs_diff_eq!(s1 + s2, 1.0_f64, epsilon = 1e-9); - assert!( - s2 > 0.999_999 && s1 < 1e-6, - "expected s2≈1, s1≈0; got s1={s1}, s2={s2}" - ); - }); - }); -} - -/// If subnets have negative EMA flows, but they are above the cut-off, emissions are proportional -/// for all except the bottom one, which gets nothing -#[test] -fn get_shares_both_negative_above_cutoff() { - new_test_ext(1).execute_with(|| { - // 2 subnets - let owner_hotkey = U256::from(60); - let owner_coldkey = U256::from(61); - let n1 = add_dynamic_network(&owner_hotkey, &owner_coldkey); - let n2 = add_dynamic_network(&owner_hotkey, &owner_coldkey); - let n3 = add_dynamic_network(&owner_hotkey, &owner_coldkey); - - // Configure blending window and current block - let half_life: u64 = FlowHalfLife::::get(); - FlowNormExponent::::set(u64f64(1.0)); - frame_system::Pallet::::set_block_number(half_life); - TaoFlowCutoff::::set(I64F64::from_num(-1000.0)); - - // Equal EMA prices so price side doesn't bias - SubnetMovingPrice::::insert(n1, i96f32(1.0)); - SubnetMovingPrice::::insert(n2, i96f32(1.0)); - SubnetMovingPrice::::insert(n3, i96f32(1.0)); - - // Set flows - let now = frame_system::Pallet::::block_number(); - SubnetEmaTaoFlow::::insert(n1, (now, i64f64(-100.0))); - SubnetEmaTaoFlow::::insert(n2, (now, i64f64(-300.0))); - SubnetEmaTaoFlow::::insert(n3, (now, i64f64(-400.0))); - - let shares = SubtensorModule::get_shares(&[n1, n2, n3]); - let s1 = shares.get(&n1).unwrap().to_num::(); - let s2 = shares.get(&n2).unwrap().to_num::(); - let s3 = shares.get(&n3).unwrap().to_num::(); - - assert_abs_diff_eq!(s1, 0.75, epsilon = s1 / 100.0); - assert_abs_diff_eq!(s2, 0.25, epsilon = s2 / 100.0); - assert_abs_diff_eq!(s3, 0.0, epsilon = 1e-9); - assert_abs_diff_eq!(s1 + s2 + s3, 1.0, epsilon = 1e-9); - }); -} +// /// If one subnet has a negative EMA flow and the other positive, +// /// the negative one should contribute no weight (treated as zero), +// /// so the positive-flow subnet gets the full share. +// #[test] +// fn get_shares_negative_vs_positive_flow() { +// new_test_ext(1).execute_with(|| { +// // 2 subnets +// let owner_hotkey = U256::from(60); +// let owner_coldkey = U256::from(61); +// let n1 = add_dynamic_network(&owner_hotkey, &owner_coldkey); +// let n2 = add_dynamic_network(&owner_hotkey, &owner_coldkey); + +// // Configure blending window and current block +// let half_life: u64 = FlowHalfLife::::get(); +// FlowNormExponent::::set(u64f64(1.0)); +// frame_system::Pallet::::set_block_number(half_life); +// TaoFlowCutoff::::set(I64F64::from_num(0)); + +// // Equal EMA prices so price side doesn't bias +// SubnetMovingPrice::::insert(n1, i96f32(1.0)); +// SubnetMovingPrice::::insert(n2, i96f32(1.0)); + +// // Set flows: n1 negative, n2 positive +// let now = frame_system::Pallet::::block_number(); +// SubnetEmaTaoFlow::::insert(n1, (now, i64f64(-100.0))); +// SubnetEmaTaoFlow::::insert(n2, (now, i64f64(500.0))); + +// let shares = SubtensorModule::get_shares(&[n1, n2]); +// let s1 = shares.get(&n1).unwrap().to_num::(); +// let s2 = shares.get(&n2).unwrap().to_num::(); + +// // Sum ~ 1 +// assert_abs_diff_eq!(s1 + s2, 1.0_f64, epsilon = 1e-9); +// // Negative flow subnet should not get weight from flow; with equal prices mid-window, +// // positive-flow subnet should dominate and get all the allocation. +// assert!( +// s2 > 0.999_999 && s1 < 1e-6, +// "expected s2≈1, s1≈0; got s1={s1}, s2={s2}" +// ); +// }); +// } + +// /// If both subnets have negative EMA flows, flows should contribute zero weight +// #[test] +// fn get_shares_both_negative_flows_zero_emission() { +// new_test_ext(1).execute_with(|| { +// // 2 subnets +// let owner_hotkey = U256::from(60); +// let owner_coldkey = U256::from(61); +// let n1 = add_dynamic_network(&owner_hotkey, &owner_coldkey); +// let n2 = add_dynamic_network(&owner_hotkey, &owner_coldkey); + +// // Configure blending window and current block +// let half_life: u64 = FlowHalfLife::::get(); +// FlowNormExponent::::set(u64f64(1.0)); +// frame_system::Pallet::::set_block_number(half_life); +// TaoFlowCutoff::::set(I64F64::from_num(0)); + +// // Equal EMA prices so price side doesn't bias +// SubnetMovingPrice::::insert(n1, i96f32(1.0)); +// SubnetMovingPrice::::insert(n2, i96f32(1.0)); + +// // Set flows +// let now = frame_system::Pallet::::block_number(); +// SubnetEmaTaoFlow::::insert(n1, (now, i64f64(-100.0))); +// SubnetEmaTaoFlow::::insert(n2, (now, i64f64(-200.0))); + +// let shares = SubtensorModule::get_shares(&[n1, n2]); +// let s1 = shares.get(&n1).unwrap().to_num::(); +// let s2 = shares.get(&n2).unwrap().to_num::(); + +// assert!( +// s1 < 1e-20 && s2 < 1e-20, +// "expected s2≈0, s1≈0; got s1={s1}, s2={s2}" +// ); +// }); +// } + +// /// If both subnets have positive EMA flows lower than or equal to cutoff, flows should contribute zero weight +// #[test] +// fn get_shares_both_below_cutoff_zero_emission() { +// new_test_ext(1).execute_with(|| { +// // 2 subnets +// let owner_hotkey = U256::from(60); +// let owner_coldkey = U256::from(61); +// let n1 = add_dynamic_network(&owner_hotkey, &owner_coldkey); +// let n2 = add_dynamic_network(&owner_hotkey, &owner_coldkey); + +// // Configure blending window and current block +// let half_life: u64 = FlowHalfLife::::get(); +// FlowNormExponent::::set(u64f64(1.0)); +// frame_system::Pallet::::set_block_number(half_life); +// TaoFlowCutoff::::set(I64F64::from_num(2_000)); + +// // Equal EMA prices so price side doesn't bias +// SubnetMovingPrice::::insert(n1, i96f32(1.0)); +// SubnetMovingPrice::::insert(n2, i96f32(1.0)); + +// // Set flows +// let now = frame_system::Pallet::::block_number(); +// SubnetEmaTaoFlow::::insert(n1, (now, i64f64(1000.0))); +// SubnetEmaTaoFlow::::insert(n2, (now, i64f64(2000.0))); + +// let shares = SubtensorModule::get_shares(&[n1, n2]); +// let s1 = shares.get(&n1).unwrap().to_num::(); +// let s2 = shares.get(&n2).unwrap().to_num::(); + +// assert!( +// s1 < 1e-20 && s2 < 1e-20, +// "expected s2≈0, s1≈0; got s1={s1}, s2={s2}" +// ); +// }); +// } + +// /// If one subnet has positive EMA flow lower than cutoff, the other gets full emission +// #[test] +// fn get_shares_one_below_cutoff_other_full_emission() { +// new_test_ext(1).execute_with(|| { +// [(1000.0, 2000.00001), (1000.0, 2000.001), (1000.0, 5000.0)] +// .into_iter() +// .for_each(|(flow1, flow2)| { +// // 2 subnets +// let owner_hotkey = U256::from(60); +// let owner_coldkey = U256::from(61); +// let n1 = add_dynamic_network(&owner_hotkey, &owner_coldkey); +// let n2 = add_dynamic_network(&owner_hotkey, &owner_coldkey); + +// // Configure blending window and current block +// let half_life: u64 = FlowHalfLife::::get(); +// FlowNormExponent::::set(u64f64(1.0)); +// frame_system::Pallet::::set_block_number(half_life); +// TaoFlowCutoff::::set(I64F64::from_num(2_000)); + +// // Equal EMA prices (price side doesn't bias) +// SubnetMovingPrice::::insert(n1, i96f32(1.0)); +// SubnetMovingPrice::::insert(n2, i96f32(1.0)); + +// // Set flows +// let now = frame_system::Pallet::::block_number(); +// SubnetEmaTaoFlow::::insert(n1, (now, i64f64(flow1))); +// SubnetEmaTaoFlow::::insert(n2, (now, i64f64(flow2))); + +// let shares = SubtensorModule::get_shares(&[n1, n2]); +// let s1 = shares.get(&n1).unwrap().to_num::(); +// let s2 = shares.get(&n2).unwrap().to_num::(); + +// // Sum ~ 1 +// assert_abs_diff_eq!(s1 + s2, 1.0_f64, epsilon = 1e-9); +// assert!( +// s2 > 0.999_999 && s1 < 1e-6, +// "expected s2≈1, s1≈0; got s1={s1}, s2={s2}" +// ); +// }); +// }); +// } + +// /// If subnets have negative EMA flows, but they are above the cut-off, emissions are proportional +// /// for all except the bottom one, which gets nothing +// #[test] +// fn get_shares_both_negative_above_cutoff() { +// new_test_ext(1).execute_with(|| { +// // 2 subnets +// let owner_hotkey = U256::from(60); +// let owner_coldkey = U256::from(61); +// let n1 = add_dynamic_network(&owner_hotkey, &owner_coldkey); +// let n2 = add_dynamic_network(&owner_hotkey, &owner_coldkey); +// let n3 = add_dynamic_network(&owner_hotkey, &owner_coldkey); + +// // Configure blending window and current block +// let half_life: u64 = FlowHalfLife::::get(); +// FlowNormExponent::::set(u64f64(1.0)); +// frame_system::Pallet::::set_block_number(half_life); +// TaoFlowCutoff::::set(I64F64::from_num(-1000.0)); + +// // Equal EMA prices so price side doesn't bias +// SubnetMovingPrice::::insert(n1, i96f32(1.0)); +// SubnetMovingPrice::::insert(n2, i96f32(1.0)); +// SubnetMovingPrice::::insert(n3, i96f32(1.0)); + +// // Set flows +// let now = frame_system::Pallet::::block_number(); +// SubnetEmaTaoFlow::::insert(n1, (now, i64f64(-100.0))); +// SubnetEmaTaoFlow::::insert(n2, (now, i64f64(-300.0))); +// SubnetEmaTaoFlow::::insert(n3, (now, i64f64(-400.0))); + +// let shares = SubtensorModule::get_shares(&[n1, n2, n3]); +// let s1 = shares.get(&n1).unwrap().to_num::(); +// let s2 = shares.get(&n2).unwrap().to_num::(); +// let s3 = shares.get(&n3).unwrap().to_num::(); + +// assert_abs_diff_eq!(s1, 0.75, epsilon = s1 / 100.0); +// assert_abs_diff_eq!(s2, 0.25, epsilon = s2 / 100.0); +// assert_abs_diff_eq!(s3, 0.0, epsilon = 1e-9); +// assert_abs_diff_eq!(s1 + s2 + s3, 1.0, epsilon = 1e-9); +// }); +// } diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index d8277164e2..548c192ece 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: 334, + spec_version: 335, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From 3ec6631689de3acfe39e61f50cafc7e32ddc30ed Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Tue, 4 Nov 2025 20:31:27 -0500 Subject: [PATCH 3/8] Migration to remove SubnetEmaTaoFlow and cause it's re-initialization --- .../src/coinbase/subnet_emissions.rs | 3 ++- pallets/subtensor/src/macros/hooks.rs | 2 +- .../src/migrations/migrate_init_tao_flow.rs | 23 +++---------------- pallets/subtensor/src/migrations/mod.rs | 2 +- runtime/src/lib.rs | 2 +- 5 files changed, 8 insertions(+), 24 deletions(-) diff --git a/pallets/subtensor/src/coinbase/subnet_emissions.rs b/pallets/subtensor/src/coinbase/subnet_emissions.rs index 80ecf85a42..2d9c3b1473 100644 --- a/pallets/subtensor/src/coinbase/subnet_emissions.rs +++ b/pallets/subtensor/src/coinbase/subnet_emissions.rs @@ -75,10 +75,11 @@ impl Pallet { } } else { // Initialize EMA flow, set S(current_block) = min(price, ema_price) * init_factor + let init_factor = I64F64::saturating_from_num(1_000_000_000); let moving_price = I64F64::saturating_from_num(Self::get_moving_alpha_price(netuid)); let current_price = I64F64::saturating_from_num(T::SwapInterface::current_alpha_price(netuid)); - let ema_flow = moving_price.min(current_price); + let ema_flow = init_factor.saturating_mul(moving_price.min(current_price)); SubnetEmaTaoFlow::::insert(netuid, (current_block, ema_flow)); ema_flow } diff --git a/pallets/subtensor/src/macros/hooks.rs b/pallets/subtensor/src/macros/hooks.rs index 2369b25275..7095ce8ecb 100644 --- a/pallets/subtensor/src/macros/hooks.rs +++ b/pallets/subtensor/src/macros/hooks.rs @@ -161,7 +161,7 @@ mod hooks { // Remove obsolete map entries .saturating_add(migrations::migrate_remove_tao_dividends::migrate_remove_tao_dividends::()) // Re-init tao flows - .saturating_add(migrations::migrate_init_tao_flows::migrate_init_tao_flows::()); + .saturating_add(migrations::migrate_init_tao_flow::migrate_init_tao_flow::()); weight } diff --git a/pallets/subtensor/src/migrations/migrate_init_tao_flow.rs b/pallets/subtensor/src/migrations/migrate_init_tao_flow.rs index c0cdb87336..477410600f 100644 --- a/pallets/subtensor/src/migrations/migrate_init_tao_flow.rs +++ b/pallets/subtensor/src/migrations/migrate_init_tao_flow.rs @@ -1,12 +1,10 @@ use alloc::string::String; -use frame_support::IterableStorageMap; use frame_support::{traits::Get, weights::Weight}; -use subtensor_runtime_common::NetUid; use super::*; -pub fn migrate_init_tao_flows() -> Weight { +pub fn migrate_init_tao_flow() -> Weight { let migration_name = b"migrate_init_tao_flow".to_vec(); // Initialize the weight with one read operation. @@ -25,23 +23,8 @@ pub fn migrate_init_tao_flows() -> Weight { String::from_utf8_lossy(&migration_name) ); - let netuids: Vec = as IterableStorageMap>::iter() - .map(|(netuid, _)| netuid) - .collect(); - weight = weight.saturating_add(T::DbWeight::get().reads(netuids.len() as u64)); - - for netuid in netuids.iter() { - if netuid.is_root() { - continue; - } - // Set SubnetEmaTaoFlow - SubnetEmaTaoFlow::::insert(*netuid, I64F64::saturating_from_num(0)); - - - - - weight = weight.saturating_add(T::DbWeight::get().writes(1)); - } + let _ = SubnetEmaTaoFlow::::clear(u32::MAX, None); + weight = weight.saturating_add(T::DbWeight::get().writes(1)); // Mark the migration as completed HasMigrationRun::::insert(&migration_name, true); diff --git a/pallets/subtensor/src/migrations/mod.rs b/pallets/subtensor/src/migrations/mod.rs index dc14de151f..7fe37617fd 100644 --- a/pallets/subtensor/src/migrations/mod.rs +++ b/pallets/subtensor/src/migrations/mod.rs @@ -20,7 +20,7 @@ pub mod migrate_fix_is_network_member; pub mod migrate_fix_root_subnet_tao; pub mod migrate_fix_root_tao_and_alpha_in; pub mod migrate_identities_v2; -pub mod migrate_init_tao_flows; +pub mod migrate_init_tao_flow; pub mod migrate_init_total_issuance; pub mod migrate_kappa_map_to_default; pub mod migrate_network_immunity_period; diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index d8277164e2..548c192ece 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: 334, + spec_version: 335, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From 04337b0d51b8e3cca36c097ca978400815c0c249 Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Tue, 4 Nov 2025 20:38:55 -0500 Subject: [PATCH 4/8] Spec bump --- 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 548c192ece..7bd2f459b4 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: 335, + spec_version: 336, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From 54b5090fece276f4ec99bdfbdbf67b99f4b3bd02 Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Tue, 4 Nov 2025 21:12:49 -0500 Subject: [PATCH 5/8] Spec bump --- 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 548c192ece..ae7e3d80fc 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: 335, + spec_version: 337, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From a95bc8e08546c17acb711362575fb348d81a2ca1 Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Tue, 4 Nov 2025 21:22:01 -0500 Subject: [PATCH 6/8] Reorder functions --- pallets/subtensor/src/coinbase/subnet_emissions.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pallets/subtensor/src/coinbase/subnet_emissions.rs b/pallets/subtensor/src/coinbase/subnet_emissions.rs index 4f3911e3ae..d1cd4ffdd4 100644 --- a/pallets/subtensor/src/coinbase/subnet_emissions.rs +++ b/pallets/subtensor/src/coinbase/subnet_emissions.rs @@ -213,6 +213,12 @@ impl Pallet { offset_flows } + // Combines ema price method and tao flow method linearly over FlowHalfLife blocks + pub(crate) fn get_shares(subnets_to_emit_to: &[NetUid]) -> BTreeMap { + // Self::get_shares_flow(subnets_to_emit_to) + Self::get_shares_price_ema(subnets_to_emit_to) + } + // DEPRECATED: Implementation of shares that uses EMA prices will be gradually deprecated fn get_shares_price_ema(subnets_to_emit_to: &[NetUid]) -> BTreeMap { // Get sum of alpha moving prices @@ -240,10 +246,4 @@ impl Pallet { }) .collect::>() } - - // Combines ema price method and tao flow method linearly over FlowHalfLife blocks - pub(crate) fn get_shares(subnets_to_emit_to: &[NetUid]) -> BTreeMap { - // Self::get_shares_flow(subnets_to_emit_to) - Self::get_shares_price_ema(subnets_to_emit_to) - } } From 120be4f85a95fe3964e01ba69e1ee6fe1acb1c8e Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Tue, 4 Nov 2025 22:42:27 -0500 Subject: [PATCH 7/8] Re-enable tao flow --- pallets/subtensor/src/coinbase/subnet_emissions.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pallets/subtensor/src/coinbase/subnet_emissions.rs b/pallets/subtensor/src/coinbase/subnet_emissions.rs index cb9fe95ce0..184f27a4ba 100644 --- a/pallets/subtensor/src/coinbase/subnet_emissions.rs +++ b/pallets/subtensor/src/coinbase/subnet_emissions.rs @@ -216,11 +216,12 @@ impl Pallet { // Combines ema price method and tao flow method linearly over FlowHalfLife blocks pub(crate) fn get_shares(subnets_to_emit_to: &[NetUid]) -> BTreeMap { - // Self::get_shares_flow(subnets_to_emit_to) - Self::get_shares_price_ema(subnets_to_emit_to) + Self::get_shares_flow(subnets_to_emit_to) + // Self::get_shares_price_ema(subnets_to_emit_to) } // DEPRECATED: Implementation of shares that uses EMA prices will be gradually deprecated + #[allow(dead_code)] fn get_shares_price_ema(subnets_to_emit_to: &[NetUid]) -> BTreeMap { // Get sum of alpha moving prices let total_moving_prices = subnets_to_emit_to From e48ef843214a525aa65796e65d6abb3d015d1a2d Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Tue, 4 Nov 2025 22:44:23 -0500 Subject: [PATCH 8/8] Spec bump --- 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 ae7e3d80fc..266a755708 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: 337, + spec_version: 338, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1,