Author

Topic: How does Bitcoin verify a signature against its hash160 pubkey? (Read 1653 times)

legendary
Activity: 1260
Merit: 1019
What are the detailed steps for doing this?
The first step is looking for ECDSA_SIG_recover_key_GFp method in Bitcoin Core sources.

Having the public key saves on computation time since it is hashed and compared first before
doing the more expensive signature validation operations. Otherwise attackers could just put
invalid signatures which first have to go through expensive signature operations to get the public key,
and then compare the public key last. That could potentially be a DoS attack vector.
These lines should be printed in bold font in "ECDSA for dummies" book  Grin
sr. member
Activity: 364
Merit: 255
There is also some additional overhead for transaction version and data lengths.
In fact, the public key is also "overhead", because it can be derived from digest, signature and hash160.


What are the detailed steps for doing this?
staff
Activity: 3458
Merit: 6793
Just writing some code
There is also some additional overhead for transaction version and data lengths.
In fact, the public key is also "overhead", because it can be derived from digest, signature and hash160.
Having the public key saves on computation time since it is hashed and compared first before doing the more expensive signature validation operations. Otherwise attackers could just put invalid signatures which first have to go through expensive signature operations to get the public key, and then compare the public key last. That could potentially be a DoS attack vector.
legendary
Activity: 1260
Merit: 1019
There is also some additional overhead for transaction version and data lengths.
In fact, the public key is also "overhead", because it can be derived from digest, signature and hash160.
sr. member
Activity: 364
Merit: 255
hero member
Activity: 793
Merit: 1026
So, consider two transactions Tx1 and Tx2, in this case Tx2 spends the output of Tx1.

The output of Tx1 contains the receiver's Hash160 public key.

When the receiver wants to spend his Bitcoin, he creates Tx2, which references Tx1's output as input.

In the scriptSig part of Tx2, the receiver inserts his signature and his original public key, then broadcast this transaction to the network.

If the scriptSig passes verification, then Tx1 is spent by Tx2.

Did I explain this correctly?

Yes, that is correct.

To get into more detail:  the verification process is actually a program that runs and outputs "true" or "false" at the end of it, or crashes while running, which is treated as a "false".  In the case of a normal address spend -- like the situation you are talking about -- the program is:


Code:
Step 1:  keep the signature handy because we'll need it later


Step 2:  keep the public key handy because we'll need that also


Step 3:  make a copy of whatever data was in Step 2 (which in this case is the public key)
-- which stands for DUPLICATE

Step 4:  make a hash160 of the copied data from step 3


Step 5:  Put this other hash next to the hash we derived in step 4


Step 6:  Compare the two values produced by steps 4 and 5 (in this case, two hashes -- the one provided by the output, and the one derived by the scriptSig field's public key) and check to make sure the two hashes are equal, otherwise the transaction is invalid. Then, assuming they're equal, toss them out, so all we have is that original signature and public key from the first two steps.


Step 7:  Assume the two things left are a signature and public key and attempt to validate the signature with the given public key.  If it's a bad signature, or if they're not a signature and public key, mark the transaction as invalid. If they are a signautre and public key and it's a good signature, output "true"


That's the full program that runs.  The "code" for that program is "written" by putting whatever code is in the spending transaction's signature field in front of whatever code is in the input transaction's output field, and combining them together, and running that combined code as a single program.  If the program runs without fail and returns "true", the transaction is valid.

There are for example "addresses" where the output "address" code just says "return true" and the spending transaction doesn't have any code at all.  And of course that combined program does indeed return true and is a valid transaction.  And there are "addresses" that can never be spent.  You've heard of "OP_RETURN"?  Well that particular bit of code means "stop validating the transaction and return false".  That's why those outputs can never be spent.  Because eventually the code-checker hits that instruction and dutifully stops checking and returns false, making the transaction invalid.

The term "address" is really deceiving, because there aren't actually addresses.  There are no accounts.  There are only these little mini-programs that run.  The term "address" is just for us humans to make Bitcoin seem easier.  An "address" is just an output with a piece of code which gets executed when it is spent.
sr. member
Activity: 364
Merit: 255
So, consider two transactions Tx1 and Tx2, in this case Tx2 spends the output of Tx1.

The output of Tx1 contains the receiver's Hash160 public key.

When the receiver wants to spend his Bitcoin, he creates Tx2, which references Tx1's output as input.

In the scriptSig part of Tx2, the receiver inserts his signature and his original public key, then broadcast this transaction to the network.

If the scriptSig passes verification, then Tx1 is spent by Tx2.

Did I explain this correctly?
legendary
Activity: 3472
Merit: 4801
- snip -
So, the spending transaction contains both the original public key and its hash160 version?
- snip -

That is incorrect.

As has been explained twice:

- snip -
the script in the spending transaction is:

Code:

- snip -

- snip -
the format of the input is as follows
Code:

When verifying the signature, a node will first hash the provided public key.  Then it will compare that to the hash in the output that is being spent. This proves that the provided public key is the correct one. It will then verify the signature against the provided public key.

staff
Activity: 3458
Merit: 6793
Just writing some code
Thanks. So, the spending transaction contains both the original public key and its hash160 version?
No. The hash160 is not put in the spending transaction. In order to fully verify a transaction, you must have the transactions that it spends from (or at least their outputs) so that the scripts can be concatenated to be validated.

If you want to spend your coins, you send your public key, signature along with the hash160 to miners, correct?
No. You create a transaction and broadcast that transaction to everyone on the network. The transaction contains the reference to the outputs that you are spending from, the input scripts necessary to spend those outputs, and the outputs that you want to create. There is also some additional overhead for transaction version and data lengths.
sr. member
Activity: 364
Merit: 255
The signature field of the spending transaction (the "scriptSig" field) contains both the signature and the public key.  To validate the transaction, the public key is first hashed and compared against the hash in the reference output.  If the hashes match, then the public key is used to verify the signature.

The script for the output is:

Code:
xxx(hash)xxx

and the script in the spending transaction is:

Code:


Those get concatinated together to form the complete script:

Code:
xxx(hash)xxx

which is executed as per the rules found here:

https://en.bitcoin.it/wiki/Script


Thanks. So, the spending transaction contains both the original public key and its hash160 version? If you want to spend your coins, you send your public key, signature along with the hash160 to miners, correct?
staff
Activity: 3458
Merit: 6793
Just writing some code
The public key is part of the transaction. When spending from a P2PKH output, the format of the input is as follows
Code:
hero member
Activity: 793
Merit: 1026
The signature field of the spending transaction (the "scriptSig" field) contains both the signature and the public key.  To validate the transaction, the public key is first hashed and compared against the hash in the reference output.  If the hashes match, then the public key is used to verify the signature.

The script for the output is:

Code:
xxx(hash)xxx

and the script in the spending transaction is:

Code:


Those get concatinated together to form the complete script:

Code:
xxx(hash)xxx

which is executed as per the rules found here:

https://en.bitcoin.it/wiki/Script
sr. member
Activity: 364
Merit: 255
In a Bitcoin transaction, the TxIn contains the signature of the current redeemer and TxOut the hash160 of the next redeemer's public key. The hash160 is defined as ripemd160(sha256(data)). So, it's impossible to get the original hash of the public key. My question is, to verify a ECDSA signature, one must has the original public key. In which step does this original public key appear? Is this key also sent to other peer nodes? Does Bitcoin maintain a global database of public keys for every address?
Jump to: