Skip to content

fix: remove unbounded collect in finalize_all_subnet_root_dividends#2456

Open
ionodeionode wants to merge 1 commit intoopentensor:mainfrom
ionodeionode:fix/unbounded-root-dividends-cleanup
Open

fix: remove unbounded collect in finalize_all_subnet_root_dividends#2456
ionodeionode wants to merge 1 commit intoopentensor:mainfrom
ionodeionode:fix/unbounded-root-dividends-cleanup

Conversation

@ionodeionode
Copy link

Summary

Fixes #2411

Problem

finalize_all_subnet_root_dividends collects all hotkey keys from RootClaimable storage into a Vec before iterating and mutating each one:

let hotkeys = RootClaimable::<T>::iter_keys().collect::<Vec<_>>();

This is O(N) in both reads and memory where N is the total number of hotkeys with any root claimable balance. Since this function is called from do_dissolve_network (an extrinsic), with thousands of hotkeys this could:

  • Exceed block weight limits
  • Cause high memory usage from the collect::<Vec<_>>()

Solution

Replace the unbounded `collect()" with a lazy iterator drain:

let mut cursor = RootClaimable::<T>::iter_keys();
while let Some(hotkey) = cursor.next() {
    RootClaimable::<T>::mutate(&hotkey, |claimable| {
        claimable.remove(&netuid);
    });
}

This processes each hotkey without materializing the full key set in memory. Substrate's storage iterators are safe to use while mutating other keys of the same map (cursor invalidation only occurs when the current key is removed, which we don't do here — we only mutate the value).

Impact

  • Memory: O(1) instead of O(N)
  • Behavior: Functionally identical — same keys are processed, same mutations applied
  • Weight: The actual computation remains the same, but avoids the risk of exceeding block limits due to memory allocation

…pentensor#2411)

Replace the unbounded Vec collect with a lazy iterator drain to avoid
O(N) memory allocation when cleaning up RootClaimable entries during
subnet dissolution. This prevents potential block weight limit
violations and high memory usage with large numbers of hotkeys.

The storage iterator cursor remains valid while mutating other keys
in the same map, so we can safely process each hotkey without
materializing the full key set in memory.

Closes opentensor#2411
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.

finalize_all_subnet_root_dividends has unbounded iteration over all hotkeys

1 participant