Skip to content

Fix #2411: finalize_all_subnet_root_dividends has unbounded iteration over all hotkeys#2425

Open
0xRozier wants to merge 5 commits intoopentensor:mainfrom
0xRozier:fix/issue-2411-unbounded-root-claimable-iteration
Open

Fix #2411: finalize_all_subnet_root_dividends has unbounded iteration over all hotkeys#2425
0xRozier wants to merge 5 commits intoopentensor:mainfrom
0xRozier:fix/issue-2411-unbounded-root-claimable-iteration

Conversation

@0xRozier
Copy link

@0xRozier 0xRozier commented Feb 13, 2026

Description

Replace unbounded iter_keys().collect::<Vec<_>>() in
finalize_all_subnet_root_dividends with StorageMap::translate(),
which iterates entries one at a time without allocating all keys in
memory. Empty RootClaimable entries are also cleaned up.

Related Issue(s)

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Other (please describe):

Breaking Change

N/A

Checklist

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have run ./scripts/fix_rust.sh to ensure my code is formatted and linted correctly
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

Screenshots (if applicable)

N/A

Additional Notes

N/A

…ividends

Replace `iter_keys().collect::<Vec<_>>()` + mutate loop with
`StorageMap::translate()` which processes entries one at a time without
collecting all hotkey keys into memory.

This also removes empty RootClaimable entries (returning None from
translate) instead of leaving behind empty BTreeMaps.

Closes opentensor#2411

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@0xRozier
Copy link
Author

0xRozier commented Feb 18, 2026

Hi, @l0r1s , @sam0x17 , @shamil-gadelshin , @JohnReedV , sorry to ping you all but can someone check this ?

@0xRozier
Copy link
Author

0xRozier commented Mar 10, 2026

@l0r1s Friendly bump — this PR fixes the unbounded memory allocation reported in #2411 by replacing collect::<Vec<_>>() with translate(). The change is small (~20 lines + tests), all checks pass, and the PR body now follows the repo template. Would appreciate a review when you get a chance. Thanks!

0xRozier and others added 3 commits March 11, 2026 20:55
Fix rustfmt closure formatting in finalize_all_subnet_root_dividends
and remove unnecessary borrows flagged by clippy::needless_borrows_for_generic_args.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The spec_version must be greater than the on-chain version (377)
for the Finney deploy check to pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@l0r1s l0r1s added the skip-cargo-audit This PR fails cargo audit but needs to be merged anyway label Mar 16, 2026

// hotkey_single's entry should be entirely gone (empty map removed).
assert!(
RootClaimable::<Test>::get(hotkey_single).is_empty(),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
RootClaimable::<Test>::get(hotkey_single).is_empty(),
!RootClaimable::<Test>::contains_key(hotkey_single),

Copy link
Collaborator

@l0r1s l0r1s left a comment

Choose a reason for hiding this comment

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

Looks good to me. Thanks.

claimable.remove(&netuid);
});
}
RootClaimable::<T>::translate::<BTreeMap<NetUid, I96F32>, _>(|_hotkey, mut claimable| {
Copy link
Contributor

Choose a reason for hiding this comment

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

For optimization purposes, translate_values is more efficient because it skips all key decoding work, so the optimal code would be something like:

RootClaimable::<T>::translate_values::<BTreeMap<NetUid, I96F32>, _>(|mut claimable| {
    claimable.remove(&netuid);
    (!claimable.is_empty()).then_some(claimable)
});

…sertion

Use translate_values instead of translate to skip key decoding work,
and assert with contains_key instead of get().is_empty() to verify
entry removal.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@0xRozier
Copy link
Author

Thanks for the reviews! I've applied both suggestions — switched to translate_values and updated the test assertion to
use contains_key.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-cargo-audit This PR fails cargo audit but needs to be merged anyway

Projects

None yet

Development

Successfully merging this pull request may close these issues.

finalize_all_subnet_root_dividends has unbounded iteration over all hotkeys

3 participants