Libbitcoin: Embedd Data in the Blockchain with OP_Return


OP_RETURN is the formal way of embedding data into the blockchain. By using a special script operation, we can create an output with a value of 0 and a script that includes up to 80 bytes of arbitrary data. By using the OP_RETURN code we create an unspendable output, meaning no unlocking script will satisfy this and the network nodes can remove them from their utxo mempools. Now, these transaction’s still need to pay a fee in order for the miner’s to include them in a block, and since the size of these transactions is generally higher than a standard transaction the fee included should be higher to ensure it gets confirmed. Any data can be stored in this field of the output, including special protocol tags for digital assets, contracts and metacoins.


In libbitcoin, creating a null data script is easy with the help of a stack factory which means we just need to create another output with a special script to add data. I’m going to append my previous rawTX program to include another output which includes some data.

For the initial output I’m going to send the value of a utxo back to myself, minus the miner fee. I’m going to do this by updating the presets in my getInput() testing function. I also went ahead and added a 7th preset field with a string of ascii characters to post on the blockchain.

//This is a testing class
//use it to pass hardcoded strings
//to the prompts by changing the string
//declarations function and passing the preset
std::string getInput(int preset)
 if(preset == 1)
 return "[ YOUR MNEMONIC SEED ]"; //Mnemonic
 } else if (preset == 2)
 return "1"; //Index of child key
 }else if (preset == 3)

 return "n2ge1S4bLDvJKx8AGXrK5JHY2D5cReVytu"; //Destination Adress
 }else if (preset == 4)
 return "1.48192700"; //Amount of Bitcoin to Spend
 } else if (preset == 5)
 return "ce7f741625dfa86a50a1f18e3664e927441e27ef2f1c526e3aff8ea6c7a650fd"; //UTXO hash to spend

 }else if (preset == 6)
 return "0"; //Output index of UTXO
 }else if (preset == 7) 
 return "HelloWorld";

Now, all I need to do to include the data in the transaction is add get the string and use a special made libbitcoin serializer to write the string as data. Bitcoin output’s can have up to 80 bytes of data included so we are making the data chunk 80 bytes.

For obvious reasons, namely fees, it’s usually practical to only use the amount of data you need as not to bloat the blockchain when not on the testnet.

Once we have the data_chunk and an 80 byte buffer we can create the serializer and deserializer and write the string to the data chunk. After that we can output the encoded bytes to the terminal and save the bytes in the nullData variable.

 std::string messageString = getInput(7);
 data_chunk data(80);
 auto source = make_safe_deserializer(data.begin(), data.end());
 auto sink = make_unsafe_serializer(data.begin());

 const auto nullData = source.read_bytes(80);
 std::cout <<; "Message: " << std::endl;
 std::cout << encode_base16(nullData) << std::endl; 

Once the data is saved, we can create an output object and use a to_null_data_pattern script factory to pass the data into an OP_RETURN script. By passing that script factory and and the value 0 to the output setters, the output is finished.

 output output2 = output();

With the output done, it simply needs to be pushed back on the transaction objects outputs vector.

 //build TX
 transaction tx = transaction();

This script can be compile the same as the last rawTX program and the displayed rawTX can be broadcast to the network embedding the message.

 $ g++ -std=c++11 -o rawTX rawTX.cpp $(pkg-config --cflags libbitcoin --libs libbitcoin)
$ ./rawTX

The output should look like this:


Inspect your transaction on blocktrail and you can see the two script’s one sending the change back to you and the other with your encoded message.


This hex data represents the ascii characters in your message, some block explorers, like blocktrail will convert the hex to ascii for you:


Bam! Data Embedded for all Eternity.

Leave a Reply

Your email address will not be published.