Open
Conversation
Add EffectiveRootProp StorageMap (NetUid -> U64F64) computed during distribute_dividends_and_incentives() as: sum(RootAlphaDividendsPerSubnet[netuid]) / (sum(AlphaDividendsPerSubnet[netuid]) + sum(RootAlphaDividendsPerSubnet[netuid])) This measures the proportion of dividends on a subnet flowing to root stakers, stored per-subnet for efficient single-read access during emission preparation. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When enabled, multiplies each subnet's emission share by its stored EffectiveRootProp value and re-normalizes. This allows root governance to weight emission toward subnets with higher root staker participation. - Storage: EffectiveRootPropEmissionScaling (bool, default false) - Admin extrinsic: sudo_set_effective_root_prop_emission_scaling (call_index 88) - Helper: normalize_shares(), apply_effective_root_prop_scaling() - Event: EffectiveRootPropEmissionScalingApplied Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Only the top proportion of subnets (ranked by emission share) receive emission. Default is 50% (5000 basis points). Remaining subnets have shares zeroed and redistributed to top subnets. Uses ceil(count * proportion / 10000) so a single subnet always qualifies (ceil(1 * 0.5) = 1). - Storage: EmissionTopSubnetProportion (u16, default 5000) - Admin extrinsic: sudo_set_emission_top_subnet_proportion (call_index 89) - Helpers: zero_and_redistribute_bottom_shares(), apply_top_subnet_proportion_filter() - Event: EmissionTopSubnetFilterApplied Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds absolute cap on the number of subnets that can receive emission. Default is 0 (disabled). When set to N > 0, only the top N subnets by share receive emission; the rest are zeroed and redistributed. Applied after proportion filter so the stricter constraint wins. - Storage: EmissionTopSubnetAbsoluteLimit (u16, default 0) - Admin extrinsic: sudo_set_emission_top_subnet_absolute_limit (call_index 90) - Helper: apply_top_subnet_absolute_limit() - Event: EmissionAbsoluteLimitApplied - Fixed 5 existing coinbase tests to disable proportion filter Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace slice indexing `sorted[top_k..]` with `.get(top_k..)` to avoid potential panic (clippy::indexing_slicing) - Replace `(total as u64) * (proportion as u64)` with `.saturating_mul()` to avoid arithmetic side effects (clippy::arithmetic_side_effects) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…tests Remove workaround EmissionTopSubnetProportion::<Test>::set(10000) from existing coinbase tests that was needed when default was 50%. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…efault Remove EffectiveRootPropEmissionScalingApplied, EmissionTopSubnetFilterApplied, and EmissionAbsoluteLimitApplied events and their test assertions. Update proportion filter tests to explicitly set 5000 (50%) since default is now 100%. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When subnets tie at the k-th position, all tied subnets are now kept rather than arbitrarily zeroing some. Uses a threshold-based approach: find the share value at position top_k-1 and keep all entries >= that value, avoiding deterministic bias toward lower NetUIDs. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use min(EffectiveRootProp, RootProp) when scaling emission shares. This prevents a subnet from inflating its EffectiveRootProp above the configured RootProp by disabling alpha validators, which would cause all dividends to flow to root and artificially boost the scaling factor. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
shamil-gadelshin
requested changes
Feb 3, 2026
Collaborator
shamil-gadelshin
left a comment
There was a problem hiding this comment.
The tests don't cover the whole run_coinbase. There are some concerns about the calculation order and other minor issues.
- Remove log::debug! statements from admin extrinsics - Change EffectiveRootProp storage type from U64F64 to U96F32 to match context types and avoid unnecessary conversions in run_coinbase - Change EmissionTopSubnetProportion from u16 basis points (0-10000) to U64F64 fractional range (0.0-1.0) - Change EmissionTopSubnetAbsoluteLimit from u16 ValueQuery (0=disabled) to u16 OptionQuery (None=disabled) for idiomatic representation - Fix empty array iteration guard in zero_and_redistribute_bottom_shares - Add detailed comment explaining ERP timing (computed for next round) and exploitation mitigation via min(EffectiveRootProp, RootProp) - Update all tests for new storage types Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Three tests covering 2 subnets with 6 neurons each (owner, major/minor
root validators, major/minor subnet validators, miner):
1. test_basic_all_validators_set_weights_to_miners (price=0.6)
- root_sell_flag=true, root validators earn dividends
- Verifies miner incentive, validator dividend proportionality,
root validator earnings, owner cut (18%), incentive vector
2. test_no_root_sell_all_validators_set_weights_to_miners (price=0.5)
- root_sell_flag=false, root validators earn 0
- Same structure but verifies root channel is unfunded
3. test_basic_major_root_no_weights (price=0.6)
- Major root validator (5.55M TAO) does NOT set weights
- Verifies major root earns 0 while minor root still earns
Test structure: 5 blocks total (setup at block 1, epochs at blocks 3+5),
SN1 only with tempo=1, TaoWeight=0.18, SubnetOwnerCut=18%.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* wide-scope-dividend-test: (44 commits) Add wide_scope_dividend test suite for emission distribution Fix sudo_set_max_allowed_uids benchmark raise fee on `set_pending_childkey_cooldown` less sleep catch error with wrong nonce bump version add transaction replacement test case Fix try-runtime build bump version bump psdk/frontier with patch to prevent node panic Spec bump Spec bump auto-update benchmark weights bump frontier hash 2 by removing comment bump spec version bump Cargo toml frontier deps Bump spec version Add SubnetBuyback event format code test is ok ...
EffectiveRootProp now multiplies the raw dividend ratio by a utilization factor: active_root_stake / total_root_stake. This ensures subnets where most root stake is idle (validators not setting weights) get a much lower EffectiveRootProp than subnets where all root stake is active. Also enables EffectiveRootPropEmissionScaling in wide_scope_dividend tests and updates all assertions accordingly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Change compute_and_store_effective_root_prop to use dividend-efficiency metric instead of binary active/inactive. Returns U96F32 utilization. - Move ERP computation from distribute_dividends_and_incentives to distribute_emission; add utilization scaling (< 1.0) and hard cap (< 0.5 recycles all root dividends, sets ERP to 0). - Add 555k unstaked TAO to test setup_test(). - Add 3 new tests: unstaked_tao_does_not_affect_utilization, half_weights_to_validator, half_weights_no_minor_root. - Update existing test assertions for hard cap behavior. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Skip hard cap and scaling when root_alpha_dividends is empty (e.g. root_sell_flag=false). Fixes tests where validators with root stake but no root dividend emission were incorrectly having their alpha dividends recycled. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
sudo_set_effective_root_prop_emission_scaling was assigned the same call_index(88) as sudo_set_max_mechanism_count. Reassign to 91. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Verifies that when root validators stop setting weights on a subnet, the hard cap triggers (ERP=0, root dividends recycled), but the subnet recovers once root validators resume validating (ERP>0, dividends flow). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Refactors the inline utilization scaling logic from distribute_emission into two testable functions: - get_root_dividend_fraction: computes root stake fraction of dividends - apply_utilization_scaling: applies hard cap / scaling to dividend maps Adds 10 unit tests covering: no root stake, no alpha stake, mixed stake, high tao_weight, full utilization, no root dividends, partial scaling, hard cap, boundary (0.5), and just-below-boundary (0.4999). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reads on-chain state to compute dividend-efficiency utilization per subnet and simulate hard cap / scaling. Supports --debug mode for per-hotkey breakdown of a single subnet. Filters root dividends to registered-only hotkeys (pre-delegation) to match the Rust utilization computation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This PR introduces a system to control which subnets receive TAO emission. Previously, all eligible subnets received emission proportional to their "share." Now, three optional filters can reduce or zero-out emission for lower-performing subnets.
New metric: EffectiveRootProp
Each subnet distributes dividends to two groups: alpha stakers (staked directly on subnet) and root stakers (staked on root network). EffectiveRootProp measures what fraction flows to root stakers:
This is computed during each epoch and stored per-subnet.
Filters
Three emission filters are applied sequentially in
get_subnet_block_emissions():After each filter, shares are re-normalized to sum to 1.0. Subnets that get filtered out receive zero emission.
But why?
We had a couple of problems since Taoflow emission schedule was deployed:
btcli stake movecoupled with randomly chosen "miner" (they are self-mining, the subnet doesn't really do anything). We think they can safely inflow to increase emissions and we want to mitigate this risk.It looks like this can be fixed with EffectiveRootProp. The filters were added because they were requested and the change was on the way.
Type of Change
Checklist
./scripts/fix_rust.shto ensure my code is formatted and linted correctlyOriginal prompt
Use Plan subagent to write a step-by-step detailed development plan, which then after a final confirmation from me you'll go implement in the main agent by following the task list until it is completed. Use a fresh sonnet-based subagent for every subfeature, but do not run agents in parallel or you'll run out of memory and disk space. Work on
taoflow2 branch which starts off origin/devnet-ready. Run scripts/fix_rust.sh after every commit. Remember about checking in tests that events indicating key information are emitted. Rather than long methods use functions that have descriptive names and that are easy to test.The changes we do today will focus on
get_subnet_block_emissions() in src/coinbase/subnet_emissions.rs.Add
EffectiveRootPropEmissionScaling root hyperparameter which will allow root to enable multiplication of shares by EffectiveRootProp, which for a given netuid is sum(RootAlphaDividendsPerSubnet[netuid]) / (sum(AlphaDividendsPerSubnet[netuid]) + sum(RootAlphaDividendsPerSubnet[netuid]) (document it as such), though it should be calculated during epoch near where RootAlphaDividendsPerSubnet is being written and stored in the global vector, so that during emission preparation reading EffectiveRootProp requires a single db get for all subnets.Add root hyperparameter to ensure only a certain proportion (by default 50%) of subnets get any emission, while the rest is redistributed to other subnets (so shares must be zeroed except topk and normalized). Round up so that a single subnet counts as in top 50%.
Add another hyperparameter to limit the number of subnets which receive emission to an absolute number (there is no default and this means by default there will be no absolute limit).
AI reviewers