## Explanation of what an OP_RETURN transaction looks like

55

35

How is OP_RETURN used and why was it introduced in the first place?

83

Note: I went out and learned about how the OP_RETURN opcode works at the byte level in a bitcoin transaction. I’m writing it here so that others can learn quickly. First, a brief history of why we’re even talking about OP_RETURN.

Back in 2013 different players in the bitcoin ecosystem were trying to include bits of information into transactions so that they could take advantage of the irreversibility of the blockchain. Imagine for instance you wanted to write a contract and place it in an unchangeable location that at any future date one could go back to verify it existed. You can do this by using the blockchain. You add some bits to the transaction's scriptSig value that don't alter the end result of running that script, but allow you to store information like “I hereby declare to give asset A to address XYZ at time UNIX_TIMESTAMP”. There were even stranger ways people would add extra bits, like including it in the BTC value of an output. Some members of the community did not like this, as they saw these extra bits as polluting the blockchain. The extra bits were a network efficiency concern because more bits meant larger block chains and more of an onus on those who are running full nodes, and it was also a community consensus concern because they thought “we all implicitly agreed to store financial data in the blockchain, which is important to everyone, but we did not agree to store data like small text messages and invoice text”.

To reach a middle ground in these opposing views, the core-developers made the opcode OP_RETURN a valid opcode to be used in a bitcoin transaction, which allows 80 arbitrary bytes to be used in an unspendable transaction. A good explanation of this can be found here:

https://bitcoinfoundation.org/bitcoin/core-development-update-5/


Later in February 2014, the bytes count was reduced from 80 to 40 bytes. This change is documented in the link below. Note that in this pull discussion we learn that no more than one output with OP_RETURN can be included in a single transaction:

https://github.com/bitcoin/bitcoin/pull/3737


Now that we’ve got the reason behind OP_RETURN down, let’s look at an example of OP_RETURN. I used chain.com’s API to find a transaction which has an OP_RETURN in its scriptSig. That tx’s hash is

8bae12b5f4c088d940733dcd1455efc6a3a69cf9340e17a981286d3778615684


Make sure you are connected to a fully-loaded bitcoind node, and run this command:

\$> bitcoind getrawtransaction 8bae12b5f4c088d940733dcd1455efc6a3a69cf9340e17a981286d3778615684 1


which will give you this output:

{
"txid" : "8bae12b5f4c088d940733dcd1455efc6a3a69cf9340e17a981286d3778615684",
"version" : 1,
"locktime" : 0,
"vin" : [
{
"txid" : "8e40bb1db9029dd648432c56c295788221c1dd97fe1dbee52f767d605fba58c8",
"vout" : 1,
"scriptSig" : {
},
"sequence" : 4294967295
}
],
"vout" : [
{
"value" : 0.00000000,
"n" : 0,
"scriptPubKey" : {
"asm" : "OP_RETURN 636861726c6579206c6f766573206865696469",
"hex" : "6a13636861726c6579206c6f766573206865696469",
"type" : "nulldata"
}
},
{
"value" : 0.00200000,
"n" : 1,
"scriptPubKey" : {
"asm" : "OP_DUP OP_HASH160 b8268ce4d481413c4e848ff353cd16104291c45b OP_EQUALVERIFY OP_CHECKSIG",
"hex" : "76a914b8268ce4d481413c4e848ff353cd16104291c45b88ac",
"reqSigs" : 1,
"type" : "pubkeyhash",
"1HnhWpkMHMjgt167kvgcPyurMmsCQ2WPgg"
]
}
}
],
"blockhash" : "000000000000000004c31376d7619bf0f0d65af6fb028d3b4a410ea39d22554c",
"confirmations" : 2655,
"time" : 1404107109,
"blocktime" : 1404107109
}


Now, look at this transaction’s list of outputs, in particular the 1st one. By referencing the Bitcoin Wiki’s page on Script, Bitcoin’s stack-based programming language, we can see here that the OP_RETURN opcode is represented by the hex value 0x6a. This first byte it followed by a byte which represents the length of the rest of the bytes in the scriptPubKey. In this case we see the hex value Ox13, which means there are 19 more bytes. These bytes comprise the arbitrary less-than-40 bytes you are allowed to send in a transaction marked by the OP_RETURN opcode. If you pop the message bytes into a UTF8 decoder, you’ll see that

636861726c6579206c6f766573206865696469


becomes “charley loves heidi”. Aw! It’s almost like a digital version of a couple’s romantic heart tree carving. Now you understand at a byte level how OP_RETURN is supposed to work. You can write software now that searches for the OP_RETURN opcode in an output’s scriptPubKey, and use it to verify a contract or some other digital asset.

