Author

Topic: Step by step guide to go from public key to a P2WSH Bech32 encoded address (Read 420 times)

newbie
Activity: 4
Merit: 0
I think the result is correct, so whats the matter with that added half-byte in step 4? Sorry to be stubborn...
Nothing if your code can add 5 bits to an input that contains 8-bit values and you can handle the subsequent conversions and data interpretation.
But programmatically speaking, when our input is an octet string, anything added is also an octet (8 bit). So you should postpone adding the 5-bit version to when your octet string is converted to 5-bit array.

Hm, I think we're talking past each other... but I don't know how to express myself better...

Step 4 and step 6 are executed in the OP example, the result is correct. You are telling me that step 4 is wrong or should only be done at step 6. Then the result in OP should also be wrong, because there an 0 (halfbyte) is appended in step 4 (in addition to the added version byte in step 6)...

Can anyone else help? Probably nobody else at home here...

Thank you for your efforts pooya87 Kiss

legendary
Activity: 3472
Merit: 10611
I think the result is correct, so whats the matter with that added half-byte in step 4? Sorry to be stubborn...
Nothing if your code can add 5 bits to an input that contains 8-bit values and you can handle the subsequent conversions and data interpretation.
But programmatically speaking, when our input is an octet string, anything added is also an octet (8 bit). So you should postpone adding the 5-bit version to when your octet string is converted to 5-bit array.
newbie
Activity: 4
Merit: 0
Quote
What we have in step 4 is still an octet string (the hex) which means each value (2 characters) represents 8 bits. If we add OP_0 (0x00) in this step, we would be adding 8 bits which is wrong because witness versions are 5 bits added when the input's octet string was broken into 5-bit chunks.

If you look at the values in step 5, the first one is 0b00011000 which is 0x18 meaning OP didn't add OP_0 in step 4.
It was instead correctly added in step 6 as 0b00000 when we already have the 5-bit chunks 0b00011 0b00001 etc.
He did not add an OP_0 in step 4 but he sure did add a 0 in the end (4 bits 0000)... in addition to that, he added - as you mention -  the witness version in step 6 (as 00000 here). If you dont do both of that, you wont get the same result. So either both steps are necessary or the code provided (and the resulting adress) is wrong. I think the result is correct, so whats the matter with that added half-byte in step 4? Sorry to be stubborn...
legendary
Activity: 3472
Merit: 10611
Thanks for the reply. What do you mean by OP didnt perform either? There seems to be an extra 0, yes. What am I missing?
What we have in step 4 is still an octet string (the hex) which means each value (2 characters) represents 8 bits. If we add OP_0 (0x00) in this step, we would be adding 8 bits which is wrong because witness versions are 5 bits added when the input's octet string was broken into 5-bit chunks.

If you look at the values in step 5, the first one is 0b00011000 which is 0x18 meaning OP didn't add OP_0 in step 4.
It was instead correctly added in step 6 as 0b00000 when we already have the 5-bit chunks 0b00011 0b00001 etc.
newbie
Activity: 4
Merit: 0
4. Add OP_0 in back of the step 3
Code:
1863143c14c5166804bd19203356da136c985678cd4d27a1b8c63296049032620
can somebody explain this step, please?
...if anyone is here still....^^
That is a wrong step that OP didn't perform either! It's just written that way. The OP_0 (witness program version) is added in step 6 as a 5-bit integer before computing the Bech32 checksum instead of adding it as an 8-bit integer to the hex/bytes you have in step 4. If you do the later, it will break step 5 where you're splitting your hex into 5-bit chunks.

Thanks for the reply. What do you mean by OP didnt perform either? There seems to be an extra 0, yes. What am I missing?

Strangely enough it only works for me (in many other examples), when i execute this step 4 exactly as written... but I suck at programming and probably I made some mistakes in the latter steps...

In my code the result after step 4 (with the added 4 bits "0000") is
1100001100011000101000011110000010100110001010001011001101000000001001011110100 0110010010000000110011010101101101101000010011011011001001100001010110011110001 1001101010011010010011110100001101110001100011000110010100101100000010010010000 0011001001100010 0000

and after adding the padding 0 and the version number in the beginning it is
['00000', '00011', '00001', '10001', '10001', '01000', '01111', '00000', '10100', '11000', '10100', '01011', '00110', '10000', '00001', '00101', '11101', '00011', '00100', '10000', '00011', '00110', '10101', '10110', '11010', '00010', '01101', '10110', '01001', '10000', '10101', '10011', '11000', '11001', '10101', '00110', '10010', '01111', '01000', '01101', '11000', '11000', '11000', '11001', '01001', '01100', '00001', '00100', '10000', '00110', '01001', '10001', '00000']



legendary
Activity: 3472
Merit: 10611
4. Add OP_0 in back of the step 3
Code:
1863143c14c5166804bd19203356da136c985678cd4d27a1b8c63296049032620
can somebody explain this step, please?
...if anyone is here still....^^
That is a wrong step that OP didn't perform either! It's just written that way. The OP_0 (witness program version) is added in step 6 as a 5-bit integer before computing the Bech32 checksum instead of adding it as an 8-bit integer to the hex/bytes you have in step 4. If you do the later, it will break step 5 where you're splitting your hex into 5-bit chunks.
newbie
Activity: 4
Merit: 0


4. Add OP_0 in back of the step 3
Code:
1863143c14c5166804bd19203356da136c985678cd4d27a1b8c63296049032620




can somebody explain this step, please?

...if anyone is here still....^^
full member
Activity: 161
Merit: 168
I'll watch it tomorrow, thank you very much!
newbie
Activity: 3
Merit: 0
Quote
hex2bin from "21751e76e8199196d454941c45d1b3a323f1433bd6ac" = base64_decode (Anm+Zn753LusVaBilc6HCwcCm/zbLc4o2VnygVsW+BeY)

These are many intermediate steps that should be in the instructions.
It would be great if they could still do that.
I try to program it but don't get any further here.

I just updated it please excuse me you are right
full member
Activity: 161
Merit: 168
Quote
hex2bin from "21751e76e8199196d454941c45d1b3a323f1433bd6ac" = base64_decode (Anm+Zn753LusVaBilc6HCwcCm/zbLc4o2VnygVsW+BeY)

These are many intermediate steps that should be in the instructions.
It would be great if they could still do that.
I try to program it but don't get any further here.
full member
Activity: 161
Merit: 168
And what comes out as a result?
Please read what SHA256 says below!
For me it says: 778c47e6b44dfea35d93795ad0e920bff040f17383419285cfa467dbbb6e937b
And this is a different number, as in your guide.
full member
Activity: 161
Merit: 168
I do not know what you mean by hashing a binary value, you can explain that in more detail ?


http://www.fileformat.info/tool/hash.htm?hex=21751e76e8199196d454941c45d1b3a323f1433bd6ac

= 778c47e6b44dfea35d93795ad0e920bff040f17383419285cfa467dbbb6e937b

Your instructions are somehow not correct there!
full member
Activity: 161
Merit: 168
Can you please insert point 4.1?

hex2bin: Description

hex2bin from "21751e76e8199196d454941c45d1b3a323f1433bd6ac"

= ###

