[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-
luke-jr commented at 1:31 am on November 5, 2025: member
-
97088fa75a
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
-
56626300b8
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
-
020ed613be
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
-
5a0506eea0
tests: add sighash caching tests to feature_taproot
Github-Pull: #32473 Rebased-From: 9014d4016ad9351cb59b587541895e55f5d589cc
-
354d46bc10
script: (refactor) prepare for introducing sighash midstate cache
Github-Pull: #32473 Rebased-From: 8f3ddb0bccebc930836b4a6745a7cf29b41eb302
-
ddfb9150b8
script: (optimization) introduce sighash midstate caching
Github-Pull: #32473 Rebased-From: 92af9f74d74e76681f7d98f293eab226972137b4
-
73d3ab8fc9
qa: simple differential fuzzing for sighash with/without caching
Github-Pull: #32473 Rebased-From: b221aa80a081579b8d3b460e3403f7ac0daa7139
-
f24291bd96
qa: unit test sighash caching
Github-Pull: #32473 Rebased-From: 83950275eddacac56c58a7a3648ed435a5593328
-
65bcbbc538
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
-
be0857745a
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
-
6f136cd391
tests: drop expect_disconnect behaviour for tx relay
Github-Pull: #33050 Rebased-From: 876dbdfb4702410dfd4037614dc9298a0c09c63e
-
DrahtBot added the label Backport on Nov 5, 2025
-
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.
-
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)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)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 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
More mirrored repositories can be found on mirror.b10c.me