urbit/pkg/arvo/lib/naive-transactions.hoon

224 lines
4.8 KiB
Plaintext

/+ naive, ethereum
:: Types
|%
+$ address address:ethereum
+$ nonce @ud
+$ proxy ?(%own %spawn %manage %vote %transfer)
--
::
|%
::
:: TODO: does this uniquely produce the pubkey?
++ verifier
^- ^verifier:naive
|= [dat=octs v=@ r=@ s=@]
?: (gth v 3) ~ :: TODO: move to jet
=/ result
%- mule
|.
=, secp256k1:secp:crypto
%- address-from-pub:key:ethereum
%- serialize-point
(ecdsa-raw-recover (hash-tx dat) v r s)
?- -.result
%| ~
%& `p.result
==
:: Verify signature and produce signer address
::
++ verify-sig
|= [sig=@ txdata=octs]
^- (unit address)
|^
:: Reversed of the usual r-s-v order because Ethereum integers are
:: big-endian
::
=^ v sig (take 3)
=^ s sig (take 3 32)
=^ r sig (take 3 32)
:: In Ethereum, v is generally 27 + recid, and verifier expects a
:: recid. Old versions of geth used 0 + recid, so most software
:: now supports either format. See:
::
:: https://github.com/ethereum/go-ethereum/issues/2053
::
=? v (gte v 27) (sub v 27)
(verifier txdata v r s)
::
++ take
|= =bite
[(end bite sig) (rsh bite sig)]
--
::
++ unsigned-tx
|= [chain-id=@ud =nonce tx=octs]
^- octs
=/ prepared-data (prepare-for-sig chain-id nonce tx)
=/ len (rsh [3 2] (scot %ui p.prepared-data))
%: cad:naive 3
26^'\19Ethereum Signed Message:\0a'
(met 3 len)^len
prepared-data
~
==
::
++ sign-tx
|= [pk=@ =nonce tx=octs] ^- octs
=/ sign-data
%- hash-tx
(unsigned-tx 1.337 nonce tx)
=+ (ecdsa-raw-sign:secp256k1:secp:crypto sign-data pk)
(cad:naive 3 1^v 32^s 32^r tx ~)
::
++ prepare-for-sig
|= [chain-id=@ud =nonce tx=octs]
^- octs
=/ chain-t (rsh [3 2] (scot %ui chain-id))
%: cad:naive 3
14^'UrbitIDV1Chain'
(met 3 chain-t)^chain-t
1^':'
4^nonce
tx
~
==
::
++ extract-address
|= [=raw-tx:naive nas=^state:naive chain-id=@]
^- (unit @ux)
?~ point=(get:orm:naive points.nas ship.from.tx.raw-tx)
~
=/ =nonce:naive
=< nonce
(proxy-from-point:naive proxy.from.tx.raw-tx u.point)
=/ message=octs
(unsigned-tx chain-id nonce raw.raw-tx)
(verify-sig sig.raw-tx message)
::
++ gen-tx
|= [=nonce tx=tx:naive pk=@] ^- octs
:: takes in a nonce, tx:naive, and private key and returned a signed transactions as octs
%^ sign-tx pk nonce (gen-tx-octs tx)
::
++ gen-tx-octs
:: generates octs for a transaction
|= tx=tx:naive
|^
^- octs
=/ raw=octs
?- +<.tx
%spawn (get-spawn +>.tx)
%transfer-point (get-transfer +>.tx)
%configure-keys (get-keys +>.tx)
%escape (get-escape +.tx)
%cancel-escape (get-escape +.tx)
%adopt (get-escape +.tx)
%reject (get-escape +.tx)
%detach (get-escape +.tx)
%set-management-proxy (get-ship-address +.tx)
%set-spawn-proxy (get-ship-address +.tx)
%set-transfer-proxy (get-ship-address +.tx)
==
raw
::
++ get-spawn
|= [child=ship to=address] ^- octs
%: cad:naive 3
(from-proxy proxy.from.tx)
4^ship.from.tx
1^%1 :: %spawn
4^child
20^to
~
==
::
++ get-transfer
|= [=address reset=?] ^- octs
%: cad:naive 3
(from-proxy proxy.from.tx)
4^ship.from.tx
1^(can 0 7^%0 1^reset ~) :: %transfer-point
20^address
~
==
::
++ get-keys
|= [crypt=@ auth=@ suite=@ breach=?] ^- octs
%: cad:naive 3
(from-proxy proxy.from.tx)
4^ship.from.tx
1^(can 0 7^%2 1^breach ~) :: %configure-keys
32^crypt
32^auth
4^suite
~
==
::
++ get-escape
|= [action=@tas other=ship] ^- octs
=/ op
?+ action !!
%escape %3
%cancel-escape %4
%adopt %5
%reject %6
%detach %7
==
%: cad:naive 3
(from-proxy proxy.from.tx)
4^ship.from.tx
1^(can 0 7^op 1^0 ~)
4^other
~
==
::
++ get-ship-address
|= [action=@tas =address] ^- octs
=/ op
?+ action !!
%set-management-proxy %8
%set-spawn-proxy %9
%set-transfer-proxy %10
==
%: cad:naive 3
(from-proxy proxy.from.tx)
4^ship.from.tx
1^(can 0 7^op 1^0 ~)
20^address
~
==
::
++ from-proxy
|= prx=@tas
^- [@ @]
=/ proxy
?+ prx !!
%own %0
%spawn %1
%manage %2
%vote %3
%transfer %4
==
1^(can 0 3^proxy 5^0 ~)
::
--
::
++ reverse-hash
|= keccak=@ux
^+ keccak
(rev 3 (met 3 keccak) keccak)
::
++ hash-tx keccak-256:keccak:crypto
::
++ hash-raw-tx
|= raw-tx:naive
^- @ux
%- hash-tx
%: cad:naive 3
65^sig
raw
~
==
::
--