The mempool downloader's verification-timeout arm removed the `cancel_handles`
entry (the GHSA-65jj memory fix) with a bare `remove`, discarding the stored
`source` and skipping the shared per-peer slot release. After
`MAX_INBOUND_CONCURRENCY_PER_PEER` timed-out transactions from one source, that
source's `pending_per_peer` count stayed pinned at the cap with no tasks left,
so further queueing from it returned `FullQueue`.
Destructure the removed handle and call `release_peer_slot`, matching the
success and verifier-error arms while preserving the GHSA-65jj handle removal.
Adds a regression test that times out `MAX_INBOUND_CONCURRENCY_PER_PEER`
peer-sourced transactions and asserts a further one from the same source queues.
Motivation
Closes #10684.
The mempool downloader's verification-timeout arm (
Downloads::poll_next,zebrad/src/components/mempool/downloads.rs) removed thecancel_handlesentry with a bareremove(the GHSA-65jj-fmw8-468q memory fix) but discarded the storedsourceand never released the peer'spending_per_peerslot. AfterMAX_INBOUND_CONCURRENCY_PER_PEER(5) timed-out transactions from one source, that source's count stayed pinned at the cap with no tasks left, so further queueing from it returnedFullQueue.Solution
Route the timeout arm through the shared terminal-cleanup path (
completed_txid = Some(txid)) instead of a barecancel_handles.remove. That shared block already removes the handle (dropping the residentGossip, preserving the GHSA-65jj fix, for all sources) and callsrelease_peer_slot, so success, verifier-error, and timeout now share one uniform path.completed_txidonly drives cleanup; the returnedErr((txid, elapsed))is unchanged.Low risk, confined to mempool inbound-download accounting: no consensus, state-format, RPC, or config change; no DB format bump.
Tests
verification_timeout_releases_peer_slot(mempool/tests/vector.rs) times outMAX_INBOUND_CONCURRENCY_PER_PEERpeer-sourced transactions understart_paused, drains them, then queues another from the same source and asserts it succeeds. Fails before the fix (FullQueue), passes after; the GHSA-65jj test still passes.cargo fmt/clippyclean.Specifications & References
Preserves the GHSA-65jj-fmw8-468q memory fix.
Follow-up Work
None.
AI Disclosure
PR Checklist
type(scope): description