Skip to content

Commit c194de4

Browse files
author
unconst
committed
Merge branch 'feat/rao-2025-01' of github.com:opentensor/subtensor into feat/rao-2025-01
2 parents f778f91 + 9eabb47 commit c194de4

File tree

2 files changed

+157
-98
lines changed

2 files changed

+157
-98
lines changed

pallets/subtensor/src/coinbase/run_coinbase.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,11 @@ impl<T: Config> Pallet<T> {
521521
.saturating_div(I96F32::from_num(u16::MAX));
522522
// NOTE: Only the validation emission should be split amongst parents.
523523

524+
// Reserve childkey take
525+
let child_emission_take: I96F32 =
526+
childkey_take_proportion.saturating_mul(I96F32::from_num(validating_emission));
527+
let remaining_emission: I96F32 = validating_emission.saturating_sub(child_emission_take);
528+
524529
// Initialize variables to track emission distribution
525530
let mut to_parents: u64 = 0;
526531

@@ -577,29 +582,24 @@ impl<T: Config> Pallet<T> {
577582
let emission_factor: I96F32 = contribution
578583
.checked_div(total_contribution)
579584
.unwrap_or(I96F32::from_num(0));
580-
let total_emission: u64 =
581-
(validating_emission.saturating_mul(emission_factor)).to_num::<u64>();
582-
583-
// Reserve childkey take
584-
let child_emission_take: u64 = childkey_take_proportion
585-
.saturating_mul(I96F32::from_num(total_emission))
586-
.to_num::<u64>();
587-
let parent_total_emission = total_emission.saturating_sub(child_emission_take);
585+
let parent_emission: u64 =
586+
(remaining_emission.saturating_mul(emission_factor)).to_num::<u64>();
588587

589588
// Add the parent's emission to the distribution list
590-
dividend_tuples.push((parent, parent_total_emission));
589+
dividend_tuples.push((parent, parent_emission));
591590

592591
// Keep track of total emission distributed to parents
593-
to_parents = to_parents.saturating_add(parent_total_emission);
592+
to_parents = to_parents.saturating_add(parent_emission);
594593
}
595594
// Calculate the final emission for the hotkey itself.
596595
// This includes the take left from the parents and the self contribution.
597-
let final_hotkey_emission = validating_emission
596+
let child_emission = remaining_emission
597+
.saturating_add(child_emission_take)
598598
.to_num::<u64>()
599599
.saturating_sub(to_parents);
600600

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

604604
dividend_tuples
605605
}

pallets/subtensor/src/tests/children.rs

Lines changed: 145 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#![allow(clippy::arithmetic_side_effects)]
44
use super::mock::*;
55
use frame_support::{assert_err, assert_noop, assert_ok};
6+
use substrate_fixed::types::I96F32;
67

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

32733274
// let netuid: u16 = 1;
32743275
// add_network(netuid, 1, 0);
3276+
// // Set owner cut to 0
3277+
// SubtensorModule::set_subnet_owner_cut(0_u16);
32753278

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

32893292
// // Add initial stakes
3290-
// SubtensorModule::add_balance_to_coldkey_account(&coldkey_a, 300_000);
3291-
// SubtensorModule::add_balance_to_coldkey_account(&coldkey_b, 100_000);
3292-
// SubtensorModule::add_balance_to_coldkey_account(&coldkey_c, 50_000);
3293+
// SubtensorModule::add_balance_to_coldkey_account(&coldkey_a, 1_000);
3294+
// SubtensorModule::add_balance_to_coldkey_account(&coldkey_b, 1_000);
3295+
// SubtensorModule::add_balance_to_coldkey_account(&coldkey_c, 1_000);
32933296

