Verifying a digital signature that a transaction is going to an output with value X inside a script 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.