[29.x] Backport fixes for CVE-2025-46598#33788
Conversation
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: bitcoin#33105 Rebased-From: eb07320
…wit 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: bitcoin#33105 Rebased-From: 2907b58
Since it was introduced in 4eb5155 (bitcoin#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: bitcoin#33105 Rebased-From: 27aefac
Github-Pull: bitcoin#32473 Rebased-From: 9014d40
Github-Pull: bitcoin#32473 Rebased-From: 8f3ddb0
Github-Pull: bitcoin#32473 Rebased-From: 92af9f7
Github-Pull: bitcoin#32473 Rebased-From: b221aa8
Github-Pull: bitcoin#32473 Rebased-From: 8395027
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: bitcoin#33050 Rebased-From: 266dd0e
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: bitcoin#33050 Rebased-From: b29ae9e
Github-Pull: bitcoin#33050 Rebased-From: 876dbdf
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code Coverage & BenchmarksFor details see: https://corecheck.dev/bitcoin/bitcoin/pulls/33788. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please copy-paste |
| with node.assert_debug_log(['Erased 100 orphan transaction(s) from peer=26']): | ||
| with node.assert_debug_log(['Erased 100 orphan transaction(s) from peer=']): |
There was a problem hiding this comment.
Note: Not in master commit (another approach is used for this test)
| badtx.rehash() | ||
| badblock = self.update_block(blockname, [badtx]) | ||
| reject_reason = (template.block_reject_reason or template.reject_reason) | ||
| if reject_reason and reject_reason.startswith("mempool-script-verify-flag-failed"): |
There was a problem hiding this comment.
Note: reject_reason could be None here, so a check was added (not in master commit)
|
Useful to anyone who wants to continue to run core v29... not confident enough to ACK consensus-adjacent code as a newer contributor, but the backport mechanics look clean. What I checked:
cc: @glozow @sipa in case you have bandwidth to look at this since you reviewed the original PRs. |
|
Concept ACK, will review in some more detail soon. |
darosior
left a comment
There was a problem hiding this comment.
Concept ACK. Backport looks good, the functional test adaptation are fine. Been running the sighash_cache fuzz target and now doing a full sync on this branch for good measure, although there has been virtually no change to the interpreter between 29 and 30.
|
ACK 6f136cd, looks correct |
No description provided.