p2p: plug "tier 1" 1p1c liveness holes #36506

pull instagibbs wants to merge 5 commits into bitcoin:master from instagibbs:2026-10-1p1c-liveness-fixes changing 15 files +1103 −22
  1. instagibbs commented at 9:20 PM on October 12, 2026: member

    Follow-up to #36437 which resolves a few key weaknesses in 1p1c relay, focusing on issues that can be easily achieved on average cpfp behavior.

    Resolves two fuzz harness "holes" and narrows a third.

    This is a proposed stopping point on resolving the holes, as it's unclear if further work is worth the churn vs a sender-initiated package relay protocol update that would resolve this directly.

    Known issues doc: https://gist.github.com/instagibbs/880a76535fd802fced9f9a5253cdbb40

  2. fuzz: add end-to-end liveness target for parent and child relay
    Check that if an honest peer announces the child of an acceptable
    parent and child, the child ends up in the mempool within a bounded
    time, whatever other peers do. The target drives a real PeerManager
    with real messages and validation, which the existing targets cannot,
    as they model validation results.
    
    After an adversarial prefix the honest peer only answers requests. With
    an outbound honest peer the adversaries keep acting; with an inbound
    one they go quiet. Adversary connections are limited, and adversaries
    do not refill outbound slots.
    
    Known liveness holes are marked in the target and turn the check off
    once opened, including the lost orphan reconsideration fixed in the
    next commit.
    47776a909e
  3. txorphanage: hand reconsideration over when its announcement is erased
    A child that arrives before its parent is kept as an orphan. Once the
    parent is accepted on its own, the orphan is put in one randomly chosen
    announcer's work set to be retried. If that announcer disconnects or is
    evicted first, the orphan is never retried, and re-announcements by the
    other announcers don't fetch it again since it is already held. This
    keeps e.g. a CPFP child of a parent that pays for itself out of the
    mempool until the orphan is evicted, and an announcer can cause it on
    purpose.
    
    Hand reconsideration over to the remaining announcer with the lowest
    NodeId instead.
    
    Remove its hole from the liveness target.
    65b48ba1f1
  4. DrahtBot added the label P2P on Oct 12, 2026
  5. DrahtBot commented at 9:20 PM on October 12, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--006a51241073e994b41acfe9ec718e94-->

    External sites

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline and AI policy for information on the review process.

    Type Reviewers
    ACK fametrano

    If your review is incorrectly listed, please copy-paste <code>&lt;!--meta-tag:bot-skip--&gt;</code> into the comment that the bot should ignore.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #36074 <sub><img src="https://drahtbot.space/ack_count/bitcoin/bitcoin/36074.svg"></sub> (scripted-diff: [test] Add util/check.h includes for assertions by maflcko)
    • #36015 <sub><img src="https://drahtbot.space/ack_count/bitcoin/bitcoin/36015.svg"></sub> (txorphanage: bound orphan memory by storing transactions serialized by brunoerg)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

  6. instagibbs force-pushed on Oct 14, 2026
  7. instagibbs marked this as ready for review on Oct 14, 2026
  8. instagibbs renamed this:
    p2p: plug various 1p1c liveness holes
    p2p: plug "tier 1" 1p1c liveness holes
    on Oct 14, 2026
  9. instagibbs force-pushed on Oct 14, 2026
  10. DrahtBot added the label CI failed on Oct 14, 2026
  11. instagibbs commented at 2:07 AM on October 14, 2026: member

    @marcofleon @mzumsande this will be the ultimate target PR to fuzz

  12. instagibbs force-pushed on Oct 14, 2026
  13. DrahtBot removed the label CI failed on Oct 14, 2026
  14. fametrano commented at 2:43 PM on October 14, 2026: contributor

    Tested c8abd9ee41: each of the four fixes is caught by a test this PR adds or extends. I reverted each fix on its own, keeping the tests, and each revert made txdownload_tests, orphanage_tests or p2p_opportunistic_1p1c.py fail, while the unchanged branch passes them all. I did not review the C++ changes. Details on request.

  15. fametrano commented at 3:31 PM on October 14, 2026: contributor

    ACK c8abd9ee41. I have now reviewed the four fixes commit by commit and found nothing blocking. One gap remains for a follow-up: in the 1p1c package path, a DIFFERENT_WITNESS result still goes through ProcessInvalidTx, so a witness-stripped copy of a mempool parent puts the parent's txid in the reject filter, as TX_CONFLICT did before 3a2b5539a1. A functional test shows it end to end: an attacker peer re-sends the stripped copy with an orphan of its own, and after the parent leaves the mempool, an honest child is dropped as having a rejected parent. Test on request.

  16. p2p: don't add already-known transactions to the reject filter
    TX_CONFLICT means the transaction is already known, in the mempool or
    confirmed, not that it is invalid. Its wtxid still went into the reject
    filter. For a witnessless copy that is also the txid, so if the known
    parent then left the mempool before the next block, a child arriving
    afterwards was dropped as having a rejected parent. For the honest
    version of a parent whose other-witness version is in the mempool, the
    honest parent itself was ignored once that version left.
    
    Don't add TX_CONFLICT results to the reject filter. The entry only saved
    re-downloading and re-checking a transaction we already have. Do the
    same for a DIFFERENT_WITNESS result in 1p1c package evaluation, which
    ProcessPackageResult passed to ProcessInvalidTx with a valid state and
    so reached the filter by another path.
    
    This also keeps a witnessless copy of a confirmed transaction out of
    the filter, as it is rejected as already known when one of its outputs
    is in the coins cache, so children spending that transaction are no
    longer dropped. A copy of a coinbase is rejected as TX_CONSENSUS
    instead, before any input lookup, and still poisons the coinbase's
    txid.
    
    Update the rejection-type table for TX_CONFLICT. In the liveness
    target, remove the replayed-parent hole and narrow the stripped
    confirmed-parent hole to children funded by a coinbase.
    152f7b74ce
  17. p2p: keep orphan after a package feerate failure
    When a 1p1c package fails the package feerate check, the child gets a
    TX_RECONSIDERABLE result, and ProcessPackageResult passed it to
    ProcessInvalidTx, which erased the child from the orphanage for all of
    its announcers.
    
    The failure is a property of that pair of wtxids, which
    MempoolRejectedPackage already caches, not of the child. The child can
    still succeed with another version of the parent, such as the one an
    honest announcer holds, so it should stay available.
    
    Skip ProcessInvalidTx for package members with a TX_RECONSIDERABLE
    result. A child that is too low feerate on its own is still rejected
    when its parent's work set is processed. Remove the hole from the
    liveness target.
    feff499de9
  18. txrequest: forget announcements by type, keep orphan parent requests
    A reconsiderable rejection of a witnessless copy of a transaction forgot its
    wtxid in TxRequestTracker regardless of announcement type, and since that
    wtxid equals the txid, it also cancelled every peer's txid-typed request for
    the transaction, including orphan resolution requests for a missing parent.
    Now only wtxid-typed announcements of that hash are forgotten, so witnessless
    parents are treated like witnessed ones, which were never affected since
    their wtxid differs from the txid.
    8d44ac8909
  19. instagibbs force-pushed on Oct 15, 2026
  20. fametrano commented at 3:28 AM on October 15, 2026: contributor

    reACK 8d44ac8909. The new DIFFERENT_WITNESS case closes the 1p1c gap I noted at c8abd9ee41, and the only other code change is its test, known_parent_in_package_does_not_poison_after_eviction. I built test_bitcoin and ran txdownload_tests, orphanage_tests and txpackage_tests: the new test passes, and fails with that case moved back next to INVALID.

  21. instagibbs commented at 4:04 AM on October 15, 2026: member

    @fametrano fuzzer hit it, which is a good sign


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-10-24 07:51 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me