Author

Topic: Step by step guide to creating a P2SH-P2WPKH and P2SH-P2WSH addresses (Read 339 times)

legendary
Activity: 1042
Merit: 2805
Bitcoin and C♯ Enthusiast
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.
full member
Activity: 161
Merit: 168
You forgot Checksum hash in step 7:

hash= SHA256(SHA256 (057db6766dce18d816eaac1198391e8bdcf70b253a));
addr = addr + hash.substring (0 ,8 );
legendary
Activity: 1042
Merit: 2805
Bitcoin and C♯ Enthusiast
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
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
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
Jump to: