Bitcoin Forum
May 06, 2024, 06:05:12 PM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: Step by step guide to creating a P2SH-P2WPKH and P2SH-P2WSH addresses  (Read 311 times)
Coding Enthusiast (OP)
Legendary
*
Offline Offline

Activity: 1039
Merit: 2783


Bitcoin and C♯ Enthusiast


View Profile WWW
February 28, 2020, 03:19:06 PM
Merited by Welsh (8), ABCbits (6), bones261 (4), o_e_l_e_o (2), AdolfinWolf (2), mocacinno (1), Pmalek (1)
 #1

As a developer who prefers documentation I've always liked these step-by-step guides with actual values that could also be used in tests. Since my previous topic on the subject (Bech32 P2WPKH addresses)[1] was bumped I thought about creating a new one here maybe it could help other developers spend less time trying to understand how it works or for debugging their code,...
Read more about details in[2].

Pre-requirement
A P2SH address is the human readable form of a pay-to-script-hash pubkey script and as the name suggests it is a payment to hash of a script. In other words in order to create a P2SH address all we need is a script. This script can be anything from an empty script or a single OP code to complex smart contracts. You usually see it as a multi-signature redeem script (OP_m Pub1 Pub2 ... Pubn OP_n OP_CheckMultiSig).
In a P2SH-P2WPKH address this script is a special redeem script created by using the hash of the public key.

Steps for creating a P2SH-P2WPKH address:
1. Having a compressed[3] public key (0x02 or 0x03 followed by 32 byte X coordinate):
Code:
02d0de0aaeaefad02b8bdc8a01a1b8b11c696bd3d66a2c5f10780d95b7df42645c

2. Compute SHA-256 hash of the public key:
Code:
fecf7bb8fef0756dedfaf16fcdbe7b38f15a1edf29a621ad6c9189c24f0ce959

3. Compute RIPEMD-160 hash of the result of SHA-256:
Code:
d9351dcbad5b8f3b8bfa2f2cdc85c28118ca9326

4. Build the redeem script that is OP_0 PushData<Step_3_Result>
Code:
0014d9351dcbad5b8f3b8bfa2f2cdc85c28118ca9326
(This redeem script also goes in signature script of a transaction while spending)

Now we use the script from step 4 to create the address (the following steps are similar to creating a P2SH address for a multi-signature redeem script)
5. Compute SHA-256 of the script (step 4)
Code:
1ecdf8533accbb86c5d264adfa0d9af869a37386b9e8733b55bef753db486981

6. Compute RIPEMD-160 hash of the result of step 5
Code:
7db6766dce18d816eaac1198391e8bdcf70b253a

7. Add P2SH version byte at the beginning of the result from step 6 and encode the result using Base-58 encoding with a checksum[4][5]
Code:
057db6766dce18d816eaac1198391e8bdcf70b253a
=> Final result
Code:
3D9iyFHi1Zs9KoyynUfrL82rGhJfYTfSG4


How about P2SH-P2WSH?
It is very similar to this but instead of starting from a public key we start from having a "script" (step 1) and instead of 2 hashes (step 2 and 3) only one hash is performed on it and that is a single SHA-256. The rest is the same.
1.
Code:
OP_1 PushData(02d0de0aaeaefad02b8bdc8a01a1b8b11c696bd3d66a2c5f10780d95b7df42645c) PushData(02588d202afcc1ee4ab5254c7847ec25b9a135bbda0f2bc69ee1a714749fd77dc9) OP_2 OP_CheckMultiSig
Code:
512102d0de0aaeaefad02b8bdc8a01a1b8b11c696bd3d66a2c5f10780d95b7df42645c2102588d202afcc1ee4ab5254c7847ec25b9a135bbda0f2bc69ee1a714749fd77dc952ae

2&3. A single SHA256
Code:
773ab29f89711d3211ced9978c70539c2f078e3e1e83c985c6b24f6f7c4ba917

