The following content was written by Coding Enthusiast on September 01, 2018, 03:05:04 PM in the thread Step by step guide to go from public key to a Bech32 encoded address. All content is owned by the author of the bitcointalk.org post. (original)
Bitcoin wiki has a pretty good step-by-step explanation of how to go from a public key to a base58_encoded address which contains the values for each step of the way[1]. But unfortunately I could not find anything similar for Bech32_encoding. Additionally I found the reference implementations a bit confusing[2]! The information is out there[3] but I feel like having it step-by-step like “[1]” can make it a lot easier specially for developers. For example during unit testing I was getting a different address (bc1qp63uahgrxged4z5jswyt5dn5v3lzsem6c0qqhg8) for below public key and I wasn’t sure where the bug was coming from, this visualization helped me [4] realize I was appending the version byte before converting the bits instead of after. So hopefully these steps can help someone like me looking for them.
How to create a Bech32 address from a public key:
1. Having a compressed[5] public key (0x02 or 0x03 followed by 32 byte X coordinate):
2. Perform SHA-256 hashing on the public key:
3. Perform RIPEMD-160 hashing on the result of SHA-256:
4. The result of step 3 is an array of 8-bit unsigned integers (base 2^8=256) and Bech32 encoding converts this to an array of 5-bit unsigned integers (base 2^5=32) so we “squash” the bytes to get:
in hex:
5. Add the witness version byte in front of the step 4 result (current version is 0):
6. Compute the checksum by using the data from step 5 and the H.R.P (bc for MainNet and tb for TestNet)
7. Append the checksum to result of step 5 (we now have an array of 5-bit integers):
8. Map each value to its corresponding character in Bech32Chars (qpzry9x8gf2tvdw0s3jn54khce6mua7l) 00 -> q, 0e -> w,…
9. A Bech32_encoded address consists of 3 parts: HRP + Separator + Data:
The final result from step 9 is the same as example in BIP173[6]
References:
[1] https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses
[2] https://github.com/sipa/bech32
[3] https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki
[4] https://en.bitcoin.it/w/images/en/4/48/Address_map.jpg
[5] Only compressed public keys are allowed: https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki#restrictions-on-public-key-type
[6] https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#examples
The following content was written by ETFbitcoin on September 01, 2018, 03:26:19 PM in the thread Step by step guide to go from public key to a Bech32 encoded address. All content is owned by the author of the bitcointalk.org post. (original)
Great guide and mostly it’s easy to understand. But i don’t understand the 8th steps, is it encode/decode result from Bech32 characters?
The following content was written by Coding Enthusiast on September 01, 2018, 03:38:49 PM in the thread Step by step guide to go from public key to a Bech32 encoded address. All content is owned by the author of the bitcointalk.org post. (original)
Yes. Note that step7 is the hexadecimal representation of an array of 5-bit integers {0, 14, 20, 15, 7, …, 11, 21} so 0 is item at index 0 of B32Chars or the letter q and 14 is the character at index 14 or w, 20 is 5 and so on.
In C♯
StringBuilder result = new StringBuilder();
foreach (byte item in step7Array)
{
result.Append(B32Chars[item]);
}
Basically this:
.join in python implementation (https://github.com/sipa/bech32/blob/master/ref/python/segwit_addr.py#L59)
or the for loop in JavaScript implementation (https://github.com/sipa/bech32/blob/master/ref/javascript/bech32.js#L74-L76)
The following content was written by odolvlobo on September 02, 2018, 08:06:11 AM in the thread Step by step guide to go from public key to a Bech32 encoded address. All content is owned by the author of the bitcointalk.org post. (original)
I feel that your description is confusing. You write “array of 5-bit integers”, but displaying the results as a hex string implies that it is a string of 8-bit values. I recommend inserting spaces between each value to emphasize that each element is distinct, and perhaps using decimal values to avoid implying that the values could lie outside of the range 0 – 31.
For example:
or even better:
Also,
I recommend removing “byte” since the witness version is not a byte. Note that bip-173 also calls it a “byte” when it isn’t.
The following content was written by Coding Enthusiast on September 02, 2018, 02:47:35 PM in the thread Step by step guide to go from public key to a Bech32 encoded address. All content is owned by the author of the bitcointalk.org post. (original)
Additionally hex or base-16 is a very easy and convenient way to transfer arrays of “numbers”. For instance you can not input each of those “numbers” (14, 20, 15…) one by one in an array when coding, it would take a long time and it is easy to make a mistake. But you can very easily give your code the hexadecimal string representation of it and decode it into the array of “numbers” then treat those “numbers” however you like.
I am going to add both numbers and binary, maybe that helps visualizing it better.
https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#witness-program
https://github.com/bitcoin/bips/blob/master/bip-0142.mediawiki#rationale
The following content was written by TheArchaeologist on September 03, 2018, 07:13:05 AM in the thread Step by step guide to go from public key to a Bech32 encoded address. All content is owned by the author of the bitcointalk.org post. (original)
If you want to play around with this using Python you can check: https://github.com/mcdallas/cryptotools
Example:
>>> private = PrivateKey.random()
>>> private.int()
8034465994996476238286561766373949549982328752707977290709076444881813294372
>>> public = private.to_public()
>>> public
PublicKey(102868560361119050321154887315228169307787313299675114268359376451780341556078, 83001804479408277471207716276761041184203185393579361784723900699449806360826)
>>> public.point in CURVE
True
>>> public.to_address(‘P2WPKH’)
‘bc1qh2egksgfejqpktc3kkdtuqqrukrpzzp9lr0phn’
The following content was written by denisdo95 on November 23, 2019, 01:01:01 PM in the thread Step by step guide to go from public key to a Bech32 encoded address. All content is owned by the author of the bitcointalk.org post. (original)
3. Perform RIPEMD-160 hashing on the result of SHA-256:
4. The result of step 3 is an array of 8-bit unsigned integers (base 2^8=256) and Bech32 encoding converts this to an array of 5-bit unsigned integers (base 2^5=32) so we “squash” the bytes to get:
in hex:
Hey.
Please tell me, how did you get the string “0e140f070d1a001912060b0d081504140311021d030c1d03040f1814060e1e16” from the string “751e76e8199196d454941c45d1b3a323f1433bd6”? What command do you need to execute for this?
The following content was written by DannyHamilton on November 24, 2019, 03:17:04 AM in the thread Step by step guide to go from public key to a Bech32 encoded address. All content is owned by the author of the bitcointalk.org post. (original)
4. The result of step 3 is an array of 8-bit unsigned integers (base 2^8=256) and Bech32 encoding converts this to an array of 5-bit unsigned integers (base 2^5=32) so we “squash” the bytes to get:
in hex:
Please tell me, how did you get the string “0e140f070d1a001912060b0d081504140311021d030c1d03040f1814060e1e16” from the string “751e76e8199196d454941c45d1b3a323f1433bd6”? What command do you need to execute for this?
Here’s a simple way to understand it…
Convert the first value from a hex value to an array of bits where: 0 = 0000, 1=0001, 2=0010, 3-0011, 4=0100, etc
7 5 1 e 7 6 e …
0111 0101 0001 1110 0111 0110 1110 …
Change the spacing of the 1’s and zeros so that they are grouped 5 in a set instead of 4:
01110 10100 01111 00111 01101 110 …
Convert each set of 5 into a hex value:
01110 10100 01111 00111 01101 110…
0e 14 0f 07 0d …
The following content was written by TsaPaka on February 23, 2020, 06:30:33 PM in the thread Step by step guide to go from public key to a Bech32 encoded address. All content is owned by the author of the bitcointalk.org post. (original)
Thank you because I could understand until the last soft fork.
I explain here how a segwit address in P2WSH format is derived so as not to mix the segwit between P2WPKH and P2WSH.
Note that the guide explained above generates in P2WPKH format about 42 characters but P2WSH format about 62 characters.
https://bitcointalk.org/index.php?topic=5227953
The following content was written by MixMAx123 on February 25, 2020, 06:01:57 PM in the thread Step by step guide to go from public key to a Bech32 encoded address. All content is owned by the author of the bitcointalk.org post. (original)
I have now successfully reached step 5.
I have: 000e140f070d1a001912060b0d081504140311021d030c1d03040f1814060e1e16
Now I do not come to step 6.
When I calculate: SHA256 (SHA256 (000e140f070d1a001912060b0d081504140311021d030c1d03040f1814060e1e16)) = 103ede5cc41abfd088a368bb40df3d52e5614460521d88daa202917c7f3de88d.
The first 6 bytes are then with me: 10 3e de 5c c4 1a
And this is a different number than yours.
What am I doing wrong?
The following content was written by Coding Enthusiast on February 25, 2020, 07:23:24 PM in the thread Step by step guide to go from public key to a Bech32 encoded address. All content is owned by the author of the bitcointalk.org post. (original)
The encoding is Bech-32 not Base-58 and there is no SHA256 in this encoding, there is only playing around with bits. Read BIP-173 for details of how you should compute the checksum.
The following content was written by Headphones on July 02, 2020, 07:34:13 PM in the thread Step by step guide to go from public key to a Bech32 encoded address. All content is owned by the author of the bitcointalk.org post. (original)
Hey, great post! It’s really useful.
I’m trying to decode a bech32 address tb1qwm3dqje4wc7cs2u9sv39yh2as8ae0ntzqkjunw into the h160 of the public key, which is step 3 in your guide, using the reference implementation in python.
I end up with an array of integers: [118, 226, 208, 75, 53, 118, 61, 136, 43, 133, 131, 34, 82, 93, 93, 129, 251, 151, 205, 98] which I think corresponds with step 4 of your guide.
How do I go from the array of numbers into the hex version of the h160 which according to https://slowli.github.io/bech32-buffer/ should be: 751e76e8199196d454941c45d1b3a323f1433bd6
Any help would be appreciated!