mirror of
https://github.com/ChristopherA/Learning-Bitcoin-from-the-Command-Line.git
synced 2025-06-07 16:06:26 +00:00
updates with btcdeb
This commit is contained in:
parent
4646453213
commit
53066b1f40
@ -1,4 +1,4 @@
|
|||||||
# 8.2: Building the Structure of P2SH
|
# 10.2: Building the Structure of P2SH
|
||||||
|
|
||||||
> :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.
|
> :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.
|
||||||
|
|
||||||
@ -6,11 +6,11 @@ In the previous section we overviewed the theory of how to create P2SH transacti
|
|||||||
|
|
||||||
## Create a Locking Script
|
## Create a Locking Script
|
||||||
|
|
||||||
Any P2SH transaction starts with a locking script. This is the subject of chapters 7 and 9-10. You can use any of the Bitcoin Script methods described therein to create any sort of locking script, as long as the resulting serialized `redeemScript` is 520 bytes or less.
|
Any P2SH transaction starts with a locking script. This is the subject of chapters 9 and 11-12. You can use any of the Bitcoin Script methods described therein to create any sort of locking script, as long as the resulting serialized `redeemScript` is 520 bytes or less.
|
||||||
|
|
||||||
_Why are P2SH scripts limited to 520 bytes?_ As with many things in Bitcoin, the answer is backward compatibility: new functionality has to constantly be built within the old constraints of the system. Is this case, 520 bytes is the maximum that can be pushed onto the stack at once. Since the whole redeemScript is pushed onto the stack as part of the redemption process, it hits that limit.
|
> :book: ***Why are P2SH scripts limited to 520 bytes?*** As with many things in Bitcoin, the answer is backward compatibility: new functionality has to constantly be built within the old constraints of the system. Is this case, 520 bytes is the maximum that can be pushed onto the stack at once. Since the whole redeemScript is pushed onto the stack as part of the redemption process, it hits that limit.
|
||||||
|
|
||||||
## Serialize a Locking Script
|
## Serialize a Locking Script the Hard Way
|
||||||
|
|
||||||
After you create a locking script, you need to serialize it before it can be input into Bitcoin. This is a two-part process. First, you must turn it into hexcode, then you must transform that hex into binary.
|
After you create a locking script, you need to serialize it before it can be input into Bitcoin. This is a two-part process. First, you must turn it into hexcode, then you must transform that hex into binary.
|
||||||
|
|
||||||
@ -55,9 +55,9 @@ In addition, you always need to know the size of any data that you put on the st
|
|||||||
$ echo -n $lehex | wc -c | awk '{print $1/2}'
|
$ echo -n $lehex | wc -c | awk '{print $1/2}'
|
||||||
4
|
4
|
||||||
```
|
```
|
||||||
With that whole rigamarole, you'd know that you could translate the integer 1546288031 into an `04` opcode (to push four bytes onto the stack) followed by 9f7b2a5c (the little-endian hex representation of 1546288031).
|
With that whole rigamarole, you'd know that you could translate the integer 1546288031 into an `04` opcode (to push four bytes onto the stack) followed by `9f7b2a5c` (the little-endian hex representation of 1546288031).
|
||||||
|
|
||||||
If you instead had a negative number, you would need to (1) do your calculations on the absolute value of the number, then (2) bitwise-or 0x80 to your final, little-endian result. For example, 9f7b2a5c, which is 1546288031, would become 9f7b2adc, which is -1546288031:
|
If you instead had a negative number, you would need to (1) do your calculations on the absolute value of the number, then (2) bitwise-or 0x80 to your final, little-endian result. For example, `9f7b2a5c`, which is 1546288031, would become 9f7b2adc, which is -1546288031:
|
||||||
```
|
```
|
||||||
$ neglehex=$(printf '%x\n' $((0x$lehex | 0x80)))
|
$ neglehex=$(printf '%x\n' $((0x$lehex | 0x80)))
|
||||||
$ echo $neglehex
|
$ echo $neglehex
|
||||||
@ -73,42 +73,63 @@ To complete your serialization, you translate the hexcode into binary. On the co
|
|||||||
|
|
||||||
To better understand this process, we will reverse-engineer the P2SH multisig that we created in [§6.1: Sending a Transaction to a Multisig](06_1_Sending_a_Transaction_to_a_Multisig.md). Take a look at the `redeemScript` that you used, which you now know is the hex-serialized version of the locking script:
|
To better understand this process, we will reverse-engineer the P2SH multisig that we created in [§6.1: Sending a Transaction to a Multisig](06_1_Sending_a_Transaction_to_a_Multisig.md). Take a look at the `redeemScript` that you used, which you now know is the hex-serialized version of the locking script:
|
||||||
```
|
```
|
||||||
52210307fd375ed7cced0f50723e3e1a97bbe7ccff7318c815df4e99a59bc94dbcd819210367c4f666f18279009c941e57fab3e42653c6553e5ca092c104d1db279e328a2852ae
|
522102da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d1912102bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa352ae
|
||||||
```
|
```
|
||||||
You can translate this back to Script by hand using the [Bitcoin Wiki Script page](https://en.bitcoin.it/wiki/Script) as a reference. Just look at one byte (two hex characters) of data at a time, unless you're told to look at more by an OP_PUSHDATA command (an opcode in the range of 0x01 to 0x4e).
|
You can translate this back to Script by hand using the [Bitcoin Wiki Script page](https://en.bitcoin.it/wiki/Script) as a reference. Just look at one byte (two hex characters) of data at a time, unless you're told to look at more by an OP_PUSHDATA command (an opcode in the range of 0x01 to 0x4e).
|
||||||
|
|
||||||
The whole Script will break apart as follows:
|
The whole Script will break apart as follows:
|
||||||
```
|
```
|
||||||
52 / 21 / 0307fd375ed7cced0f50723e3e1a97bbe7ccff7318c815df4e99a59bc94dbcd819 / 21 / 0367c4f666f18279009c941e57fab3e42653c6553e5ca092c104d1db279e328a28 / 52 / ae
|
52 / 21 / 02da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d191 / 21 / 02bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa3 / 52 / ae
|
||||||
```
|
```
|
||||||
Here's what the individual parts mean:
|
Here's what the individual parts mean:
|
||||||
|
|
||||||
* 0x52 = OP_2
|
* 0x52 = OP_2
|
||||||
* 0x21 = OP_PUSHDATA 33 bytes (hex: 0x21)
|
* 0x21 = OP_PUSHDATA 33 bytes (hex: 0x21)
|
||||||
* 0x0307fd375ed7cced0f50723e3e1a97bbe7ccff7318c815df4e99a59bc94dbcd819 = the next 33 bytes (public-key hash)
|
* 0x02da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d191 = the next 33 bytes (public-key hash)
|
||||||
* 0x21 = OP_PUSHDATA 33 bytes (hex: 0x21)
|
* 0x21 = OP_PUSHDATA 33 bytes (hex: 0x21)
|
||||||
* 0x0367c4f666f18279009c941e57fab3e42653c6553e5ca092c104d1db279e328a28 = the next 33 bytes (public-key hash)
|
* 0x02bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa3 = the next 33 bytes (public-key hash)
|
||||||
* 0x52 = OP_2
|
* 0x52 = OP_2
|
||||||
* 0xae = OP_CHECKMULTISIG
|
* 0xae = OP_CHECKMULTISIG
|
||||||
|
|
||||||
In other words, that `redeemScript` was a translation of of `2 0307fd375ed7cced0f50723e3e1a97bbe7ccff7318c815df4e99a59bc94dbcd819 0367c4f666f18279009c941e57fab3e42653c6553e5ca092c104d1db279e328a28 2 OP_CHECKMULTISIG`. We'll return to this script in [§8.4: Scripting a Multisig](8_4_Scripting_a_Multisig.md) when we detail exactly how multisigs work within the P2SH paradigm.
|
In other words, that `redeemScript` was a translation of of `2 02da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d191 02bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa3 2 OP_CHECKMULTISIG`. We'll return to this script in [§10.4: Scripting a Multisig](10_4_Scripting_a_Multisig.md) when we detail exactly how multisigs work within the P2SH paradigm.
|
||||||
|
|
||||||
If you'd like a mechanical hand with this sort of translation in the future, you can use `bitcoin-cli decodescript`:
|
If you'd like a mechanical hand with this sort of translation in the future, you can use `bitcoin-cli decodescript`:
|
||||||
```
|
```
|
||||||
$ bitcoin-cli -named decodescript hexstring=52210307fd375ed7cced0f50723e3e1a97bbe7ccff7318c815df4e99a59bc94dbcd819210367c4f666f18279009c941e57fab3e42653c6553e5ca092c104d1db279e328a2852ae
|
$ bitcoin-cli -named decodescript hexstring=522102da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d1912102bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa352ae
|
||||||
{
|
{
|
||||||
"asm": "2 0307fd375ed7cced0f50723e3e1a97bbe7ccff7318c815df4e99a59bc94dbcd819 0367c4f666f18279009c941e57fab3e42653c6553e5ca092c104d1db279e328a28 2 OP_CHECKMULTISIG",
|
"asm": "2 02da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d191 02bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa3 2 OP_CHECKMULTISIG",
|
||||||
"reqSigs": 2,
|
"reqSigs": 2,
|
||||||
"type": "multisig",
|
"type": "multisig",
|
||||||
"addresses": [
|
"addresses": [
|
||||||
"mg7YqyvK8HUFvpgZ5iYTfZ5vjfaJWnNTd9",
|
"mmC2x2FoYwBnVHMPRUAzPYg6WDA31F1ot2",
|
||||||
"mfduLxpR6Bq1ARctV2TauhetWwqnqH1vYS"
|
"mhwZFJUnWqTqy4Y7pXVum88qFtUnVG1keM"
|
||||||
],
|
],
|
||||||
"p2sh": "2NAGfA4nW6nrZkD5je8tSiAcYB9xL2xYMCz"
|
"p2sh": "2N8MytPW2ih27LctLjn6LfLFZZb1PFSsqBr",
|
||||||
|
"segwit": {
|
||||||
|
"asm": "0 6fe9f451ccedb8e4090b822dcad973d0388a37b4c89fd1aed485110adecab2a9",
|
||||||
|
"hex": "00206fe9f451ccedb8e4090b822dcad973d0388a37b4c89fd1aed485110adecab2a9",
|
||||||
|
"reqSigs": 1,
|
||||||
|
"type": "witness_v0_scripthash",
|
||||||
|
"addresses": [
|
||||||
|
"tb1qdl5lg5wvakuwgzgtsgku4ktn6qug5da5ez0artk5s5gs4hk2k25szvjky9"
|
||||||
|
],
|
||||||
|
"p2sh-segwit": "2NByn92W1vH5oQC1daY69F5sU7PEStKKQBR"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
It's especially helpful for checking your work when you're serializing.
|
It's especially helpful for checking your work when you're serializing.
|
||||||
|
|
||||||
|
## Serialize a Locking Script the Easy Way
|
||||||
|
|
||||||
|
When you installed `btcdeb` in [§9.3](09_3_Testing_a_Bitcoin_Script.md) you also installed `btcc` which can be used to serialize Bitcoin scripts:
|
||||||
|
```
|
||||||
|
$ btcc 2 02da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d191 02bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa3 2 OP_CHECKMULTISIG
|
||||||
|
warning: ambiguous input 2 is interpreted as a numeric value; use OP_2 to force into opcode
|
||||||
|
warning: ambiguous input 2 is interpreted as a numeric value; use OP_2 to force into opcode
|
||||||
|
522102da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d1912102bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa352ae
|
||||||
|
```
|
||||||
|
That's a lot easier than figuring that out by hand!
|
||||||
|
|
||||||
Also consider the Python [Transaction Script Compiler](https://github.com/Kefkius/txsc), which translates back and forth.
|
Also consider the Python [Transaction Script Compiler](https://github.com/Kefkius/txsc), which translates back and forth.
|
||||||
|
|
||||||
## Hash a Serialized Script
|
## Hash a Serialized Script
|
||||||
@ -117,25 +138,25 @@ After you've created a locking script and serialized it, the third step in creat
|
|||||||
|
|
||||||
Here's the whole pipe, including the previous transformation of the hex-serialized script into binary:
|
Here's the whole pipe, including the previous transformation of the hex-serialized script into binary:
|
||||||
```
|
```
|
||||||
$ redeemScript="52210307fd375ed7cced0f50723e3e1a97bbe7ccff7318c815df4e99a59bc94dbcd819210367c4f666f18279009c941e57fab3e42653c6553e5ca092c104d1db279e328a2852ae"
|
$ redeemScript="522102da2f10746e9778dd57bd0276a4f84101c4e0a711f9cfd9f09cde55acbdd2d1912102bfde48be4aa8f4bf76c570e98a8d287f9be5638412ab38dede8e78df82f33fa352ae"
|
||||||
$ echo -n $redeemScript | xxd -r -p | openssl dgst -sha256 -binary | openssl dgst -rmd160
|
$ echo -n $redeemScript | xxd -r -p | openssl dgst -sha256 -binary | openssl dgst -rmd160
|
||||||
(stdin)= babf9063cee8ab6e9334f95f6d4e9148d0e551c2
|
(stdin)= a5d106eb8ee51b23cf60d8bd98bc285695f233f3
|
||||||
```
|
```
|
||||||
## Create a P2SH Transaction
|
## Create a P2SH Transaction
|
||||||
|
|
||||||
Creating your 20-bit hash just gives you the hash at the center of a P2SH locking script. You still need to put it together with the other opcodes that create a standard P2SH transaction: `OP_HASH160 babf9063cee8ab6e9334f95f6d4e9148d0e551c2 OP_EQUAL`.
|
Creating your 20-bit hash just gives you the hash at the center of a P2SH locking script. You still need to put it together with the other opcodes that create a standard P2SH transaction: `OP_HASH160 a5d106eb8ee51b23cf60d8bd98bc285695f233f3 OP_EQUAL`.
|
||||||
|
|
||||||
Depending on your API, you might be able to enter this as an `asm`-style `scriptPubKey` for your transaction, or you might have to translate it to `hex` code as well. If you have to translate, use the same methods described above for "Creating the Hex Code", resulting in `a914babf9063cee8ab6e9334f95f6d4e9148d0e551c287`.
|
Depending on your API, you might be able to enter this as an `asm`-style `scriptPubKey` for your transaction, or you might have to translate it to `hex` code as well. If you have to translate, use the same methods described above for "Creating the Hex Code" (or `btcc`), resulting in `a914a5d106eb8ee51b23cf60d8bd98bc285695f233f387`.
|
||||||
|
|
||||||
Note that the `hex scriptPubKey` for P2SH Script transaction will _always_ start with an `a914`, which is the `OP_HASH160` followed by an `OP_PUSHDATA` of 20 bytes (hex: 0x14); and it will _always_ end with a `87`, which is an `OP_EQUAL`. So all you have to do is put your hashed redeem script in between those numbers.
|
Note that the `hex scriptPubKey` for P2SH Script transaction will _always_ start with an `a914`, which is the `OP_HASH160` followed by an `OP_PUSHDATA` of 20 bytes (hex: 0x14); and it will _always_ end with a `87`, which is an `OP_EQUAL`. So all you have to do is put your hashed redeem script in between those numbers.
|
||||||
|
|
||||||
## Summary: Understanding the Foundation of P2SH
|
## Summary: Understanding the Foundation of P2SH
|
||||||
|
|
||||||
Actually creating the P2SH locking script dives further into the guts of Bitcoin than you've ever gone before. Though it's helpful to know how all of this works at a very low level, it's most likely that you'll have an API taking care of all of the heavy-lifting for you. Your task will simply be to create the Bitcoin Script to do the locking ... which is the main topic of chapters 7 and 9-10.
|
Actually creating the P2SH locking script dives further into the guts of Bitcoin than you've ever gone before. Though it's helpful to know how all of this works at a very low level, it's most likely that you'll have an API taking care of all of the heavy-lifting for you. Your task will simply be to create the Bitcoin Script to do the locking ... which is the main topic of chapters 9 and 11-12.
|
||||||
|
|
||||||
## What's Next?
|
## What's Next?
|
||||||
|
|
||||||
Continue "Embedding Bitcoin Scripts" with [§8.3: Running a Bitcoin Script with P2SH](08_3_Running_a_Bitcoin_Script_with_P2SH.md).
|
Continue "Embedding Bitcoin Scripts" with [§10.3: Running a Bitcoin Script with P2SH](10_3_Running_a_Bitcoin_Script_with_P2SH.md).
|
||||||
|
|
||||||
## Appendix: The Integer Conversion Script
|
## Appendix: The Integer Conversion Script
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user