1

I want to create P2WSH native like https://en.bitcoin.it/wiki/BIP_0173. I have already a script to generate P2WPKH and it works, thank the python part and re-arrange group byte works.

I read that witnessScript (scriptPubKey) is hash of SHA256 without RIPEMD160. Below a little bit of my code.

PB=0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798

#REDEEM SCRIPT <Public Key> OP_CHECKSIG
SCRIPT=210279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798AC

#SCRIPT HASH
$ printf $SCRIPT | xxd -r -p | openssl sha256| sed 's/^.* //'
1863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262

Convert scripthash to base 2

11000 01100 01100 01010 00011 11000 00101 00110 00101 00010 11001 10100 00000 01001 01111 01000 11001 00100 00000 11001 10101 01101 10110 10000 10011 01101 10010 01100 00101 01100 11110 00110 01101 01001 10100 10011 11010 00011 01110 00110 00110 00110 01010 01011 00000 01001 00100 00001 10010 01100 010

I need to add two zero at the beginning in order to Re-arrange those bits into groups of 5

00110 00011 00011 00010 10000 11110 00001 01001 10001 01000 10110 01101 00000 00010 01011 11010 00110 01001 00000 00110 01101 01011 01101 10100 00100 11011 01100 10011 00001 01011 00111 10001 10011 01010 01101 00100 11110 10000 11011 10001 10001 10001 10010 10010 11000 00010 01001 00000 01100 10011 00010

Add witness program

00000 00110 00011 00011 00010 10000 11110 00001 01001 10001 01000 10110 01101 00000 00010 01011 11010 00110 01001 00000 00110 01101 01011 01101 10100 00100 11011 01100 10011 00001 01011 00111 10001 10011 01010 01101 00100 11110 10000 11011 10001 10001 10001 10010 10010 11000 00010 01001 00000 01100 10011 00010

Convert each bits to base10

0, 6, 3, 3, 2, 16, 30, 1, 9, 17, 8, 22, 13, 0, 2, 11, 26, 6, 9, 0, 6, 13, 11, 13, 20, 4, 27, 12, 19, 1, 11, 7, 17, 19, 10, 13, 4, 30, 16, 27, 17, 17, 17, 18, 18, 24, 2, 9, 0, 12, 19, 2    

Create the checksum with python code

15
29
21
28
10
6

my result is:

tb1qxrrzs7pf3gkdqzt6xfqxdtd5ymvnpt83n2dy7sm333jjczfqvnz0a4u2x

but the result in BIP 0173 is

tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7

I use the same script to generate P2WPKH that you can find in BIP_173 and it works. Of course I change Public key with public key hash, but the logic of create group of 5 bits and python part is the same.

Another question: can I create these address (P2WPKH and P2SH native) from bitcoin-cli?

7
  • The data encoded using 8->5 bit conversion is not the entire scriptPubKey, just the witness program itself (=the 32 bytes coming out of SHA256). You then prefix it with a 'q' (for witness version 0). Commented Mar 27, 2020 at 22:13
  • thanks for reply, but I don't understand sorry. Now I use Public key to generate group of 5 bits. You mean use the SHA256 of SCRIPTPUBKEY? In that way I have the same problem, I don't receive the right result. thanks
    – monkeyUser
    Commented Mar 27, 2020 at 22:19
  • You're converting the entire scriptPubKey to groups of 5 bits. You're only supposed to convert the script hash (this is also the case with P2WPKH, except with ripemd160(sha256(pubkey)) instead of sha256(script)). Commented Mar 27, 2020 at 22:24
  • Script is SCRIPT=210279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798AC script hash is 1863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262 scriptPubKey is: 00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262 Then I convert to base2 the scripthash 1863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262 but I can't get the right result
    – monkeyUser
    Commented Mar 27, 2020 at 22:32
  • 1
    Ok, that sounds correct. I was confused by your first "00000" 5-bit group that came out. I don't have time right now to go into more detail, but perhaps someone else will. Commented Mar 27, 2020 at 22:36

1 Answer 1

2

Bech32 encoding, apart from the checksum, is a simple matter of converting base-256 (8-bits) to base-32 (5-bits). Base-256 is the byte array (octet string) that you get from a hash function. Only focusing on first 3 bytes of the hash:

as hex    = 0x18     0x63     0x14 
as bytes  = 24       99       20 
as binary = 00011000 01100011 00010100 

In order to convert the above base-256 (8-bits) input to base-32 (5-bits) we start from the most significant bit and select 5 bits at a time until we run out.

12345123 45123451 23451234 ...
00011000 01100011 00010100
(00011) (00001) (10001) (10001) (0100 ...

For a bech-32 address there is an extra step here after the base conversion is done. That step is to append of the "witness version" to the beginning of this group as an already converted value in base-32 (since witness version is defined from 0 to 16 inclusive it is already in range).

[00000] (00011) (00001) (10001) (10001) (0100 ...

This final result can be converted to an array of numbers that are between 0 and 31

0, 3, 1, 17, 17

To convert this "number" array to human readable format we print the corresponding character from the bech32 charset (qpzry9x8gf2tvdw0s3jn54khce6mua7l)

0->q, 3->r, 1->p, 17->3, 17->3 ...

P.S. There is a checksum calculation that I skipped to keep it simple but it is just another appended set of 5-bit values at the end of what we have in last step.

5
  • oh thanks, I just convert SHA256 digest into base2. it's not enough? SCRIPT_HASH=`printf $SCRIPT | xxd -r -p | openssl sha256| sed 's/^.* //' Then convert to base2echo "ibase=16; obase=2; $(echo $SCRIPT_HASH | tr '[:lower:]' '[:upper:]') " | bc | sed 's/\\//g' | tr -d '\n' > base2.txt
    – monkeyUser
    Commented Mar 28, 2020 at 17:19
  • that command is not correct echo 'ibase=16; obase=2; 18' | bc? I use the same logic and script for P2WPKH and same logic to calculate Seed phrase. thanks again
    – monkeyUser
    Commented Mar 28, 2020 at 21:37
  • I can generate P2WPKH without a problem with same logic, even your post in bitcoin talk (bitcointalk.org/index.php?topic=4992632.0). the P2WSH logic about Base2 is different?
    – monkeyUser
    Commented Apr 6, 2020 at 15:07
  • 1
    I can't understand the code you posted so I can't tell which part of it is wrong. But you may be having a bug that works with 20 bytes input but not with 32. There is a padding involved when converting bits (20 byte = 160 bit % 5 = 0 but 32 byte = 256 bit % 5 = 1). Commented Apr 6, 2020 at 15:14
  • Enthusuast. Thanks for your time, it's very funny because with 20 byte it works. Anyway maybe I find a bug, but I have a new problem with checksum (in 20 byte is ok obviously)
    – monkeyUser
    Commented Apr 6, 2020 at 17:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.