Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
camfairchild committed Jan 9, 2025
1 parent c542916 commit 9eabb47
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 98 deletions.
24 changes: 12 additions & 12 deletions pallets/subtensor/src/coinbase/run_coinbase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,11 @@ impl<T: Config> Pallet<T> {
.saturating_div(I96F32::from_num(u16::MAX));
// NOTE: Only the validation emission should be split amongst parents.

// Reserve childkey take
let child_emission_take: I96F32 =
childkey_take_proportion.saturating_mul(I96F32::from_num(validating_emission));
let remaining_emission: I96F32 = validating_emission.saturating_sub(child_emission_take);

// Initialize variables to track emission distribution
let mut to_parents: u64 = 0;

Expand Down Expand Up @@ -577,29 +582,24 @@ impl<T: Config> Pallet<T> {
let emission_factor: I96F32 = contribution
.checked_div(total_contribution)
.unwrap_or(I96F32::from_num(0));
let total_emission: u64 =
(validating_emission.saturating_mul(emission_factor)).to_num::<u64>();

// Reserve childkey take
let child_emission_take: u64 = childkey_take_proportion
.saturating_mul(I96F32::from_num(total_emission))
.to_num::<u64>();
let parent_total_emission = total_emission.saturating_sub(child_emission_take);
let parent_emission: u64 =
(remaining_emission.saturating_mul(emission_factor)).to_num::<u64>();

// Add the parent's emission to the distribution list
dividend_tuples.push((parent, parent_total_emission));
dividend_tuples.push((parent, parent_emission));

// Keep track of total emission distributed to parents
to_parents = to_parents.saturating_add(parent_total_emission);
to_parents = to_parents.saturating_add(parent_emission);
}
// Calculate the final emission for the hotkey itself.
// This includes the take left from the parents and the self contribution.
let final_hotkey_emission = validating_emission
let child_emission = remaining_emission
.saturating_add(child_emission_take)
.to_num::<u64>()
.saturating_sub(to_parents);

// Add the hotkey's own emission to the distribution list
dividend_tuples.push((hotkey.clone(), final_hotkey_emission));
dividend_tuples.push((hotkey.clone(), child_emission));

dividend_tuples
}
Expand Down
231 changes: 145 additions & 86 deletions pallets/subtensor/src/tests/children.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#![allow(clippy::arithmetic_side_effects)]
use super::mock::*;
use frame_support::{assert_err, assert_noop, assert_ok};
use substrate_fixed::types::I96F32;

