Skip to content

Release 449: enable root weight setting with a 1/16 concentration cap - #3109

Merged
IntiTechnologies merged 20 commits into
mainfrom
release-449
Aug 25, 2026
Merged

Release 449: enable root weight setting with a 1/16 concentration cap#3109
IntiTechnologies merged 20 commits into
mainfrom
release-449

Conversation

@UnArbosFour

@UnArbosFour UnArbosFour commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Motivation

Root Reborn shipped with set_root_weights gated off (RootWeightSettingEnabled = false), so root validators could not curate their baskets. Runtime 449 opens the gate — but with a guardrail: a new concentration cap prevents a fund from recreating single-subnet concentration through basket curation.

Changes

Runtime (spec 448 → 449)

  • New hyperparameter RootWeightsCap (pallets/subtensor): the largest u16-normalized share (u16::MAX = 100%) any single destination may take of a set_root_weights vector (share = weight / sum of weights). Default 4096 (= u16::MAX / 16 + 1, ≈ 1/16), the smallest cap that admits a 16-way equal split — so a fund must spread its basket across at least 16 destinations. Stored as a map keyed by netuid; only the root entry is consulted, mirroring RootClaimableThreshold.
  • Enforcement in do_set_root_weights: vectors with any destination above the cap are rejected with the new RootWeightCapExceeded error. The check is skipped while the chain has fewer destinations than the cap demands (young chains, tests), mirroring the existing diversity-floor softening. Checked on the raw values, independent of max-upscaling.
  • New admin extrinsic AdminUtils::sudo_set_root_weights_cap (call index 105, root-only) with RootWeightsCapSet event; zero is rejected.
  • Migration enable_root_weight_setting_v1: flips RootWeightSettingEnabled on and pins RootWeightsCap[0] to 4096 explicitly in storage. Idempotent; a re-run does not clobber later governance changes.

Python SDK (11.2.0.dev0 → 11.3.0.dev0)

  • RootWeightCapExceeded mapped to limit_exceeded with full prose + remediation.
  • RootWeightSettingDisabled description updated for the post-449 world.
  • Client-side preflight in the SetRootWeights intent mirrors the chain check on the exact quantized u16 values, keyed off live RootWeightsCap[0] and network count, so violations fail before signing.
  • Bindings, golden fixture, shape corpus, and Ledger metadata-digest vector regenerated from the 449 node.

Docs / website

  • v449 release notes page: what changed, how to register on root (btcli), and how to set basket weights under the cap.
  • Generated tx/query/error reference pages regenerated (includes new sudo-set-root-weights-cap and RootWeightCapExceeded pages; line-anchor churn from the pallet edits).

Tests

  • test_set_root_weights_enforces_concentration_cap: concentrated vector rejected at 16 destinations; equal 16-way split accepted; cap relaxation to 100% accepts the concentrated vector.
  • test_set_root_weights_cap_skipped_below_required_destinations: cap skipped with 2 destinations.
  • test_migrate_enable_root_weight_setting: gate + cap set, idempotency, no clobber on re-run.
  • test_sudo_set_root_weights_cap: origin, bounds, storage, event.
  • SDK: full unit suite green (1726 passed) including regenerated corpus/golden/ledger vectors; codegen coverage/names/units/namespaces gates green; docs --check clean.

Behavioral impact

After the upgrade, root validators can call set_root_weights. At the launch cap a basket needs ≥ 16 destinations with no destination above 1/16 of the vector's summed weight. Governance can tune or effectively disable the cap via sudo_set_root_weights_cap.

@vercel

vercel Bot commented Aug 21, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
subtensor Ready Ready Preview Aug 25, 2026 6:37pm

Request Review

@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

🛡️ AI Review — Skeptic (security review)

VERDICT: VULNERABLE

VERY HIGH scrutiny: one public repository; repository write access mitigates, but commits use a different author account; no Gittensor association found; release-449 → main.

Static analysis confirms both previously reported resource-exhaustion paths remain. No AI-review trust-boundary changes were found.

Findings

Sev File Finding
HIGH pallets/subtensor/src/coinbase/root.rs:86 Manual weight adjustment omits subnet-linear execution time inline
HIGH pallets/subtensor/src/macros/dispatches.rs:2068 Direct basket deposits reopen the known state-bloat path inline

