Bitcoin Forum

Bitcoin => Development & Technical Discussion => Topic started by: fabbit on January 12, 2020, 04:18:17 PM



Title: Digital signature in Bitcoin
Post by: fabbit on January 12, 2020, 04:18:17 PM
The meaning of digital signature in Bitcoin can be summarize as "a digital signature can be used to unlock outputs, because it shows that we know the private key of an address"? Where the address refers to the receiver.

Following this guide https://bitcoin.org/en/transactions-guide#introduction (https://bitcoin.org/en/transactions-guide#introduction) I don't understand this:
Quote
the data Bob signs includes:
1) the txid and output index of the previous transaction
2)the previous output’s pubkey script
3) the pubkey script Bob creates which will let the next recipient spend this transaction’s output
4)the amount of satoshis to spend to the next recipient

I don't understand in particular these points:
2) Why do we need to sign previous output's pubkey script?
3) and 4) if this is the unlocking script  why do we need to sign things for next transactions?

Thanks,


Title: Re: Digital signature in Bitcoin
Post by: Theb on January 12, 2020, 05:00:00 PM
I'm not the best member to answer this but basically this is all about validating the new transaction. Since for example this guy "Bob" is trying to make a transaction/spend from his unspent transaction output (UXTO) which he received earlier and a validator needs to find the txout from this UXTO and validate it if this is spendable on Bob's end. Basically what it tries to do is to see if that UXTO was really received by Bob and to see if he can spend it on a new transaction.


Title: Re: Digital signature in Bitcoin
Post by: darosior on January 12, 2020, 05:48:35 PM
Hi,

The meaning of digital signature in Bitcoin can be summarize as "a digital signature can be used to unlock outputs, because it shows that we know the private key of an address"? Where the address refers to the receiver.
"because it satisfies the conditions of a standard script type", but yeah it "shows" that you own the private key without revealing it.
The address doesn't refer to the receiver, see it more like "the conditions to satisfy to spend the newly created output".

I don't understand in particular these points:
2) Why do we need to sign previous output's pubkey script?
3) and 4) if this is the unlocking script  why do we need to sign things for next transactions?
As you broadcast the transaction in an untrusted environment, signing crucial parts certifies that it cannot be tampered. Here tampering, for example, the locking script (scriptpubkey) of the newly created output would change the conditions under which this output is spendable. With a higher level of abstraction it'd "send the coins to another destination".

EDIT: For going further, you could give a look to SIGHASHes which dictates which parts of a transaction are signed, leaving some malleability/flexibility for some advanced usage.


Title: Re: Digital signature in Bitcoin
Post by: Coding Enthusiast on January 12, 2020, 06:21:56 PM
2) Why do we need to sign previous output's pubkey script?

