-
Notifications
You must be signed in to change notification settings - Fork 37.7k
Replace MIN_STANDARD_TX_NONWITNESS_SIZE to preclude 64 non-witness bytes only #26398
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
4824737
to
a67341a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
code review ACK, looks OK. I suggest to change the title of this PR though, it suggests that we are relaxing the restriction to ALLOW 64 byte transactions, and might confuse someone.
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/26398. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. ConflictsReviewers, this pull request conflicts with the following ones:
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rajarshimaitra fwiw, I agree, I like this test code materially more, which suggests it's the right direction, with less indirection happening |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
Concept ACK, prefer this over #26265 |
c361621
to
2ddd3a8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept and code-review ACK 2ddd3a8
nit: could utilize more MiniWallet magic here, in order to avoid crafting the output of the parent tx and the input of the spending tx manually (works only as long as a segwit wallet mode is used, i.e. ADDRESS_OP_TRUE
with segwitv1 outputs currently):
b/test/functional/mempool_accept.py
index c2d94ddad..09f8c3b23 100755
--- a/test/functional/mempool_accept.py
+++ b/test/functional/mempool_accept.py
@@ -36,7 +36,6 @@ from test_framework.script_util import (
NONSTANDARD_OP_RETURN_SCRIPT,
NONSTANDARD_TX_NONWITNESS_SIZE,
script_to_p2sh_script,
- script_to_p2wsh_script,
)
from test_framework.util import (
assert_equal,
@@ -340,16 +339,13 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
maxfeerate=0,
)
- # Prep for tiny-tx tests with wsh(OP_TRUE) output
- seed_tx = self.wallet.send_to(from_node=node, scriptPubKey=script_to_p2wsh_script(CScript([OP_TRUE])), amount=COIN)
+ # Prep for tiny-tx tests with MiniWallet anyone-can-spend output
+ seed_utxo = self.wallet.send_self_transfer(from_node=node)["new_utxo"]
self.generate(node, 1)
self.log.info('A tiny transaction(in non-witness bytes) that is disallowed')
- tx = CTransaction()
- tx.vin.append(CTxIn(COutPoint(int(seed_tx[0], 16), seed_tx[1]), b"", SEQUENCE_FINAL))
- tx.wit.vtxinwit = [CTxInWitness()]
- tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([OP_TRUE])]
- tx.vout.append(CTxOut(0, NONSTANDARD_OP_RETURN_SCRIPT))
+ tx = self.wallet.create_self_transfer(utxo_to_spend=seed_utxo)["tx"]
+ tx.vout[0].scriptPubKey = NONSTANDARD_OP_RETURN_SCRIPT
# Note it's only non-witness size that matters!
assert_equal(len(tx.serialize_without_witness()), NONSTANDARD_TX_NONWITNESS_SIZE)
assert len(tx.serialize()) != NONSTANDARD_TX_NONWITNESS_SIZE
@@ -361,7 +357,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
)
self.log.info('Just-below size transaction(in non-witness bytes) that is allowed')
- tx.vout[0] = CTxOut(COIN - 1000, CScript([OP_RETURN] + ([OP_0] * (INVALID_SPK_LEN - 2))))
+ tx.vout[0] = CTxOut(int(seed_utxo["value"] * COIN) - 1000, CScript([OP_RETURN] + ([OP_0] * (INVALID_SPK_LEN - 2))))
assert_equal(len(tx.serialize_without_witness()), NONSTANDARD_TX_NONWITNESS_SIZE - 1)
self.check_mempool_result(
result_expected=[{'txid': tx.rehash(), 'allowed': True, 'vsize': tx.get_vsize(), 'fees': { 'base': Decimal('0.00001000')}}],
@@ -370,7 +366,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
)
self.log.info('Just-above size transaction(in non-witness bytes) that is allowed')
- tx.vout[0] = CTxOut(COIN - 1000, CScript([OP_RETURN] + ([OP_0] * (INVALID_SPK_LEN))))
+ tx.vout[0] = CTxOut(int(seed_utxo["value"] * COIN) - 1000, CScript([OP_RETURN] + ([OP_0] * (INVALID_SPK_LEN))))
assert_equal(len(tx.serialize_without_witness()), NONSTANDARD_TX_NONWITNESS_SIZE + 1)
self.check_mempool_result(
result_expected=[{'txid': tx.rehash(), 'allowed': True, 'vsize': tx.get_vsize(), 'fees': { 'base': Decimal('0.00001000')}}],
review ACK 2ddd3a8 🏊 Show signatureSignature:
For historical context, see #26265 (review) Was there a recent thread on the mailing list you could link to? I can't seem to find the one you created, as there are about 5 trillion messages about RBF. About the practical impact of this change: My understanding is that 60-byte transactions are still not policy-allowed, because an empty scriptPubKey is nonstandard. The smallest transaction this would allow is a 61-byte transaction with one |
@MarcoFalke I agree with your statements https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2022-October/020995.html Also found this old one just now that I was a part of 2 years ago and don't recall: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2020-May/017883.html |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
code review ACK 2ddd3a8
Could you please link the ML post in the OP and write a release note?
2ddd3a8
to
a75b0fd
Compare
Restricting sizes below 64 vbytes interferes with specific use-cases, and does not interfere with proposed consensus changes such as the Great Consensus Cleanup of 2025. We change software to protect against the case we care about: 64 bytes
a873be7
to
72ddf42
Compare
Re-opened due to the recent Great Consensus Cleanup work, though I still think there may be minor debate about the utility of the change. |
Align with Bitcoin Core's policy by reducing the minimum non-witness transaction size from 82 to 65 bytes. This change allows for more minimal transaction cases (e.g., 1 input with 1 OP_RETURN output), while still maintaining protection against CVE-2017-12842. Matches bitcoin/bitcoin#26398
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for rebasing! Needs release note.
That's easily fixed by having the 1-out be a 0sat OP_RETURN pushing three bytes of data... I remain Concept and Approach NACK on this, supporting 60-63 byte txs but not 64 byte txs just seems like it's asking for trouble. ie, just add the extra bytes to your output in your tests, this isn't worth optimising. And if it were worth optimising, we should actually optimise it. OTOH, it might be plausible to just not worry about small-tx's at all, in which case the check could just be removed entirely, avoiding any discontinuities... |
@ajtowns Bit of a tomato/tomato situation imo, because I think the rules as-is invite more trouble than clearly marking the exact case we're worried about. The strongest case against this PR, imo, is not some application-level danger about discontinuity but the fact that once you open it up it's difficult to close. But it's been many years and no one has made an argument why this would be dangerous at a network level.
If we end up deciding to not ban 64b by consensus, we should seriously consider this. |
Concept ACK. I don't buy that the discontinuity would cause any more confusion than making harmless transactions non-standard. The upgrade hook argument made sense back when this PR was closed, but i don't think it holds anymore now that no proposal includes invalidating <64 bytes transactions.
This goes completely against your earlier argument of keeping our options open with regard to upgrade hooks! There is a current proposal to make those transactions invalid, so making them standard now seems unnecessarily risky.
I'm sympathetic to this view but i'm not sure. We might decide it's not worth changing consensus over this, but it's not necessarily a reason to make it easier to exploit? |
If there is a need to worry about small transactions, then the conservative thing to do in consensus is forbid as little as possible (because things that have been forbidden are very difficult to re-enable), and the conservative thing to do in policy is to continue to forbid everything that's not obviously useful (because things that are enabled are very difficult to forbid). In both cases, it's the conservative option because it keeps more future possibilities open. Personally, I think ">65 is okay" is easier to deal with than "60 isn't really okay for different reasons, 61, 62, 63 are okay, 64 isn't, 65+ is".
|
Suggested PR title: Policy: reallow short transactions except 64-byte And extra sentence for the description:
As for the actual change, I'm not sure either way. But to expand on @ajtowns's comment:
And @glozow's finding:
It seems there's a potential footgun in wallets that can generate < 64 transactions, and then for whatever reason one byte gets added and the transaction is stuck. From that perspective it's safer to have a policy that simplify requires > 64 bytes. So from the perspective of using policy as a way to encourage safe designs, the current approach is better. On the flip side, someone may feel that the current policy is too "pedantic" and start running relays using the commit from this PR. But that applies to every single policy != consensus rule, and is probably only an (economic) issue for very common transactions. |
🐙 This pull request conflicts with the target branch and needs rebase. |
Concept ACK |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 72ddf42
While I don't think the changes here are pressing, I'm for aligning policy more closely with the actual behaviour we'd like to prohibit and (eventually) enforce.
It seems there's a potential footgun in wallets that can generate < 64 transactions, and then for whatever reason one byte gets added and the transaction is stuck.
This seems a bit constructed. Why would a wallet correctly report a failed send for < 64, but fail to do so with 64 because of this rule change? Scenarios where transactions get stuck because of fees are far likelier in any case.
Follow-on to to #26265
Implements the logic not effected by Great Consensus Cleanup 2025 effort: bitcoin/bips#1800