urbit/pkg/arvo/lib/bitcoin-utils.hoon

167 lines
3.3 KiB
Plaintext
Raw Normal View History

2021-02-19 17:11:01 +03:00
:: lib/bitcoin-utils.hoon
2021-02-01 11:49:54 +03:00
:: Utilities for working with BTC data types and transactions
::
2021-02-18 15:13:06 +03:00
/- sur=bitcoin
2020-10-30 14:45:38 +03:00
=, sur
2020-10-04 11:56:38 +03:00
|%
2021-02-19 15:27:12 +03:00
::
2021-02-20 13:28:49 +03:00
:: TODO: move this bit/byt stuff to zuse
2021-02-19 15:27:12 +03:00
:: bit/byte utilities
::
::
:: +blop: munge bit and byt sequences (cat, flip, take, drop)
::
++ blop
|_ =bloq
+$ biyts [wid=@ud dat=@]
++ cat
|= bs=(list biyts)
^- biyts
:- (roll (turn bs |=(b=biyts -.b)) add)
(can bloq (flop bs))
:: +flip: flip endianness while preserving lead/trail zeroes
::
++ flip
|= b=biyts
^- biyts
[wid.b (rev bloq b)]
:: +take: take n bloqs from front
:: pads front with extra zeroes if n is longer than input
::
++ take
|= [n=@ b=biyts]
^- biyts
?: (gth n wid.b)
[n dat.b]
[n (rsh [bloq (sub wid.b n)] dat.b)]
:: +drop: drop n bloqs from front
:: returns 0^0 if n >= width
::
++ drop
|= [n=@ b=biyts]
^- biyts
?: (gte n wid.b)
0^0x0
=+ n-take=(sub wid.b n)
[n-take (end [bloq n-take] dat.b)]
--
2021-02-21 14:03:21 +03:00
++ byt ~(. blop 3)
2021-02-19 15:27:12 +03:00
::
++ bit
2021-02-21 13:13:50 +03:00
=/ bl ~(. blop 0)
2021-02-19 15:27:12 +03:00
|%
++ cat cat:bl:bit
++ flip flip:bl:bit
++ take take:bl:bit
++ drop drop:bl:bit
++ from-atoms
|= [bitwidth=@ digits=(list @)]
^- bits
%- cat:bit
%+ turn digits
|= a=@
?> (lte (met 0 a) bitwidth)
[bitwidth `@ub`a]
:: +to-atoms: convert bits to atoms of bitwidth
::
++ to-atoms
|= [bitwidth=@ bs=bits]
^- (list @)
=| res=(list @)
?> =(0 (mod wid.bs bitwidth))
|-
?: =(0 wid.bs) res
%= $
res (snoc res dat:(take:bit bitwidth bs))
bs (drop:bit bitwidth bs)
==
--
2021-02-20 14:43:21 +03:00
:: big endian sha256: input and output are both MSB first (big endian)
::
++ sha256
|= =byts
^- hexb
%- flip:byt
[32 (shay (flip:byt byts))]
::
++ dsha256
|= =byts
(sha256 (sha256 byts))
::
++ hash-160
|= val=byts
^- hexb
=, ripemd:crypto
:- 20
%- ripemd-160
(sha256 val)
2021-02-20 13:28:49 +03:00
::
:: hxb: hex parsing utilities
::
++ hxb
|%
++ from-cord
|= h=@t
^- hexb
?: =('' h) 1^0x0
:: Add leading 00
::
=+ (lsh [3 2] h)
:: Group by 4-size block
::
=+ (rsh [3 2] -)
:: Parse hex to atom
::
:- (div (lent (trip h)) 2)
`@ux`(rash - hex)
::
2021-02-20 13:28:49 +03:00
++ to-cord
|= =hexb
^- cord
(en:base16:mimes:html hexb)
--
::
2021-02-20 13:28:49 +03:00
:: +csiz: CompactSize integers (a Bitcoin-specific datatype)
:: https://btcinformation.org/en/developer-reference#compactsize-unsigned-integers
2021-02-09 08:02:46 +03:00
:: - encode: big endian to little endian
:: - decode: little endian to big endian
2021-02-08 22:21:19 +03:00
::
2021-02-09 08:02:46 +03:00
++ csiz
|%
++ en
|= a=@
^- hexb
=/ l=@ (met 3 a)
?: =(l 1) 1^a
?: =(l 2) (cat:byt ~[1^0xfd (flip:byt 2^a)])
?: (lte l 4) (cat:byt ~[1^0xfe (flip:byt 4^a)])
?: (lte l 8) (cat:byt ~[1^0xff (flip:byt 8^a)])
~|("Cannot encode CompactSize longer than 8 bytes" !!)
2021-02-09 12:29:51 +03:00
::
2021-02-09 08:02:46 +03:00
++ de
|= h=hexb
^- [n=hexb rest=hexb]
=/ s=@ux dat:(take:byt 1 h)
?: (lth s 0xfd) [1^s (drop:byt 1 h)]
~| "Invalid compact-size at start of {<h>}"
=/ len=bloq
2021-02-08 22:21:19 +03:00
?+ s !!
2021-02-09 08:02:46 +03:00
%0xfd 1
%0xfe 2
%0xff 3
2021-02-08 22:21:19 +03:00
==
2021-02-09 12:29:51 +03:00
:_ (drop:byt (add 1 len) h)
%- flip:byt
(take:byt (bex len) (drop:byt 1 h))
2021-02-09 13:25:38 +03:00
:: +dea: atom instead of hexb for parsed CompactSize
2021-02-09 12:29:51 +03:00
::
++ dea
|= h=hexb
^- [a=@ rest=hexb]
=> (de h)
[dat.n rest]
2021-02-09 08:02:46 +03:00
--
2021-01-25 16:01:36 +03:00
::
2020-10-04 11:56:38 +03:00
--