First of all, this is caused by the TODO comment below, just put this PR here to ask some questions about this TODO since I'm not very familiar with all the use pattern of lockedpool:
From AI analysis, the arena.size() is related with the number of wallets, and 10000 wallets causes about 10 arenas, is this a real production scenario in practice? Do we really has to keep this TODO there?
// TODO we can do better than this linear search by keeping a map
// of arena extents to arena, and looking up the address.
Mirror the existing chunks_used / chunks_free fields by adding a sibling arena_count field that exposes LockedPool's arenas.size() directly. All three are internal implementation details of the secure-memory pool surfaced to operators and diagnostic tooling.
Beyond observability, arena_count is also performance-relevant. As the existing TODO in LockedPool::free() points out:
// TODO we can do better than this linear search by keeping a map
// of arena extents to arena, and looking up the address.
LockedPool::free() walks the arena list linearly on every secure deallocation. While this is fine for the common case of a single arena, the cost scales with arena count. Exposing arena_count gives operators and developers a way to see when the pool has grown past that hot path's sweet spot, without having to estimate it from total / ARENA_SIZE (which is wrong when the first arena is capped by RLIMIT_MEMLOCK and misleading when memory is fragmented).
Includes unit-test coverage in allocator_tests (mock pool, before and after multi-arena allocation) and a functional-test assertion in rpc_misc.py.