Prior-comment reconciliation

  • 1c168406: not addressed — The adjustment still assigns zero reference time to the newly introduced subnet-linear execution.
  • 7ca326d0: not addressed — The dispatcher still enables direct deposits without a storage bond or protocol-level bound on distinct caller positions.

Conclusion

The manual registration charge still omits subnet-linear execution time, and direct basket deposits still permit unbounded persistent per-caller state. Both HIGH findings block merge.


📜 Previous run (superseded)
Sev File Finding Status
HIGH pallets/subtensor/src/coinbase/root.rs:86 Manual weight adjustment omits subnet-linear execution time ➡️ Carried forward to current findings
The adjustment still assigns zero reference time to the newly introduced subnet-linear execution.
HIGH pallets/subtensor/src/macros/dispatches.rs:2068 Direct basket deposits reopen the known state-bloat path ➡️ Carried forward to current findings
The dispatcher still enables direct deposits without a storage bond or protocol-level bound on distinct caller positions.

🔍 AI Review — Auditor (domain review)

VERDICT: 👍

Gittensor association UNKNOWN; newer account, but an active repository collaborator with substantial subtensor contributions. Applied full external-contributor scrutiny.

The implementation matches the substantive PR description, and the overlapping PRs are not semantic duplicates. The new admin dispatchable has dedicated benchmark coverage and the reference runner’s measured weight.

Static review was sufficient; no builds or tests were run. git diff --check passed and git status --short was clean. cargo fmt --check --all could not run because rustup’s locked environment was read-only; Python Ruff and generated-doc checks were skipped because uv was unavailable.

Findings

No findings.

Conclusion

The prior benchmark-weight concern remains resolved. The change is coherent, documented, tested, and ready to merge.

@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: SAFE Auditor: 👍

unarbos and others added 2 commits August 24, 2026 13:23
… (v449)

Opens root basket curation for root validators: a migration flips
RootWeightSettingEnabled on and pins the new RootWeightsCap hyperparameter
to 1/16 (4096/65535), so no single destination may take more than 1/16 of a
set_root_weights vector — a fund must spread across at least 16 destinations.
Adds AdminUtils::sudo_set_root_weights_cap, the RootWeightCapExceeded error,
spec 449, SDK error taxonomy + client-side cap preflight, regenerated
bindings/fixtures/docs, and v449 release notes.

Co-authored-by: Cursor <cursoragent@cursor.com>
@unarbos unarbos changed the title Release 449 Release 449: enable root weight setting with a 1/16 concentration cap Aug 24, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review — see the sticky summary comment for the verdict and the inline comments below for specific findings.

Comment thread pallets/admin-utils/src/lib.rs Outdated
@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: SAFE Auditor: 👎

…n 449 digest vectors

Addresses the auditor finding and the cargo-test failures: gives
sudo_set_root_weights_cap its own benchmark and WeightInfo entries (estimate
pending a measured run), adds it to RootConfigCalls so the proxy call-group
coverage test passes, and re-records the bittensor-core metadata digest pin
and Ledger proof vector against the 449 golden metadata (digest cross-checked
against @polkadot-api/merkleize-metadata).

Co-authored-by: Cursor <cursoragent@cursor.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review — see the sticky summary comment for the verdict and the inline comments below for specific findings.

Comment thread pallets/admin-utils/src/weights.rs
@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: SAFE Auditor: 👎

@unarbos unarbos added the run-benchmarks run benchmarks label Aug 24, 2026
Replaces the placeholder estimate with the value measured on the reference
Benchmarking runner by the validate-benchmarks run for this PR
(4_916_000 ref-time, 0 reads / 1 write, steps 50 / repeat 20).

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: SAFE Auditor: 👍

Ungate stake_into_basket and wire btcli root subscribe to it so TAO
deploys into the fund and credits β immediately. Adds the StakeIntoBasket
intent, index-spliced fund list / claim / weights porcelain, and the
V449 Curated Beta release notes.

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: SAFE Auditor: 👍

Co-authored-by: Cursor <cursoragent@cursor.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review — see the sticky summary comment for the verdict and the inline comments below for specific findings.

Comment thread pallets/subtensor/src/macros/dispatches.rs
@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: VULNERABLE

Co-authored-by: Cursor <cursoragent@cursor.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review — see the sticky summary comment for the verdict and the inline comments below for specific findings.

