Edit; after writing this post i have found that OP_CHECKDATASIG is basically this in a nutshell. It is implemented on Bitcoin Cash and may soon be on Bitcoin Core as well.

Someone has even written this post into a Bitcoin Cash smart contract: https://honest.cash/pein_sama/spending-constraints-with-op_checkdatasig-172


but in bitcoin usually the message is a hash of the previous transaction and the 'to' pubkey-hash and/or transaction? Unless i am missing something, the SIGHASH_SINGLE parameter specifically signs only the input and output of the new transaction. So, if you could create this input and output, and sign it inside an OP_CODE with a privatekey, you could verify that an output was going to a particular person inside a bitcoin script sig. Of course, the private key holding that UTXO would be unusable except for returning BTC to the user, or perhaps another pubkey could be used to spend the UTXO.

This is incorrect. Transaction signing works by:

for every input i in inputs:
    Start with a transaction skeleton that matches the transaction for non-input/output fields like tx version
    Add the input i
    Add other inputs and outputs based on the sighash flag
    Hash this update tx skeleton
    Sign the hash

The SIGHASH flags simplify specify which inputs and outputs are covered by the signature. For SIGHASH_ALL, the entire input and output set is signed. For SIGHASH_SINGLE, only the output corresponding to the index of the input is signed (for the first input in a tx, the first output will be signed). You also have additional options such as ANYONE_CAN_PAY which allow addition inputs to be added later, by only signing your input (for use with coinjoins).

By using SIGHASH_ALL | SIGHASH_ANYONECANPAY or SIGHASH_SINGLE | SIGHASH_ANYONECANPAY flags, if you already control an output, you can specify something such as:

If this output is used as an input, at least X BTC must be sent to {these|this} new output(s).

However, this restriction only applies if the final transaction uses this specific signed input - nothing prevents you from creating another signed tx that spends that same output to a different destination and broadcasting it first.

Your example fails since within the signature, you have no information about the output. The data that is signed is that of an augmented tx skeleton as a whole - you cannot use Bitcoin Script to inspect a subset of that data and validate the signature.

To take the example another way, let us say we construct a bitcoin script equivalent to:

Accept a signature and a public key
Verify that the signature is over the data (input,hash160(public_key)
Verify the signature is performed by the same key that unlocks the input being spent

This would seem to imply that we can sign the destination public key using the same private key that owns the input, and then have a script that validates both the tx signature, and the signature over the public key we claim to send to.

However, in this case, nothing prevents you from feeding a valid signature and destination public key to the script, but specifying a completely different output in the actual tx - This is because there is simply no way for the Bitcoin Script program to read and check where the tx output(s) are actually going.

  • Wait, really? I can sign a group of inputs, and a group of outputs. Where the inputs provides only 0.1 BTC from my accounts. And the outputs provide 10.0 BTC as output. (invalid tx) And If i sign it with "SIGHASH_ALL | SIGHASH_ANYONE_CAN_PAY", then the transaction will go through if someone adds inputs totaling 9.9 BTC? (And I understand that it would only apply to this signed input; I could rebroadcast if i wanted) Mar 30 '19 at 4:17
  • Or can you still only sign valid TX like this? Mar 30 '19 at 4:18
  • 1
    Yes, that's correct. You can construct a partial tx, with insufficient inputs or outputs and wait for other people to complete it. I wrote a blog post on this some time ago with more detail/examples, if you are interested: raghavsood.com/blog/2018/06/10/bitcoin-signature-types-sighash Mar 30 '19 at 4:19
  • Thanks. I have been studying your blog post. It seems if I want people to be able to add outputs, the SIGHASH_SINGLE is the only way to do it. But this limits to a single output. I wish that I could sign multiple outputs and still have someone else add outputs. Mar 30 '19 at 5:00
  • You can, in a round about way. If you own n utxos, you can create a tx with n inputs, each signed with SIGHASH_SINGLE for their corresponding output (1 through n). Then, anyone else can add more outputs after the fifth one Mar 30 '19 at 5:49

Yes, this is possible in the Bitcoin Cash blockchain only. It would also be possible in OP_CODES, but much harder.

Here's how it works:

In the script signature, we check both OP_CHECKSIG and OP_CHECKDATASIG. First, OP_CHECKSIG goes "outside" and checks that the signature validates the transaction outputs. Thus, the signature variable has now been externally-verified to contain information from the transaction outputs.

In OP_CHECKDATASIG, we then verify that an input variable called "preimage" is the precursor to this exact "signature". Since digital signatures are unique, this pre-image must be the transaction itself. So, we now have a variable called preimage, that, transitively, is externally-verified to the transaction outputs. Coincidentally, this is also the raw transaction data containing the outputs.

Finally, we step through the preimage to determine the contents of the transaction before allowing spending. Very cool. (edited)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.