3

Is the OP_PUSHBYTES opcode always expected after OP_RETURN?

For instance, the 2nd output of transaction 6dfb16dd580698242bcfd8e433d557ed8c642272a368894de27292a8844a4e75 is:

OP_RETURN
OP_PUSHBYTES_11
68656c6c6f20776f726c64

Would

OP_RETURN
68656c6c6f20776f726c64

work just as well? If not, where in the bitcoin core source code is the requirement for the OP_PUSHBYTES code enforced?

Is there a difference in requirement here (aside from the 80 byte limit) between standard and non-standard transactions?

From bitcoin.it, it seems OP_PUSHBYTES is not required but I've not yet found an example main net transaction without one.

1

4 Answers 4

2

My existing answer stands, but as I feel we're talking past each other due to different assumptions about what Script notations mean, let me add this to dig deeper into that.

I'm going to change the literals in your question a bit for simplicity, and try to answer the question:

I see an output with scriptPubKey OP_RETURN OP_PUSHBYTES_3 686c77. Would an output with scriptPubKey OP_RETURN 686c77 also be valid and/or standard?

The first point is that in your notation, the string OP_RETURN 686c77 simply has no meaning. It does not correspond to any script at all. I don't mean that such a script would be invalid; I mean that literally this cannot be translated to actual script bytes.

For background, the script OP_RETURN OP_PUSHBYTES_3 686c77 corresponds the script bytes whose hex encoding is 6a03686c77 (6a being OP_RETURN, and 03 being OP_PUSHBYTES_3). My assumption is that what you mean by OP_RETURN 686c77 is the script whose hex bytes are 6a686c77, i.e., the same bytes as before, but with the OP_PUSHBYTES_3 byte dropped.

However, those script bytes would not be denoted OP_RETURN 686c77. It would be denoted OP_RETURN OP_ENDIF OP_FROMALTSTACK OP_NIP (because without the 03 bytes, the 3 bytes that follow are interpreted as opcodes, rather than as a literal).

If your question is about the script OP_RETURN OP_ENDIF OP_FROMALTSTACK OP_NIP (hex 6a686c77), the answer is that by consensus rules this output is valid (even though it has an OP_ENDIF without corresponding OP_IF!) because Scripts are not executed or interpreted until they are spent, and an OP_RETURN output like this is obviously unspendable. The only consensus rules governing scriptPubKeys is that they cannot exceed 10000 bytes, but there are absolutely no rules restricting what those bytes can be. As for standardness, the answer as of Bitcoin Core 27.0 is no; the requirement for OP_RETURN outputs to be standard is (among other things) that the OP_RETURN is only followed by pushes, not by other opcodes.

To add to the confusion, there exist other human-readable notations for Script, including a common one which just never uses OP_PUSHBYTES_xx. In the Bitcoin Core notation, the script whose hex bytes are 6a03686c77 is simply denoted OP_RETURN 686c77 (with the 03 byte, and the pushing, implicit in the hex constant). So if you ask about OP_RETURN 686c77, it really matters what you mean by that. Either you've switched to another encoding (for the same script, and nothing changed), or you've described something meaningless.

1
  • Another valuable answer! I was not aware of the intricacies around notation. Had I been, I'd have perhaps used all hex in the question. I.e. Is 6a68656c6c6f20776f726c64 a non-standard but valid output scriptPubKey, and is it practically equivalent to 6a0b68656c6c6f20776f726c64? The last section of your answer covers that and I'm glad of the grey-matter upgrade from the rest.
    – Lee
    Commented Jun 27 at 15:06
3

This is a notational issue, resulting from how you're choosing to write the Scripts in readable form.

This question simply makes no sense when you look at the actual binary encoding of Scripts, because the way to have a literal like "68656c6c6f20776f726c64" in Script is through what you call OP_PUSHBYTES_11. It's a stretch to call it an opcode even: it's simply a specific byte which means "the next 11 bytes in the Script encoding are a literal that is to be pushed onto the stack". If you'd drop that byte, the bytes of your literal would instead be interpreted as opcodes, resulting in OP_RETURN OP_ENDIF (invalid) OP_FROMALTSTACK OP_FROMALTSTACK (invalid) (unfinished push of 32 bytes).

There are multiple ways to write Scripts in human-readable form, but for example Bitcoin Core's disassembler will denote your script as OP_RETURN 68656c6c6f20776f726c64. The byte corresponding to what you call OP_PUSHBYTES_11 is implicit in the length of the hex string that follows.

Also note that all of this is completely unrelated to OP_RETURN. OP_RETURN is typically followed by a byte push like this, but it does not have to be. And the rules for how to encode byte pushes in Script apply always, whether the push follows an OP_RETURN or something else.

9
  • Yeah, there is a number of questions mentioning an OP_PUSHBYTES_X and i believe it is because they use rust-bitcoin which names the size prefixes this way: github.com/rust-bitcoin/rust-bitcoin/blob/…. Commented Jun 27 at 13:44
  • Would say a coinbase tx (non-standard tx) with an output of OP_RETURN 68656c6c6f20776f726c64 be accepted by a node (assuming work threshold is met)?
    – Lee
    Commented Jun 27 at 13:51
  • 1
    See my updated answer, no the byte is absolutely not optional. It is just that in some ways of writing the script an OP_PUSHBYTES_11 is emitted for it, and in others it's not (because it is implied by the fact that a hex character string follows). Commented Jun 27 at 14:18
  • 1
    @Lee The script 6a0b68656c6c6f20776f726c64 contains two operations: 6a (OP_RETURN) and 0b68656c6c6f20776f726c64 (OP_PUSHBYTES_11 followed by 11 bytes of data.) The OP_PUSHBYTES_11 is always there; it's just a question of how you display the script. In the more explicit style of displaying it, you show the OP_PUSHBYTES_NN, followed by NN bytes of data. In the less explicit style, you can just show the data; if you have 11 bytes of data, that ALWAYS means there is an OP_PUSHBYTES_11, so you don't really need to show it. But both ways, it's the same script with the same opcodes. Commented Jun 28 at 4:01
  • 1
    It's slightly silly that there are two different ways people display the same script, but it's not ambiguous (because data in a script ALWAYS requires a push opcode, and you can tell which one just by looking at the data.) Commented Jun 28 at 4:02
2

It is not necessary for a data push to follow an OP_RETURN.

By consensus, it is not required that an OP_RETURN be followed by a data push. Encountering an OP_RETURN stops Script execution immediately with an error.

By standardness, a transaction may contain a single output with a bare script starting with an OP_RETURN. This OP_RETURN needs not be followed by a data push.

1

Script Notation:

OP_RETURN <11 bytes hexadecimal>

and

OP_RETURN PUSH_BYTES_11 <11 bytes hexadecimal>

are synonyms.

They both translate to 0x6a0b<11 bytes hexadecimal>.

I didn't know this when I asked the question...


Standardness of arbitrary bytes following OP_RETURN

For clarity, my question should have been:

Does 0x6a<any_bytes> in a ScriptPubKey, where the first byte of <any_bytes> is not the correct PUSH_BYTES value, mean that the resulting transaction is 1. non-standard or 2. non-consensus-valid?

1. Yes, it would be non-standard (not accepted to mempool/not forwarded by nodes).

2. No, it would be consensus valid (acceptable if seen in an otherwise valid block) so long as the ScriptPubKey like this was <10000 bytes.


Credit to Pieter Wuille's answers/comments. I wrote this to help me get to grips with it!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.