3294-
// SubtensorModule::increase_stake_on_coldkey_hotkey_account(&coldkey_a, &hotkey_a, 300_000);
3295-
// SubtensorModule::increase_stake_on_coldkey_hotkey_account(&coldkey_b, &hotkey_b, 100_000);
3296-
// SubtensorModule::increase_stake_on_coldkey_hotkey_account(&coldkey_c, &hotkey_c, 50_000);
3297+
// // Swap to alpha
3298+
// let total_tao: I96F32 = I96F32::from_num(300_000 + 100_000 + 50_000);
3299+
// let total_alpha: I96F32 = I96F32::from_num(SubtensorModule::swap_tao_for_alpha(
3300+
// netuid,
3301+
// total_tao.saturating_to_num::<u64>(),
3302+
// ));
3303+
3304+
// // Set the stakes directly
3305+
// // This avoids needing to swap tao to alpha, impacting the initial stake distribution.
3306+
// SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet(
3307+
// &hotkey_a,
3308+
// &coldkey_a,
3309+
// netuid,
3310+
// (total_alpha * I96F32::from_num(300_000) / total_tao).saturating_to_num::<u64>(),
3311+
// );
3312+
// SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet(
3313+
// &hotkey_b,
3314+
// &coldkey_b,
3315+
// netuid,
3316+
// (total_alpha * I96F32::from_num(100_000) / total_tao).saturating_to_num::<u64>(),
3317+
// );
3318+
// SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet(
3319+
// &hotkey_c,
3320+
// &coldkey_c,
3321+
// netuid,
3322+
// (total_alpha * I96F32::from_num(50_000) / total_tao).saturating_to_num::<u64>(),
3323+
// );
3324+
3325+
// // Get old stakes
3326+
// let stake_a: u64 = SubtensorModule::get_total_stake_for_hotkey(&hotkey_a);
3327+
// let stake_b: u64 = SubtensorModule::get_total_stake_for_hotkey(&hotkey_b);
3328+
// let stake_c: u64 = SubtensorModule::get_total_stake_for_hotkey(&hotkey_c);
3329+
3330+
// let total_stake: I96F32 = I96F32::from_num(stake_a + stake_b + stake_c);
3331+
3332+
// // Assert initial stake is correct
3333+
// let rel_stake_a = I96F32::from_num(stake_a) / total_tao;
3334+
// let rel_stake_b = I96F32::from_num(stake_b) / total_tao;
3335+
// let rel_stake_c = I96F32::from_num(stake_c) / total_tao;
3336+
3337+
// log::info!("rel_stake_a: {:?}", rel_stake_a); // 0.6666 -> 2/3
3338+
// log::info!("rel_stake_b: {:?}", rel_stake_b); // 0.2222 -> 2/9
3339+
// log::info!("rel_stake_c: {:?}", rel_stake_c); // 0.1111 -> 1/9
3340+
// assert_eq!(rel_stake_a, I96F32::from_num(300_000) / total_tao);
3341+
// assert_eq!(rel_stake_b, I96F32::from_num(100_000) / total_tao);
3342+
// assert_eq!(rel_stake_c, I96F32::from_num(50_000) / total_tao);
32973343

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

3305-
// step_block(2);
3306-
3307-
// // Set weights
3308-
// let origin = RuntimeOrigin::signed(hotkey_a);
3309-
// let uids: Vec<u16> = vec![0, 1, 2]; // UIDs for hotkey_a, hotkey_b, hotkey_c
3310-
// let values: Vec<u16> = vec![65535, 65535, 65535]; // Set equal weights for all hotkeys
3311-
// let version_key = SubtensorModule::get_weights_version_key(netuid);
3351+
// // Set CHK take rate to 1/9
3352+
// let chk_take: I96F32 = I96F32::from_num(1_f64 / 9_f64);
3353+
// let chk_take_u16: u16 = (chk_take * I96F32::from_num(u16::MAX)).saturating_to_num::<u16>();
3354+
// ChildkeyTake::<Test>::insert(hotkey_b, netuid, chk_take_u16);
3355+
// ChildkeyTake::<Test>::insert(hotkey_c, netuid, chk_take_u16);
33123356

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

3316-
// assert_ok!(SubtensorModule::set_weights(
3317-
// origin,
3318-
// netuid,
3319-
// uids,
3320-
// values,
3321-
// version_key
3322-
// ));
3360+
// let hardcoded_emission: I96F32 = I96F32::from_num(1_000_000); // 1 million (adjust as needed)
33233361

