mirror of
https://github.com/ChristopherA/Learning-Bitcoin-from-the-Command-Line.git
synced 2025-06-06 23:46:22 +00:00
first, edited draft
This commit is contained in:
parent
36209965b9
commit
482fa16835
@ -1,297 +1,119 @@
|
||||
# 7.3: Scripting a P2PKH
|
||||
# 9.5: Scripting a P2WPKH
|
||||
|
||||
> :information_source: **NOTE:** This is a draft in progress, so that I can get some feedback from early reviewers. It is not yet ready for learning.
|
||||
|
||||
With a basic understanding of Bitcoin Scripting in hand, you can now easily analyze the functioning of a standard P2PKH script.
|
||||
P2PKHs are fine for explaining the fundamental way that Bitcoin Scripts work, but what about native Segwit P2WPKH scripts, which are increasingly becoming the majority of Bitcoin transactions? As it turns out, P2WPKH addresses don't use Bitcoin Scripts like traditional Bitcoin addresses do, and so this section is really a digression from the scripting of this chapter — but an important one, because it outlines the _other_ major way in which Bitcoins can be transacted.
|
||||
|
||||
## Understand the Unlocking Script
|
||||
## View a P2WPKH Script
|
||||
|
||||
We've long said that when funds are sent to a Bitcoin address, they're locked to the private key associated with that address. This is managed through the `scriptPubKey` of a P2PKH transaction, which is designed such that it requires the recipient to have the private key associated with the the P2PKH Bitcoin address. To be precise, the recipient must supply both the actual public key and a signature generated by the private key.
|
||||
|
||||
That's what the `scriptSig` unlocking script seen in the previous section showed, a `<signature> <pubKey>`:
|
||||
`3045022100c4ef5b531061a184404e84ab46beee94e51e8ae15ce98d2f3e10ae7774772ffd02203c546c399c4dc1d6eea692f73bb3fff490ea2e98fe300ac6a11840c7d52b6166[ALL] 0319cd3f2485e3d47552617b03c693b7f92916ac374644e22b07420c8812501cfb`.
|
||||
|
||||
## Understand the Locking Script
|
||||
|
||||
The associated `scriptPubKey` locking script from the previous section was `OP_DUP OP_HASH160 371c20fb2e9899338ce5e99908e64fd30b789313 OP_EQUALVERIFY OP_CHECKSIG`, which is the standard locking methodology for a P2PKH address. That long string in the middle is a `<pubKeyHash>`.
|
||||
|
||||
## Run a P2PKH Script
|
||||
|
||||
When you unlock a P2PKH UTXO, you (effectively) concatenate the unlocking and locking scripts, producing:
|
||||
It's easy enough to see what a P2WPKH script looks like. The following raw transaction was created by spending a P2WPKH UTXO and then sending the money on to a P2WPKH change address — just as we did with a legacy address in [§9.1](09_1_Understanding_the_Foundation_of_Transactions.md).
|
||||
```
|
||||
Script: <signature> <pubKey> OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
|
||||
$ bitcoin-cli -named decoderawtransaction hexstring=$signedtx
|
||||
{
|
||||
"txid": "bdf8f12768a9870d41ac280f8bb4f8ecd9d2fa66fffc75606811f5751c17cb3a",
|
||||
"hash": "ec09c84cae48694bec7fd3461b3c5b38a76829c56e9d876037bf2484d443174b",
|
||||
"version": 2,
|
||||
"size": 191,
|
||||
"vsize": 110,
|
||||
"weight": 437,
|
||||
"locktime": 0,
|
||||
"vin": [
|
||||
{
|
||||
"txid": "3f5417bc7a3a4144d715f3f006d35ea2b405f06091cbb9ce492e04ccefe02b18",
|
||||
"vout": 0,
|
||||
"scriptSig": {
|
||||
"asm": "",
|
||||
"hex": ""
|
||||
},
|
||||
"txinwitness": [
|
||||
"3044022064f633ccfc4e937ef9e3edcaa9835ea9a98d31fbea1622c1d8a38d4e7f8f6cb602204bffef45a094de1306f99da055bd5a603a15c277a59a48f40a615aa4f7e5038001",
|
||||
"03839e6035b33e37597908c83a2f992ec835b093d65790f43218cb49ffe5538903"
|
||||
],
|
||||
"sequence": 4294967295
|
||||
}
|
||||
],
|
||||
"vout": [
|
||||
{
|
||||
"value": 0.00090000,
|
||||
"n": 0,
|
||||
"scriptPubKey": {
|
||||
"asm": "0 92a0db923b3a13eb576a40c4b35515aa30206cba",
|
||||
"hex": "001492a0db923b3a13eb576a40c4b35515aa30206cba",
|
||||
"reqSigs": 1,
|
||||
"type": "witness_v0_keyhash",
|
||||
"addresses": [
|
||||
"tb1qj2sdhy3m8gf7k4m2grztx4g44gczqm96y6sszv"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
Now, you can evaluate how the P2PKH UTXO is unlocked.
|
||||
There are probably two surprising things here: (1) There's no `scriptSig` to unlock the previous transaction; and (2) the `scriptPubKey` to lock the new transaction is just `0 92a0db923b3a13eb576a40c4b35515aa30206cb`.
|
||||
|
||||
First, you put the initial constants on the stack, then make a duplicate of the pubKey with `OP_DUP`:
|
||||
That's, quite simply, because P2WPKH works differently!
|
||||
|
||||
## Understand a P2WPKH Transaction
|
||||
|
||||
A P2WPKH transaction contains all the same information as a classic P2PKH transaction, but it places it in weird places, not within a traditional Bitcoin Script — and, that's the exact point of SegWit transactions, to pull the "witness" information, which is to say the public keys and signatures, out of the transaction to support a change to block size.
|
||||
|
||||
But, if you look carefully, you'll see that the empty `scriptSig` has been replaced with two entries in a new `txinwitness` section. If you examine their sizes and formatting, they should seem familiar: they're a signature and public key. Similarly, if you look in the `scriptPubKey`, you'll see that it's made up of a `0` (actually: `OP_0`, it's the SegWit version number) and another long number, which is the public-key hash.
|
||||
|
||||
Here's a comparison of our two examples:
|
||||
| Type | PubKeyHash | PubKey | Signature |
|
||||
|----------------|----------|-------------|---------|
|
||||
| SegWit | 92a0db923b3a13eb576a40c4b35515aa30206cba | 03839e6035b33e37597908c83a2f992ec835b093d65790f43218cb49ffe5538903 | 3044022064f633ccfc4e937ef9e3edcaa9835ea9a98d31fbea1622c1d8a38d4e7f8f6cb602204bffef45a094de1306f99da055bd5a603a15c277a59a48f40a615aa4f7e5038001 |
|
||||
| SegWit | 06b5c6ba5330cdf738a2ce91152bfd0e71f9ec39 | 0315a0aeb37634a71ede72d903acae4c6efa77f3423dcbcd6de3e13d9fd989438b | 04402201cc39005b076cb06534cd084fcc522e7bf937c4c9654c1c9dfba68b92cbab7d1022066f273178febc7a37568e2e9f4dec980a2e9a95441abe838c7ef64c39d85849c |
|
||||
|
||||
So how does this work? It depends on old code interpreting this as a valid transaction and new code knowing to check the new "witness" information
|
||||
|
||||
### Read a SegWit Script on an Old Machine
|
||||
|
||||
If a node has not been upgraded to support SegWit, then it does its usual trick of concatenating the `scriptSig` and the `scriptPubKey`. This produces: `0 92a0db923b3a13eb576a40c4b35515aa30206cba` (because there's only a `scriptPubKey`). Running that will produce a stack with everything on it in reverse order:
|
||||
```
|
||||
Script: <signature> <pubKey> OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
|
||||
Stack: [ ]
|
||||
|
||||
Script: <pubKey> OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
|
||||
Stack: [ <signature> ]
|
||||
|
||||
Script: OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
|
||||
Stack: [ <signature> <pubKey> ]
|
||||
|
||||
Script: OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
|
||||
Running: <pubKey> OP_DUP
|
||||
Stack: [ <signature> <pubKey> <pubKey> ]
|
||||
```
|
||||
Why the duplicate? Because that's what's required by the script!
|
||||
|
||||
Next, `OP_HASH160` pops the `<pubKey>` off the stack, hashes it, and puts the result back on the stack.
|
||||
```
|
||||
Script: <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
|
||||
Running: <pubKey> OP_HASH160
|
||||
Stack: [ <signature> <pubKey> <pubKeyHash> ]
|
||||
```
|
||||
Then, you place the `<pubKeyHash>` that was in the locking script on the stack:
|
||||
```
|
||||
Script: OP_EQUALVERIFY OP_CHECKSIG
|
||||
Stack: [ <signature> <pubKey> <pubKeyHash> <pubKeyHash> ]
|
||||
```
|
||||
`OP_EQUALVERIFY` is effectively two opcodes: `OP_EQUAL`, which pops two items from the stack and pushes `True` or `False` depending on if they're equal; and `OP_VERIFY` which pops that result and immediately marks the transaction as invalid if it's `False`. (Chapter 10 talks more about the use of `OP_VERIFY` as a conditional.)
|
||||
|
||||
Assuming the two `<pubKeyHash>es` are equal, you will have the following result:
|
||||
```
|
||||
Script: OP_CHECKSIG
|
||||
Running: <pubKeyHash> <pubKeyHash> OP_EQUALVERIFY
|
||||
Stack: [ <signature> <pubKey> ]
|
||||
```
|
||||
At this point you've proven that the `<pubKey>` supplied in the `scriptSig` hashes to the Bitcoin address in question, so you know that the redeemer knew the public key. They just need to prove knowledge of the private key, which is done with `OP_CHECKSIG`, which confirms that the unlocking script's signature matches that public key.
|
||||
```
|
||||
Script:
|
||||
Running: <signature> <pubKey> OP_CHECKSIG
|
||||
Stack: [ True ]
|
||||
```
|
||||
The Script now ends and the transaction is allowed to respend the UTXO in question.
|
||||
|
||||
|
||||
## Running through a real example
|
||||
|
||||
If you have a scriptPubKey (the script) and a signature and pubkey (the result of running the sigScript of the input), you can debug these by doing
|
||||
|
||||
```Bash
|
||||
$ btcdeb <script> <signature> <pubkey>
|
||||
```
|
||||
|
||||
For example, transaction [4de699d05b416175ad7a119013563a0f436abe46c6a52f05bf59baca1b2aec41](https://www.smartbit.com.au/tx/4de699d05b416175ad7a119013563a0f436abe46c6a52f05bf59baca1b2aec41) in block 499033 has as its first output the script sig `483045022100c7d8e302908fdc601b125c2734de63ed3bf54353e13a835313c2a2aa5e8f21810220131fad73787989d7fbbdbbd8420674f56bdf61fed5dc2653c826a4789c685011012103b05bdbdf395e495a61add92442071e32703518b8fca3fc34149db4b56c93be42`.
|
||||
|
||||
The spent transaction output (txid [d0fcb7713582e7cda598d79b3ab084132f93db00e2ccde9bbd1d2660c55abe47](https://www.smartbit.com.au/tx/d0fcb7713582e7cda598d79b3ab084132f93db00e2ccde9bbd1d2660c55abe47) index 33) has as its script pub key `76a914897c81ac37ae36f7bc5b91356cfb0138bfacb3c188ac`.
|
||||
|
||||
We can interpret this in two ways. Either put the two together into one big script:
|
||||
```Bash
|
||||
$ btcdeb 483045022100c7d8e302908fdc601b125c2734de63ed3bf54353e13a835313c2a2aa5e8f21810220131fad73787989d7fbbdbbd8420674f56bdf61fed5dc2653c826a4789c685011012103b05bdbdf395e495a61add92442071e32703518b8fca3fc34149db4b56c93be4276a914897c81ac37ae36f7bc5b91356cfb0138bfacb3c188ac
|
||||
btcdeb -- type `btcdeb -h` for start up options
|
||||
$ btcdeb '[0 92a0db923b3a13eb576a40c4b35515aa30206cba]'
|
||||
btcdeb 0.2.19 -- type `btcdeb -h` for start up options
|
||||
miniscript failed to parse script; miniscript support disabled
|
||||
valid script
|
||||
7 op script loaded. type `help` for usage information
|
||||
script | stack
|
||||
-------------------------------------------------------------------+--------
|
||||
3045022100c7d8e302908fdc601b125c2734de63ed3bf54353e13a835313c2a... |
|
||||
03b05bdbdf395e495a61add92442071e32703518b8fca3fc34149db4b56c93be42 |
|
||||
OP_DUP |
|
||||
OP_HASH160 |
|
||||
897c81ac37ae36f7bc5b91356cfb0138bfacb3c1 |
|
||||
OP_EQUALVERIFY |
|
||||
OP_CHECKSIG |
|
||||
```
|
||||
Or we can interpret them one at a time, and use the script sig resulting stack as the input stack to the script pub key -- since we only really want the
|
||||
output, we can pipe the script to `btcdeb` and it will just print out the results (presuming the script executes cleanly):
|
||||
```Bash
|
||||
$ echo "483045022100c7d8e302908fdc601b125c2734de63ed3bf54353e13a835313c2a2aa5e8f21810220131fad73787989d7fbbdbbd8420674f56bdf61fed5dc2653c826a4789c685011012103b05bdbdf395e495a61add92442071e32703518b8fca3fc34149db4b56c93be42" | btcdeb
|
||||
3045022100c7d8e302908fdc601b125c2734de63ed3bf54353e13a835313c2a2aa5e8f21810220131fad73787989d7fbbdbbd8420674f56bdf61fed5dc2653c826a4789c68501101
|
||||
03b05bdbdf395e495a61add92442071e32703518b8fca3fc34149db4b56c93be42
|
||||
```
|
||||
We can then run the script pub key with these two stack entries as arguments:
|
||||
```Bash
|
||||
$ btcdeb 76a914897c81ac37ae36f7bc5b91356cfb0138bfacb3c188ac \
|
||||
3045022100c7d8e302908fdc601b125c2734de63ed3bf54353e13a835313c2a2aa5e8f21810220131fad73787989d7fbbdbbd8420674f56bdf61fed5dc2653c826a4789c68501101 \
|
||||
03b05bdbdf395e495a61add92442071e32703518b8fca3fc34149db4b56c93be42
|
||||
btcdeb -- type `btcdeb -h` for start up options
|
||||
valid script
|
||||
5 op script loaded. type `help` for usage information
|
||||
script | stack
|
||||
-----------------------------------------+-------------------------------------------------------------------
|
||||
OP_DUP | 03b05bdbdf395e495a61add92442071e32703518b8fca3fc34149db4b56c93be42
|
||||
OP_HASH160 | 3045022100c7d8e302908fdc601b125c2734de63ed3bf54353e13a835313c2a...
|
||||
897c81ac37ae36f7bc5b91356cfb0138bfacb3c1 |
|
||||
OP_EQUALVERIFY |
|
||||
OP_CHECKSIG |
|
||||
#0001 OP_DUP
|
||||
```
|
||||
We can also be fancy and run the results of the pipe call as argument to the second call,
|
||||
```Bash
|
||||
$ btcdeb 76a914897c81ac37ae36f7bc5b91356cfb0138bfacb3c188ac $(echo "483045022100c7d8e302908fdc601b125c2734de63ed3bf54353e13a835313c2a2aa5e8f21810220131fad73787989d7fbbdbbd8420674f56bdf61fed5dc2653c826a4789c685011012103b05bdbdf395e495a61add92442071e32703518b8fca3fc34149db4b56c93be42" | btcdeb)
|
||||
btcdeb -- type `btcdeb -h` for start up options
|
||||
valid script
|
||||
5 op script loaded. type `help` for usage information
|
||||
script | stack
|
||||
-----------------------------------------+-------------------------------------------------------------------
|
||||
OP_DUP | 03b05bdbdf395e495a61add92442071e32703518b8fca3fc34149db4b56c93be42
|
||||
OP_HASH160 | 3045022100c7d8e302908fdc601b125c2734de63ed3bf54353e13a835313c2a...
|
||||
897c81ac37ae36f7bc5b91356cfb0138bfacb3c1 |
|
||||
OP_EQUALVERIFY |
|
||||
OP_CHECKSIG |
|
||||
#0001 OP_DUP
|
||||
```
|
||||
|
||||
Either way we do it, we end up with the script on the left hand side and the stack on the right hand side.
|
||||
The top-most item in the stack is the top item, and things are "popped off" from top to bottom.
|
||||
The first item here is a public key and the second item is a signature.
|
||||
|
||||
We can check the stack directly using the `stack` command.
|
||||
```Bash
|
||||
btcdeb> stack
|
||||
<01> 03b05bdbdf395e495a61add92442071e32703518b8fca3fc34149db4b56c93be42 (top)
|
||||
<02> 3045022100c7d8e302908fdc601b125c2734de63ed3bf54353e13a835313c2a2aa5e8f21810220131fad73787989d7fbbdbbd8420674f56bdf61fed5dc2653c826a4789c68501101
|
||||
```
|
||||
We can also check the script we're running with `print`:
|
||||
```Bash
|
||||
btcdeb> print
|
||||
-> #0001 OP_DUP
|
||||
#0002 OP_HASH160
|
||||
#0003 897c81ac37ae36f7bc5b91356cfb0138bfacb3c1
|
||||
#0004 OP_EQUALVERIFY
|
||||
#0005 OP_CHECKSIG
|
||||
```
|
||||
The `->` arrow shows us the next instruction that is to be executed. If we run `step` we will perform the `OP_DUP` command:
|
||||
```Bash
|
||||
2 op script loaded. type `help` for usage information
|
||||
script | stack
|
||||
-----------------------------------------+--------
|
||||
0 |
|
||||
92a0db923b3a13eb576a40c4b35515aa30206cba |
|
||||
#0000 0
|
||||
btcdeb> step
|
||||
<> PUSH stack 03b05bdbdf395e495a61add92442071e32703518b8fca3fc34149db4b56c93be42
|
||||
script | stack
|
||||
-----------------------------------------+-------------------------------------------------------------------
|
||||
OP_HASH160 | 03b05bdbdf395e495a61add92442071e32703518b8fca3fc34149db4b56c93be42
|
||||
897c81ac37ae36f7bc5b91356cfb0138bfacb3c1 | 03b05bdbdf395e495a61add92442071e32703518b8fca3fc34149db4b56c93be42
|
||||
OP_EQUALVERIFY | 3045022100c7d8e302908fdc601b125c2734de63ed3bf54353e13a835313c2a...
|
||||
OP_CHECKSIG |
|
||||
#0002 OP_HASH160
|
||||
```
|
||||
Firstly, directly following the command are any PUSH or POP operations done to the stack, listed with some right-indentation and with a `<>` prefix.
|
||||
Here we see that `03b...` was pushed onto the stack. The right side shows us that the `03b...` that was there was duplicated and put on the
|
||||
stack again at the top.
|
||||
|
||||
We can keep stepping through the program and watch as it operates on the stack based on the left hand opcodes.
|
||||
```Bash
|
||||
<> PUSH stack
|
||||
script | stack
|
||||
-----------------------------------------+--------
|
||||
92a0db923b3a13eb576a40c4b35515aa30206cba | 0x
|
||||
#0001 92a0db923b3a13eb576a40c4b35515aa30206cba
|
||||
btcdeb> step
|
||||
<> PUSH stack 03b05bdbdf395e495a61add92442071e32703518b8fca3fc34149db4b56c93be42
|
||||
script | stack
|
||||
-----------------------------------------+-------------------------------------------------------------------
|
||||
OP_HASH160 | 03b05bdbdf395e495a61add92442071e32703518b8fca3fc34149db4b56c93be42
|
||||
897c81ac37ae36f7bc5b91356cfb0138bfacb3c1 | 03b05bdbdf395e495a61add92442071e32703518b8fca3fc34149db4b56c93be42
|
||||
OP_EQUALVERIFY | 3045022100c7d8e302908fdc601b125c2734de63ed3bf54353e13a835313c2a...
|
||||
OP_CHECKSIG |
|
||||
#0002 OP_HASH160
|
||||
btcdeb> step
|
||||
<> POP stack
|
||||
<> PUSH stack 897c81ac37ae36f7bc5b91356cfb0138bfacb3c1
|
||||
script | stack
|
||||
-----------------------------------------+-------------------------------------------------------------------
|
||||
897c81ac37ae36f7bc5b91356cfb0138bfacb3c1 | 897c81ac37ae36f7bc5b91356cfb0138bfacb3c1
|
||||
OP_EQUALVERIFY | 03b05bdbdf395e495a61add92442071e32703518b8fca3fc34149db4b56c93be42
|
||||
OP_CHECKSIG | 3045022100c7d8e302908fdc601b125c2734de63ed3bf54353e13a835313c2a...
|
||||
#0003 897c81ac37ae36f7bc5b91356cfb0138bfacb3c1
|
||||
btcdeb>
|
||||
<> PUSH stack 897c81ac37ae36f7bc5b91356cfb0138bfacb3c1
|
||||
script | stack
|
||||
-----------------------------------------+-------------------------------------------------------------------
|
||||
OP_EQUALVERIFY | 897c81ac37ae36f7bc5b91356cfb0138bfacb3c1
|
||||
OP_CHECKSIG | 897c81ac37ae36f7bc5b91356cfb0138bfacb3c1
|
||||
| 03b05bdbdf395e495a61add92442071e32703518b8fca3fc34149db4b56c93be42
|
||||
| 3045022100c7d8e302908fdc601b125c2734de63ed3bf54353e13a835313c2a...
|
||||
#0004 OP_EQUALVERIFY
|
||||
<> PUSH stack 92a0db923b3a13eb576a40c4b35515aa30206cba
|
||||
script | stack
|
||||
-----------------------------------------+-----------------------------------------
|
||||
| 92a0db923b3a13eb576a40c4b35515aa30206cba
|
||||
| 0x
|
||||
```
|
||||
In the second step above, the "opcode" was simply a chunk of data. Data is interpreted as a "push" operation of the data itself,
|
||||
which you can see is what happened here. The next operator is the `OP_EQUALVERIFY` which checks that the two top items are identical.
|
||||
Which you can observe that they are, so the operation should succeed. If the two were not identical, it should fail.
|
||||
Bitcoin Scripts are considered successful if there's something in the Stack, and it's non-zero, so SegWit scripts automatically succeed on old nodes as long as the `scriptPubKey` is correctly created with a non-zero pub-key hash. This is called an "anyone-can-spend" transaction, because old nodes verified them as correct without any need for signatures.
|
||||
|
||||
> *EXERCISE:* Pop off the top entry, and push some other random data on and step into the data. You should receive an error. Now pop your data off and push 897c81ac37ae36f7bc5b91356cfb0138bfacb3c1 back onto the stack and then try stepping again. It should now succeed. Use the `exec` command to perform operations on-the-fly.
|
||||
> :book: ***What can't old nodes steal SegWit UTXOs?*** SegWit was enabled on the Bitcoin network when 95% of miners signalled that they were ready to start using it. That means that only 5% of nodes at that point might have validated anyone-can-spend SegWit transactions as valid without going through the proper work of checking the `txinwitness`. If they incorrectly incorporated an invalid anyone-can-spend UTXO into a block, the other 95% of nodes would refuse to validate that block, and so it would quickly be orphaned rather than being added to the "main" blockchain. (Certainly, 51% of nodes could choose to stop interpreting SegWit transactions correctly, but 51% of nodes can do anything on a consensus network like a blockchain.)
|
||||
|
||||
If you `step` two more times, you will have an error. This is because `btcdeb` does not know enough to verify
|
||||
the signature of the transaction (specifically, it needs the transaction itself). We can pass that in to test the
|
||||
signature verification part as well by grabbing the transaction hex (note: not the txid, we need the entire hex
|
||||
of the transaction) and including it in the call to `btcdeb`.
|
||||
Because old nodes always see SegWit scripts as correct, they will always verify them, even without understanding their content.
|
||||
|
||||
We can get the hex of any transaction by appending `?format=hex` to the end of a transaction on
|
||||
blockchain.info. The transaction here is found at: https://blockchain.info/tx/4de699d05b416175ad7a119013563a0f436abe46c6a52f05bf59baca1b2aec41?format=hex
|
||||
### Read a SegWit Script on a New Machine
|
||||
|
||||
Restart btcdeb with `tx=`(hex):
|
||||
A machine that understands how SegWit work does the exact same things that it would with an old P2PKH script, but it doesn't use a script per se: it just knows that it needs to hash the public key in the `txinwitness`, check that against the hashed key after the version number in the `scriptPubKey` and then runs `OP_CHECKSIG` on the signature and public key in the `txinwitness`.
|
||||
|
||||
```Bash
|
||||
$ ./btcdeb \
|
||||
tx=010000000247be5ac560261dbd9bdecce200db932f1384b03a9bd798a5cde7823571b7fcd0210000006b483045022100c7d8e302908fdc601b125c2734de63ed3bf54353e13a835313c2a2aa5e8f21810220131fad73787989d7fbbdbbd8420674f56bdf61fed5dc2653c826a4789c685011012103b05bdbdf395e495a61add92442071e32703518b8fca3fc34149db4b56c93be42ffffffffc6f5428a05fc20d1aa27c14e1e9bacb07f16d67895d2d48b97792167ad9c7cd1010000006a47304402201b0e1e9e3632740859c1f76dc002af546d28ecca10dbe96f5350fbc8daa3b279022017878fda5c2d47bb03d1554ed4637b554ec63b135df5387a4a32125cda6dd794012103e7cfd3c98952410dd14079e9160f91f968240da2603e25e4b3ef555fc7ed7d09ffffffff030066e9000000000017a9146c52f451a2bc85b815610fa5cd13127cb5c5a7c787c3df5307000000001976a914726d8c8926da39704d60dd401fa4026aa836068e88aca0950100000000001976a91475eac11f3cfda3e79c90469dac0ebaaaacde701488ac00000000 \
|
||||
76a914897c81ac37ae36f7bc5b91356cfb0138bfacb3c188ac \
|
||||
3045022100c7d8e302908fdc601b125c2734de63ed3bf54353e13a835313c2a2aa5e8f21810220131fad73787989d7fbbdbbd8420674f56bdf61fed5dc2653c826a4789c68501101 \
|
||||
03b05bdbdf395e495a61add92442071e32703518b8fca3fc34149db4b56c93be42
|
||||
btcdeb -- type `./btcdeb -h` for start up options
|
||||
got transaction:
|
||||
CTransaction(hash=4de699d05b, ver=1, vin.size=2, vout.size=3, nLockTime=0)
|
||||
CTxIn(COutPoint(d0fcb77135, 33), scriptSig=483045022100c7d8e302908f)
|
||||
CTxIn(COutPoint(d17c9cad67, 1), scriptSig=47304402201b0e1e9e363274)
|
||||
CScriptWitness()
|
||||
CScriptWitness()
|
||||
CTxOut(nValue=0.15296000, scriptPubKey=a9146c52f451a2bc85b815610fa5cd)
|
||||
CTxOut(nValue=1.22937283, scriptPubKey=76a914726d8c8926da39704d60dd40)
|
||||
CTxOut(nValue=0.00103840, scriptPubKey=76a91475eac11f3cfda3e79c90469d)
|
||||
So, it's another way of doing the same thing, but without having the scripts built into the transactions. (The process is built into the node software instead.)
|
||||
|
||||
valid script
|
||||
5 op script loaded. type `help` for usage information
|
||||
script | stack
|
||||
-----------------------------------------+-------------------------------------------------------------------
|
||||
OP_DUP | 03b05bdbdf395e495a61add92442071e32703518b8fca3fc34149db4b56c93be42
|
||||
OP_HASH160 | 3045022100c7d8e302908fdc601b125c2734de63ed3bf54353e13a835313c2a...
|
||||
897c81ac37ae36f7bc5b91356cfb0138bfacb3c1 |
|
||||
OP_EQUALVERIFY |
|
||||
OP_CHECKSIG |
|
||||
#0001 OP_DUP
|
||||
btcdeb> step
|
||||
[...]
|
||||
々 step
|
||||
TransactionSignatureChecker::CheckSig(72 len sig, 33 len pubkey, sigversion=0)
|
||||
sig = 3045022100c7d8e302908fdc601b125c2734de63ed3bf54353e13a835313c2a2aa5e8f21810220131fad73787989d7fbbdbbd8420674f56bdf61fed5dc2653c826a4789c68501101
|
||||
pub key = 03b05bdbdf395e495a61add92442071e32703518b8fca3fc34149db4b56c93be42
|
||||
script code = 76a914897c81ac37ae36f7bc5b91356cfb0138bfacb3c188ac
|
||||
hash type = 01 (SIGHASH_ALL)
|
||||
SignatureHash(nIn=0, nHashType=01)
|
||||
- sigversion = SIGVERSION_BASE (non-segwit style)
|
||||
Serializing transaction
|
||||
<< txTo.nVersion (00000001)
|
||||
<< nInputs = 2 [compact]
|
||||
(serialize input 0)
|
||||
<< txTo.vin[nInput=0].prevout = COutPoint(d0fcb77135, 33)
|
||||
(SerializeScriptCode)
|
||||
<< scriptCode.size()=25 - nCodeSeparators=0
|
||||
<< script:76a914897c81ac37ae36f7bc5b91356cfb0138bfacb3c188ac
|
||||
<< txTo.vin[nInput].nSequence = 4294967295 [0xffffffff]
|
||||
(serialize input 1)
|
||||
<< txTo.vin[nInput=1].prevout = COutPoint(d17c9cad67, 1)
|
||||
<< [empty script] (reason: nInput != nIn)
|
||||
<< txTo.vin[nInput].nSequence = 4294967295 [0xffffffff]
|
||||
<< nOutputs = 3 [compact]
|
||||
(serialize output 0)
|
||||
<< txTo.vout[nOutput] = CTxOut(nValue=0.15296000, scriptPubKey=a9146c52f451a2bc85b815610fa5cd)
|
||||
(serialize output 1)
|
||||
<< txTo.vout[nOutput] = CTxOut(nValue=1.22937283, scriptPubKey=76a914726d8c8926da39704d60dd40)
|
||||
(serialize output 2)
|
||||
<< txTo.vout[nOutput] = CTxOut(nValue=0.00103840, scriptPubKey=76a91475eac11f3cfda3e79c90469d)
|
||||
<< txTo.nLockTime = 0 [0x0]
|
||||
sighash = 8b2fc7c4b0ce353c524dbd1059f2fcb7355597555e5d840ad5506d9b473923fd
|
||||
pubkey.Verify(sig=3045022100c7d8e302908fdc601b125c2734de63ed3bf54353e13a835313c2a2aa5e8f21810220131fad73787989d7fbbdbbd8420674f56bdf61fed5dc2653c826a4789c685011, sighash=8b2fc7c4b0ce353c524dbd1059f2fcb7355597555e5d840ad5506d9b473923fd):
|
||||
- secp256k1_ecdsa_verify() returned success
|
||||
result: success
|
||||
<> POP stack
|
||||
<> POP stack
|
||||
<> PUSH stack 01
|
||||
script | stack
|
||||
-----------------------------------------+-------------------------------------------------------------------
|
||||
| 01
|
||||
btcdeb>
|
||||
```
|
||||
## Summary: Scripting a Pay to Witness Public Key Hash
|
||||
|
||||
## Summary: Scripting a Pay to Public Key Hash
|
||||
To a large extent you _don't_ script a P2WPKH. Instead, Bitcoin Core creates the transaction in a different way, placing the witness information in a different place rather than a traditional `scriptSig`. That means that P2WPKHs are a digression from the Bitcoin Scripts of this part of the book, because they're an expansion of Bitcoin that steps away from traditional Scripting.
|
||||
|
||||
Sending to a P2PKH address was relatively easy when you were just using `bitcoin-cli`. Examining the Bitcoin Script underlying it lays bare the cryptographic functions that were implicit in funding that transaction: how the UTXO was unlocked with a signature and a public key.
|
||||
However, SegWit was also a clever usage of Bitcoin Scripts. Knowing that there would be nodes that didn't upgrade and needing to stay backward compatible, the developers created the P2WPKH format so that it generated a script that always validated on old nodes (while still having that script provide information to new nodes in the form of a version number and a hashed public key).
|
||||
|
||||
When you're programming from the command line, you fundamentally don't have to worry about this, other than knowing that you won't find traditional scripts in raw SegWit transactions (which, again, was the point).
|
||||
|
||||
## What's Next?
|
||||
|
||||
Continue "Introducing Bitcoin Scripts" with [§7.4: Testing a Bitcoin Script](07_4_Testing_a_Bitcoin_Script.md).
|
||||
Continue "Bitcoin Scripting" with [Chapter 10: Embedding Bitcoin Scripts in P2SH Transactions](10_0_Embedding_Bitcoin_Scripts_in_P2SH_Transactions.md).
|
||||
|
Loading…
x
Reference in New Issue
Block a user