#36578 p2p: clean up a 1p1c package child that is already in the mempool

ReviewabilityReviewsAgreementSize
#36578 instagibbs p2p: clean up a 1p1c package child that is already in the mempoolReady1 (+1)Strong8 + 25 tests
  • Prevent debug assertion failures when an orphan enters the mempool through RPC or non-peer mechanisms.
  • Ensure 1P1C package relay skips and removes orphans that are already admitted to the mempool.
  • Ready to review.
  • Verified by reproducing the assertion failure on master and testing the fix (fametrano)
  • Prefers reactive cleanup during package selection over adding mempool hooks (fametrano)
  • Suggested proactive cleanup on mempool entry, answered and declined for now (ismaelsadeeq)
  • 8 lines added or modified outside tests
  • 25 lines added or modified in tests
  • 1 lines removed in total
  • 3 files, 1 commits
P2P#33 of 71
P3 · bug fix
  • P3 because it fixes an assertion failure triggered in debug builds during an uncommon orphan race.
  • Edge case requires an orphan transaction to enter the mempool via RPC or other non-peer relay.
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:

ReviewerTypeHarm, request, or questionStatusMust beAuthor repliedQuote
ismaelsadeeq (member)suggestion, approachClean the orphanage proactively on mempool entry via TransactionAddedToMempool so orphans entering by any path are removed, rather than reactive cleanupanswered · author switched to Find1P1CPackage strategy but declined async sweep for nowansweredyes2026-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

dossier JSON · extract JSON · model ledger, generated 2026-10-26T01:22, confidence high, input hash 6b61a3eddd634c33
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