3324-
// // Run epoch with a hardcoded emission value
3325-
// let hardcoded_emission: u64 = 1_000_000; // 1 million (adjust as needed)
33263362
// let hotkey_emission: Vec<(U256, u64, u64)> =
3327-
// SubtensorModule::epoch(netuid, hardcoded_emission);
3328-
3329-
// // Process the hotkey emission results
3330-
// for (hotkey, mining_emission, validator_emission) in hotkey_emission {
3331-
// SubtensorModule::accumulate_hotkey_emission(
3332-
// &hotkey,
3333-
// netuid,
3334-
// validator_emission,
3335-
// mining_emission,
3336-
// );
3337-
// }
3338-
3339-
// // Log PendingEmission Tuple for a, b, c
3340-
// let pending_emission_a = SubtensorModule::get_pending_hotkey_emission(&hotkey_a);
3341-
// let pending_emission_b = SubtensorModule::get_pending_hotkey_emission(&hotkey_b);
3342-
// let pending_emission_c = SubtensorModule::get_pending_hotkey_emission(&hotkey_c);
3343-
3344-
// log::info!("Pending Emission for A: {:?}", pending_emission_a);
3345-
// log::info!("Pending Emission for B: {:?}", pending_emission_b);
3346-
// log::info!("Pending Emission for C: {:?}", pending_emission_c);
3347-
3348-
// // Assert that pending emissions are non-zero
3349-
// // A's pending emission: 2/3 of total emission (due to having 2/3 of total stake)
3363+
// SubtensorModule::epoch(netuid, hardcoded_emission.saturating_to_num::<u64>());
3364+
// log::info!("hotkey_emission: {:?}", hotkey_emission);
3365+
// let total_emission: I96F32 = hotkey_emission
3366+
// .iter()
3367+
// .map(|(_, _, emission)| I96F32::from_num(*emission))
3368+
// .sum();
3369+
3370+
// // Verify emissions match expected from CHK arrangements
3371+
// let em_eps: I96F32 = I96F32::from_num(1e-4); // 4 decimal places
3372+
// // A's pending emission:
33503373
// assert!(
3351-
// pending_emission_a == 666667,
3352-
// "A should have pending emission of 2/3 of total emission"
3374+
// ((I96F32::from_num(hotkey_emission[0].2) / total_emission) -
3375+
// I96F32::from_num(2_f64 / 3_f64 * 1_f64 / 2_f64)).abs() // 2/3 * 1/2 = 1/3; 50% -> B
3376+
// <= em_eps,
3377+
// "A should have pending emission of 1/3 of total emission"
33533378
// );
3354-
// // B's pending emission: 2/9 of total emission (1/3 of A's emission + 1/3 of total emission)
3379+
// // B's pending emission:
33553380
// assert!(
3356-
// pending_emission_b == 222222,
3357-
// "B should have pending emission of 2/9 of total emission"
3381+
// ((I96F32::from_num(hotkey_emission[1].2) / total_emission) -
3382+
// (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
3383+
// <= em_eps,
3384+
// "B should have pending emission of 4/9 of total emission"
33583385
// );
3359-
// // C's pending emission: 1/9 of total emission (1/2 of B's emission)
3386+
// // C's pending emission:
33603387
// assert!(
3361-
// pending_emission_c == 111109,
3388+
// ((I96F32::from_num(hotkey_emission[2].2) / total_emission) -
3389+
// (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
3390+
// <= em_eps,
33623391
// "C should have pending emission of 1/9 of total emission"
33633392
// );
33643393

