/+ 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 ~) :: -- :: ++ hash-tx keccak-256:keccak:crypto :: ++ hash-raw-tx |= =raw-tx:naive ^- @ux (hash-tx raw.raw-tx) :: --