second edit, improved btcdeb discussion

This commit is contained in:
Shannon Appelcline 2020-07-21 08:55:18 -10:00 committed by GitHub
parent 4098d55699
commit 373f052b52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -51,12 +51,13 @@ You can see that its `scriptSig` unlocking script has two values. That's a `<sig
``` ```
304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b92cbab7d1022066f273178febc7a37568e2e9f4dec980a2e9a95441abe838c7ef64c39d85849c[ALL] 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b 304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b92cbab7d1022066f273178febc7a37568e2e9f4dec980a2e9a95441abe838c7ef64c39d85849c[ALL] 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b
``` ```
That's all an unlock script is! (For a P2PKH.)
## Understand the Locking Script ## Understand the Locking Script
Remember that each unlocking script unlocks a previous UTXO. In the above example, the `vin` reveals that it's actually unlocking vout `0` of txif `bb4362dec15e67d366088f5493c789f22fb4a604e767dae1f6a631687e2784aa`. Remember that each unlocking script unlocks a previous UTXO. In the above example, the `vin` reveals that it's actually unlocking vout `0` of txid `bb4362dec15e67d366088f5493c789f22fb4a604e767dae1f6a631687e2784aa`.
You can examine that with `gettransaction`. You can examine that UTXO with `gettransaction`.
``` ```
$ bitcoin-cli gettransaction "bb4362dec15e67d366088f5493c789f22fb4a604e767dae1f6a631687e2784aa" $ bitcoin-cli gettransaction "bb4362dec15e67d366088f5493c789f22fb4a604e767dae1f6a631687e2784aa"
{ {
@ -84,7 +85,7 @@ $ bitcoin-cli gettransaction "bb4362dec15e67d366088f5493c789f22fb4a604e767dae1f6
"hex": "020000000001011efcc3bf9950ac2ea08c53b43a0f8cc21e4b5564e205f996f7cadb7d13bb79470000000017160014c4ea10874ae77d957e170bd43f2ee828a8e3bc71feffffff0218730100000000001976a91441d83eaffbf80f82dee4c152de59a38ffd0b602188ac713b10000000000017a914b780fc2e945bea71b9ee2d8d2901f00914a25fbd8702473044022025ee4fd38e6865125f7c315406c0b3a8139d482e3be333727d38868baa656d3d02204b35d9b5812cb85894541da611d5cec14c374ae7a7b8ba14bb44495747b571530121033cae26cb3fa063c95e2c55a94bd04ab9cf173104555efe448b1bfc3a68c8f873342c1b00" "hex": "020000000001011efcc3bf9950ac2ea08c53b43a0f8cc21e4b5564e205f996f7cadb7d13bb79470000000017160014c4ea10874ae77d957e170bd43f2ee828a8e3bc71feffffff0218730100000000001976a91441d83eaffbf80f82dee4c152de59a38ffd0b602188ac713b10000000000017a914b780fc2e945bea71b9ee2d8d2901f00914a25fbd8702473044022025ee4fd38e6865125f7c315406c0b3a8139d482e3be333727d38868baa656d3d02204b35d9b5812cb85894541da611d5cec14c374ae7a7b8ba14bb44495747b571530121033cae26cb3fa063c95e2c55a94bd04ab9cf173104555efe448b1bfc3a68c8f873342c1b00"
} }
``` ```
But as you can see, you didn't get the `scriptPubKey`. You need to take an additional step to retrieve that by examining the raw transaction info (that's the `hex`) with `decoderawtransaction`: But as you can see, you didn't get the `scriptPubKey` with `gettransaction`. You need to take an additional step to retrieve that by examining the raw transaction info (that's the `hex`) with `decoderawtransaction`:
``` ```
$ hex=$(bitcoin-cli gettransaction "bb4362dec15e67d366088f5493c789f22fb4a604e767dae1f6a631687e2784aa" | jq -r '.hex') $ hex=$(bitcoin-cli gettransaction "bb4362dec15e67d366088f5493c789f22fb4a604e767dae1f6a631687e2784aa" | jq -r '.hex')
$ bitcoin-cli decoderawtransaction $hex $ bitcoin-cli decoderawtransaction $hex
@ -143,15 +144,15 @@ $ bitcoin-cli decoderawtransaction $hex
``` ```
You can now look at `vout` `0` and see it was locked with the `scriptPubKey` of `OP_DUP OP_HASH160 41d83eaffbf80f82dee4c152de59a38ffd0b6021 OP_EQUALVERIFY OP_CHECKSIG`. That's the standard locking methodology used for an older P2PKH address with the `<pubKeyHash>` stuck in the middle. You can now look at `vout` `0` and see it was locked with the `scriptPubKey` of `OP_DUP OP_HASH160 41d83eaffbf80f82dee4c152de59a38ffd0b6021 OP_EQUALVERIFY OP_CHECKSIG`. That's the standard locking methodology used for an older P2PKH address with the `<pubKeyHash>` stuck in the middle.
Running it will show how it works. Running it will demonstrate how it works.
## Run a P2PKH Script ## Run a P2PKH Script
When you unlock a P2PKH UTXO, you (effectively) concatenate the unlocking and locking scripts, producing: When you unlock a P2PKH UTXO, you (effectively) concatenate the unlocking and locking scripts. For a P2PKH address, like the example used in this chapter, that produces:
``` ```
Script: <signature> <pubKey> OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG Script: <signature> <pubKey> OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
``` ```
Now, you can examinine how the P2PKH UTXO is unlocked. With that put together, you can examinine how a P2PKH UTXO is unlocked.
First, you put the initial constants on the stack, then make a duplicate of the pubKey with `OP_DUP`: First, you put the initial constants on the stack, then make a duplicate of the pubKey with `OP_DUP`:
``` ```
@ -168,7 +169,7 @@ Script: OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
Running: <pubKey> OP_DUP Running: <pubKey> OP_DUP
Stack: [ <signature> <pubKey> <pubKey> ] Stack: [ <signature> <pubKey> <pubKey> ]
``` ```
Why the duplicate? Because that's what the script says to do! Why the duplicate? Because it's needed to check the two unlocking elements: the public key and the signature.
Next, `OP_HASH160` pops the `<pubKey>` off the stack, hashes it, and puts the result back on the stack. Next, `OP_HASH160` pops the `<pubKey>` off the stack, hashes it, and puts the result back on the stack.
``` ```
@ -195,11 +196,11 @@ Script:
Running: <signature> <pubKey> OP_CHECKSIG Running: <signature> <pubKey> OP_CHECKSIG
Stack: [ True ] Stack: [ True ]
``` ```
The Script now ends and the transaction is allowed to respend the UTXO in question. The Script now ends and if it was successful, the transaction is allowed to respend the UTXO in question.
### Use btcdeb for a P2PKH Example ### Use btcdeb for a P2PKH Example
Testing out actual Bitcoin transactions with `btcdeb` is a bit trickier, because you need to know the public key and a signature to make everything work, and generating the latter is somewhat difficult. However, one way to test things is to let Bitcoin do the work for you in generating a transaction that will unlock a UTXO. That's what you've done above, generating a new transaction to let `bitcoin-cli` do the work of calculating the `<signature>` and `<pubKey>` and then looking at the raw transaction information of the UTXO to learn the locking script including the `<pubKeyHash>` Testing out actual Bitcoin transactions with `btcdeb` is a bit trickier, because you need to know the public key and a signature to make everything work, and generating the latter is somewhat difficult. However, one way to test things is to let Bitcoin do the work for you in generating a transaction that _would_ unlock a UTXO. That's what you've done above: generating the transaction to spend the UTXO caused `bitcoin-cli` to calculate the `<signature>` and `<pubKey>`. You then look at the raw transaction information of the UTXO to learn the locking script including the `<pubKeyHash>`
You can put together the locking script, the signature, and the pubkey using `btcdeb`, showing how simple a P2PKH script is. You can put together the locking script, the signature, and the pubkey using `btcdeb`, showing how simple a P2PKH script is.
``` ```
@ -210,30 +211,33 @@ valid script
7 op script loaded. type `help` for usage information 7 op script loaded. type `help` for usage information
script | stack script | stack
-------------------------------------------------------------------+------------------------------------------------------------------- -------------------------------------------------------------------+-------------------------------------------------------------------
304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b... | and_v( 304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b... |
0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b | sig(304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c... 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b |
OP_DUP | and_v( OP_DUP |
OP_HASH160 | pk(0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3... OP_HASH160 |
41d83eaffbf80f82dee4c152de59a38ffd0b6021 | c:pk_h(030500000000000000000000000000000000000000000000... 41d83eaffbf80f82dee4c152de59a38ffd0b6021 |
OP_EQUALVERIFY | ) OP_EQUALVERIFY |
OP_CHECKSIG | OP_CHECKSIG |
| ) |
| |
#0000 304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b92cbab7d1022066f273178febc7a37568e2e9f4dec980a2e9a95441abe838c7ef64c39d85849c #0000 304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b92cbab7d1022066f273178febc7a37568e2e9f4dec980a2e9a95441abe838c7ef64c39d85849c
```
You push the `<signature>` and `<pubKey>` onto the stack:
```
btcdeb> step btcdeb> step
<> PUSH stack 304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b92cbab7d1022066f273178febc7a37568e2e9f4dec980a2e9a95441abe838c7ef64c39d85849c <> PUSH stack 304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b92cbab7d1022066f273178febc7a37568e2e9f4dec980a2e9a95441abe838c7ef64c39d85849c
script | stack script | stack
-------------------------------------------------------------------+------------------------------------------------------------------- -------------------------------------------------------------------+-------------------------------------------------------------------
0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b | 304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b... 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b | 304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b...
OP_DUP | OP_DUP |
OP_HASH160 | and_v( OP_HASH160 |
41d83eaffbf80f82dee4c152de59a38ffd0b6021 | sig(304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c... 41d83eaffbf80f82dee4c152de59a38ffd0b6021 |
OP_EQUALVERIFY | and_v( OP_EQUALVERIFY |
OP_CHECKSIG | pk(0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3... OP_CHECKSIG |
| c:pk_h(030500000000000000000000000000000000000000000000... |
| ) |
|
| |
| )
| |
#0001 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b #0001 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b
btcdeb> step btcdeb> step
@ -243,15 +247,18 @@ script |
OP_DUP | 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b OP_DUP | 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b
OP_HASH160 | 304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b... OP_HASH160 | 304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b...
41d83eaffbf80f82dee4c152de59a38ffd0b6021 | 41d83eaffbf80f82dee4c152de59a38ffd0b6021 |
OP_EQUALVERIFY | and_v( OP_EQUALVERIFY |
OP_CHECKSIG | sig(304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c... OP_CHECKSIG |
| and_v(
| pk(0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3...
| c:pk_h(030500000000000000000000000000000000000000000000...
| )
| |
| )
| |
|
|
|
|
|
```
You `OP_DUP` and `OP_HASH` the `<pubKey>`:
```
#0002 OP_DUP #0002 OP_DUP
btcdeb> step btcdeb> step
<> PUSH stack 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b <> PUSH stack 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b
@ -261,14 +268,14 @@ OP_HASH160 | 0315a0aeb37
41d83eaffbf80f82dee4c152de59a38ffd0b6021 | 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b 41d83eaffbf80f82dee4c152de59a38ffd0b6021 | 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b
OP_EQUALVERIFY | 304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b... OP_EQUALVERIFY | 304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b...
OP_CHECKSIG | OP_CHECKSIG |
| and_v(
| sig(304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c...
| and_v(
| pk(0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3...
| c:pk_h(030500000000000000000000000000000000000000000000...
| )
| |
| ) |
|
|
|
|
|
|
| |
#0003 OP_HASH160 #0003 OP_HASH160
btcdeb> step btcdeb> step
@ -280,15 +287,18 @@ script |
OP_EQUALVERIFY | 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b OP_EQUALVERIFY | 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b
OP_CHECKSIG | 304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b... OP_CHECKSIG | 304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b...
| |
| and_v(
| sig(304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c...
| and_v(
| pk(0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3...
| c:pk_h(030500000000000000000000000000000000000000000000...
| )
| |
| )
| |
|
|
|
|
|
|
|
```
You push the `<pubKeyHash>` from the locking script onto the stack and verify it:
```
#0004 41d83eaffbf80f82dee4c152de59a38ffd0b6021 #0004 41d83eaffbf80f82dee4c152de59a38ffd0b6021
btcdeb> step btcdeb> step
<> PUSH stack 41d83eaffbf80f82dee4c152de59a38ffd0b6021 <> PUSH stack 41d83eaffbf80f82dee4c152de59a38ffd0b6021
@ -299,14 +309,14 @@ OP_CHECKSIG |
| 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b | 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b
| 304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b... | 304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b...
| |
| and_v(
| sig(304402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c...
| and_v(
| pk(0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3...
| c:pk_h(030500000000000000000000000000000000000000000000...
| )
| |
| ) |
|
|
|
|
|
|
| |
#0005 OP_EQUALVERIFY #0005 OP_EQUALVERIFY
btcdeb> step btcdeb> step
@ -328,16 +338,21 @@ OP_CHECKSIG | 0315a0aeb37
| |
| ) | )
| |
```
And that point, all that's required is the `OP_CHECKSIG`:
```
#0006 OP_CHECKSIG #0006 OP_CHECKSIG
btcdeb> step btcdeb> step
error: Signature is found in scriptCode error: Signature is found in scriptCode
[[NOTE: THIS CURRENTLY HAS SOME MESS IN THE OUTPUT AND THE CHECKSUM]]
``` ```
If you read through that you can see the usage of elements like the `OP_DUP` to duplicate the hash for testing, and how that result is then pushed out of the way to test out the signature. As is shown, a P2PKH is quite simple: its protection comes about those the strength of its cryptography. (Unfortunately this checking may or may not be working at any point due to vagaries of the Bitcoin Core and `btcdeb` code.)
As is shown, a P2PKH is quite simple: its protection comes about those the strength of its cryptography.
### How to Look Up a Pub Key & Signature by Hand ### How to Look Up a Pub Key & Signature by Hand
What if you wanted to generate the <signature> and <PubKey> information yourself, without leaning on `bitcoin-cli` to create a transaction. What if you wanted to generate the `<signature>` and `<PubKey>` information needed to unlock a UTXO yourself, without leaning on `bitcoin-cli` to create a transaction?
It turns out that it's pretty easy to get a `<pubKey>` You just need to use `getaddressinfo` to examine the address where the UTXO is currently sitting: It turns out that it's pretty easy to get a `<pubKey>` You just need to use `getaddressinfo` to examine the address where the UTXO is currently sitting:
``` ```
@ -363,7 +378,7 @@ $ bitcoin-cli getaddressinfo mmX7GUoXq2wVcbnrnFJrGKsGR14fXiGbD9
] ]
} }
``` ```
Figuring out that signature, however, requires really understanding the nuts and bolts of how Bitcoin transactions are created. So we leave that as advanced study for the reader: creating a transaction to "solve" a UTXO is the best solution to that for the moment. Figuring out that signature, however, requires really understanding the nuts and bolts of how Bitcoin transactions are created. So we leave that as advanced study for the reader: creating a `bitcoin-cli` transaction to "solve" a UTXO is the best solution to that for the moment.
## Summary: Scripting a Pay to Public Key Hash ## Summary: Scripting a Pay to Public Key Hash