Guest Opinion/Editorial by Antony Zegers, taken from his “The Story of OP_CHECKDATASIG.”

This article describes the design of an opcode recently added to the Bitcoin Cash scripting language called OP_CHECKDATASIG [1]. This opcode was activated on the Bitcoin Cash network during the recent upgrade. It allows Script to validate arbitrary messages from outside the blockchain, opening up many exciting possible use cases.

More Spice: Bitcoin White Paper Webcomic by Comics Legend Scott McCloud

OP_CHECKDATASIG: Opening Many Exciting Possible Use Cases

When someone sends a Bitcoin Cash transaction, they sign it to prove to the network that the owner of the private key authorizes the transaction. The signature is typically verified using an opcode called “OP_CHECKSIG” that calculates a hash based on a portion of the data in the transaction, and checks the signature against that.

The signature is equivalent to a contract that says the owner of the private key authorizes the transaction. OP_CHECKSIG has a few different ways it can hash the transaction (known as the “Sighash”), to allow different conditions on the transfer.

In general, however, it is equivalent to a contract that only defines the transfer of money. But what if you could also sign other pieces of information in the transaction? This would allow other information to be included and signed as part of the transfer contract. This is the idea behind OP_CHECKDATASIG.

Un-Bundling

One way to think of OP_CHECKDATASIG is as an un-bundling of OP_CHECKSIG. The design of OP_CHECKSIG bundles two distinct concepts together: calculating the Sighash, and checking the signature of that hash. If we imagine re-implementing OP_CHECKSIG as two instructions, OP_CHECKDATASIG would be the second instruction.

It simply checks a signature against a supplied message and public key. This unbundling means that OP_CHECKDATASIG is not designed for any particular use-case, but can instead be used flexibly for any use that requires checking a signature against a supplied message. A non-exhaustive list of uses that have emerged so far can be found in Appendix A.

Motivation

The motivation behind OP_CHECKDATASIG was to continue the process of improving the Bitcoin Cash Script language. As such, the instruction is intended to be a generic and flexible building block with many potential uses.

OP_CHECKDATASIG is based on Andrew Stone’s OP_DATASIGVERIFY proposal [2]. The original motivation behind the opcode was to be able to validate signatures from an “oracle” on messages from outside the blockchain.

This use case has been described in an article by Andrew Stone [3]. After the original proposal was made, it went through a series of changes and design refinements based on review and discussion by stakeholders and subject-matter experts [4].

Little Quirks

Overall, the theme of the changes was to make the design mirror existing opcodes more closely, and making no assumptions about how it would be used. This makes it a more conservative and minimal change than the original proposal. For example, the OP_DATASIGVERIFY proposal used a pubkey-recoverable signature encoding, different from OP_CHECKSIG.

Though the design choices of the original proposal may have had certain advantages, in general the reviewers preferred an approach of sticking close to the design of what is already in the protocol. This helps lower risk by creating minimal change in the implementation.

All the little quirks of OP_CHECKSIG are well understood, having been battle-tested on the blockchain for many years. Sticking to the same underlying primitives keep the design in a well understood and safe territory. As a result, the implementation details of OP_CHECKDATASIG are very close to OP_CHECKSIG [5].

Novel Potential Use-Cases

An interesting thing happened on this journey, however. Though the driving motivation of the design changes were conservatism and safety, by making the implementation mirror OP_CHECKSIG, some novel potential use-cases were discovered.

The original OP_DATASIGVERIFY proposal took a message of any size as input, then hashed it before checking the signature. Through the review process, following the idea of structuring OP_CHECKDATASIG as the second step in OP_CHECKSIG, it seemed like a nice design to make the opcode take a hash value as input. This also fit with the philosophy of keeping the opcode as a simple minimal building block.

Upon further review, it was realized that passing in a value to be signed without hashing allows it to be used in a potentially insecure manner. This problem was identified by Andrew Stone on June 16th, as well as other reviewers. This not be a problem if used properly, but made it possible for Script authors to use it insecurely if they were careless. So the design was changed back to hashing the input with double-SHA256, which is the standard hash method in Bitcoin.

Threading the Needle

However, in the period where the design did not hash the input, some people (awemany in particular) realized something interesting: the fact that the opcode did not hash the input meant that you could pass in a Sighash value from another transaction as the message, and the signatures would match. This means that it becomes possible for OP_CHECKDATASIG to test whether it has been supplied with the valid signature for a completely different transaction.

Changing the opcode to doing a double-SHA256 hash on the input would still allow this sighash-as-message use, however now you would have to pass in the full pre-image of the hash, which is the serialized transaction data. This data would typically be be hundreds of bytes which would need to be included in the transaction, making this use unwieldy. Luckily, the reviewers found a solution that threaded the needle between both options, yielding both safety and convenience: do a single-SHA256 hash in the input.

Doing a single-SHA256 means the input is hashed, so it is secure, but it also means that a partial sighash which has only gone through one round of SHA256 can be passed in (only 32 bytes on the stack), which when hashed again with another round will yield the full sighash.

Spendability

Mark B. Lundeberg also noticed that PGP signatures use a single-SHA256. So moving to single-SHA256 makes the signature compatible with PGP, also opening up other potential uses.

These capabilities open up exciting possibilities. It means that OP_CHECKDATASIG can make spendability dependent on completely separate unrelated transaction being signed. This can work even for transactions on different blockchains, as long as the transaction signing algorithm is compatible with Bitcoin Cash.

This group includes Bitcoin, Litecoin, Dash, ZCash. I will leave it to people more creative that I to find novel ways to use this capability. There have already been several ideas floated such as atomic digital goods purchase, and double-spend prevention [6, 7]. A list of some uses that have emerged so far is provided in Appendix A, and I look forward to many new uses haven’t yet been thought of.

Conclusion

The addition of OP_CHECKDATASIG adds a useful new capability to the Bitcoin Cash scripting language: the ability to validate messages from outside the blockchain. By reaching out and engaging subject matter experts and different stakeholders, the initial proposal was modified to address concerns.

Through this process, not only did it retain the core utility, but the capabilities were expanded with more exciting potential uses. The modifications made the new version a more conservative change that sticks closer to the existing system, and also a more flexible tool with novel capabilities.

For acknowledgements, postscripts, references, and appendices, please click here.