2023.07 Vol.2

Bit of signature hashes

Signature Hashes

The CHECKSIG opcode in bitcoin’s Script is the bread and butter of bitcoin transactions. One of the most popular ways to lock bitcoin into a UTXO is with a script which can only be unlocked by the holder of a private key. The CHECKSIG-based scripts require the private key holders to create a signature with the private key to prove ownership. What do the holders sign for the signature? Well, the spending transaction itself! This is a double-whammy of proof-of-ownership of the key as well as proof that the owner wants to move the bitcoin in the UTXO. A transaction is a set of inputs and a set of outputs and usually all of them are hash’d and then signed. However, it is possible for an input to only “cover” a subset of the inputs or outputs. This is done through the SIGHASH flag which describes which inputs and outputs are being signed off by the signer. The flag is appended to the signature so that the CHECKSIG opcode knows what parts of the transaction to check. The flag is also appended to the transaction before it is signed so that it too is “covered” by the signature.

There are six possible flags:

  • ALL – Signature applies to all inputs and outputs. The general case.
  • NONE – Signature applies to all inputs, none of the outputs. A “blank check”.
  • SINGLE – Signature applies to all inputs but only the one output with the same index number as the input. Dunno of a use case.
  • ALL|ANYONECANPAY – Signature applies to one input and all outputs. A “crowd fund” transaction.
  • NONE|ANYONECANPAY – Signature applies to one input, none of the outputs. A “dust” donation.
  • SINGLE|ANYONECANPAY – Signature applies to one input and the one output with the same index number as the input. Dunno of a use case.

Granular transaction hashing is a cool concept, but it doesn’t seem like a ton of uses cases have taken off yet. Even coinjoin transactions, which I figured would be a great use case of one of these more granular flags, just uses the default ALL. I think it has something to do with the more granular flags giving away who owns the resulting UTXOs, kinda defeating the point of a coinjoin.

Anyways, the general concept behind the SIGHASH flag can kinda be viewed as a “sneak preview” of some hotly debated new opcodes. The original model for transaction inputs, in my mind at least, was “if you can unlock this, you can do what ever you want with this bitcoin”. It is a subtle difference, but the CHECKSIG opcode doesn’t just unlock the UTXO, it describes how the outputs of the new transactions have to use the unlocked bitcoin. Now there is not a lot of flexibility in how to describe these outputs. The signature needs to exactly match output script and amount for all “covered” outputs. It doesn’t have the smarts of some thing like “send X sats to Y OR Z sats to A”. There is also the fact that the transaction and the signature are both produced by the payee. But what if the payer wants to describe the possible outputs?

Why would we want that flexibility? Time to talk about covenants.