From e809cb2f3a6c75ea99de1413132bcd37c4a1d865 Mon Sep 17 00:00:00 2001 From: timlucmiptev Date: Thu, 15 Oct 2020 13:55:41 +0300 Subject: [PATCH] working decode of bech32 to hex --- bippy-scratch.md | 138 +++++++++++++++++++++++++++++++---------------- lib/btc.hoon | 76 ++++++++++++++++++++++---- sur/btc.hoon | 7 +++ 3 files changed, 167 insertions(+), 54 deletions(-) diff --git a/bippy-scratch.md b/bippy-scratch.md index d818aac04..1aecacd0f 100644 --- a/bippy-scratch.md +++ b/bippy-scratch.md @@ -3,7 +3,7 @@ The below requires norsyr's fix to `decompress-point` in order to work. ## Set Credentials and Ping Servers ``` -:btc-bridge|command [%become-host [rpc-url='http://localhost:8332' rpc-user='__cookie__' rpc-password='8e12e5bad1808aed64627192165304e9b804f971efa34f36ae93e9fb088fe22c'] [rpc-url='http://localhost:50002']] +:btc-bridge|command [%become-host [rpc-url='http://localhost:8332' rpc-user='__cookie__' rpc-password='2cce52a532a078764cd9e56630603adaedfbb130ccf3b2f0a5f0dd718a5c35e0'] [rpc-url='http://localhost:50002']] :btc-bridge|rpc-action [%brpc %get-block-count ~] :btc-bridge|rpc-action [%erpc %get-address-balance [%bech32 'bc1q59u5epktervh6fxqay2dlph0wxu9hjnx6v8n66']] @@ -48,6 +48,52 @@ abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon `@t`(scot %uc `@uc`(scan "17xg1BZLn63zCxdTxbsFLoWpQeSnD7zSHW" fim:ag)) ``` +## sha256 Implementation +This is needed for hashing to/from big endian, possibly with leading and trailing 0s. + +We use 20 byte value `0x7f5a.997b.83f5.1f79.3b89.10be.9950.8b00.a136.f900` + +### JS Reference Values +``` +val = "7f5a997b83f51f793b8910be99508b00a136f900"; +b = Buffer.from(val, "hex"); +createHash('sha256').update(b).digest(); +// yields: + +val2 = "007f5a997b83f51f793b8910be99508b00a136f900"; +b2 = Buffer.from(val2, "hex"); +createHash('sha256').update(b2).digest(); +// yields: +``` + +In the Hoon version, we indicate leading zeros by increasing the byte count, rather than with a string +``` +:: trailing 0s +=val 0x7f5a.997b.83f5.1f79.3b89.10be.9950.8b00.a136.f900 +`@ux`dat:(sha256:btc 20 val) +:: gives 0x4d9a.8e9b.966c.f83a.695c.607b.c323.74a0.d270.35aa.52a0.b673.8dc4.73fe.95c6.8fb3 + +:: leading 0s--pass 21 as byte count +`@ux`dat:(sha256:btc 21 val) +0x66ee.cb4f.b50e.9d93.f85e.7869.6a34.097a.b859.fbc9.b7f6.f087.3329.423b.5fdd.8072 +``` + +## 8bit to 5bit conversion, and back again +Start with a Hash160 (8bit hex). Convert to bech32. Decode the bech32, drop the leading 0, and run through `digits-to-atom`. + +### 8 bits to 5 bits + +### 5 bits to 8 bits +``` +:: base32: +=val ~[0 0 31 31 31 31 0 0] +(from-digits:bits:btc 5 val) +:: gives ~[0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0] + +`@ux`(to-atom:bits:btc (from-digits:bits:btc 5 val)) +:: gives 0x3fff.fc00 +``` + ## BIP 173 (Bech32 Addresses) ``` =btc -build-file %/lib/btc/hoon @@ -64,30 +110,40 @@ https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses That one starts with pubkey below. The following runs it through sha256 and ripemd160 to get Hash-160: ``` -0xf54a.5851.e937.2b87.810a.8e60.cdd2.e7cf.d80b.6e31 ``` Use `@uc` to make the Hash-160 into a BTC P2PKH address ``` =pubkey 0x2.5086.3ad6.4a87.ae8a.2fe8.3c1a.f1a8.403c.b53f.53e4.86d8.511d.ad8a.0488.7e5b.2352 (hash-160:btc pubkey) -`@uc`(hash-160:btc pubkey)`@uc`(hash-160:btc pubkey) +:: gives 0xf54a.5851.e937.2b87.810a.8e60.cdd2.e7cf.d80b.6e31 + +`@uc`(hash-160:btc pubkey) +:: gives 1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs ``` ### trailing zero -s Need to test with this because it shows need to input num bytes ``` 0x3.f3c1.3839.3683.93e7.0caf.4148.4775.b805.312d.58be.d157.1308.3d27.5cf5.6998.0100 ``` ### bip173 test pubkey -Pubkey -0x2.79be.667e.f9dc.bbac.55a0.6295.ce87.0b07.029b.fcdb.2dce.28d9.59f2.815b.16f8.1798 +The below code also shows how to convert from bech32 back to a 20-byte hash. This is used for transaction building. +``` +=pubkey 0x2.79be.667e.f9dc.bbac.55a0.6295.ce87.0b07.029b.fcdb.2dce.28d9.59f2.815b.16f8.1798 +(encode-pubkey:bech32:btc %main pubkey) +:: should be [~ "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"] -Hash-160 (has leading 0s, so good to check) -751e76e8199196d454941c45d1b3a323f1433bd6 -0xf54a.5851.e937.2b87.810a.8e60.cdd2.e7cf.d80b.6e31 +(hash-160:btc pubkey) +:: should be 0x751e.76e8.1991.96d4.5494.1c45.d1b3.a323.f143.3bd6 + +(decode-raw:bech32:btc "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4") +:: prints data: ~[0 14 20 15 7 13 26 0 25 18 6 11 13 8 21 4 20 3 17 2 29 3 12 29 3 4 15 24 20 6 14 30 22] + +(to-hex:bech32:btc "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4") +:: gives 0x751e.76e8.1991.96d4.5494.1c45.d1b3.a323.f143.3bd6, the hash160 +``` ### bip84 public keys From seed mnemonic: @@ -99,42 +155,6 @@ process child keen cargo design install parrot hold pole unveil dance reason dri 0x3.109a.2082.eaa6.8925.1465.5393.d635.7fb9.d9b5.e191.3826.8837.69cd.db88.7a4b.b4f0 ``` -## Deprecated: `btc-address` library -Left here just for reference - -**Test child public key from xpub** -``` -=btca -build-file %/lib/btc-address/hoon -=ecc secp256k1:secp:crypto -`@ux`(child-from-xpub:btca zpub 0) -(child-from-xpub:btca xpub (dec (bex 31))) - -:: should error as index is too high (hardened key range) -(child-from-xpub:btca zpub (bex 31)) -``` - -**Test xpub parsing** -``` -(parse-xpub:btca xpub) -``` - -**Test addition and ECC point checking** -``` -=px (parse-xpub:btca xpub) -=pubk ?~ px ~ pubk.u.px -(is-point:btca pubk) -(pubkey-to-point:btca pubk) -=index 256 -`@ux`(add (lsh 3 4 (big-endian-brap:btca pubk)) index) -``` - -**Test computing I** -``` -(bind px |=(px=parsed-xpub:btca (compute-i:btca px 1))) -``` - - -0x3.1589.edf6.2798.1d49.77a1.d4e2.58b8.aeaa.060a.d518.94e1.e122.406f.af29.b197.c1f1 ## Signing Scratch =unsigned 0x100.0000.015a.800f.d903.679a.cfe9.d4e2.fedb.752b.24c4.d7a5.74b4.c82a.113d.fb99.3b38.64b7.7201.0000.0019.76a9.1495.3de6.57be.4b30.5f60.6d9a.9fbd.35b0.70a6.8247.5788.acff.ffff.ff01.c09e.e605.0000.0000.1976.a914.dd6c.ce9f.255a.8cc1.7bda.8ba0.373d.f8e8.61cb.866e.88ac.0000.0000.0100.0000 @@ -142,3 +162,31 @@ Left here just for reference =txhash (shay (met 3 unsigned) (swp 3 unsigned)) =privkey 0xdc57.c6d0.6737.6c36.bbed.632c.9d00.f037.6786.7f33.7d5a.86b5.b030.8a60.004f.08ee + +0x7f5a.997b.83f5.1f79.3b89.10be.9950.8b00.a136.f922 + +0xbd9.a59c.4ffc.92d3.f5dd.8ba3.a2ed.93b3.d1d9.f9cf.91cf.0982.db70.9be7.0a37.db76 + + +### cutting off the last 20 bytes (for bech32 address outputs): +``` +`@ux`(end 3 2 0x14.6655) +:: gives 0x6655 +``` + +### BIP143 Reference +https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki#P2SHP2WPKH + +## more scratch +7f5a997b83f51f793b8910be99508b00a136f922 +0x7f5a.997b.83f5.1f79.3b89.10be.9950.8b00.a136.f922 + +db6b1b20aa0fd7b23880be2ecbd4a98130974cf4748fb66092ac4d3ceb1a547701000000 + + +0x46.c323.0000.0000 + +bip143 hash preimage: +0x100.0000.96b8.27c8.483d.4e9b.9671.2b67.13a7.b68d.6e80.03a7.81fe.ba36.c311.4347.0b4e.fd37.52b0.a642.eea2.fb7a.e638.c36f.6252.b675.0293.dbe5.74a8.0698.4b8e.4d85.4833.9a3b.ef51.e1b8.04cc.89d1.82d2.7965.5c3a.a89e.815b.1b30.9fe2.87d9.b2b5.5d57.b90e.c68a.0100.0000.1976.a914.1d0f.172a.0ecb.48ae.e1be.1f26.87d2.963a.e33f.71a1.88ac.0046.c323.0000.0000.ffff.ffff.863e.f3e1.a92a.fbfd.b97f.31ad.0fc7.683e.e943.e9ab.cf25.0159.0ff8.f655.1f47.e5e5.1100.0000.0100.0000 + + diff --git a/lib/btc.hoon b/lib/btc.hoon index 257813ab6..3845c7443 100644 --- a/lib/btc.hoon +++ b/lib/btc.hoon @@ -1,17 +1,48 @@ /- *btc |% :: big endian sha256: input and output are both MSB first (big endian) +:: ++ sha256 |= =byts - ^- @ux + ^- ^byts + :: if there are leading 0s, lshift by their amount after flip to little endian to preserve + =/ pad=@ (sub wid.byts (met 3 dat.byts)) + =/ little-endian=@ + (lsh 3 pad (swp 3 dat.byts)) + :- 32 %+ swp 3 - (shay wid.byts (swp 3 dat.byts)) + (shay wid.byts little-endian) ++ hash-160 |= pubkey=@ux ^- @ux =, ripemd:crypto - %+ ripemd-160 32 + %- ripemd-160 %- sha256 [(met 3 pubkey) pubkey] +:: +++ script + |% + :: DUMMY + ++ compile + |= chunks=(list @ux) + ^- @ux + 0x0 + -- +++ payments + |% + ++ p2pkh + |= script=@ux +:: ^- @ux + ^- (list @ux) + =/ chunks=(list (list @)) + :~ ~[op-dup:ops] + ~[op-hash160:ops] + ~[(met 3 script)] + ::TODO FLOP rip in HERE + ~[op-equalverify:ops] + ~[op-checksig:ops] + == + (zing chunks) + -- :: Converts a list of bits to a list of n-bit numbers :: input-bits should be big-endian :: @@ -24,15 +55,15 @@ ^- (list @) =/ bits=(list @) (flop (rip 0 a)) =/ r=@ (mod (lent bits) bitwidth) - ?: =(0 r) bits :: no remainder, i.e. no leading zeros + ?: ?&(=(0 r) (gth (lent bits) 0)) :: no remainder & more than 0 bits + bits (weld (reap (sub bitwidth r) 0) bits) - :: converts from atom a with bitwidth s to a list of atoms each with bitwidth d + :: converts from bit list to a list of atoms each with bitwidth d(est) :: ++ convert - |= [s=@ d=@ a=@] + |= [d=@ bits=(list @)] ^- (list @) =| ret=(list @) - =/ bits (zeros-brip s a) |- ?~ bits ret =/ dest-bits (scag d ((list @) bits)) :: left-shift the "missing" number of bits @@ -42,6 +73,23 @@ (rep 0 (flop dest-bits)) == $(ret (snoc ret num), bits (slag d ((list @) bits))) + :: Converts e.g. ~[0 0 31 31 31 31 0 0] in base32 (5 bitwidth) + :: to ~[0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0] + :: + ++ from-digits + |= [bitwidth=@ digits=(list @)] + ^- (list @) + %- zing + %+ turn digits + |= d=@ (zeros-brip bitwidth d) + :: converts 40 bits: ~[0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0] + :: to 0x3fff.fc00 when cast to hex + :: + ++ to-atom + |= bits=(list @) + ^- @ + %+ rep 0 + %- flop bits -- :: ++ bech32 @@ -147,7 +195,18 @@ ~ =/ checksum-pos (sub (lent data-and-checksum) 6) `[hrp (scag checksum-pos data-and-checksum) (slag checksum-pos data-and-checksum)] + :: goes from a bech32 address to hex + :: + ++ to-hex + |= bech=tape + ^- @ux + =/ d=(unit raw-decoded) (decode-raw bech) + ?~ d ~|("Invalid bech32 address" !!) + %- to-atom:bits + %+ from-digits:bits 5 + (slag 1 data.u.d) :: pubkey is the 33 byte ECC compressed public key + :: ++ encode-pubkey |= [=network pubkey=@ux] ^- (unit tape) @@ -157,8 +216,7 @@ ?~ prefix ~ :- ~ %+ encode-raw u.prefix - (weld ~[0] (convert:bits 8 5 (hash-160 pubkey))) + (weld ~[0] (convert:bits 5 (zeros-brip:bits 8 (hash-160 pubkey)))) -- - :: -- diff --git a/sur/btc.hoon b/sur/btc.hoon index bd3b0ee3a..e2e68c91b 100644 --- a/sur/btc.hoon +++ b/sur/btc.hoon @@ -3,4 +3,11 @@ +$ legacy-address $%([%legacy @uc]) +$ bech32-address $%([%bech32 cord]) +$ address ?(legacy-address bech32-address) +++ ops + |% + ++ op-dup 118 + ++ op-equalverify 136 + ++ op-hash160 169 + ++ op-checksig 172 + -- --