Mempool policy
requires
that transactions be at least 82 bytes (non-witness size). This rule was introduced in PR
#11423.
The original justification given was “A transaction with 1 segwit input and 1 P2WPKH output has
non-witness size of 82 bytes. Transactions smaller than this are not relayed to reduce unnecessary
malloc overhead.”
While 64-byte transactions are nonstandard in Bitcoin Core, it is still possible to create one
that is consensus-valid. It has been
proposed in PR
#15482 to disallow transactions smaller than 65 bytes in consensus. This proposal has not been accepted.
PR #26265 relaxes the policy rule from 82-byte
minimum to 65-byte minimum. Another approach could be to simply disallow 64-byte transactions.
The author also
posted
this proposal to the mailing list, adding that a 65-byte minimum would allow
transactions with 1 input, 1 OP_RETURN output to be standard. Optech newsletters
#99 and
#222 have
discussed this topic.
Why was the minimum transaction size 82 bytes? Can you describe the attack? Why does setting this
policy help prevent the attack? Does it eliminate the attack vector entirely?
What does “non-witness size” mean, and why do we care about the “non-witness” distinction?
Why might we want to change the minimum transaction size to 65 bytes, apart from the fact that we
no longer need to try to obfuscate the CVE outlined in the notes?
Between disallowing sizes less than 65 bytes and sizes equal to 64 bytes, which approach do you
think is better and why? What are the different implications of both approaches?
What is “OP_RETURN padding”? What do 10, 9, and 41 represent in the calculation of
MIN_PADDING?
What does the “tiny transaction” created
here consist of?
What is the tiny transaction’s size serialized with witness (Hint: see
CTransaction
functions)?
<glozow> and hello to everyone else of course! Welcome to bitcoin core pr review club, we're looking at #26265 today: https://bitcoincore.reviews/26265
<hernanmarino> Because it mitigated an attack regarding SPV wallets. Also it was believed to be the minimum size of a valid transaction , i.e. transactions with 1 input and 1 output.
<glozow> I don't think anyone believed that was the minimum size of a valid transaction, but yes it would effectively be the smallest standard payment, so this rule was disguised as a little exit early condition
<stickies-v> OP_RETURN was made standard in 0.9.0 it seems (released in March 2014), so it seems that smaller standard txs were indeed possible prior to #11423 (May 2018) ?
<lightlike> given that the attack was costly ($1M) according to https://github.com/advisories/GHSA-v55p-4chq-6grj and that it seems unlikely that people would use SPV clients for payments that are that large, was it really necessary to fix this covertly?
<stickies-v> we care about the non-witness distinction because (as part of the segwit upgrade) witness data is excluded from calculation of the merkle root
<stickies-v> and since the attack requires the malicious transaction to be 64 bytes in the merkle root construction (so it looks like inner nodes), we need to exclude witness data from it
<LarryRuane> I'm wondering, is BIP 37 still used today? I know most node configurations don't enable bloom filters. Can SPV clients use the newer block filters?
<LarryRuane> because inner merkle tree nodes can only be exactly 64 bytes? so requiring tx size to never be 64 prevents a tx from being interpreted as an inner node? I think it does eliminate the attack entirely (but not sure)
<stickies-v> LarryRuane: good point, I think merkle proofs are not inherent to bloom filters but I don't know where Bitcoin Core would provide merkle proofs elsewhere, since indeed I think they're not used with compact block filters
<inauman> Because the nodes in merkle tree are used in pairs (32+32) and a transactions can also be of 64 bytes, an attacker can masquerade a node with a transaction..by increasing it to 65, this attack can be eliminated
<hernanmarino> It mitigates this risk beacuse the attack requires exactly 64 byte transactions. Regarding the last question I understand it eliminates the attack completely, but I have a hunch telling me this is not the right answer : )
<andrewtoth_> it prevents the attacking tx from being relayed to miners, but it doesn't prevent it from being mined so it can still be included in a block
<glozow> Why might we want to change the minimum transaction size to 65 bytes, apart from the fact that it's unnecessary to try to obfuscate the CVE outlined in the notes?
<andrewtoth_> I believe this is part of a proposal to get OP_TRUE payments standardized, which would allow anyone to CPFP the tx. But first the size of such an output must be allowed to be relayed?
<LarryRuane> higher level question prompted by glozow's comment (about Bitcoin Core): for something like this, would we expect the maintainers of other bitcoin clients to make the analogous changes? I would imagine they follow the ML?
<_aj_> if you're going to burn dust, you could supply an ANYONECANPAY|NONE signature, and then once you've got two dust outputs to combine, you're tx is already >72 bytes stripped just to reference the input utxos
<glozow> oh wait is OP_TRUE no longer reasoning? "I went down the rabbit hole with naked OP_TRUE, forgetting that wsh(OP_TRUE) is standard for making and spending... will remove"
<_aj_> LarryRuane: if you've got a lot of dust to burn, then better to combine it all into a single tx (saving 10B tx overhead and 10B output overhead)
<_aj_> the only use i came up with that felt like it made sense was if you wanted to CPFP by burning an entire output to fees; which is plausible but seems kind of rare (better than forcing you to add another utxo as input just so you add a change output, and then not even be able to claim all your extra input back as change)
<glozow> Between disallowing sizes less than 65 bytes and sizes equal to 64 bytes, which approach do you think is better and why? What are the different implications of both approaches?
<theStack> not sure if this would count as "legit use case", but what about txs with 1 segwit input and 1 null data (OP_RETURN) output? didn't those have to have a minimum size of 20 bytes nulldata to pass the check?
<instagibbs> if an output scriptpubkey doesn't match a known template, it's considered non-standard. It was never given one. very much into the rabbit hold now...
<theStack> glozow: yeah, i was trying to find out whether users could now relay 1-segwit-input 1-nulldata-outputs with smaller nulldata payload than before (though i'm not sure why anyone would need that)