The only person who can answer this is the creator (Satoshi Nakamoto) since it was his decision to design the system like this. There are discussions about this already here (https://bitcoin.stackexchange.com/a/50566/87716) and here (https://bitcointalk.org/index.php?topic=102487.0) that you can read for more information.

Security-wise I can think of no reason why you would include previous transaction's PubkeyScript in your transaction since your transaction already has a reference to it when it includes the hash of the previous tx and signs it no matter what SigHashType you use.


Title: Re: Digital signature in Bitcoin
Post by: gmaxwell on January 14, 2020, 07:36:48 PM
Security-wise I can think of no reason why you would include previous transaction's PubkeyScript in your transaction since your transaction already has a reference to it when it includes the hash of the previous tx and signs it no matter what SigHashType you use.

It makes more sense when you consider codeseperator.

Say there is some txout that can be spent by:   (yoursig AND mysig) or (mysig and hash-preimage-you-provide).   You tell me you're gonna redeem using the hash path and ask me to sign a transaction paying to you.  I'm happy with you taking the coins so long as I learn the hash, so I sign.

But then you're evil and you use my signature in the first branch along with your signature which isn't what I agreed to.  If there is a codeseperator between these branches the signed scriptpubkey is different and the signature cannot be rebound.

You could use a different pubkey for each of these cases, but that's another 33 bytes required which could be avoided.

Satoshi also might have been anticipating sighash flags that didn't commit to the input. In those cases you'd still want the scriptpubkey in the signature. It turns out that not signing the input creates a big mess... so if he was thinking of that he might have abandoned the idea because of all the issues with it.


Title: Re: Digital signature in Bitcoin
Post by: fabbit on January 15, 2020, 01:37:59 PM
EDIT: For going further, you could give a look to SIGHASHes which dictates which parts of a transaction are signed, leaving some malleability/flexibility for some advanced usage.

I'm reading about this, but for example considering SIGHASH_SINGLE "This type of signature signs all inputs, and exactly one corresponding output", in a transaction like this A->B->C, B's unlocking script has the sign but does he signs A's outputs or new generated B's output?


Title: Re: Digital signature in Bitcoin
Post by: BrewMaster on January 15, 2020, 04:17:45 PM
in a transaction like this A->B->C, B's unlocking script has the sign but does he signs A's outputs or new generated B's output?

a transaction is like this:
Code:
input1
input2
...
inputn
Code:
output1
output2
...
outputm

each input has a reference inside of it (called outpoint which is a hash and an index) which determines which locking script they use. when you are signing that input you first get that script and use it in producing the signature while setting every other input's script to empty.

different SIGHASH doesn't change this at all. the only thing they change is which parts of the entire transaction structure is being signed.
for example if it is SIGHASH_SINGLE then you still do the same thing as i said but instead of hashing the entire transaction you hash the inputs and one output (it is a little more complicated than that).


Title: Re: Digital signature in Bitcoin
Post by: fabbit on January 15, 2020, 05:05:04 PM
Because according to this:
Quote
the data Bob signs includes the txid and output index of the previous transaction, the previous output’s pubkey script, the pubkey script Bob creates which will let the next recipient spend this transaction’s output, and the amount of satoshis to spend to the next recipient. In essence, the entire transaction is signed except for any signature scripts, which hold the full public keys and secp256k1 signatures.

These are the parts that are signed in a transaction by default so using SIGHASH_ALL


Title: Re: Digital signature in Bitcoin
Post by: darosior on January 15, 2020, 08:43:37 PM
*Sorry I answered but never clicked on post.....*
I'm reading about this, but for example considering SIGHASH_SINGLE "This type of signature signs all inputs, and exactly one corresponding output", in a transaction like this A->B->C, B's unlocking script has the sign but does he signs A's outputs or new generated B's output?
`SIGHASH_SINGLE` signs the input and output at the same index, and partially signs other inputs.

I'm not sure of this `A->B->C` transaction you're describing; if this is something like
Code:
 ---------------------------
| A's input | output 0 (C?) |
| B's input | output 1 (C?) |
 ---------------------------
then A signs the input at index 0 and the output at index 0, and B signs the input at index 1 along with the output at index 1. Could you be more precise about the structure of the transaction you're talking about ?


Title: Re: Digital signature in Bitcoin
Post by: BrewMaster on January 16, 2020, 04:42:44 AM
i think you may have been thrown off because of SIGHASHes and you may benefit from looking at what a transaction looks like.
a transaction is like this:
Code:
version
txin_count(3)
   [input_0]:txid | index | scriptsig | sequence
   [input_1]:txid | index | scriptsig | sequence
   [input_3]:txid | index | scriptsig | sequence
txout_count(2)
   [output_0]:amount | scriptpub
   [output_1]:amount | scriptpub
locktime
forget about SegWit and SIGHAH for now.

to sign or verify the signature of this transaction you look at each input. they all have a "reference" to what they are spending. using the txid and the index you can find that transaction. so lets say the input_0 is this (from this transaction (https://blockchair.com/bitcoin/transaction/61888c8209d1bb63e6a00d5f3c5bed86b3982482ab049f2c06a9023dd33708cf):
Code:
txid= 7f920a59108b7434a77af8c392a940e51d50db998280969ab80d9428a80d8448
index = 1
now the node is going to get the transaction that is being spent by having its hash and then look among its txouts at index 1 and it can get this:
Code:
OP_DUP OP_HASH160 <0148352b01e7b93c6af2aa134d3a59a1bfbf3fd8> OP_EqualVerify OP_CheckSig
now that you have the scriptpub you can start serializing the transaction in a way to be hashed and then signed.
the way it works for this type is to set the scriptsig of the txin you are signing to this scriptpub and setting every other scriptsig to empty.

up to this point is the same steps used no matter what the SIGHASH is.

now if the SIGHASH is ALL you sign the entire thing.
Code:
version
txin_count(3)
   [input_0]:txid | index | scriptpub | sequence
   [input_1]:txid | index | empty | sequence
   [input_3]:txid | index | empty | sequence
txout_count(2)
   [output_0]:amount | scriptpub
   [output_1]:amount | scriptpub
locktime

if it is NONE then you sign everything except outputs:
Code:
version
txin_count(3)
   [input_0]:txid | index | scriptpub | sequence
   [input_1]:txid | index | empty | 0
   [input_3]:txid | index | empty | 0
txout_count(0)
locktime

if it is SINGLE then you sign a single "input" (your own input) and the outputs
Code:
version
txin_count(3)
   [input_0]:txid | index | scriptpub | 0
   [input_1]:txid | index | empty | 0
   [input_3]:txid | index | empty | 0
txout_count(1)
   [output_0]:amount | scriptpub
locktime

and if any of the above has ANYONECANPAY only one input is being signed. there are also some more details that i skipped.

now that you are done with first input (input_0) you move to the next input (input_1) and repeat the same thing for that:
look at its txid:index, get the scriptpub, build the serialization, hash, sign/verify.
for example for ALL:
Code:
version
txin_count(3)
   [input_0]:txid | index | empty | sequence
   [input_1]:txid | index | scriptpub | sequence
   [input_3]:txid | index | empty | sequence
txout_count(2)
   [output_0]:amount | scriptpub
   [output_1]:amount | scriptpub
locktime


Title: Re: Digital signature in Bitcoin
Post by: fabbit on January 17, 2020, 06:37:39 PM
For example could you show me how SIGHASH works for this kind of transaction?
https://imgur.com/a/4suwZTO

Thanks,


Title: Re: Digital signature in Bitcoin
Post by: BrewMaster on January 18, 2020, 03:19:41 AM
For example could you show me how SIGHASH works for this kind of transaction?
https://imgur.com/a/4suwZTO

Thanks,

there are 2 transactions in this picture and there are 6 total SIGHASHes that could be used to sign a transaction and since each input can have its own different SIGHASH that makes it 24 different ways to sign the 2 transactions in that picture with total of 4 inputs!
please be more precise about which one you want to see?


Title: Re: Digital signature in Bitcoin
Post by: fabbit on January 18, 2020, 02:23:50 PM
After reading this article (page 30): https://www.lopp.net/pdf/Bitcoin_Developer_Reference.pdf (https://www.lopp.net/pdf/Bitcoin_Developer_Reference.pdf)
it is clearer, but I don't understand point a).
I don't understand why the scriptSig is replaced with pubKeyScript and what OP_CODESEPARATOR does.

Thanks,