10An important aspect of OP_RETURN is that outputs which use it in the standard way are provable unspendable. This means that nodes can immediately remove such outputs from their unspent outputs cache and potentially forget about them altogether (though Bitcoin Core doesn't do this yet). This makes OP_RETURN transactions much less expensive for the network than other ways of stuffing data into the block chain. – theymos – 2014-07-17T22:47:49.460

7FYI if anyone is looking to decode that message 636861726c6579206c6f766573206865696469 in php, it's the hex value so use hex2bin() – OACDesigns – 2015-02-02T10:34:11.427

Why does this cost less to the network that just sending 1 satoshi to an arbitrary address that contains the 20 bytes of information itself ? – Nathan Parker – 2015-09-08T08:23:28.460

3@NathanParker Because with OP_RETURN, the node knows that the transaction output index is unspendable and can just ignore it. Whereas when sending 1 satoshi, the node will need to keep that unspent output in memory or in a database, waiting until someone spends it someday. – Nayuki – 2015-09-16T23:43:53.220

@almel Nowadays the command to get the tx details is bitcoin-cli and not bitcoind. – Thalis K. – 2016-10-20T15:39:55.313

In *NIX the xxd command can be used. echo 636861726c6579206c6f766573206865696469 | xxd -p -r returns charley loves heidi – user207863 – 2018-07-24T19:56:45.663

How is it possible that this famous transaction contains more than 80 bytes?

– robermann – 2018-08-24T08:42:34.320

(it pushes 983 bytes) – robermann – 2018-08-24T09:03:34.827

You say that "no more than one output with OP_RETURN can be included in a single transaction" and provide a pull request as a source for this. Where in this pull request discussion is this mentioned? – dionyziz – 2018-09-21T05:57:55.110

For those wishing to decode the message using JavaScript, the one-liner in Node would be Buffer.from('636861726c6579206c6f766573206865696469', 'hex').toString('utf8'); – Thalis K. – 2019-03-12T11:43:15.023

According to the Script wiki: it is usually considered non-standard (though valid) for a transaction to have more than one OP_RETURN output or an OP_RETURN output with more than one pushdata op.

– Thalis K. – 2019-03-12T11:45:06.803

10

If you want to write OP_RETURNs to the blockchain without getting into the internals of how transactions are built, an easy way is to use our libraries for PHP and Python:

https://github.com/coinspark/php-OP_RETURN

https://github.com/coinspark/python-OP_RETURN

These support either sending individual transactions with one OP_RETURN attached, or else sending a batch of linked transactions to embed larger pieces of content. That content can then be retrieved from the blockchain using a single identifier.

Assuming you're using Bitcoin Core 0.11, you can change the value of OP_RETURN_MAX_BYTES to 80, rather than 40 as it currently stands in the code.

1

OP_RETURN is a way to get arbitrary data into the blockchain with less burden to the network

As a consequence, the data will also be present in less clients, as OP_RETURN data can be pruned out.

The goal of this answer is to explain https://bitcoin.stackexchange.com/a/29555/21282 explained but with a bit more context for Bitcoin newbies.

How a standard transaction looks like

As seen in the JSON disassembly from https://bitcoin.stackexchange.com/a/29555/21282 each transaction has a list of outputs, and each output has a script.

The most common script by far is pay-to-pubkey-hash which basically says:

this output can be consumed by the person who controls the private key to this public key

or in simpler terms "pay X bitcoint to address Y".

That script has format:

OP_DUP OP_HASH160 <length-of-hash> <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG


where pubKeyHash is 20 bytes and all other 5 fields are 1 byte.

It is impossible to know if a standard transaction hash is an actual hash or arbitrary data

Because pubKeyHash is a hash, it is impossible to know if that is the actual hash of something, or arbitrary data someone wants to encode into the blockchain.

The catch is: if you add arbitrary data there, you won't have a corresponding private key to claim back those funds. So what people do is to make transactions with the smallest amount possible that miners are willing to take for the verification work.

Now, every transaction in the blockchain takes as input a previous unspent output.

Therefore, embedding this data costs you a little, because that output is unspendable: it can never be used ad an input of another transaction.

In order to verify if a transaction is valid, Bitcoin implementations have to keep around a full list of every unspent output ever created, known as the UTXO set.

Spent outputs can be pruned to save space, but unspent ones can't.

Therefore, whenever you burn your fake pubkey hash output, you force every single implementation to keep that information around forever, since those funds can never be spent.

How OP_RETURN solves that problem

OP return is another type of script transaction different from the standard pay-to-pubkey-hash transaction.

As mentioned at: https://en.bitcoin.it/wiki/Script#Provably_Unspendable.2FPrunable_Outputs the transaction has simply the form:

OP_RETURN <data>


OP_RETURN simply stops the script execution with a failure, making it impossible for anyone to use that output as the input of another transaction.

Therefore, when a bitcoin implementation sees that transaction, it can immediately decide that it is unspendable, unlike the pay-to-pubkey-hash transaction above, where it is impossible to make that decision. That's why this transaction is called "provably unspendable".

So the miner can mine if for a mining fee, but then implementations immediately prune it from the UTXO set.

This allows the UTXO set to be smaller, thus making bitcoin more efficient to everyone.

But on the other hand, it also means that your embedded data will be present in less people's computers.

0

Note: This is javascript / typescript

export default class OpReturnConverter {

// Input -> <Buffer 35 33 36 39...>
// Output -> 53696d706c6520616e737765722120f09f988a
public static convertBufferToHex(buffer: Buffer) {
const str = buffer.toString('hex')
return Buffer.from(str, 'hex').toString()
}

// Input -> 53696d706c6520616e737765722120f09f988a
public static convertHexToString(hex: string) {
return Buffer.from(hex, 'hex').toString()
}

// Output -> <Buffer 35 33 36 39...>
public static convertStringToBuffer(message: string) {
const hexBuffer = Buffer.from(message).toString('hex')
return Buffer.from(hexBuffer)
}

}


Results

const string = 'Simple answer! '
console.log('Original ->', string)

const buf = OpReturnConverter.convertStringToBuffer(string)
console.log('Buffer ->', buf)

const hex = OpReturnConverter.convertBufferToHex(buf)
console.log('Hex ->', hex)

const unhex = OpReturnConverter.convertHexToString(hex)
console.log('Unhex ->', unhex)