Supertestnet is back with more fun things to do on the weird fringes of Bitcoin script.
You can watch him explain it here or skip the video to read his explanation down lower:
The Sighash Single Bug (SSB) is a bug in bitcoin's signature checking algorithm that affects certain legacy transactions, i.e. ones that don't use segwit.
The bug involves bitcoin's "sighash" function, which determines what message a user has to sign to create a valid signature for their transaction. All signatures in bitcoin are supposed to sign the hash -- or "sighash," as it is called -- of a truncated version of the transaction about to be broadcasted.
That strange bug causes several headaches. For example, if someone knows you have a bitcoin address containing a bunch of money, and they somehow convince you to sign that message with its private key, they can take your money. They have to manually create a bitcoin transaction that has your address in one of the inputs, e.g. in position 2, don't create an output in position 2, and add the signature they got from you in the signature field. Then they can use their own bitcoin addresses to fill any gaps in the input list, add one of their own bitcoin addresses as an output, and voila! Any money you had becomes theirs.
Recently, I realized that the bug can be exploited to do a basic form of transaction introspection. If you create a bitcoin script that "intentionally" exploits the sighash_single bug, it tells you information about the transaction that triggered it. A bitcoin script can require the user to pass in a signature that uses sighash_single and a pubkey, and check if the resulting signature is valid for the buggy sighash.
I ended up coming up with a list of things your script can learn by checking if the exploit triggers, and here is that list:
- if the exploit triggers, then the "input position" of the utxo being spent is greater than position 1 (or 0, if you prefer indexing from 0)
- if the exploit triggers, then the number of inputs is at least 2
- if the exploit triggers, then the number of outputs is less than the number of inputs
- if the exploit does NOT trigger, then there is an output at the current input position
With that list in mind, I started playing with scripts that check if the bug triggers and either succeed or fail depending on the outcome, and figured out that I can create bitcoin addresses that use this information to place "restrictions" on the transactions that try to spend them -- like "this transaction must have more inputs than outputs" (an FTX restriction, also used in the Cleanup restriction) or "this transaction must have an output at index N" (a GTX restriction).
Is any of this useful? I'm not sure, it's certainly interesting to me, and that was enough for me to work on it. But I did think of one use case: an FTX restriction forces the spender's transaction to have more inputs than outputs, which means you can create and fund a bitcoin address that can only be spent from in a transaction that "cleans up" more utxos than it creates.
In an interesting side note, @1440000bytes also spent some time poking around the sighash bug in 2023, and speculated that it might be useful.
And Andrew Poelstra wrote about something similar in 2021.