Bitcoin transactions are validated using scripts. Nowadays, the great majority of users and wallets use standard scripts forms, 99.9% of Bitcoins are stored in transaction outputs using standard scripts. The remaining 0.01% of non-standard outputs use more complex script forms, represent challenges, or just are the result of bugs. In this post, I’ll look at some different families of non-standard outputs. The data was collected using bitcoin-blockchain-parser, a Python 3 library I wrote to parse bitcoind database files.
The Bitcoin script language
Present since the first version of Bitcoin, but absent from its original whitepaper, the Bitcoin script language is stack based, like Forth, and is used to validate transactions. In order to spend Bitcoins, a user must provide the missing part of a script that describes how to spend them. This makes Bitcoin a programmable money.
The most common script form is called Pay-To-Pubkeyhash. When redeeming Bitcoins secured by this script form, the user must provide a public key corresponding to a given hash and then sign the transaction with the private key, hence proving he owns the coins.
The available instruction set is not limited to cryptographic operations and allows users to build complex scripts. Conditional flow, arithmetic operations, hash functions, etc. can be used to validate transactions. However, a lot of instructions, such as most of the string related operations as well as some arithmetic and bitwise logic operators, are disabled due to security concerns.
Mistakes and bugs
Some non-standard scripts are visibly the result of mistakes or bugs.
Between February 2nd, 2012 and April 1st, 2012, a bug in P2Pool software created a bogus output at the end of every coinbase of the majority of the blocks the pool mined. The total amount lost was 0.60280235 BTC. This bogus output was:
OP_IFDUP OP_IF OP_2SWAP OP_VERIFY OP_2OVER OP_DEPTH
This script does not make any sense and is not even valid as the OP_IF is not closed by a corresponding OP_ENDIF. However, we can understand what happened by looking at the script’s ascii value: “script”. A discussion of the event is available on this Bitcointalk thread.
Another series of non-standard outputs due to a bug occured on November 28th, 2011. In these outputs, the script structure is identical to a Pay-To-PubkeyHash output, with the difference that the pubkeyhash is set to a null byte, making them unspendable. This time, the outputs represents a value of 2609.36304319 BTC, around $8000 at that time. A Bitcointalk thread indicates that this mistake was made by MtGox and represented a loss of one week of their BTC-only revenue.
Hash function challenges
Another family of non-standard outputs uses the presence of standard hash functions in the script instruction set to create challenges. These outputs can only be spent by providing data that once hashed by a cryptographic function is equal to a given hash.
Using such outputs to secure Bitcoins is not secure at all as anyone can reproduce a transaction spending such outputs. At least 55 outputs used this technique, representing a combined value of 2.04 BTC. At the moment I write these lines, only 5 of these outputs remain unpsent, with a combined value of 1.0056 BTC. The biggest unredeemed output (1 BTC) is interesting. In order to spend it, you must provide data that gives the following hash when hashed twice using SHA-256:
This is the hash of the genesis block, but as block hashes’ string are represented as the inverse of their hexadecimal value, this script is for the moment unredeemable.
Some non-standard outputs are just standard outputs in disguise, using the OP_DROP operator to add data that is discarded during verification.
For example, in this transaction, the script :
was used to send 0.2 BTC to the address 1LoLCaTphKrx1ohbRu7r8rPDr5sNq3Kqbg without any block explorer indexing the address.
Only 8 outputs used this technique, the most recent dating back to May 2014, for a combined value of 0.335 BTC.
Some scripts are trivial to solve, for example, OP_1, which is in itself a valid script or OP_MIN OP_3 OP_EQUAL, used 4 times, which requires to provide 2 numbers of which the smallest is 3.
Some scripts represent more complex mathematical equations, such as:
OP_2DUP OP_ADD OP_8 OP_EQUALVERIFY OP_SUB OP_2 OP_EQUAL
which represents the equation:
x + y - 8 = x - y - 2 = 0
This script was redeemed using x=5 and y=3 (the only solution).
Another equation can be found in this script:
OP_ADD OP_ADD OP_13 OP_EQUAL 203c73637269707420747970653d27746578742f6a617661736372697074273e646f63756d656e742e777269746528273c696d67207372633d5c27687474703a2f2f7777772e74726f6c6c626f742e6f72672f7873732d626c6f636b636861696e2d6465746563746f722e7068703f62633d62746326687265663d27202b206c6f636174696f6e2e68726566202b20275c273e27293b3c2f7363726970743e20 OP_DROP
The script itself is made of two parts, a mathematical equation :
x + y + z = 13
And an XSS detector, a hex value is pushed then dropped from the stack and represents the ascii for:
This output was spent with the numbers 4, 6 and 3.