From f62a6823f97107b71d05ba91c123de572f8a95ef Mon Sep 17 00:00:00 2001 From: konrad0960 Date: Mon, 10 Nov 2025 22:24:22 +0100 Subject: [PATCH 1/5] consensus modes --- pallets/subtensor/src/epoch/run_epoch.rs | 98 +++- pallets/subtensor/src/lib.rs | 24 + pallets/subtensor/src/tests/consensus_mode.rs | 421 ++++++++++++++++++ pallets/subtensor/src/tests/epoch.rs | 2 + pallets/subtensor/src/tests/mod.rs | 1 + pallets/subtensor/src/utils/misc.rs | 8 + 6 files changed, 550 insertions(+), 4 deletions(-) create mode 100644 pallets/subtensor/src/tests/consensus_mode.rs diff --git a/pallets/subtensor/src/epoch/run_epoch.rs b/pallets/subtensor/src/epoch/run_epoch.rs index 5e4dd1f43e..cbb50ac03c 100644 --- a/pallets/subtensor/src/epoch/run_epoch.rs +++ b/pallets/subtensor/src/epoch/run_epoch.rs @@ -1327,9 +1327,13 @@ impl Pallet { .iter() .any(|&c| c != I32F32::saturating_from_num(0)) { - // Liquid Alpha is enabled, compute the liquid alphas matrix. + // Liquid Alpha is enabled, compute the appropriate consensus for liquid alpha based on mode + let consensus_for_liquid_alpha = Self::compute_consensus_for_liquid_alpha(netuid, consensus); + log::trace!("consensus_for_liquid_alpha: {:?}", &consensus_for_liquid_alpha); + + // Compute the liquid alphas matrix. let alphas: Vec> = - Self::compute_liquid_alpha_values(netuid, weights, bonds, consensus); + Self::compute_liquid_alpha_values(netuid, weights, bonds, &consensus_for_liquid_alpha); log::trace!("alphas: {:?}", &alphas); // Compute the Exponential Moving Average (EMA) of bonds using the provided clamped alpha values. @@ -1369,9 +1373,13 @@ impl Pallet { .iter() .any(|&c| c != I32F32::saturating_from_num(0)) { - // Liquid Alpha is enabled, compute the liquid alphas matrix. + // Liquid Alpha is enabled, compute the appropriate consensus for liquid alpha based on mode + let consensus_for_liquid_alpha = Self::compute_consensus_for_liquid_alpha(netuid, consensus); + log::trace!("consensus_for_liquid_alpha: {:?}", &consensus_for_liquid_alpha); + + // Compute the liquid alphas matrix. let alphas: Vec> = - Self::compute_liquid_alpha_values_sparse(netuid, weights, bonds, consensus); + Self::compute_liquid_alpha_values_sparse(netuid, weights, bonds, &consensus_for_liquid_alpha); log::trace!("alphas: {:?}", &alphas); // Compute the Exponential Moving Average (EMA) of bonds using the provided clamped alpha values. @@ -1385,6 +1393,68 @@ impl Pallet { } } + /// Compute the consensus to use for liquid alpha calculation based on the configured mode + /// + /// # Args: + /// * `netuid` - The network ID. + /// * `current_consensus` - The current in-memory consensus values. + /// + /// # Returns: + /// A vector of consensus values to use for liquid alpha calculation + pub fn compute_consensus_for_liquid_alpha( + netuid: NetUid, + current_consensus: &[I32F32], + ) -> Vec { + let mode = Self::get_liquid_alpha_consensus_mode(netuid); + let bonds_penalty = Self::get_float_bonds_penalty(netuid); + + match mode { + ConsensusMode::Current => { + // Use the in-memory consensus (current behavior) + current_consensus.to_vec() + } + ConsensusMode::Previous => { + // Use consensus from storage + let previous_consensus_u16 = Consensus::::get(netuid); + previous_consensus_u16 + .iter() + .map(|&c| I32F32::saturating_from_num(c).safe_div(I32F32::saturating_from_num(u16::MAX))) + .collect() + } + ConsensusMode::Max => { + // Use element-wise max of current and previous + let previous_consensus_u16 = Consensus::::get(netuid); + let previous_consensus: Vec = previous_consensus_u16 + .iter() + .map(|&c| I32F32::saturating_from_num(c).safe_div(I32F32::saturating_from_num(u16::MAX))) + .collect(); + + // For each position: max(current, previous) + // If previous doesn't exist at that index (network grew), treat previous as 0 + current_consensus + .iter() + .enumerate() + .map(|(i, &curr)| { + let prev = previous_consensus.get(i).copied().unwrap_or(I32F32::from_num(0)); + if curr > prev { curr } else { prev } + }) + .collect() + } + ConsensusMode::Auto => { + // Auto mode: Previous if bond_penalty == 1, otherwise Current + if bonds_penalty == I32F32::from_num(1) { + let previous_consensus_u16 = Consensus::::get(netuid); + previous_consensus_u16 + .iter() + .map(|&c| I32F32::saturating_from_num(c).safe_div(I32F32::saturating_from_num(u16::MAX))) + .collect() + } else { + current_consensus.to_vec() + } + } + } + } + /// Compute liquid alphas matrix /// There is a separate alpha param for each validator-miner binding /// @@ -1592,6 +1662,26 @@ impl Pallet { Ok(()) } + pub fn do_set_liquid_alpha_consensus_mode( + origin: T::RuntimeOrigin, + netuid: NetUid, + mode: ConsensusMode, + ) -> Result<(), DispatchError> { + Self::ensure_subnet_owner_or_root(origin, netuid)?; + + ensure!( + Self::get_liquid_alpha_enabled(netuid), + Error::::LiquidAlphaDisabled + ); + + Self::set_liquid_alpha_consensus_mode(netuid, mode.clone()); + + log::debug!( + "LiquidAlphaConsensusModeSet( netuid: {netuid:?}, mode: {mode:?} )", + ); + Ok(()) + } + pub fn do_reset_bonds( netuid_index: NetUidStorageIndex, account_id: &T::AccountId, diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index 5df8a9c429..bfa09761e9 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -346,6 +346,20 @@ pub mod pallet { Manual, } + /// Enum for consensus mode used in liquid alpha calculation + #[derive(Encode, Decode, Default, TypeInfo, Clone, PartialEq, Eq, Debug)] + pub enum ConsensusMode { + /// Use current in-memory consensus (current behavior) + Current, + /// Use previous consensus from storage + Previous, + /// Use max of current and previous consensus + Max, + /// Auto mode: Previous if bond_penalty == 1, otherwise Current + #[default] + Auto, + } + #[pallet::type_value] /// Default minimum root claim amount. /// This is the minimum amount of root claim that can be made. @@ -861,6 +875,12 @@ pub mod pallet { pub fn DefaultAlphaValues() -> (u16, u16) { (45875, 58982) } + + #[pallet::type_value] + /// Default consensus mode for liquid alpha calculation + pub fn DefaultConsensusMode() -> ConsensusMode { + ConsensusMode::default() + } #[pallet::type_value] /// Default value for coldkey swap schedule duration pub fn DefaultColdkeySwapScheduleDuration() -> BlockNumberFor { @@ -1632,6 +1652,10 @@ pub mod pallet { pub type AlphaValues = StorageMap<_, Identity, NetUid, (u16, u16), ValueQuery, DefaultAlphaValues>; #[pallet::storage] + /// MAP ( netuid ) --> consensus mode for liquid alpha calculation + pub type LiquidAlphaConsensusMode = + StorageMap<_, Identity, NetUid, ConsensusMode, ValueQuery, DefaultConsensusMode>; + #[pallet::storage] /// --- MAP ( netuid ) --> If subtoken trading enabled pub type SubtokenEnabled = StorageMap<_, Identity, NetUid, bool, ValueQuery, DefaultFalse>; diff --git a/pallets/subtensor/src/tests/consensus_mode.rs b/pallets/subtensor/src/tests/consensus_mode.rs new file mode 100644 index 0000000000..bdb6442516 --- /dev/null +++ b/pallets/subtensor/src/tests/consensus_mode.rs @@ -0,0 +1,421 @@ +#![allow( + clippy::arithmetic_side_effects, + clippy::expect_used, + clippy::indexing_slicing, + clippy::unwrap_used +)] + +use frame_support::{assert_err, assert_ok}; +use sp_core::U256; +use substrate_fixed::types::I32F32; +use subtensor_runtime_common::NetUid; + +use super::mock::*; +use crate::*; + +/// Test setting consensus mode when liquid alpha is disabled +#[test] +fn test_set_consensus_mode_liquid_alpha_disabled() { + new_test_ext(1).execute_with(|| { + let hotkey = U256::from(1); + let coldkey = U256::from(1 + 456); + let netuid = add_dynamic_network(&hotkey, &coldkey); + let signer = RuntimeOrigin::signed(coldkey); + + // Setup network + migrations::migrate_create_root_network::migrate_create_root_network::(); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_000); + assert_ok!(SubtensorModule::root_register(signer.clone(), hotkey)); + assert_ok!(SubtensorModule::register_network(signer.clone(), hotkey)); + + // Liquid Alpha is disabled by default + assert!(!SubtensorModule::get_liquid_alpha_enabled(netuid)); + + // Should fail to set consensus mode when liquid alpha is disabled + assert_err!( + SubtensorModule::do_set_liquid_alpha_consensus_mode( + signer.clone(), + netuid, + ConsensusMode::Previous + ), + Error::::LiquidAlphaDisabled + ); + + // Enable Liquid Alpha + SubtensorModule::set_liquid_alpha_enabled(netuid, true); + + // Should now succeed + assert_ok!(SubtensorModule::do_set_liquid_alpha_consensus_mode( + signer.clone(), + netuid, + ConsensusMode::Previous + )); + }); +} + +/// Test that only subnet owner or root can set consensus mode +#[test] +fn test_set_consensus_mode_permissions() { + new_test_ext(1).execute_with(|| { + let hotkey = U256::from(1); + let coldkey = U256::from(1 + 456); + let non_owner = U256::from(999); + let netuid = add_dynamic_network(&hotkey, &coldkey); + let owner_signer = RuntimeOrigin::signed(coldkey); + let non_owner_signer = RuntimeOrigin::signed(non_owner); + + // Setup network + SubtensorModule::set_liquid_alpha_enabled(netuid, true); + migrations::migrate_create_root_network::migrate_create_root_network::(); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_000); + assert_ok!(SubtensorModule::root_register(owner_signer.clone(), hotkey)); + assert_ok!(SubtensorModule::register_network( + owner_signer.clone(), + hotkey + )); + + // Non-owner should fail + assert_err!( + SubtensorModule::do_set_liquid_alpha_consensus_mode( + non_owner_signer, + netuid, + ConsensusMode::Previous + ), + DispatchError::BadOrigin + ); + + // Owner should succeed + assert_ok!(SubtensorModule::do_set_liquid_alpha_consensus_mode( + owner_signer, + netuid, + ConsensusMode::Previous + )); + }); +} + +/// Test default consensus mode is Auto +#[test] +fn test_default_consensus_mode() { + new_test_ext(1).execute_with(|| { + let hotkey = U256::from(1); + let coldkey = U256::from(1 + 456); + let netuid = add_dynamic_network(&hotkey, &coldkey); + + // Default should be Auto + let mode = SubtensorModule::get_liquid_alpha_consensus_mode(netuid); + assert_eq!(mode, ConsensusMode::Auto); + }); +} + +/// Test setting and getting all consensus modes +#[test] +fn test_set_and_get_consensus_modes() { + new_test_ext(1).execute_with(|| { + let hotkey = U256::from(1); + let coldkey = U256::from(1 + 456); + let netuid = add_dynamic_network(&hotkey, &coldkey); + let signer = RuntimeOrigin::signed(coldkey); + + // Setup network + SubtensorModule::set_liquid_alpha_enabled(netuid, true); + migrations::migrate_create_root_network::migrate_create_root_network::(); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_000); + assert_ok!(SubtensorModule::root_register(signer.clone(), hotkey)); + assert_ok!(SubtensorModule::register_network(signer.clone(), hotkey)); + + // Test Current mode + assert_ok!(SubtensorModule::do_set_liquid_alpha_consensus_mode( + signer.clone(), + netuid, + ConsensusMode::Current + )); + assert_eq!( + SubtensorModule::get_liquid_alpha_consensus_mode(netuid), + ConsensusMode::Current + ); + + // Test Previous mode + assert_ok!(SubtensorModule::do_set_liquid_alpha_consensus_mode( + signer.clone(), + netuid, + ConsensusMode::Previous + )); + assert_eq!( + SubtensorModule::get_liquid_alpha_consensus_mode(netuid), + ConsensusMode::Previous + ); + + // Test Max mode + assert_ok!(SubtensorModule::do_set_liquid_alpha_consensus_mode( + signer.clone(), + netuid, + ConsensusMode::Max + )); + assert_eq!( + SubtensorModule::get_liquid_alpha_consensus_mode(netuid), + ConsensusMode::Max + ); + + // Test Auto mode + assert_ok!(SubtensorModule::do_set_liquid_alpha_consensus_mode( + signer.clone(), + netuid, + ConsensusMode::Auto + )); + assert_eq!( + SubtensorModule::get_liquid_alpha_consensus_mode(netuid), + ConsensusMode::Auto + ); + }); +} + +/// Test compute_consensus_for_liquid_alpha with Current mode +#[test] +fn test_compute_consensus_current_mode() { + new_test_ext(1).execute_with(|| { + let netuid: NetUid = 1.into(); + let n: usize = 4; + + // Create network + add_network(netuid, 0, 0); + SubtensorModule::set_liquid_alpha_enabled(netuid, true); + SubtensorModule::set_liquid_alpha_consensus_mode(netuid, ConsensusMode::Current); + + // Setup some current consensus values + let current_consensus: Vec = vec![ + I32F32::from_num(0.2), + I32F32::from_num(0.3), + I32F32::from_num(0.4), + I32F32::from_num(0.1), + ]; + + // Store some different previous consensus values in storage + let previous_consensus_u16: Vec = vec![ + (0.1 * u16::MAX as f32) as u16, + (0.2 * u16::MAX as f32) as u16, + (0.3 * u16::MAX as f32) as u16, + (0.4 * u16::MAX as f32) as u16, + ]; + Consensus::::insert(netuid, previous_consensus_u16); + + // Compute consensus for liquid alpha + let result = SubtensorModule::compute_consensus_for_liquid_alpha(netuid, ¤t_consensus); + + // Should return current consensus (not previous) + assert_eq!(result.len(), n); + for i in 0..n { + assert_eq!(result[i], current_consensus[i]); + } + }); +} + +/// Test compute_consensus_for_liquid_alpha with Previous mode +#[test] +fn test_compute_consensus_previous_mode() { + new_test_ext(1).execute_with(|| { + let netuid: NetUid = 1.into(); + let n: usize = 4; + + // Create network + add_network(netuid, 0, 0); + SubtensorModule::set_liquid_alpha_enabled(netuid, true); + SubtensorModule::set_liquid_alpha_consensus_mode(netuid, ConsensusMode::Previous); + + // Setup some current consensus values + let current_consensus: Vec = vec![ + I32F32::from_num(0.2), + I32F32::from_num(0.3), + I32F32::from_num(0.4), + I32F32::from_num(0.1), + ]; + + // Store some different previous consensus values in storage + let previous_values: Vec = vec![0.1, 0.2, 0.3, 0.4]; + let previous_consensus_u16: Vec = previous_values + .iter() + .map(|&v| (v * u16::MAX as f32) as u16) + .collect(); + Consensus::::insert(netuid, previous_consensus_u16.clone()); + + // Compute consensus for liquid alpha + let result = SubtensorModule::compute_consensus_for_liquid_alpha(netuid, ¤t_consensus); + + // Should return previous consensus from storage (not current) + assert_eq!(result.len(), n); + for i in 0..n { + let expected = I32F32::from_num(previous_values[i]); + // Allow small floating point difference + let diff = if result[i] > expected { + result[i] - expected + } else { + expected - result[i] + }; + assert!(diff < I32F32::from_num(0.001), "Values should be approximately equal"); + } + }); +} + +/// Test compute_consensus_for_liquid_alpha with Max mode +#[test] +fn test_compute_consensus_max_mode() { + new_test_ext(1).execute_with(|| { + let netuid: NetUid = 1.into(); + let n: usize = 4; + + // Create network + add_network(netuid, 0, 0); + SubtensorModule::set_liquid_alpha_enabled(netuid, true); + SubtensorModule::set_liquid_alpha_consensus_mode(netuid, ConsensusMode::Max); + + // Setup current consensus values (some larger, some smaller than previous) + let current_consensus: Vec = vec![ + I32F32::from_num(0.2), // larger than 0.1 + I32F32::from_num(0.2), // same as 0.2 + I32F32::from_num(0.25), // smaller than 0.3 + I32F32::from_num(0.5), // larger than 0.4 + ]; + + // Store previous consensus values in storage + let previous_values: Vec = vec![0.1, 0.2, 0.3, 0.4]; + let previous_consensus_u16: Vec = previous_values + .iter() + .map(|&v| (v * u16::MAX as f32) as u16) + .collect(); + Consensus::::insert(netuid, previous_consensus_u16); + + // Compute consensus for liquid alpha + let result = SubtensorModule::compute_consensus_for_liquid_alpha(netuid, ¤t_consensus); + + // Should return element-wise max of current and previous + assert_eq!(result.len(), n); + + // Expected max values + let expected: Vec = vec![0.2, 0.2, 0.3, 0.5]; + for i in 0..n { + let expected_val = I32F32::from_num(expected[i]); + let diff = if result[i] > expected_val { + result[i] - expected_val + } else { + expected_val - result[i] + }; + assert!(diff < I32F32::from_num(0.001), "Values should be approximately equal at index {}", i); + } + }); +} + +/// Test compute_consensus_for_liquid_alpha with Max mode when network grows +/// (current consensus is longer than previous consensus) +#[test] +fn test_compute_consensus_max_mode_network_growth() { + new_test_ext(1).execute_with(|| { + let netuid: NetUid = 1.into(); + + // Create network + add_network(netuid, 0, 0); + SubtensorModule::set_liquid_alpha_enabled(netuid, true); + SubtensorModule::set_liquid_alpha_consensus_mode(netuid, ConsensusMode::Max); + + // Setup current consensus with 6 values (network has grown) + let current_consensus: Vec = vec![ + I32F32::from_num(0.2), // larger than 0.1 + I32F32::from_num(0.15), // smaller than 0.2 + I32F32::from_num(0.25), // smaller than 0.3 + I32F32::from_num(0.5), // larger than 0.4 + I32F32::from_num(0.1), // new position (no previous) - should use current + I32F32::from_num(0.3), // new position (no previous) - should use current + ]; + + // Store previous consensus values in storage (only 4 values - network was smaller) + let previous_values: Vec = vec![0.1, 0.2, 0.3, 0.4]; + let previous_consensus_u16: Vec = previous_values + .iter() + .map(|&v| (v * u16::MAX as f32) as u16) + .collect(); + Consensus::::insert(netuid, previous_consensus_u16); + + // Compute consensus for liquid alpha + let result = SubtensorModule::compute_consensus_for_liquid_alpha(netuid, ¤t_consensus); + + // Should return element-wise max of current and previous + // For positions where previous doesn't exist, treat previous as 0 (so use current) + assert_eq!(result.len(), 6); + + // Expected max values: + // [0] max(0.2, 0.1) = 0.2 + // [1] max(0.15, 0.2) = 0.2 + // [2] max(0.25, 0.3) = 0.3 + // [3] max(0.5, 0.4) = 0.5 + // [4] max(0.1, 0) = 0.1 (no previous, treat as 0) + // [5] max(0.3, 0) = 0.3 (no previous, treat as 0) + let expected: Vec = vec![0.2, 0.2, 0.3, 0.5, 0.1, 0.3]; + for i in 0..6 { + let expected_val = I32F32::from_num(expected[i]); + let diff = if result[i] > expected_val { + result[i] - expected_val + } else { + expected_val - result[i] + }; + assert!( + diff < I32F32::from_num(0.001), + "Values should be approximately equal at index {}. Expected: {}, Got: {}", + i, + expected[i], + result[i] + ); + } + }); +} + +/// Test compute_consensus_for_liquid_alpha with Auto mode +#[test] +fn test_compute_consensus_auto_mode() { + new_test_ext(1).execute_with(|| { + let netuid: NetUid = 1.into(); + let n: usize = 4; + + // Create network + add_network(netuid, 0, 0); + SubtensorModule::set_liquid_alpha_enabled(netuid, true); + SubtensorModule::set_liquid_alpha_consensus_mode(netuid, ConsensusMode::Auto); + + // Setup current consensus values + let current_consensus: Vec = vec![ + I32F32::from_num(0.2), + I32F32::from_num(0.3), + I32F32::from_num(0.4), + I32F32::from_num(0.1), + ]; + + // Store previous consensus values in storage + let previous_values: Vec = vec![0.1, 0.2, 0.3, 0.4]; + let previous_consensus_u16: Vec = previous_values + .iter() + .map(|&v| (v * u16::MAX as f32) as u16) + .collect(); + Consensus::::insert(netuid, previous_consensus_u16); + + // Test 1: bond_penalty != 1, should use Current + SubtensorModule::set_bonds_penalty(netuid, u16::MAX / 2); // 0.5 + let result = SubtensorModule::compute_consensus_for_liquid_alpha(netuid, ¤t_consensus); + + assert_eq!(result.len(), n); + for i in 0..n { + assert_eq!(result[i], current_consensus[i], "Should use current consensus when bond_penalty != 1"); + } + + // Test 2: bond_penalty == 1, should use Previous + SubtensorModule::set_bonds_penalty(netuid, u16::MAX); // 1.0 + let result = SubtensorModule::compute_consensus_for_liquid_alpha(netuid, ¤t_consensus); + + assert_eq!(result.len(), n); + for i in 0..n { + let expected = I32F32::from_num(previous_values[i]); + let diff = if result[i] > expected { + result[i] - expected + } else { + expected - result[i] + }; + assert!(diff < I32F32::from_num(0.001), "Should use previous consensus when bond_penalty == 1"); + } + }); +} \ No newline at end of file diff --git a/pallets/subtensor/src/tests/epoch.rs b/pallets/subtensor/src/tests/epoch.rs index cdf44df645..f281b0da12 100644 --- a/pallets/subtensor/src/tests/epoch.rs +++ b/pallets/subtensor/src/tests/epoch.rs @@ -3560,6 +3560,8 @@ fn test_liquid_alpha_equal_values_against_itself() { // compute bonds with liquid alpha enabled SubtensorModule::set_liquid_alpha_enabled(netuid.into(), true); + // Set consensus mode to Current to match the original behavior (using in-memory consensus) + SubtensorModule::set_liquid_alpha_consensus_mode(netuid.into(), ConsensusMode::Current); let new_bonds_liquid_alpha_on = SubtensorModule::compute_bonds(netuid.into(), &weights, &bonds, &consensus); diff --git a/pallets/subtensor/src/tests/mod.rs b/pallets/subtensor/src/tests/mod.rs index bbaf25af58..78b8c718a4 100644 --- a/pallets/subtensor/src/tests/mod.rs +++ b/pallets/subtensor/src/tests/mod.rs @@ -4,6 +4,7 @@ mod children; mod claim_root; mod coinbase; mod consensus; +mod consensus_mode; mod delegate_info; mod difficulty; mod emission; diff --git a/pallets/subtensor/src/utils/misc.rs b/pallets/subtensor/src/utils/misc.rs index 7a14fafd6d..2a9c63a902 100644 --- a/pallets/subtensor/src/utils/misc.rs +++ b/pallets/subtensor/src/utils/misc.rs @@ -801,6 +801,14 @@ impl Pallet { (converted_low, converted_high) } + pub fn get_liquid_alpha_consensus_mode(netuid: NetUid) -> ConsensusMode { + LiquidAlphaConsensusMode::::get(netuid) + } + + pub fn set_liquid_alpha_consensus_mode(netuid: NetUid, mode: ConsensusMode) { + LiquidAlphaConsensusMode::::insert(netuid, mode); + } + pub fn set_alpha_sigmoid_steepness(netuid: NetUid, steepness: i16) { AlphaSigmoidSteepness::::insert(netuid, steepness); } From d38b4b5310040980130ea81ba3e0cc2e15567fc5 Mon Sep 17 00:00:00 2001 From: konrad0960 Date: Tue, 11 Nov 2025 21:30:56 +0100 Subject: [PATCH 2/5] commit Cargo.lock --- pallets/subtensor/src/epoch/run_epoch.rs | 19 -- pallets/subtensor/src/lib.rs | 2 - pallets/subtensor/src/tests/consensus_mode.rs | 314 +++++------------- 3 files changed, 81 insertions(+), 254 deletions(-) diff --git a/pallets/subtensor/src/epoch/run_epoch.rs b/pallets/subtensor/src/epoch/run_epoch.rs index cbb50ac03c..ef2c0a6c22 100644 --- a/pallets/subtensor/src/epoch/run_epoch.rs +++ b/pallets/subtensor/src/epoch/run_epoch.rs @@ -1421,25 +1421,6 @@ impl Pallet { .map(|&c| I32F32::saturating_from_num(c).safe_div(I32F32::saturating_from_num(u16::MAX))) .collect() } - ConsensusMode::Max => { - // Use element-wise max of current and previous - let previous_consensus_u16 = Consensus::::get(netuid); - let previous_consensus: Vec = previous_consensus_u16 - .iter() - .map(|&c| I32F32::saturating_from_num(c).safe_div(I32F32::saturating_from_num(u16::MAX))) - .collect(); - - // For each position: max(current, previous) - // If previous doesn't exist at that index (network grew), treat previous as 0 - current_consensus - .iter() - .enumerate() - .map(|(i, &curr)| { - let prev = previous_consensus.get(i).copied().unwrap_or(I32F32::from_num(0)); - if curr > prev { curr } else { prev } - }) - .collect() - } ConsensusMode::Auto => { // Auto mode: Previous if bond_penalty == 1, otherwise Current if bonds_penalty == I32F32::from_num(1) { diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index bfa09761e9..eca58ef58c 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -353,8 +353,6 @@ pub mod pallet { Current, /// Use previous consensus from storage Previous, - /// Use max of current and previous consensus - Max, /// Auto mode: Previous if bond_penalty == 1, otherwise Current #[default] Auto, diff --git a/pallets/subtensor/src/tests/consensus_mode.rs b/pallets/subtensor/src/tests/consensus_mode.rs index bdb6442516..8ca6a8ec33 100644 --- a/pallets/subtensor/src/tests/consensus_mode.rs +++ b/pallets/subtensor/src/tests/consensus_mode.rs @@ -1,32 +1,68 @@ -#![allow( - clippy::arithmetic_side_effects, - clippy::expect_used, - clippy::indexing_slicing, - clippy::unwrap_used -)] - use frame_support::{assert_err, assert_ok}; use sp_core::U256; use substrate_fixed::types::I32F32; use subtensor_runtime_common::NetUid; +use super::consensus::{fixed, fixed_proportion_to_u16}; use super::mock::*; use crate::*; +// ============================================================================ +// Test Helper Functions +// ============================================================================ + +/// Sets up a network with full owner permissions (root registration + network creation) +/// Returns (netuid, hotkey, coldkey, signer) +fn setup_network_with_owner() -> (NetUid, U256, U256, RuntimeOrigin) { + let hotkey = U256::from(1); + let coldkey = U256::from(457); + let netuid = add_dynamic_network(&hotkey, &coldkey); + let signer = RuntimeOrigin::signed(coldkey); + + migrations::migrate_create_root_network::migrate_create_root_network::(); + SubtensorModule::add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_000); + assert_ok!(SubtensorModule::root_register(signer.clone(), hotkey)); + assert_ok!(SubtensorModule::register_network(signer.clone(), hotkey)); + + (netuid, hotkey, coldkey, signer) +} + +/// Sets up a basic network environment for consensus testing +/// Creates network and enables liquid alpha +fn setup_consensus_test_environment(netuid: NetUid) { + add_network(netuid, 0, 0); + SubtensorModule::set_liquid_alpha_enabled(netuid, true); +} + +/// Creates test consensus data and stores it in the system +/// Returns (current_consensus, previous_values) +fn create_test_consensus_data(netuid: NetUid) -> (Vec, Vec) { + let current_consensus: Vec = vec![ + I32F32::from_num(0.2), + I32F32::from_num(0.3), + I32F32::from_num(0.4), + I32F32::from_num(0.1), + ]; + + let previous_values: Vec = vec![0.1, 0.2, 0.3, 0.4]; + let previous_consensus_u16: Vec = previous_values + .iter() + .map(|&v| fixed_proportion_to_u16(fixed(v))) + .collect(); + Consensus::::insert(netuid, previous_consensus_u16); + + (current_consensus, previous_values) +} + +// ============================================================================ +// Tests +// ============================================================================ + /// Test setting consensus mode when liquid alpha is disabled #[test] fn test_set_consensus_mode_liquid_alpha_disabled() { new_test_ext(1).execute_with(|| { - let hotkey = U256::from(1); - let coldkey = U256::from(1 + 456); - let netuid = add_dynamic_network(&hotkey, &coldkey); - let signer = RuntimeOrigin::signed(coldkey); - - // Setup network - migrations::migrate_create_root_network::migrate_create_root_network::(); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_000); - assert_ok!(SubtensorModule::root_register(signer.clone(), hotkey)); - assert_ok!(SubtensorModule::register_network(signer.clone(), hotkey)); + let (netuid, _hotkey, _coldkey, signer) = setup_network_with_owner(); // Liquid Alpha is disabled by default assert!(!SubtensorModule::get_liquid_alpha_enabled(netuid)); @@ -57,22 +93,12 @@ fn test_set_consensus_mode_liquid_alpha_disabled() { #[test] fn test_set_consensus_mode_permissions() { new_test_ext(1).execute_with(|| { - let hotkey = U256::from(1); - let coldkey = U256::from(1 + 456); + let (netuid, _hotkey, _coldkey, owner_signer) = setup_network_with_owner(); let non_owner = U256::from(999); - let netuid = add_dynamic_network(&hotkey, &coldkey); - let owner_signer = RuntimeOrigin::signed(coldkey); let non_owner_signer = RuntimeOrigin::signed(non_owner); - // Setup network + // Enable liquid alpha for this test SubtensorModule::set_liquid_alpha_enabled(netuid, true); - migrations::migrate_create_root_network::migrate_create_root_network::(); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_000); - assert_ok!(SubtensorModule::root_register(owner_signer.clone(), hotkey)); - assert_ok!(SubtensorModule::register_network( - owner_signer.clone(), - hotkey - )); // Non-owner should fail assert_err!( @@ -98,7 +124,7 @@ fn test_set_consensus_mode_permissions() { fn test_default_consensus_mode() { new_test_ext(1).execute_with(|| { let hotkey = U256::from(1); - let coldkey = U256::from(1 + 456); + let coldkey = U256::from(457); let netuid = add_dynamic_network(&hotkey, &coldkey); // Default should be Auto @@ -111,17 +137,10 @@ fn test_default_consensus_mode() { #[test] fn test_set_and_get_consensus_modes() { new_test_ext(1).execute_with(|| { - let hotkey = U256::from(1); - let coldkey = U256::from(1 + 456); - let netuid = add_dynamic_network(&hotkey, &coldkey); - let signer = RuntimeOrigin::signed(coldkey); + let (netuid, _hotkey, _coldkey, signer) = setup_network_with_owner(); - // Setup network + // Enable liquid alpha for this test SubtensorModule::set_liquid_alpha_enabled(netuid, true); - migrations::migrate_create_root_network::migrate_create_root_network::(); - SubtensorModule::add_balance_to_coldkey_account(&coldkey, 1_000_000_000_000_000); - assert_ok!(SubtensorModule::root_register(signer.clone(), hotkey)); - assert_ok!(SubtensorModule::register_network(signer.clone(), hotkey)); // Test Current mode assert_ok!(SubtensorModule::do_set_liquid_alpha_consensus_mode( @@ -145,17 +164,6 @@ fn test_set_and_get_consensus_modes() { ConsensusMode::Previous ); - // Test Max mode - assert_ok!(SubtensorModule::do_set_liquid_alpha_consensus_mode( - signer.clone(), - netuid, - ConsensusMode::Max - )); - assert_eq!( - SubtensorModule::get_liquid_alpha_consensus_mode(netuid), - ConsensusMode::Max - ); - // Test Auto mode assert_ok!(SubtensorModule::do_set_liquid_alpha_consensus_mode( signer.clone(), @@ -176,35 +184,18 @@ fn test_compute_consensus_current_mode() { let netuid: NetUid = 1.into(); let n: usize = 4; - // Create network - add_network(netuid, 0, 0); - SubtensorModule::set_liquid_alpha_enabled(netuid, true); + // Setup network and test data + setup_consensus_test_environment(netuid); SubtensorModule::set_liquid_alpha_consensus_mode(netuid, ConsensusMode::Current); - - // Setup some current consensus values - let current_consensus: Vec = vec![ - I32F32::from_num(0.2), - I32F32::from_num(0.3), - I32F32::from_num(0.4), - I32F32::from_num(0.1), - ]; - - // Store some different previous consensus values in storage - let previous_consensus_u16: Vec = vec![ - (0.1 * u16::MAX as f32) as u16, - (0.2 * u16::MAX as f32) as u16, - (0.3 * u16::MAX as f32) as u16, - (0.4 * u16::MAX as f32) as u16, - ]; - Consensus::::insert(netuid, previous_consensus_u16); + let (current_consensus, _previous_values) = create_test_consensus_data(netuid); // Compute consensus for liquid alpha let result = SubtensorModule::compute_consensus_for_liquid_alpha(netuid, ¤t_consensus); // Should return current consensus (not previous) assert_eq!(result.len(), n); - for i in 0..n { - assert_eq!(result[i], current_consensus[i]); + for (res, curr) in result.iter().zip(current_consensus.iter()) { + assert_eq!(res, curr); } }); } @@ -216,156 +207,29 @@ fn test_compute_consensus_previous_mode() { let netuid: NetUid = 1.into(); let n: usize = 4; - // Create network - add_network(netuid, 0, 0); - SubtensorModule::set_liquid_alpha_enabled(netuid, true); + // Setup network and test data + setup_consensus_test_environment(netuid); SubtensorModule::set_liquid_alpha_consensus_mode(netuid, ConsensusMode::Previous); - - // Setup some current consensus values - let current_consensus: Vec = vec![ - I32F32::from_num(0.2), - I32F32::from_num(0.3), - I32F32::from_num(0.4), - I32F32::from_num(0.1), - ]; - - // Store some different previous consensus values in storage - let previous_values: Vec = vec![0.1, 0.2, 0.3, 0.4]; - let previous_consensus_u16: Vec = previous_values - .iter() - .map(|&v| (v * u16::MAX as f32) as u16) - .collect(); - Consensus::::insert(netuid, previous_consensus_u16.clone()); + let (current_consensus, previous_values) = create_test_consensus_data(netuid); // Compute consensus for liquid alpha let result = SubtensorModule::compute_consensus_for_liquid_alpha(netuid, ¤t_consensus); // Should return previous consensus from storage (not current) assert_eq!(result.len(), n); - for i in 0..n { - let expected = I32F32::from_num(previous_values[i]); + for (res, &prev) in result.iter().zip(previous_values.iter()) { + let expected = I32F32::from_num(prev); // Allow small floating point difference - let diff = if result[i] > expected { - result[i] - expected + let diff = if *res > expected { + *res - expected } else { - expected - result[i] + expected - *res }; assert!(diff < I32F32::from_num(0.001), "Values should be approximately equal"); } }); } -/// Test compute_consensus_for_liquid_alpha with Max mode -#[test] -fn test_compute_consensus_max_mode() { - new_test_ext(1).execute_with(|| { - let netuid: NetUid = 1.into(); - let n: usize = 4; - - // Create network - add_network(netuid, 0, 0); - SubtensorModule::set_liquid_alpha_enabled(netuid, true); - SubtensorModule::set_liquid_alpha_consensus_mode(netuid, ConsensusMode::Max); - - // Setup current consensus values (some larger, some smaller than previous) - let current_consensus: Vec = vec![ - I32F32::from_num(0.2), // larger than 0.1 - I32F32::from_num(0.2), // same as 0.2 - I32F32::from_num(0.25), // smaller than 0.3 - I32F32::from_num(0.5), // larger than 0.4 - ]; - - // Store previous consensus values in storage - let previous_values: Vec = vec![0.1, 0.2, 0.3, 0.4]; - let previous_consensus_u16: Vec = previous_values - .iter() - .map(|&v| (v * u16::MAX as f32) as u16) - .collect(); - Consensus::::insert(netuid, previous_consensus_u16); - - // Compute consensus for liquid alpha - let result = SubtensorModule::compute_consensus_for_liquid_alpha(netuid, ¤t_consensus); - - // Should return element-wise max of current and previous - assert_eq!(result.len(), n); - - // Expected max values - let expected: Vec = vec![0.2, 0.2, 0.3, 0.5]; - for i in 0..n { - let expected_val = I32F32::from_num(expected[i]); - let diff = if result[i] > expected_val { - result[i] - expected_val - } else { - expected_val - result[i] - }; - assert!(diff < I32F32::from_num(0.001), "Values should be approximately equal at index {}", i); - } - }); -} - -/// Test compute_consensus_for_liquid_alpha with Max mode when network grows -/// (current consensus is longer than previous consensus) -#[test] -fn test_compute_consensus_max_mode_network_growth() { - new_test_ext(1).execute_with(|| { - let netuid: NetUid = 1.into(); - - // Create network - add_network(netuid, 0, 0); - SubtensorModule::set_liquid_alpha_enabled(netuid, true); - SubtensorModule::set_liquid_alpha_consensus_mode(netuid, ConsensusMode::Max); - - // Setup current consensus with 6 values (network has grown) - let current_consensus: Vec = vec![ - I32F32::from_num(0.2), // larger than 0.1 - I32F32::from_num(0.15), // smaller than 0.2 - I32F32::from_num(0.25), // smaller than 0.3 - I32F32::from_num(0.5), // larger than 0.4 - I32F32::from_num(0.1), // new position (no previous) - should use current - I32F32::from_num(0.3), // new position (no previous) - should use current - ]; - - // Store previous consensus values in storage (only 4 values - network was smaller) - let previous_values: Vec = vec![0.1, 0.2, 0.3, 0.4]; - let previous_consensus_u16: Vec = previous_values - .iter() - .map(|&v| (v * u16::MAX as f32) as u16) - .collect(); - Consensus::::insert(netuid, previous_consensus_u16); - - // Compute consensus for liquid alpha - let result = SubtensorModule::compute_consensus_for_liquid_alpha(netuid, ¤t_consensus); - - // Should return element-wise max of current and previous - // For positions where previous doesn't exist, treat previous as 0 (so use current) - assert_eq!(result.len(), 6); - - // Expected max values: - // [0] max(0.2, 0.1) = 0.2 - // [1] max(0.15, 0.2) = 0.2 - // [2] max(0.25, 0.3) = 0.3 - // [3] max(0.5, 0.4) = 0.5 - // [4] max(0.1, 0) = 0.1 (no previous, treat as 0) - // [5] max(0.3, 0) = 0.3 (no previous, treat as 0) - let expected: Vec = vec![0.2, 0.2, 0.3, 0.5, 0.1, 0.3]; - for i in 0..6 { - let expected_val = I32F32::from_num(expected[i]); - let diff = if result[i] > expected_val { - result[i] - expected_val - } else { - expected_val - result[i] - }; - assert!( - diff < I32F32::from_num(0.001), - "Values should be approximately equal at index {}. Expected: {}, Got: {}", - i, - expected[i], - result[i] - ); - } - }); -} - /// Test compute_consensus_for_liquid_alpha with Auto mode #[test] fn test_compute_consensus_auto_mode() { @@ -373,34 +237,18 @@ fn test_compute_consensus_auto_mode() { let netuid: NetUid = 1.into(); let n: usize = 4; - // Create network - add_network(netuid, 0, 0); - SubtensorModule::set_liquid_alpha_enabled(netuid, true); + // Setup network and test data + setup_consensus_test_environment(netuid); SubtensorModule::set_liquid_alpha_consensus_mode(netuid, ConsensusMode::Auto); - - // Setup current consensus values - let current_consensus: Vec = vec![ - I32F32::from_num(0.2), - I32F32::from_num(0.3), - I32F32::from_num(0.4), - I32F32::from_num(0.1), - ]; - - // Store previous consensus values in storage - let previous_values: Vec = vec![0.1, 0.2, 0.3, 0.4]; - let previous_consensus_u16: Vec = previous_values - .iter() - .map(|&v| (v * u16::MAX as f32) as u16) - .collect(); - Consensus::::insert(netuid, previous_consensus_u16); + let (current_consensus, previous_values) = create_test_consensus_data(netuid); // Test 1: bond_penalty != 1, should use Current SubtensorModule::set_bonds_penalty(netuid, u16::MAX / 2); // 0.5 let result = SubtensorModule::compute_consensus_for_liquid_alpha(netuid, ¤t_consensus); assert_eq!(result.len(), n); - for i in 0..n { - assert_eq!(result[i], current_consensus[i], "Should use current consensus when bond_penalty != 1"); + for (res, curr) in result.iter().zip(current_consensus.iter()) { + assert_eq!(res, curr, "Should use current consensus when bond_penalty != 1"); } // Test 2: bond_penalty == 1, should use Previous @@ -408,12 +256,12 @@ fn test_compute_consensus_auto_mode() { let result = SubtensorModule::compute_consensus_for_liquid_alpha(netuid, ¤t_consensus); assert_eq!(result.len(), n); - for i in 0..n { - let expected = I32F32::from_num(previous_values[i]); - let diff = if result[i] > expected { - result[i] - expected + for (res, &prev) in result.iter().zip(previous_values.iter()) { + let expected = I32F32::from_num(prev); + let diff = if *res > expected { + *res - expected } else { - expected - result[i] + expected - *res }; assert!(diff < I32F32::from_num(0.001), "Should use previous consensus when bond_penalty == 1"); } From 4e6d8a2d07179c628b18e8831669afbd3c8315f4 Mon Sep 17 00:00:00 2001 From: konrad0960 Date: Tue, 11 Nov 2025 22:52:29 +0100 Subject: [PATCH 3/5] cargo fmt --- pallets/subtensor/src/epoch/run_epoch.rs | 46 +++++++++++++------ pallets/subtensor/src/tests/consensus_mode.rs | 29 ++++++++---- 2 files changed, 54 insertions(+), 21 deletions(-) diff --git a/pallets/subtensor/src/epoch/run_epoch.rs b/pallets/subtensor/src/epoch/run_epoch.rs index ef2c0a6c22..b0da4aa29c 100644 --- a/pallets/subtensor/src/epoch/run_epoch.rs +++ b/pallets/subtensor/src/epoch/run_epoch.rs @@ -1328,12 +1328,20 @@ impl Pallet { .any(|&c| c != I32F32::saturating_from_num(0)) { // Liquid Alpha is enabled, compute the appropriate consensus for liquid alpha based on mode - let consensus_for_liquid_alpha = Self::compute_consensus_for_liquid_alpha(netuid, consensus); - log::trace!("consensus_for_liquid_alpha: {:?}", &consensus_for_liquid_alpha); + let consensus_for_liquid_alpha = + Self::compute_consensus_for_liquid_alpha(netuid, consensus); + log::trace!( + "consensus_for_liquid_alpha: {:?}", + &consensus_for_liquid_alpha + ); // Compute the liquid alphas matrix. - let alphas: Vec> = - Self::compute_liquid_alpha_values(netuid, weights, bonds, &consensus_for_liquid_alpha); + let alphas: Vec> = Self::compute_liquid_alpha_values( + netuid, + weights, + bonds, + &consensus_for_liquid_alpha, + ); log::trace!("alphas: {:?}", &alphas); // Compute the Exponential Moving Average (EMA) of bonds using the provided clamped alpha values. @@ -1374,12 +1382,20 @@ impl Pallet { .any(|&c| c != I32F32::saturating_from_num(0)) { // Liquid Alpha is enabled, compute the appropriate consensus for liquid alpha based on mode - let consensus_for_liquid_alpha = Self::compute_consensus_for_liquid_alpha(netuid, consensus); - log::trace!("consensus_for_liquid_alpha: {:?}", &consensus_for_liquid_alpha); + let consensus_for_liquid_alpha = + Self::compute_consensus_for_liquid_alpha(netuid, consensus); + log::trace!( + "consensus_for_liquid_alpha: {:?}", + &consensus_for_liquid_alpha + ); // Compute the liquid alphas matrix. - let alphas: Vec> = - Self::compute_liquid_alpha_values_sparse(netuid, weights, bonds, &consensus_for_liquid_alpha); + let alphas: Vec> = Self::compute_liquid_alpha_values_sparse( + netuid, + weights, + bonds, + &consensus_for_liquid_alpha, + ); log::trace!("alphas: {:?}", &alphas); // Compute the Exponential Moving Average (EMA) of bonds using the provided clamped alpha values. @@ -1418,7 +1434,10 @@ impl Pallet { let previous_consensus_u16 = Consensus::::get(netuid); previous_consensus_u16 .iter() - .map(|&c| I32F32::saturating_from_num(c).safe_div(I32F32::saturating_from_num(u16::MAX))) + .map(|&c| { + I32F32::saturating_from_num(c) + .safe_div(I32F32::saturating_from_num(u16::MAX)) + }) .collect() } ConsensusMode::Auto => { @@ -1427,7 +1446,10 @@ impl Pallet { let previous_consensus_u16 = Consensus::::get(netuid); previous_consensus_u16 .iter() - .map(|&c| I32F32::saturating_from_num(c).safe_div(I32F32::saturating_from_num(u16::MAX))) + .map(|&c| { + I32F32::saturating_from_num(c) + .safe_div(I32F32::saturating_from_num(u16::MAX)) + }) .collect() } else { current_consensus.to_vec() @@ -1657,9 +1679,7 @@ impl Pallet { Self::set_liquid_alpha_consensus_mode(netuid, mode.clone()); - log::debug!( - "LiquidAlphaConsensusModeSet( netuid: {netuid:?}, mode: {mode:?} )", - ); + log::debug!("LiquidAlphaConsensusModeSet( netuid: {netuid:?}, mode: {mode:?} )",); Ok(()) } diff --git a/pallets/subtensor/src/tests/consensus_mode.rs b/pallets/subtensor/src/tests/consensus_mode.rs index 8ca6a8ec33..500a76e808 100644 --- a/pallets/subtensor/src/tests/consensus_mode.rs +++ b/pallets/subtensor/src/tests/consensus_mode.rs @@ -190,7 +190,8 @@ fn test_compute_consensus_current_mode() { let (current_consensus, _previous_values) = create_test_consensus_data(netuid); // Compute consensus for liquid alpha - let result = SubtensorModule::compute_consensus_for_liquid_alpha(netuid, ¤t_consensus); + let result = + SubtensorModule::compute_consensus_for_liquid_alpha(netuid, ¤t_consensus); // Should return current consensus (not previous) assert_eq!(result.len(), n); @@ -213,7 +214,8 @@ fn test_compute_consensus_previous_mode() { let (current_consensus, previous_values) = create_test_consensus_data(netuid); // Compute consensus for liquid alpha - let result = SubtensorModule::compute_consensus_for_liquid_alpha(netuid, ¤t_consensus); + let result = + SubtensorModule::compute_consensus_for_liquid_alpha(netuid, ¤t_consensus); // Should return previous consensus from storage (not current) assert_eq!(result.len(), n); @@ -225,7 +227,10 @@ fn test_compute_consensus_previous_mode() { } else { expected - *res }; - assert!(diff < I32F32::from_num(0.001), "Values should be approximately equal"); + assert!( + diff < I32F32::from_num(0.001), + "Values should be approximately equal" + ); } }); } @@ -244,16 +249,21 @@ fn test_compute_consensus_auto_mode() { // Test 1: bond_penalty != 1, should use Current SubtensorModule::set_bonds_penalty(netuid, u16::MAX / 2); // 0.5 - let result = SubtensorModule::compute_consensus_for_liquid_alpha(netuid, ¤t_consensus); + let result = + SubtensorModule::compute_consensus_for_liquid_alpha(netuid, ¤t_consensus); assert_eq!(result.len(), n); for (res, curr) in result.iter().zip(current_consensus.iter()) { - assert_eq!(res, curr, "Should use current consensus when bond_penalty != 1"); + assert_eq!( + res, curr, + "Should use current consensus when bond_penalty != 1" + ); } // Test 2: bond_penalty == 1, should use Previous SubtensorModule::set_bonds_penalty(netuid, u16::MAX); // 1.0 - let result = SubtensorModule::compute_consensus_for_liquid_alpha(netuid, ¤t_consensus); + let result = + SubtensorModule::compute_consensus_for_liquid_alpha(netuid, ¤t_consensus); assert_eq!(result.len(), n); for (res, &prev) in result.iter().zip(previous_values.iter()) { @@ -263,7 +273,10 @@ fn test_compute_consensus_auto_mode() { } else { expected - *res }; - assert!(diff < I32F32::from_num(0.001), "Should use previous consensus when bond_penalty == 1"); + assert!( + diff < I32F32::from_num(0.001), + "Should use previous consensus when bond_penalty == 1" + ); } }); -} \ No newline at end of file +} From a5e3e73d71b30bdf1b3f518c43cbbf6c367072e1 Mon Sep 17 00:00:00 2001 From: konrad0960 Date: Thu, 13 Nov 2025 21:59:52 +0100 Subject: [PATCH 4/5] commit Cargo.lock --- Cargo.lock | 6 +-- pallets/subtensor/src/epoch/run_epoch.rs | 7 +-- pallets/subtensor/src/tests/consensus_mode.rs | 51 ++++++++----------- 3 files changed, 24 insertions(+), 40 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d242b5922f..64ef0d86c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3636,7 +3636,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d162beedaa69905488a8da94f5ac3edb4dd4788b732fadb7bd120b2625c1976" dependencies = [ "data-encoding", - "syn 2.0.106", + "syn 1.0.109", ] [[package]] @@ -6390,7 +6390,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" dependencies = [ "equivalent", - "hashbrown 0.16.0", + "hashbrown 0.15.5", "serde", "serde_core", ] @@ -8536,7 +8536,7 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" dependencies = [ - "proc-macro-crate 3.4.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn 2.0.106", diff --git a/pallets/subtensor/src/epoch/run_epoch.rs b/pallets/subtensor/src/epoch/run_epoch.rs index b0da4aa29c..1f16ae212f 100644 --- a/pallets/subtensor/src/epoch/run_epoch.rs +++ b/pallets/subtensor/src/epoch/run_epoch.rs @@ -1422,7 +1422,6 @@ impl Pallet { current_consensus: &[I32F32], ) -> Vec { let mode = Self::get_liquid_alpha_consensus_mode(netuid); - let bonds_penalty = Self::get_float_bonds_penalty(netuid); match mode { ConsensusMode::Current => { @@ -1442,6 +1441,7 @@ impl Pallet { } ConsensusMode::Auto => { // Auto mode: Previous if bond_penalty == 1, otherwise Current + let bonds_penalty = Self::get_float_bonds_penalty(netuid); if bonds_penalty == I32F32::from_num(1) { let previous_consensus_u16 = Consensus::::get(netuid); previous_consensus_u16 @@ -1672,11 +1672,6 @@ impl Pallet { ) -> Result<(), DispatchError> { Self::ensure_subnet_owner_or_root(origin, netuid)?; - ensure!( - Self::get_liquid_alpha_enabled(netuid), - Error::::LiquidAlphaDisabled - ); - Self::set_liquid_alpha_consensus_mode(netuid, mode.clone()); log::debug!("LiquidAlphaConsensusModeSet( netuid: {netuid:?}, mode: {mode:?} )",); diff --git a/pallets/subtensor/src/tests/consensus_mode.rs b/pallets/subtensor/src/tests/consensus_mode.rs index 500a76e808..e9aeec6368 100644 --- a/pallets/subtensor/src/tests/consensus_mode.rs +++ b/pallets/subtensor/src/tests/consensus_mode.rs @@ -67,25 +67,34 @@ fn test_set_consensus_mode_liquid_alpha_disabled() { // Liquid Alpha is disabled by default assert!(!SubtensorModule::get_liquid_alpha_enabled(netuid)); - // Should fail to set consensus mode when liquid alpha is disabled - assert_err!( - SubtensorModule::do_set_liquid_alpha_consensus_mode( - signer.clone(), - netuid, - ConsensusMode::Previous - ), - Error::::LiquidAlphaDisabled + // Should succeed to set consensus mode even when liquid alpha is disabled + assert_ok!(SubtensorModule::do_set_liquid_alpha_consensus_mode( + signer.clone(), + netuid, + ConsensusMode::Previous + )); + + // Verify the mode was set + assert_eq!( + SubtensorModule::get_liquid_alpha_consensus_mode(netuid), + ConsensusMode::Previous ); - // Enable Liquid Alpha + // Also verify with liquid alpha enabled SubtensorModule::set_liquid_alpha_enabled(netuid, true); - // Should now succeed + // Should still succeed assert_ok!(SubtensorModule::do_set_liquid_alpha_consensus_mode( signer.clone(), netuid, - ConsensusMode::Previous + ConsensusMode::Current )); + + // Verify the mode was updated + assert_eq!( + SubtensorModule::get_liquid_alpha_consensus_mode(netuid), + ConsensusMode::Current + ); }); } @@ -97,9 +106,6 @@ fn test_set_consensus_mode_permissions() { let non_owner = U256::from(999); let non_owner_signer = RuntimeOrigin::signed(non_owner); - // Enable liquid alpha for this test - SubtensorModule::set_liquid_alpha_enabled(netuid, true); - // Non-owner should fail assert_err!( SubtensorModule::do_set_liquid_alpha_consensus_mode( @@ -119,29 +125,12 @@ fn test_set_consensus_mode_permissions() { }); } -/// Test default consensus mode is Auto -#[test] -fn test_default_consensus_mode() { - new_test_ext(1).execute_with(|| { - let hotkey = U256::from(1); - let coldkey = U256::from(457); - let netuid = add_dynamic_network(&hotkey, &coldkey); - - // Default should be Auto - let mode = SubtensorModule::get_liquid_alpha_consensus_mode(netuid); - assert_eq!(mode, ConsensusMode::Auto); - }); -} - /// Test setting and getting all consensus modes #[test] fn test_set_and_get_consensus_modes() { new_test_ext(1).execute_with(|| { let (netuid, _hotkey, _coldkey, signer) = setup_network_with_owner(); - // Enable liquid alpha for this test - SubtensorModule::set_liquid_alpha_enabled(netuid, true); - // Test Current mode assert_ok!(SubtensorModule::do_set_liquid_alpha_consensus_mode( signer.clone(), From 7d4b3cd4d70d189bb6c8753cdf4f2345de838e60 Mon Sep 17 00:00:00 2001 From: konrad0960 Date: Thu, 13 Nov 2025 22:17:07 +0100 Subject: [PATCH 5/5] Revert Cargo.lock to previous state --- Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 64ef0d86c6..d242b5922f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3636,7 +3636,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d162beedaa69905488a8da94f5ac3edb4dd4788b732fadb7bd120b2625c1976" dependencies = [ "data-encoding", - "syn 1.0.109", + "syn 2.0.106", ] [[package]] @@ -6390,7 +6390,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" dependencies = [ "equivalent", - "hashbrown 0.15.5", + "hashbrown 0.16.0", "serde", "serde_core", ] @@ -8536,7 +8536,7 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" dependencies = [ - "proc-macro-crate 1.1.3", + "proc-macro-crate 3.4.0", "proc-macro2", "quote", "syn 2.0.106",