#36578 p2p: clean up a 1p1c package child that is already in the mempool
| Reviewability | Reviews | Agreement | Size | ||||
|---|---|---|---|---|---|---|---|
| #36578 p2p: clean up a 1p1c package child that is already in the mempool | Ready | 1 (+1) | Strong | 8 + 25 tests | |||
|
|
|
| ||||
Reviewability: ReadyStalePaused Agreement: StrongPositivePositive w/ caveatsNeutralMildDisputedBlockedCrickets Reviews: current code-review ACKs, then (+stale ACKs) and -NACKs; greener = more ACKs. Size: lines added or modified outside tests, then in tests; greener = smaller. | |||||||
Goal
Updates 1P1C package construction in TxDownloadManagerImpl to check if candidate orphan transactions are already in the mempool. If a candidate child exists in the mempool, it is erased from the orphanage and skipped. This preserves the invariant that package evaluation never receives an already-admitted child, retaining the Assume(false) assertion for MEMPOOL_ENTRY in net_processing.
Problem: Orphan transactions that enter the mempool through non-peer mechanisms such as RPC submission are not automatically evicted from the orphanage. When a reconsiderable parent subsequently arrives from a peer, Find1P1CPackage could select that orphan as a package child, resulting in a MEMPOOL_ENTRY acceptance result that triggers an Assume(false) assertion failure in debug builds.
Evidence of importance:
- PR description: 'An orphan that enters the mempool other than through peer relay (e.g. by RPC) stays in the orphanage, so Find1P1CPackage can pick it as the child of a reconsiderable parent, and package evaluation then reports it as MEMPOOL_ENTRY, which hits Assume(false).'
- The added functional test (test_orphan_in_mempool) reproduces the exact issue: an orphan submitted via submitpackage enters the mempool while remaining in the orphanage, triggering the code path upon receiving the reconsiderable parent.
Risk of a mistake: medium (p2p). A flaw in mempool existence checks or orphan erasure could prematurely discard valid orphan transactions or cause 1P1C package construction to fail during peer transaction relay.
Changed since the previous assessment: Rather than removing the Assume(false) assertion in ProcessPackageResult and handling MEMPOOL_ENTRY as an acceptance notification, the PR now intercepts the case inside Find1P1CPackage, erasing the child from the orphanage and skipping it to keep the assertion intact.
Reviewability
Ready
Nothing known that would invalidate a review now.
Waiting on (from the thread read):
- nothing: no pending items or requests
Agreement
Strong
substantive support, no open objection (fametrano)
Thread notes: Added fametrano's Tested ACK confirming the bug reproduction and fix, and supporting the reactive cleanup approach over mempool hooks.
Objections, suggestions, and questions:
| Reviewer | Type | Harm, request, or question | Status | Must be | Author replied | Quote |
|---|---|---|---|---|---|---|
| ismaelsadeeq (member) | suggestion, approach | Clean the orphanage proactively on mempool entry via TransactionAddedToMempool so orphans entering by any path are removed, rather than reactive cleanup | answered · author switched to Find1P1CPackage strategy but declined async sweep for now | answered | yes | 2026-10-21: 'I'd rather we clean the orphanage proactively on mempool entry, via `TransactionAddedToMempool`? so an orphan that enters by any path is removed regardless.' Status from: 2026-10-21: instagibbs: 'swtiched to the Find1P1CPackage strategy for now; can still be convinced the extra machinery to async sweep them and tak' |
Support:
- Yudis-bit (none) (Tested ACK, 2026-10-20) [tested]: tested on Windows [not substantive]
- fametrano (contributor) (Tested ACK, 2026-10-25) [both: net_processing.cpp]: verified Assume(false) reproduces on master via sendrawtransaction and that this PR fixes it; agrees with keeping a mempool hook out of this PR
Participants:
- Yudis-bit (none, support, 1 statements 2026-10-20 to 2026-10-20): Tested ACK on Windows
- ismaelsadeeq (member, objection, 2 statements 2026-10-21 to 2026-10-21): suggests proactive orphanage cleanup via TransactionAddedToMempool rather than reactive cleanup
- fametrano (contributor, support, 1 statements 2026-10-25 to 2026-10-25): Tested ACK; verified Assume(false) bug on master and fix with this PR, agrees with reactive cleanup
Files
25 lines under test/bench/ci.
- test/functional/p2p_orphan_handling.py +25/-0
- src/node/txdownloadman_impl.cpp +6/-0
- src/net_processing.cpp +2/-1
Card
The short text the ranking pass compares across PRs.
This PR fixes a debug assertion failure during 1P1C package relay when an orphan child is already present in the mempool. Transactions entering the mempool through RPC or other non-peer paths are not pruned from the orphanage, previously allowing Find1P1CPackage to pick them as children for reconsiderable parents and triggering an Assume(false) on MEMPOOL_ENTRY during package evaluation. The change inspects candidate orphans in Find1P1CPackage, erasing them from the orphanage and skipping them if they are already in the mempool. A functional test is added to reproduce and verify the fix.
Data
thread read through 2026-10-25 (7 statements), head a93bdc8320
labels: P2P
Categories
P2P
P3 · bug fix
Fixes an orphan handling edge case where orphans admitted to the mempool via RPC trigger an Assume(false) assertion in net_processing. As described, 'An orphan that enters the mempool other than through peer relay (e.g. by RPC) stays in the orphanage, so Find1P1CPackage can pick it as the child of a reconsiderable parent, and package evaluation then reports it as MEMPOOL_ENTRY, which hits Assume(false).'
Membership: Carries the P2P label and modifies orphan handling and package transaction download in src/node/txdownloadman_impl.cpp and src/net_processing.cpp.
Factors: security/stability 1, bug 1, performance 0, user value 0, leverage 0