SHA256 (###) = 1863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262
legendary
Activity: 2128
Merit: 1293
There is trouble abrewing
this doesn't make much sense to be honest. for starters P2WSH is used when you have a "script" that you want to pay to (like a smart contract such as multi signature scheme) not a single public key. then you have to use that script to hash and encode using bech32.

your script here is a "data" followed by a "checksig" which doesn't make any sense since your checksig is going to consume that data (the hash) and fail right away. since the top stack item is supposed to be a public key not a 20 byte hash.

additionally your push data is wrong, you are setting the size to 0x21=33 byte while your data is only 20 bytes=0x14.

ps. by the way it is best that whenever you want to write a guide like this you first double check your values with another source (like using a wallet) to see if they are correct.
full member
Activity: 161
Merit: 168
4. = 21751e76e8199196d454941c45d1b3a323f1433bd6ac

SHA256(21751e76e8199196d454941c45d1b3a323f1433bd6ac) = 778c47e6b44dfea35d93795ad0e920bff040f17383419285cfa467dbbb6e937b


778c47e6b44dfea35d93795ad0e920bff040f17383419285cfa467dbbb6e937b
  !=
1863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262


Huh
newbie
Activity: 3
Merit: 0
I explain here how a segwit address in P2WSH format is derived so as not to mix the segwit between P2WPKH and P2WSH.

This is how we generate Bech32 => P2WSH:

1. Having a compressed[5] public key (0x02 or 0x03 followed by 32 byte X coordinate):
Code:
0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798

2. Add the OP_PUSH33 => (21) in front of the step 3 result and OP_CHECKSIG => (ac) in back
Code:
210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac

3. Perform SHA-256 hashing on the result of the step 2: (WitnessProgram)
Code:
1863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262

4. Add OP_0 in back of the step 3
Code:
1863143c14c5166804bd19203356da136c985678cd4d27a1b8c63296049032620

5. The result of step 4 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:
8 bits binary:
Code:
00011000 01100011 00010100 00111100 00010100 11000101 00010110 01101000 00000100 10111101 00011001 00100000 00110011 01010110 11011010 00010011 01101100 10011000 01010110 01111000 11001101 01001101 00100111 10100001 10111000 11000110 00110010 10010110 00000100 10010000 00110010 01100010 0000
5 bits binary:
Code:
00011 00001 10001 10001 01000 01111 00000 10100 11000 10100 01011 00110 10000 00001 00101 11101 00011 00100 10000 00011 00110 10101 10110 11010 00010 01101 10110 01001 10000 10101 10011 11000 11001 10101 00110 10010 01111 01000 01101 11000 11000 11000 11001 01001 01100 00001 00100 10000 00110 01001 10001 00000

6. Add the witness version byte in front of the step 5 result (current version is 0 => in 5 bits => 00000):
5 bits binary:
Code:
00000 00011 00001 10001 10001 01000 01111 00000 10100 11000 10100 01011 00110 10000 00001 00101 11101 00011 00100 10000 00011 00110 10101 10110 11010 00010 01101 10110 01001 10000 10101 10011 11000 11001 10101 00110 10010 01111 01000 01101 11000 11000 11000 11001 01001 01100 00001 00100 10000 00110 01001 10001 00000
in hex:
Code:
00 03 01 11 11 08 0f 00 14 18 14 0b 06 10 01 05 1d 03 04 10 03 06 15 16 1a 02 0d 16 09 10 15 13 18 19 15 06 12 0f 08 0d 18 18 18 19 09 0c 01 04 10 06 09 11 00
in numbers:
Code:
00 03 01 17 17 08 15 00 20 24 20 11 06 16 01 05 29 03 04 16 03 06 21 22 26 02 13 22 09 16 21 19 24 25 21 06 18 15 08 13 24 24 24 25 09 12 01 04 16 06 09 17 00

7. Compute the checksum by using the data from step 6 and the H.R.P (bc for MainNet and tb for TestNet)
in hex:
Code:
18 18 09 1b 0c 11
in numbers:
Code:
24 24 09 27 12 17

8. Append the checksum to result of step 6 (we now have an array of 5-bit integers):
in hex:
Code:
00 03 01 11 11 08 0f 00 14 18 14 0b 06 10 01 05 1d 03 04 10 03 06 15 16 1a 02 0d 16 09 10 15 13 18 19 15 06 12 0f 08 0d 18 18 18 19 09 0c 01 04 10 06 09 11 00 18 18 09 1b 0c 11
in numbers:
Code:
00 03 01 17 17 08 15 00 20 24 20 11 06 16 01 05 29 03 04 16 03 06 21 22 26 02 13 22 09 16 21 19 24 25 21 06 18 15 08 13 24 24 24 25 09 12 01 04 16 06 09 17 00 24 24 09 27 12 17

9. Map each value to its corresponding character in Bech32Chars (qpzry9x8gf2tvdw0s3jn54khce6mua7l) 00 -> q, 03 -> r,...
Code:
qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3

10. A Bech32_encoded address consists of 3 parts: HRP + Separator + Data:
Code:
bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3


DONATE: bitcoin:33cnQGn2UDBoSiUtKGYkx81VBvXTupdeoL
DONATE: bitcoin:bc1qnes35kdqp4nv2tapqgcsu34457su5rlx2pz7yx
Jump to: