summaryrefslogtreecommitdiff
path: root/app/lib/bip
diff options
context:
space:
mode:
authorpolwex <polwex@sortug.com>2025-11-12 07:11:07 +0700
committerpolwex <polwex@sortug.com>2025-11-12 07:11:07 +0700
commit284ce9ce7d9f81e54e91f917329d48926487fbf4 (patch)
tree7a156986323fd799e1457c8b7663806e32b2af7d /app/lib/bip
parent7305d67ff7f9e78b73326ef0e1f68a9613d34205 (diff)
fixes to engagement handling
Diffstat (limited to 'app/lib/bip')
-rw-r--r--app/lib/bip/b173.hoon145
1 files changed, 145 insertions, 0 deletions
diff --git a/app/lib/bip/b173.hoon b/app/lib/bip/b173.hoon
new file mode 100644
index 0000000..e554597
--- /dev/null
+++ b/app/lib/bip/b173.hoon
@@ -0,0 +1,145 @@
+:: BIP173: Bech32 Addresses
+:: https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki
+::
+:: Heavily copies:
+:: https://github.com/bitcoinjs/bech32/blob/master/index.js
+::
+:: TODO not really working at generating npub/nsec keys from hex
+/- sur=bitcoin
+/+ bcu=bitcoin-utils
+=, sur
+=, bcu
+|%
+++ prefixes
+ ^- (map network tape)
+ (my [[%main "bc"] [%testnet "tb"] [%regtest "bcrt"] ~])
+++ charset "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
++$ raw-decoded [hrp=tape data=(list @) checksum=(list @)]
+:: below is a port of: https://github.com/bitcoinjs/bech32/blob/master/index.js
+::
+++ polymod
+ |= values=(list @)
+ |^ ^- @
+ =/ gen=(list @ux)
+ ~[0x3b6a.57b2 0x2650.8e6d 0x1ea1.19fa 0x3d42.33dd 0x2a14.62b3]
+ =/ chk=@ 1
+ |- ?~ values chk
+ =/ top (rsh [0 25] chk)
+ =. chk
+ (mix i.values (lsh [0 5] (dis chk 0x1ff.ffff)))
+ $(values t.values, chk (update-chk chk top gen))
+::
+ ++ update-chk
+ |= [chk=@ top=@ gen=(list @ux)]
+ =/ is (gulf 0 4)
+ |- ?~ is chk
+ ?: =(1 (dis 1 (rsh [0 i.is] top)))
+ $(is t.is, chk (mix chk (snag i.is gen)))
+ $(is t.is)
+ --
+::
+++ expand-hrp
+ |= hrp=tape
+ ^- (list @)
+ =/ front (turn hrp |=(p=@tD (rsh [0 5] p)))
+ =/ back (turn hrp |=(p=@tD (dis 31 p)))
+ (zing ~[front ~[0] back])
+::
+++ verify-checksum
+ |= [hrp=tape data-and-checksum=(list @)]
+ ^- ?
+ %- |=(a=@ =(1 a))
+ %- polymod
+ (weld (expand-hrp hrp) data-and-checksum)
+::
+++ checksum
+ |= [hrp=tape data=(list @)]
+ ^- (list @)
+ :: xor 1 with the polymod
+ ::
+ =/ pmod=@
+ %+ mix 1
+ %- polymod
+ (zing ~[(expand-hrp hrp) data (reap 6 0)])
+ %+ turn (gulf 0 5)
+ |=(i=@ (dis 31 (rsh [0 (mul 5 (sub 5 i))] pmod)))
+::
+++ charset-to-value
+ |= c=@tD
+ ^- (unit @)
+ (find ~[c] charset)
+++ value-to-charset
+ |= value=@
+ ^- (unit @tD)
+ ?: (gth value 31) ~
+ `(snag value charset)
+::
+++ is-valid
+ |= [bech=tape last-1-pos=@] ^- ?
+ ?& ?|(=((cass bech) bech) =((cuss bech) bech)) :: to upper or to lower is same as bech
+ (gte last-1-pos 1)
+ (lte (add last-1-pos 7) (lent bech))
+ (lte (lent bech) 90)
+ (levy bech |=(c=@tD (gte c 33)))
+ (levy bech |=(c=@tD (lte c 126)))
+ ==
+:: data should be 5bit words
+::
+++ encode-raw
+ |= [hrp=tape data=(list @)]
+ ^- cord
+ =/ combined=(list @)
+ (weld data (checksum hrp data))
+ %- crip
+ (zing ~[hrp "1" (tape (murn combined value-to-charset))])
+++ decode-raw
+ |= body=cord
+ ^- (unit raw-decoded)
+ =/ bech (cass (trip body)) :: to lowercase
+ =/ pos (flop (fand "1" bech))
+ ?~ pos ~
+ =/ last-1=@ i.pos
+ ?. (is-valid bech last-1) :: check bech32 validity (not segwit validity or checksum)
+ ~
+ =/ hrp (scag last-1 bech)
+ =/ encoded-data-and-checksum=(list @)
+ (slag +(last-1) bech)
+ =/ data-and-checksum=(list @)
+ %+ murn encoded-data-and-checksum
+ charset-to-value
+ ?. =((lent encoded-data-and-checksum) (lent data-and-checksum)) :: ensure all were in CHARSET
+ ~
+ ?. (verify-checksum hrp data-and-checksum)
+ ~
+ =/ checksum-pos (sub (lent data-and-checksum) 6)
+ `[hrp (scag checksum-pos data-and-checksum) (slag checksum-pos data-and-checksum)]
+:: +from-address: BIP173 bech32 address encoding to hex
+:: https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki
+:: expects to drop a leading 5-bit 0 (the witness version)
+::
+++ from-address
+ |= body=cord
+ ^- hexb
+ ~| "Invalid bech32 address"
+ =/ d=(unit raw-decoded) (decode-raw body)
+ ?> ?=(^ d)
+ =/ bs=bits (from-atoms:bit 5 data.u.d)
+ =/ byt-len=@ (div (sub wid.bs 5) 8)
+ ?> =(5^0b0 (take:bit 5 bs))
+ ?> ?| =(20 byt-len)
+ =(32 byt-len)
+ ==
+ [byt-len `@ux`dat:(take:bit (mul 8 byt-len) (drop:bit 5 bs))]
+:: pubkey is the 33 byte ECC compressed public key
+::
+++ encode-pubkey
+ |= [=network pubkey=byts]
+ ^- (unit cord)
+ ?. =(33 wid.pubkey)
+ ~|('pubkey must be a 33 byte ECC compressed public key' !!)
+ =/ prefix (~(get by prefixes) network)
+ ?~ prefix ~
+ :- ~
+ %+ encode-raw u.prefix
+ [0v0 (to-atoms:bit 5 [160 `@ub`dat:(hash-160 pubkey)])]
+--