OP_RETURN

Storing data on the blockchain

A diagram showing the structure of an OP_RETURN locking script used for storing data.

OP_RETURN refers to a standard locking script that can be used to store data inside transactions.

The OP_RETURN opcode itself immediately ends the execution of the script and marks it as invalid.

Whilst this is an opcode on its own and can be used in a variety of different scripts, the name "OP_RETURN" is also used to refer to a standard script pattern used for storing arbitrary data inside transactions. And that's primarily what I'm talking about on this page.

This locking script cannot be unlocked, so don't use it to lock up any amount of bitcoins.

A transaction can only include one OP_RETURN locking script for it to be considered a standard transaction. Any more and it will be considered non-standard and will not be relayed by nodes.

This is sometimes referred to as a "nulldata" script. Technically that's the correct term, but it's not commonly used, so that's why I just refer to this as the OP_RETURN locking script instead.

Usage

How does an OP_RETURN script work?

ScriptPubKey

The OP_RETURN standard locking script just contains the OP_RETURN opcode followed by a data push of up to 80 bytes.

OP_RETURN
OP_PUSHBYTES_11
68656c6c6f20776f726c64
6a0b68656c6c6f20776f726c64

Transaction: 6dfb16dd580698242bcfd8e433d557ed8c642272a368894de27292a8844a4e75 (Output 2)

This data push can contain any data you like, but it's commonly used for storing ASCII-encoded text strings.

ASCII

ScriptSig

An OP_RETURN locking script is unspendable, so there's no ScriptSig that can unlock it.

A diagram showing a transaction output with an OP_RETURN locking script on it as being unspendable.

So ultimately outputs with the OP_RETURN locking script only exist to store arbitrary bytes of data, and can never be used as inputs in future transactions:

A diagram showing a transaction output with an OP_RETURN locking script storing some text data.

Examples

Where can you find OP_RETURN scripts?

Anyone can use an OP_RETURN script to store some data in a transaction, and you can find them scattered around the blockchain:

If you want to find OP_RETURN scripts in the blockchain, look for outputs with zero amount values. This is because OP_RETURN scripts are unspendable, so they're almost always placed on "empty" outputs.

ASCII

Example 1 — hello world

OP_RETURN
OP_PUSHBYTES_11
68656c6c6f20776f726c64
6a0b68656c6c6f20776f726c64

Transaction: 6dfb16dd580698242bcfd8e433d557ed8c642272a368894de27292a8844a4e75 (Output 2)

Example 2 — charley loves heidi

OP_RETURN
OP_PUSHBYTES_19
636861726c6579206c6f766573206865696469
6a13636861726c6579206c6f766573206865696469

Transaction: 8bae12b5f4c088d940733dcd1455efc6a3a69cf9340e17a981286d3778615684 (Output 0)

Example 3 — Amazing!

OP_RETURN
OP_PUSHBYTES_8
416d617a696e6721
6a08416d617a696e6721

Transaction: 2cf4f1ab0df25610231a0f4fb7e1e18720a6c555f102b75bb115e99b1ad41241 (Output 2)

Example 4 — First OPReturn Message I was here :)

OP_RETURN
OP_PUSHBYTES_36
4669727374204f5052657475726e204d6573736167652049207761732068657265203a29
6a244669727374204f5052657475726e204d6573736167652049207761732068657265203a29

Transaction: b33c1252ddc2fdb5396c7dc3ceed3749c587e3310c6df2f3605a38cc3c129e1f (Output 1)

Example 5 (wTXID Commitment)

Since the Segregated Witness upgrade, the OP_RETURN locking script is used within the coinbase transaction to store the wTXID Commitment:

OP_RETURN
OP_PUSHBYTES_36
aa21a9ed6502e8637ba29cd8a820021915339c7341223d571e5e8d66edd83786d387e715
6a39e5aeb6e6978fe38282e58f8be98194e38282e381bfe38293e381aae3818ce7ac91e9a194e381aee6af8ee697a5e3818ce381bbe38197e38184

Transaction: 2d4cdcd29d0004c762790b579bc2541da788f042031fa87fc27e402244080394 (Output 1)

This data push is not ASCII-encoded text. It's just a bunch of bytes, so there's nothing interesting to be found by converting it to ASCII.

History

Why do we have OP_RETURN scripts?

OP_RETURN was introduced as a standard locking script in Bitcoin 0.9.0 as a compromise to allow people to include arbitrary data inside transactions.

You see, before OP_RETURN was available, people were adding data to transactions by using the existing standard locking scripts. For example, here's how I stored the text string "learnmeabitcoin" in the place where the public key hash would go in a standard P2PKH locking script:

OP_DUP
OP_HASH160
00000000006c6561726e6d6561626974636f696e
OP_EQUALVERIFY
OP_CHECKSIG
76a91400000000006c6561726e6d6561626974636f696e88ac

Transaction: 64cbb86ea4f8787ea048a46e968bd51a8f675acd359565bd08522c205d22eba0 (Output 1)

ASCII

This works, but the problem with this approach is that it's a standard locking script, so the output would be stored in the UTXO database, which is a waste of storage as the output is effectively unspendable.

So this is where the OP_RETURN locking script comes in:

OP_RETURN
6c6561726e6d6561626974636f696e
6a0f6c6561726e6d6561626974636f696e

This script contains OP_RETURN, which means it provably unspendable and therefore does not need to be stored in the UTXO database (which saves on precious RAM space when Bitcoin is running).

Using the blockchain for data storage isn't ideal, but you can't stop people from doing it. Therefore, the OP_RETURN script acts as a more reasonable alternative for data storage than previous methods.

There has been some confusion and misunderstanding in the community, regarding the OP_RETURN feature in 0.9 and data in the blockchain. This change is not an endorsement of storing data in the blockchain. The OP_RETURN change creates a provably-prunable output, to avoid data storage schemes – some of which were already deployed – that were storing arbitrary data such as images as forever-unspendable TX outputs, bloating bitcoin’s UTXO database.
Bitcoin 0.9.0 Release Notes

Notes

OP_RETURN must be evaluated for a script to fail.

The presence of the OP_RETURN opcode in a script does not automatically render the script invalid.

For example, in the script below the OP_RETURN is in a branch that will never be evaluated, and so the script is valid:

OP_1 OP_IF OP_1 OP_ELSE OP_RETURN OP_ENDIF

You can see an example of this script in action (wrapped inside a P2SH) here.

Thanks to Vincenzo Iovino for pointing this out to me.

Resources