4. Build the redeem script that is OP_0 PushData<Step_3_Result>
Code:
0020773ab29f89711d3211ced9978c70539c2f078e3e1e83c985c6b24f6f7c4ba917

5. Compute SHA-256 of the script (step 4)
Code:
8f61e1b2eb81d5176379bdab2bd7075c6de384a4b01fac6976f9913a2dbd94b5

6. Compute RIPEMD-160 hash of the result of step 5
Code:
87cff96494678aaf63d568dcec99e125b4455619

7. Add P2SH version byte at the beginning of the result from step 6 and encode the result using Base-58 encoding with a checksum
Code:
3E58HjvumxkQVk9KeY9Kw69pfBSEDPnmEd


[1] Step by step guide to go from public key to a Bech32 encoded address
[2] https://bitcoincore.org/en/segwit_wallet_dev/
[3] Using uncompressed public keys would make the script non-standard and will practically lead to fund loss
[4] https://en.bitcoin.it/wiki/List_of_address_prefixes
[5] https://en.bitcoin.it/wiki/Base58Check_encoding

Projects List+Suggestion box
Donate: 1Q9s or bc1q
|
|
|
FinderOuter(0.19.1)Ann-git
Denovo(0.7.0)Ann-git
Bitcoin.Net(0.26.0)Ann-git
|
|
|
BitcoinTransactionTool(0.11.0)Ann-git
WatchOnlyBitcoinWallet(3.2.1)Ann-git
SharpPusher(0.12.0)Ann-git
1715018712
Hero Member
*
Offline Offline

Posts: 1715018712

View Profile Personal Message (Offline)

Ignore
1715018712
Reply with quote  #2

1715018712
Report to moderator
1715018712
Hero Member
*
Offline Offline

Posts: 1715018712

View Profile Personal Message (Offline)

Ignore
1715018712
Reply with quote  #2

1715018712
Report to moderator
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction.
1715018712
Hero Member
*
Offline Offline

Posts: 1715018712

View Profile Personal Message (Offline)

Ignore
1715018712
Reply with quote  #2

1715018712
Report to moderator
1715018712
Hero Member
*
Offline Offline

Posts: 1715018712

View Profile Personal Message (Offline)

Ignore
1715018712
Reply with quote  #2

1715018712
Report to moderator
MixMAx123
Full Member
***
Offline Offline

Activity: 161
Merit: 168


View Profile
February 29, 2020, 09:38:36 AM
Merited by Welsh (3), ABCbits (1)
 #2

You forgot Checksum hash in step 7:

hash= SHA256(SHA256 (057db6766dce18d816eaac1198391e8bdcf70b253a));
addr = addr + hash.substring (0 ,8 );
Coding Enthusiast (OP)
Legendary
*
Offline Offline

Activity: 1039
Merit: 2783


Bitcoin and C♯ Enthusiast


View Profile WWW
March 02, 2020, 09:18:16 AM
 #3

You forgot Checksum hash in step 7:

hash= SHA256(SHA256 (057db6766dce18d816eaac1198391e8bdcf70b253a));
addr = addr + hash.substring (0 ,8 );

True, but the idea is to explain the main steps of creating such addresses without repeating steps that are already known or explained elsewhere. The 4 byte checksum is a part of the Base58 encoding with checksum that is already known and used for P2PKH and P2SH addresses and WIFs.

If you have noticed I've also skipped calculating public key from private key, encoding a public key in compressed form, internals of hash computation, details of scripts such as data push lengths,... However, I can explain each part in details if anyone is interested; just reply here with the part you want more explanation on.

Projects List+Suggestion box
Donate: 1Q9s or bc1q
|
|
|
FinderOuter(0.19.1)Ann-git
Denovo(0.7.0)Ann-git
Bitcoin.Net(0.26.0)Ann-git
|
|
|
BitcoinTransactionTool(0.11.0)Ann-git
WatchOnlyBitcoinWallet(3.2.1)Ann-git
SharpPusher(0.12.0)Ann-git
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!