[29.x] Backport fixes for CVE-2025-46598 #33788

pull luke-jr wants to merge 11 commits into bitcoin:29.x from luke-jr:cve2025_46598_pt3-29.1 changing 22 files +563 −168
  1. luke-jr commented at 1:31 am on November 5, 2025: member
  2. qa: test witness stripping in p2p_segwit
    A stripped witness is detected as a special case in mempool acceptance to make sure we do not add
    the wtxid (which is =txid since witness is stripped) to the reject filter. This is because it may
    interfere with 1p1c parent relay which currently uses orphan reconciliation (and originally it was
    until wtxid-relay was widely adopted on the network.
    
    This commit adds a test for this special case in the p2p_segwit function test, both when spending
    a native segwit output and when spending a p2sh-wrapped segwit output.
    
    Thanks to Eugene Siegel for pointing out the p2sh-wrapped detection did not have test coverage by
    finding a bug in a related patch of mine.
    
    Github-Pull: #33105
    Rebased-From: eb073209db9efdbc2c94bc1f535a27ec6b20d954
    97088fa75a
  3. policy: introduce a helper to detect whether a transaction spends Segwit outputs
    We will use this helper in later commits to detect witness stripping without having
    to execute every input Script three times in a row.
    
    Github-Pull: #33105
    Rebased-From: 2907b58834ab011f7dd0c42d323e440abd227c25
    56626300b8
  4. validation: detect witness stripping without re-running Script checks
    Since it was introduced in 4eb515574e1012bc8ea5dafc3042dcdf4c766f26 (#18044), the detection of a
    stripped witness relies on running the Script checks 3 times. In the worst case, this consists in
    running Script validation 3 times for every single input.
    
    Detection of a stripped witness is necessary because in this case wtxid==txid, and the transaction's
    wtxid must not be added to the reject filter or it could allow a malicious peer to interfere with
    txid-based orphan resolution as used in 1p1c package relay.
    
    However it is not necessary to run Script validation to detect a stripped witness (much less so
    doing it 3 times in a row). There are 3 types of witness program: defined program types (Taproot,
    P2WPKH, P2WSH), undefined types, and the Pay-to-anchor carve-out.
    
    For defined program types, Script validation with an empty witness will always fail (by consensus).
    For undefined program types, Script validation is always going to fail regardless of the witness (by
    standardness). For P2A, an empty witness is never going to lead to a failure.
    
    Therefore it holds that we can always detect a stripped witness without re-running Script validation.
    However this might lead to more "false positives" (cases where we return witness stripping for an
    otherwise invalid transaction) than the existing implementation. For instance a transaction with one
    P2PKH input with an invalid signature and one P2WPKH input with its witness stripped. The existing
    implementation would treat it as consensus invalid while the implementation in this commit would
    always consider it witness stripped.
    
    Github-Pull: #33105
    Rebased-From: 27aefac42505e9c083fa131d3d7edbec7803f3c0
    020ed613be
  5. tests: add sighash caching tests to feature_taproot
    Github-Pull: #32473
    Rebased-From: 9014d4016ad9351cb59b587541895e55f5d589cc
    5a0506eea0
  6. script: (refactor) prepare for introducing sighash midstate cache
    Github-Pull: #32473
    Rebased-From: 8f3ddb0bccebc930836b4a6745a7cf29b41eb302
    354d46bc10
  7. script: (optimization) introduce sighash midstate caching
    Github-Pull: #32473
    Rebased-From: 92af9f74d74e76681f7d98f293eab226972137b4
    ddfb9150b8
  8. qa: simple differential fuzzing for sighash with/without caching
    Github-Pull: #32473
    Rebased-From: b221aa80a081579b8d3b460e3403f7ac0daa7139
    73d3ab8fc9
  9. qa: unit test sighash caching
    Github-Pull: #32473
    Rebased-From: 83950275eddacac56c58a7a3648ed435a5593328
    f24291bd96
  10. net_processing: drop MaybePunishNodeForTx
    Do not discourage nodes even when they send us consensus invalid
    transactions.
    
    Because we do not discourage nodes for transactions we consider
    non-standard, we don't get any DoS protection from this check in
    adversarial scenarios, so remove the check entirely both to simplify the
    code and reduce the risk of splitting the network due to changes in tx
    relay policy.
    
    NOTE: Backport required additional adjustment in test/functional/p2p_invalid_tx
    
    Github-Pull: #33050
    Rebased-From: 266dd0e10d08c0bfde63205db15d6c210a021b90
    65bcbbc538
  11. validation: only check input scripts once
    Previously, we would check failing input scripts twice when considering
    a transaction for the mempool, in order to distinguish policy failures
    from consensus failures. This allowed us both to provide a different
    error message and to discourage peers for consensus failures. Because we
    are no longer discouraging peers for consensus failures during tx relay,
    and because checking a script can be expensive, only do this once.
    
    Also renames non-mandatory-script-verify-flag error to
    mempool-script-verify-flag-failed.
    
    NOTE: Backport required additional adjustment in test/functional/feature_block
    
    Github-Pull: #33050
    Rebased-From: b29ae9efdfeeff774e32ee433ce67d8ed8ecd49f
    be0857745a
  12. tests: drop expect_disconnect behaviour for tx relay
    Github-Pull: #33050
    Rebased-From: 876dbdfb4702410dfd4037614dc9298a0c09c63e
    6f136cd391
  13. DrahtBot added the label Backport on Nov 5, 2025
  14. DrahtBot commented at 1:31 am on November 5, 2025: contributor

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

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/33788.

    Reviews

    See the guideline for information on the review process. A summary of reviews will appear here.

  15. in test/functional/p2p_invalid_tx.py:162 in 6f136cd391
    158@@ -165,7 +159,7 @@ def run_test(self):
    159             node.p2ps[0].send_txs_and_test([rejected_parent], node, success=False)
    160 
    161         self.log.info('Test that a peer disconnection causes erase its transactions from the orphan pool')
    162-        with node.assert_debug_log(['Erased 100 orphan transaction(s) from peer=26']):
    163+        with node.assert_debug_log(['Erased 100 orphan transaction(s) from peer=']):
    


    luke-jr commented at 1:35 am on November 5, 2025:
    Note: Not in master commit (another approach is used for this test)
  16. in test/functional/feature_block.py:168 in 6f136cd391
    163@@ -164,9 +164,12 @@ def run_test(self):
    164                 self.sign_tx(badtx, attempt_spend_tx)
    165             badtx.rehash()
    166             badblock = self.update_block(blockname, [badtx])
    167+            reject_reason = (template.block_reject_reason or template.reject_reason)
    168+            if reject_reason and reject_reason.startswith("mempool-script-verify-flag-failed"):
    


    luke-jr commented at 1:35 am on November 5, 2025:
    Note: reject_reason could be None here, so a check was added (not in master commit)
  17. luke-jr renamed this:
    [29.x] Backport fixes for CVE-2025 46598
    [29.x] Backport fixes for CVE-2025-46598
    on Nov 5, 2025

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: 2025-11-08 21:13 UTC

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