use crate::{utils::rate_limiting::TransactionType, *};
use sp_core::U256;
Expand Down Expand Up @@ -3264,14 +3265,16 @@ fn test_childkey_multiple_parents_emission() {
// - Runs an epoch with a hardcoded emission value
// - Checks the emission distribution among A, B, and C
// - Verifies that all parties received emissions and the total stake increased correctly
// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --test coinbase test_parent_child_chain_emission -- --nocapture
// SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::children::test_parent_child_chain_emission --exact --show-output
#[test]
fn test_parent_child_chain_emission() {
new_test_ext(1).execute_with(|| {
assert!(false);

// let netuid: u16 = 1;
// add_network(netuid, 1, 0);
// // Set owner cut to 0
// SubtensorModule::set_subnet_owner_cut(0_u16);

// // Define hotkeys and coldkeys
// let hotkey_a: U256 = U256::from(1);
Expand All @@ -3287,13 +3290,56 @@ fn test_parent_child_chain_emission() {
// register_ok_neuron(netuid, hotkey_c, coldkey_c, 0);

// // Add initial stakes
// SubtensorModule::add_balance_to_coldkey_account(&coldkey_a, 300_000);
// SubtensorModule::add_balance_to_coldkey_account(&coldkey_b, 100_000);
// SubtensorModule::add_balance_to_coldkey_account(&coldkey_c, 50_000);
// SubtensorModule::add_balance_to_coldkey_account(&coldkey_a, 1_000);
// SubtensorModule::add_balance_to_coldkey_account(&coldkey_b, 1_000);
// SubtensorModule::add_balance_to_coldkey_account(&coldkey_c, 1_000);

// SubtensorModule::increase_stake_on_coldkey_hotkey_account(&coldkey_a, &hotkey_a, 300_000);
// SubtensorModule::increase_stake_on_coldkey_hotkey_account(&coldkey_b, &hotkey_b, 100_000);
// SubtensorModule::increase_stake_on_coldkey_hotkey_account(&coldkey_c, &hotkey_c, 50_000);
// // Swap to alpha
// let total_tao: I96F32 = I96F32::from_num(300_000 + 100_000 + 50_000);
// let total_alpha: I96F32 = I96F32::from_num(SubtensorModule::swap_tao_for_alpha(
// netuid,
// total_tao.saturating_to_num::<u64>(),
// ));

// // Set the stakes directly
// // This avoids needing to swap tao to alpha, impacting the initial stake distribution.
// SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet(
// &hotkey_a,
// &coldkey_a,
// netuid,
// (total_alpha * I96F32::from_num(300_000) / total_tao).saturating_to_num::<u64>(),
// );
// SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet(
// &hotkey_b,
// &coldkey_b,
// netuid,
// (total_alpha * I96F32::from_num(100_000) / total_tao).saturating_to_num::<u64>(),
// );
// SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet(
// &hotkey_c,
// &coldkey_c,
// netuid,
// (total_alpha * I96F32::from_num(50_000) / total_tao).saturating_to_num::<u64>(),
// );

// // Get old stakes
// let stake_a: u64 = SubtensorModule::get_total_stake_for_hotkey(&hotkey_a);
// let stake_b: u64 = SubtensorModule::get_total_stake_for_hotkey(&hotkey_b);
// let stake_c: u64 = SubtensorModule::get_total_stake_for_hotkey(&hotkey_c);

// let total_stake: I96F32 = I96F32::from_num(stake_a + stake_b + stake_c);

// // Assert initial stake is correct
// let rel_stake_a = I96F32::from_num(stake_a) / total_tao;
// let rel_stake_b = I96F32::from_num(stake_b) / total_tao;
// let rel_stake_c = I96F32::from_num(stake_c) / total_tao;

// log::info!("rel_stake_a: {:?}", rel_stake_a); // 0.6666 -> 2/3
// log::info!("rel_stake_b: {:?}", rel_stake_b); // 0.2222 -> 2/9
// log::info!("rel_stake_c: {:?}", rel_stake_c); // 0.1111 -> 1/9
// assert_eq!(rel_stake_a, I96F32::from_num(300_000) / total_tao);
// assert_eq!(rel_stake_b, I96F32::from_num(100_000) / total_tao);
// assert_eq!(rel_stake_c, I96F32::from_num(50_000) / total_tao);

// // Set parent-child relationships
// // A -> B (50% of A's stake)
Expand All @@ -3302,101 +3348,114 @@ fn test_parent_child_chain_emission() {
// // B -> C (50% of B's stake)
// mock_set_children(&coldkey_b, &hotkey_b, netuid, &[(u64::MAX / 2, hotkey_c)]);

// step_block(2);

// // Set weights
// let origin = RuntimeOrigin::signed(hotkey_a);
// let uids: Vec<u16> = vec![0, 1, 2]; // UIDs for hotkey_a, hotkey_b, hotkey_c
// let values: Vec<u16> = vec![65535, 65535, 65535]; // Set equal weights for all hotkeys
// let version_key = SubtensorModule::get_weights_version_key(netuid);
// // Set CHK take rate to 1/9
// let chk_take: I96F32 = I96F32::from_num(1_f64 / 9_f64);
// let chk_take_u16: u16 = (chk_take * I96F32::from_num(u16::MAX)).saturating_to_num::<u16>();
// ChildkeyTake::<Test>::insert(hotkey_b, netuid, chk_take_u16);
// ChildkeyTake::<Test>::insert(hotkey_c, netuid, chk_take_u16);

// // Ensure we can set weights without rate limiting
// SubtensorModule::set_weights_set_rate_limit(netuid, 0);
// // Set the weight of root TAO to be 0%, so only alpha is effective.
// SubtensorModule::set_tao_weight(0);

// assert_ok!(SubtensorModule::set_weights(
// origin,
// netuid,
// uids,
// values,
// version_key
// ));
// let hardcoded_emission: I96F32 = I96F32::from_num(1_000_000); // 1 million (adjust as needed)

// // Run epoch with a hardcoded emission value
// let hardcoded_emission: u64 = 1_000_000; // 1 million (adjust as needed)
// let hotkey_emission: Vec<(U256, u64, u64)> =
// SubtensorModule::epoch(netuid, hardcoded_emission);

// // Process the hotkey emission results
// for (hotkey, mining_emission, validator_emission) in hotkey_emission {
// SubtensorModule::accumulate_hotkey_emission(
// &hotkey,
// netuid,
// validator_emission,
// mining_emission,
// );
// }

// // Log PendingEmission Tuple for a, b, c
// let pending_emission_a = SubtensorModule::get_pending_hotkey_emission(&hotkey_a);
// let pending_emission_b = SubtensorModule::get_pending_hotkey_emission(&hotkey_b);
// let pending_emission_c = SubtensorModule::get_pending_hotkey_emission(&hotkey_c);

// log::info!("Pending Emission for A: {:?}", pending_emission_a);
// log::info!("Pending Emission for B: {:?}", pending_emission_b);
// log::info!("Pending Emission for C: {:?}", pending_emission_c);

// // Assert that pending emissions are non-zero
// // A's pending emission: 2/3 of total emission (due to having 2/3 of total stake)
// SubtensorModule::epoch(netuid, hardcoded_emission.saturating_to_num::<u64>());
// log::info!("hotkey_emission: {:?}", hotkey_emission);
// let total_emission: I96F32 = hotkey_emission
// .iter()
// .map(|(_, _, emission)| I96F32::from_num(*emission))
// .sum();

// // Verify emissions match expected from CHK arrangements
// let em_eps: I96F32 = I96F32::from_num(1e-4); // 4 decimal places
// // A's pending emission:
// assert!(
// pending_emission_a == 666667,
// "A should have pending emission of 2/3 of total emission"
// ((I96F32::from_num(hotkey_emission[0].2) / total_emission) -
// I96F32::from_num(2_f64 / 3_f64 * 1_f64 / 2_f64)).abs() // 2/3 * 1/2 = 1/3; 50% -> B
// <= em_eps,
// "A should have pending emission of 1/3 of total emission"
// );
// // B's pending emission: 2/9 of total emission (1/3 of A's emission + 1/3 of total emission)
// // B's pending emission:
// assert!(
// pending_emission_b == 222222,
// "B should have pending emission of 2/9 of total emission"
// ((I96F32::from_num(hotkey_emission[1].2) / total_emission) -
// (I96F32::from_num(2_f64 / 9_f64 * 1_f64 / 2_f64 + 2_f64 / 3_f64 * 1_f64 / 2_f64))).abs() // 2/9 * 1/2 + 2/3 * 1/2; 50% -> C + 50% from A
// <= em_eps,
// "B should have pending emission of 4/9 of total emission"
// );
// // C's pending emission: 1/9 of total emission (1/2 of B's emission)
// // C's pending emission:
// assert!(
// pending_emission_c == 111109,
// ((I96F32::from_num(hotkey_emission[2].2) / total_emission) -
// (I96F32::from_num(1_f64 / 9_f64 + 1_f64 / 2_f64 * 2_f64 / 9_f64))).abs() // 1/9 + 2/9 * 1/2; 50% from B
// <= em_eps,
// "C should have pending emission of 1/9 of total emission"
// );

// SubtensorModule::set_hotkey_emission_tempo(10);

// step_block(10 + 1);
// // Retrieve the current stake for each hotkey on the subnet
// let stake_a: u64 = SubtensorModule::get_stake_for_hotkey_on_subnet(&hotkey_a, netuid);
// let stake_b: u64 = SubtensorModule::get_stake_for_hotkey_on_subnet(&hotkey_b, netuid);
// let stake_c: u64 = SubtensorModule::get_stake_for_hotkey_on_subnet(&hotkey_c, netuid);

// // Log the current stakes for debugging purposes
// log::info!("Stake for hotkey A: {:?}", stake_a);
// log::info!("Stake for hotkey B: {:?}", stake_b);
// log::info!("Stake for hotkey C: {:?}", stake_c);

// // Assert that the stakes have been updated correctly after emission distribution
// assert_eq!(
// stake_a, 483334,
// "A's stake should be 483334 (initial 300_000 + 666667 emission - 483333 given to B)"
// // Run epoch with a hardcoded emission value
// SubtensorModule::run_coinbase(hardcoded_emission);

// // Log new stake
// let stake_a_new: u64 = SubtensorModule::get_total_stake_for_hotkey(&hotkey_a);
// let stake_b_new: u64 = SubtensorModule::get_total_stake_for_hotkey(&hotkey_b);
// let stake_c_new: u64 = SubtensorModule::get_total_stake_for_hotkey(&hotkey_c);
// let total_stake_new: I96F32 = I96F32::from_num(stake_a_new + stake_b_new + stake_c_new);
// log::info!("Stake for hotkey A: {:?}", stake_a_new);
// log::info!("Stake for hotkey B: {:?}", stake_b_new);
// log::info!("Stake for hotkey C: {:?}", stake_c_new);

// let stake_inc_a: u64 = stake_a_new - stake_a;
// let stake_inc_b: u64 = stake_b_new - stake_b;
// let stake_inc_c: u64 = stake_c_new - stake_c;
// let total_stake_inc: I96F32 = total_stake_new - total_stake;
// log::info!("Stake increase for hotkey A: {:?}", stake_inc_a);
// log::info!("Stake increase for hotkey B: {:?}", stake_inc_b);
// log::info!("Stake increase for hotkey C: {:?}", stake_inc_c);
// log::info!("Total stake increase: {:?}", total_stake_inc);
// let rel_stake_inc_a = I96F32::from_num(stake_inc_a) / total_stake_inc;
// let rel_stake_inc_b = I96F32::from_num(stake_inc_b) / total_stake_inc;
// let rel_stake_inc_c = I96F32::from_num(stake_inc_c) / total_stake_inc;
// log::info!("rel_stake_inc_a: {:?}", rel_stake_inc_a);
// log::info!("rel_stake_inc_b: {:?}", rel_stake_inc_b);
// log::info!("rel_stake_inc_c: {:?}", rel_stake_inc_c);

// // Verify the final stake distribution
// let stake_inc_eps: I96F32 = I96F32::from_num(1e-4); // 4 decimal places
// // Each child has chk_take take

// let expected_a = I96F32::from_num(2_f64 / 3_f64)
// * (I96F32::from_num(1_f64) - (I96F32::from_num(1_f64 / 2_f64) * chk_take));
// assert!(
// (rel_stake_inc_a - expected_a).abs() // B's take on 50% CHK
// <= stake_inc_eps,
// "A should have {:?} of total stake increase; {:?}",
// expected_a,
// rel_stake_inc_a
// );
// assert_eq!(
// stake_b, 644445,
// "B's stake should be 644445 (initial 100_000 + 222222 emission + 483333 from A - 161110 given to C)"
// let expected_b = I96F32::from_num(2_f64 / 9_f64)
// * (I96F32::from_num(1_f64) - (I96F32::from_num(1_f64 / 2_f64) * chk_take))
// + I96F32::from_num(2_f64 / 3_f64) * (I96F32::from_num(1_f64 / 2_f64) * chk_take);
// assert!(
// (rel_stake_inc_b - expected_b).abs() // C's take on 50% CHK + take from A
// <= stake_inc_eps,
// "B should have {:?} of total stake increase; {:?}",
// expected_b,
// rel_stake_inc_b
// );
// assert_eq!(
// stake_c, 322219,
// "C's stake should be 322219 (initial 50_000 + 111109 emission + 161110 from B)"
// let expected_c = I96F32::from_num(1_f64 / 9_f64)
// + (I96F32::from_num(2_f64 / 9_f64) * I96F32::from_num(1_f64 / 2_f64) * chk_take);
// assert!(
// (rel_stake_inc_c - expected_c).abs() // B's take on 50% CHK
// <= stake_inc_eps,
// "C should have {:?} of total stake increase; {:?}",
// expected_c,
// rel_stake_inc_c
// );

// // Check that the total stake has increased by the hardcoded emission amount
// let total_stake = stake_a + stake_b + stake_c;
// let initial_total_stake = 300_000 + 100_000 + 50_000;
// let hardcoded_emission = 1_000_000; // Define the hardcoded emission value
// assert_eq!(
// total_stake,
// initial_total_stake + hardcoded_emission - 2, // U64::MAX normalization rounding error
// "Total stake should have increased by the hardcoded emission amount"
// let eps: I96F32 = I96F32::from_num(10_000);
// assert!(
// (total_stake_new - (total_stake + hardcoded_emission)).abs() <= eps,
// "Total stake should have increased by the hardcoded emission amount {:?}",
// total_stake_new - (total_stake + hardcoded_emission)
// );
});
}
Expand Down

0 comments on commit 9eabb47

Please sign in to comment.