Skip to content

finalize_all_subnet_root_dividends has unbounded iteration over all hotkeys #2411

@ppolewicz

Description

@ppolewicz

In pallets/subtensor/src/staking/claim_root.rs, the finalize_all_subnet_root_dividends function collects ALL hotkeys from RootClaimable storage into memory, then mutates each one:

pub fn finalize_all_subnet_root_dividends(netuid: NetUid) {
    let hotkeys = RootClaimable::<T>::iter_keys().collect::<Vec<_>>();
    for hotkey in hotkeys.iter() {
        RootClaimable::<T>::mutate(hotkey, |claimable| {
            claimable.remove(&netuid);
        });
    }
    let _ = RootClaimed::<T>::clear_prefix((netuid,), u32::MAX, None);
}

This is O(N) reads + O(N) writes where N is the total number of hotkeys with any root claimable balance. This function is called from do_dissolve_network, which is an extrinsic. With thousands of hotkeys, this could:

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

The weight annotation on do_dissolve_network may not account for this unbounded iteration.

Suggested fix: Consider using RootClaimable::iter_keys() without collecting, or implementing a bounded/paginated cleanup, or using a different storage layout that allows per-netuid cleanup without iterating all hotkeys.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions