-
Notifications
You must be signed in to change notification settings - Fork 37.7k
Accept any sequence of PUSHDATAs in OP_RETURN outputs #5079
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
Accept any sequence of PUSHDATAs in OP_RETURN outputs #5079
Conversation
// script. | ||
size_t nMaxOpReturnRelay = GetBoolArg("-datacarrier", true) ? MAX_OP_RETURN_RELAY : 1; | ||
if (scriptPubKey.IsUnspendable() && 1 <= scriptPubKey.size() // protect the begin() + 1 below | ||
&& scriptPubKey.size() <= nMaxOpReturnRelay) |
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.
This conditional could be written much more clearly. It is not clear that IsUnspendable() is actually checking for OP_RETURN at the beginning.
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.
Fixed
Aside from that one thing, utACK. |
8d67967
to
ba78c76
Compare
// byte passes the IsPushOnly() test we don't care what exactly is in the | ||
// script. | ||
size_t nMaxOpReturnRelay = GetBoolArg("-datacarrier", true) ? MAX_OP_RETURN_RELAY : 1; | ||
if (1 <= scriptPubKey.size() && scriptPubKey[0] == OP_RETURN |
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.
1 smaller than scriptPubKey.size, it is. Can we avoid yoda conditionals?
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.
This is scriptPubKey.IsUnspendable(), btw
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.
@theuni Lol, that's what the code was prior to @TheBlueMatt asking me to change it to something explicit. :)
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.
@TheBlueMatt I've got no strong feelings about Star Wars, so yoda removed.
WIth or without yodaspeak, utACK. |
if (1 <= scriptPubKey.size() && scriptPubKey[0] == OP_RETURN | ||
&& scriptPubKey.size() <= nMaxOpReturnRelay) | ||
{ | ||
CScript scriptData(scriptPubKey.begin() + 1, scriptPubKey.end()); |
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.
Making a full copy (apart from one byte) of every script in every transaction being relayed seems wasteful. Why is there a requirement that it's push only?
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.
sigops are counted even in scriptPubKeys, so accepting a transaction with an OP_RETURN output containing a bunch of CHECKMULTISIGS - for instance - would use up a lot of your per-block sigop quota.
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.
could easily adapt IsPushOnly() to be IsPushOnly(int startingAt), or even an iterator.
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.
@TheBlueMatt Any ideas on the best way of doing that?
ba78c76
to
f386100
Compare
You could add a IsPushOnly with an arg as follows: bool CScript::IsPushOnly() const
{
return this->IsPushOnly(begin());
}
bool CScript::IsPushOnly(const_iterator pc) const
{
... and then call it with Also add the new definition in script.h |
Sounds like a good suggestion, @devrandom. |
f386100
to
6865d23
Compare
@devrandom I implemented your suggestion re: IsPushOnly() and rebased. |
+1 |
Since the OP_RETURN doomsday some had predicted did not happen, could we also increase the space in the OP_RETURN? 20 bytes would already go a long way. |
@Flavien 0.10 is adding a -datacarriersize option to make configuring the size easy. Changing the default value is IMO outside the scope of this PR and should be proposed independently. |
Previously unlike other transaction types the TX_SCRIPTHASH would not clear vSolutionsRet, which means that unlike other transaction types if it was called twice in a row you would get the result of the previous invocation as well.
Allows IsPushOnly() to be applied to just part of the script for OP_RETURN outputs.
6865d23
to
c263701
Compare
Rebased |
Previously only one PUSHDATA was allowed, needlessly limiting applications such as matching OP_RETURN contents with bloom filters that operate on a per-PUSHDATA level. Now any combination that passes IsPushOnly() is allowed, so long as the total size of the scriptPubKey is less than 42 bytes. (unchanged modulo non-minimal PUSHDATA encodings) Also, this fixes the odd bug where previously the PUSHDATA could be replaced by any single opcode, even sigops consuming opcodes such as CHECKMULTISIG. (20 sigops!)
@Flavien Yeah, that belongs in a separate pull-req. Also, if you want this merged, do please test it and ACK... |
tested ACK |
concept ACK |
If this was rebased today, it wouldn't pass the tests. I rebased and fixed that. You were also altering the behaviour of the -datacarrier option and I fixed that too. Also since you are touching this part of the code already, it is trivial to move the nMaxDatacarrierBytes checks from Solver to IsStandard where it belongs (to be moved with #6068 to policy/policy). You can read and get my suggestions (diff only from what you already had, which had a clean rebase) here: jtimon/bitcoin@pr_5079_rebased...jtimon:pr_5079 Apart from that, utACK. |
@jtimon I disagree with some of the things you say above in minor ways, but the big picture is that you're version looks fine to me. How about you submit it as a separate pull-req and I'll close this one? |
Oh, actually re-reeading it I think it's all fine. Well, it's up to you, but I'd see this as separate to #6068, in the sense that it doesn't need to be a blocker. |
This seems very useful in my opinon. |
If the size check is removed from The solver is still successful, even if payloads are larger than The RPC calls Nevertheless, I think this is the right thing to do, and it would be in line with the behavior related to non-standard m-of-n multisig scripts. |
if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RETURN | ||
&& scriptPubKey.size() <= nMaxDatacarrierBytes+2) // to account for the pushdata opcodes | ||
{ | ||
if (scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) |
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.
This can be incorporated to the previous if
, just another &&. What makes this condition different from the others?
Please, rebase. Even if it's not strictly necessary, MAX_OP_RETURN_RELAY has changed its value and IsStandard() has moved to policy/policy. It will also become easier to compare with #6424, which I just opened (it's a rebased version of this with my nits on top, ready to be squashed). |
What still needs to happen here? |
@laanwj just merge #6424 instead? Well, after I get some more review and I remove the last "fixup?" commit.
Yes, and there's no problem with that.
So do you agree or not, I'm confused... |
With #5079 (comment) I was just pointing out that your change has an impact on how the scripts are labeled via RPC, but I think it's fine, and I agree with:
|
@dexX7 Oh, I see, it was just to inform. Thanks. |
ut ACK as-is Suggested improvement:
|
Was this rebased? There was already a rebased version (with my nits fixed) in #6424 ... |
Previously only one PUSHDATA was allowed, needlessly limiting applications such as matching OP_RETURN contents with bloom filters that operate on a per-PUSHDATA level. Now any combination that passes IsPushOnly() is allowed, so long as the total size of the scriptPubKey is less than 42 bytes. (unchanged modulo non-minimal PUSHDATA encodings)
Also, this fixes the odd bug where previously the PUSHDATA could be replaced by any single opcode, even sigops consuming opcodes such as CHECKMULTISIG. (20 sigops!)
Finally, fix a weird corner-case bug is also fixed for TX_SCRIPTHASH outputs.