3365-
// SubtensorModule::set_hotkey_emission_tempo(10);
3366-
3367-
// step_block(10 + 1);
3368-
// // Retrieve the current stake for each hotkey on the subnet
3369-
// let stake_a: u64 = SubtensorModule::get_stake_for_hotkey_on_subnet(&hotkey_a, netuid);
3370-
// let stake_b: u64 = SubtensorModule::get_stake_for_hotkey_on_subnet(&hotkey_b, netuid);
3371-
// let stake_c: u64 = SubtensorModule::get_stake_for_hotkey_on_subnet(&hotkey_c, netuid);
3372-
3373-
// // Log the current stakes for debugging purposes
3374-
// log::info!("Stake for hotkey A: {:?}", stake_a);
3375-
// log::info!("Stake for hotkey B: {:?}", stake_b);
3376-
// log::info!("Stake for hotkey C: {:?}", stake_c);
3377-
3378-
// // Assert that the stakes have been updated correctly after emission distribution
3379-
// assert_eq!(
3380-
// stake_a, 483334,
3381-
// "A's stake should be 483334 (initial 300_000 + 666667 emission - 483333 given to B)"
3394+
// // Run epoch with a hardcoded emission value
3395+
// SubtensorModule::run_coinbase(hardcoded_emission);
3396+
3397+
// // Log new stake
3398+
// let stake_a_new: u64 = SubtensorModule::get_total_stake_for_hotkey(&hotkey_a);
3399+
// let stake_b_new: u64 = SubtensorModule::get_total_stake_for_hotkey(&hotkey_b);
3400+
// let stake_c_new: u64 = SubtensorModule::get_total_stake_for_hotkey(&hotkey_c);
3401+
// let total_stake_new: I96F32 = I96F32::from_num(stake_a_new + stake_b_new + stake_c_new);
3402+
// log::info!("Stake for hotkey A: {:?}", stake_a_new);
3403+
// log::info!("Stake for hotkey B: {:?}", stake_b_new);
3404+
// log::info!("Stake for hotkey C: {:?}", stake_c_new);
3405+
3406+
// let stake_inc_a: u64 = stake_a_new - stake_a;
3407+
// let stake_inc_b: u64 = stake_b_new - stake_b;
3408+
// let stake_inc_c: u64 = stake_c_new - stake_c;
3409+
// let total_stake_inc: I96F32 = total_stake_new - total_stake;
3410+
// log::info!("Stake increase for hotkey A: {:?}", stake_inc_a);
3411+
// log::info!("Stake increase for hotkey B: {:?}", stake_inc_b);
3412+
// log::info!("Stake increase for hotkey C: {:?}", stake_inc_c);
3413+
// log::info!("Total stake increase: {:?}", total_stake_inc);
3414+
// let rel_stake_inc_a = I96F32::from_num(stake_inc_a) / total_stake_inc;
3415+
// let rel_stake_inc_b = I96F32::from_num(stake_inc_b) / total_stake_inc;
3416+
// let rel_stake_inc_c = I96F32::from_num(stake_inc_c) / total_stake_inc;
3417+
// log::info!("rel_stake_inc_a: {:?}", rel_stake_inc_a);
3418+
// log::info!("rel_stake_inc_b: {:?}", rel_stake_inc_b);
3419+
// log::info!("rel_stake_inc_c: {:?}", rel_stake_inc_c);
3420+
3421+
// // Verify the final stake distribution
3422+
// let stake_inc_eps: I96F32 = I96F32::from_num(1e-4); // 4 decimal places
3423+
// // Each child has chk_take take
3424+
3425+
// let expected_a = I96F32::from_num(2_f64 / 3_f64)
3426+
// * (I96F32::from_num(1_f64) - (I96F32::from_num(1_f64 / 2_f64) * chk_take));
3427+
// assert!(
3428+
// (rel_stake_inc_a - expected_a).abs() // B's take on 50% CHK
3429+
// <= stake_inc_eps,
3430+
// "A should have {:?} of total stake increase; {:?}",
3431+
// expected_a,
3432+
// rel_stake_inc_a
33823433
// );
3383-
// assert_eq!(
3384-
// stake_b, 644445,
3385-
// "B's stake should be 644445 (initial 100_000 + 222222 emission + 483333 from A - 161110 given to C)"
3434+
// let expected_b = I96F32::from_num(2_f64 / 9_f64)
3435+
// * (I96F32::from_num(1_f64) - (I96F32::from_num(1_f64 / 2_f64) * chk_take))
3436+
// + I96F32::from_num(2_f64 / 3_f64) * (I96F32::from_num(1_f64 / 2_f64) * chk_take);
3437+
// assert!(
3438+
// (rel_stake_inc_b - expected_b).abs() // C's take on 50% CHK + take from A
3439+
// <= stake_inc_eps,
3440+
// "B should have {:?} of total stake increase; {:?}",
3441+
// expected_b,
3442+
// rel_stake_inc_b
33863443
// );
3387-
// assert_eq!(
3388-
// stake_c, 322219,
3389-
// "C's stake should be 322219 (initial 50_000 + 111109 emission + 161110 from B)"
3444+
// let expected_c = I96F32::from_num(1_f64 / 9_f64)
3445+
// + (I96F32::from_num(2_f64 / 9_f64) * I96F32::from_num(1_f64 / 2_f64) * chk_take);
3446+
// assert!(
3447+
// (rel_stake_inc_c - expected_c).abs() // B's take on 50% CHK
3448+
// <= stake_inc_eps,
3449+
// "C should have {:?} of total stake increase; {:?}",
3450+
// expected_c,
3451+
// rel_stake_inc_c
33903452
// );
33913453

3392-
// // Check that the total stake has increased by the hardcoded emission amount
3393-
// let total_stake = stake_a + stake_b + stake_c;
3394-
// let initial_total_stake = 300_000 + 100_000 + 50_000;
3395-
// let hardcoded_emission = 1_000_000; // Define the hardcoded emission value
3396-
// assert_eq!(
3397-
// total_stake,
3398-
// initial_total_stake + hardcoded_emission - 2, // U64::MAX normalization rounding error
3399-
// "Total stake should have increased by the hardcoded emission amount"
3454+
// let eps: I96F32 = I96F32::from_num(10_000);
3455+
// assert!(
3456+
// (total_stake_new - (total_stake + hardcoded_emission)).abs() <= eps,
3457+
// "Total stake should have increased by the hardcoded emission amount {:?}",
3458+
// total_stake_new - (total_stake + hardcoded_emission)
34003459
// );
34013460
});
34023461
}

0 commit comments

Comments
 (0)