Comment thread pallets/subtensor/src/macros/dispatches.rs

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review — see the sticky summary comment for the verdict and the inline comments below for specific findings.

Comment thread pallets/subtensor/src/macros/dispatches.rs
@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: VULNERABLE

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review — see the sticky summary comment for the verdict and the inline comments below for specific findings.

Comment thread pallets/subtensor/src/macros/dispatches.rs
Comment thread pallets/subtensor/src/coinbase/root.rs
@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: VULNERABLE

The SDK still said a full senate evicts the least-staked member. Name
ImmunityPeriod, regenerate the tx page and catalog, and drop copied
7200 / τ1 from the v449 register step.

Co-authored-by: Cursor <cursoragent@cursor.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review — see the sticky summary comment for the verdict and the inline comments below for specific findings.

Comment thread pallets/subtensor/src/coinbase/root.rs
Comment thread pallets/subtensor/src/macros/dispatches.rs
@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: VULNERABLE

Lock takeover left protocol childkeys pointing at the former owner, so
prune cleanup skipped them and that owner kept inherited stake. Move
the edge to the new owner, match any single full-proportion child on
prune, and clear the same edges when sudo trims root seats.

Co-authored-by: Cursor <cursoragent@cursor.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review — see the sticky summary comment for the verdict and the inline comments below for specific findings.

Comment thread pallets/subtensor/src/coinbase/root.rs
Comment thread pallets/subtensor/src/macros/dispatches.rs
@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: VULNERABLE

move_stake treats AlphaBalance::MAX as origin stake after a batched claim,
so the follow-up includes flushed basket deposits. Docs add the beta-token
concept; CLI drops the stale subscribe and show aliases.

Co-authored-by: Cursor <cursoragent@cursor.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review — see the sticky summary comment for the verdict and the inline comments below for specific findings.

Comment thread pallets/subtensor/src/coinbase/root.rs
Comment thread pallets/subtensor/src/macros/dispatches.rs
@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: VULNERABLE

A full senate of immune seats made bench_root_register fail with
NoNeuronIdAvailable. Set immunity to 0 in the setup so the prune path
can run. Refresh move-lock after the lock.rs owner-retarget insert.

Co-authored-by: Cursor <cursoragent@cursor.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review — see the sticky summary comment for the verdict and the inline comments below for specific findings.

Comment thread pallets/subtensor/src/coinbase/root.rs
Comment thread pallets/subtensor/src/macros/dispatches.rs
@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: VULNERABLE

root_register now declares a TotalNetworks-scaled DbWeight term so prune cleanup and per-subnet persist are not free. stake_into_basket only accepts a live root uid, so entitlement state cannot grow past the root seat cap.

Co-authored-by: Cursor <cursoragent@cursor.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review — see the sticky summary comment for the verdict and the inline comments below for specific findings.

Comment on lines +79 to +86
<T as crate::pallet::Config>::WeightInfo::root_register()
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().reads(persists.saturating_mul(READS_PER_PERSIST)))
.saturating_add(T::DbWeight::get().writes(persists.saturating_mul(WRITES_PER_PERSIST)))
.saturating_add(Weight::from_parts(
0,
persists.saturating_mul(PROOF_PER_PERSIST),
))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[HIGH] Manual weight adjustment omits subnet-linear execution time

root_register now performs an auto-parent persistence pass for every subnet, and potentially another cleanup pass when pruning. This adjustment charges database operations and proof size but adds zero ref-time for the per-subnet iteration, comparisons, allocations, and persistence logic. An attacker can therefore still submit registration work whose execution time grows with TotalNetworks without paying for that CPU cost. Replace this estimate with a benchmarked WeightInfo function parameterized by the relevant bounds; until then, keep the feature gated.

Comment thread pallets/subtensor/src/macros/dispatches.rs
@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: VULNERABLE

CI fmt failed on alphabetized imports, and root_register needs the WeightInfo trait imported to call the generated weight.

Co-authored-by: Cursor <cursoragent@cursor.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review — see the sticky summary comment for the verdict and the inline comments below for specific findings.

Comment thread pallets/subtensor/src/coinbase/root.rs
Comment thread pallets/subtensor/src/macros/dispatches.rs
@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI review updated — Skeptic: VULNERABLE

@IntiTechnologies
IntiTechnologies merged commit 71136ad into main Aug 25, 2026
99 of 101 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants