diff --git a/lib/keygen.hoon b/lib/keygen.hoon index e4074b2a5..9f66cddbd 100644 --- a/lib/keygen.hoon +++ b/lib/keygen.hoon @@ -81,7 +81,7 @@ =+ => (from-seed:bip32 64^seed) (derive-path "m/44'/60'/0'/0/0") :+ [public-key private-key] - (address-from-prv:ethereum private-key) + (address-from-prv:key:ethereum private-key) chain-code :: ++ urbit diff --git a/mar/azimuth/update.hoon b/mar/azimuth/update.hoon index 37f31f447..45b0e6727 100644 --- a/mar/azimuth/update.hoon +++ b/mar/azimuth/update.hoon @@ -1,8 +1,8 @@ :: -|_ upd=update:azimuth:ethe +|_ upd=update:azimuth :: ++ grab :: convert from |% - ++ noun update:azimuth:ethe :: from %noun + ++ noun update:azimuth :: from %noun -- -- diff --git a/sys/vane/jael.hoon b/sys/vane/jael.hoon index 14f9ee068..8c2800b4b 100644 --- a/sys/vane/jael.hoon +++ b/sys/vane/jael.hoon @@ -21,10 +21,9 @@ =, able:jael =, crypto =, jael -=, ethe -=, azimuth:ethe =, ethereum -=, azimuth:ethereum +=, rpc +=, azimuth :: :::: :::: # models :: data structures :: :::: diff --git a/sys/zuse.hoon b/sys/zuse.hoon index d09121aa7..eb2af0de5 100644 --- a/sys/zuse.hoon +++ b/sys/zuse.hoon @@ -112,349 +112,78 @@ == -- -- -:: :: -:::: ++eth :: ethereum structures +:: :::: +:::: ++ethereum-types :: eth surs for jael :: :::: -++ ethe +++ ethereum-types |% - :: - :: solidity types. integer bitsizes ignored - ++ etyp - $% :: static - %address %bool - %int %uint - %real %ureal - [%bytes-n n=@ud] - :: dynamic - [%array-n t=etyp n=@ud] - [%array t=etyp] - %bytes %string - == - :: - :: solidity-style typed data. integer bitsizes ignored - ++ data - $% [%address p=address] - [%string p=tape] - [%bool p=?] - [%int p=@sd] - [%uint p=@ud] - [%real p=@rs] - [%ureal p=@urs] - [%array-n p=(list data)] - [%array p=(list data)] - [%bytes-n p=octs] ::TODO just @, because context knows length? - [%bytes p=octs] - == - :: - :: raw transaction data - +$ transaction - $: nonce=@ud - gas-price=@ud - gas=@ud - to=address - value=@ud - data=@ux - chain-id=@ux - == - :: :: ethereum address, 20 bytes. + :: ++ address @ux + :: event location :: - :: ethereum json rpc api - :: - :: supported requests. - ++ request - $% [%eth-block-number ~] - [%eth-call cal=call deb=block] - $: %eth-new-filter - fro=(unit block) - tob=(unit block) - adr=(list address) - top=(list octs) - == - [%eth-get-filter-logs fid=@ud] - $: %eth-get-logs - fro=(unit block) - tob=(unit block) - adr=(list address) - top=(list octs) - == - [%eth-get-filter-changes fid=@ud] - [%eth-send-raw-transaction dat=@ux] - == - :: - ::TODO clean up & actually use - ++ response - $% ::TODO - [%eth-new-filter fid=@ud] - [%eth-get-filter-logs los=(list event-log)] - [%eth-get-logs los=(list event-log)] - [%eth-got-filter-changes los=(list event-log)] - [%eth-transaction-hash haz=@ux] - == - :: - ++ event-log - $: :: null for pending logs - $= mined %- unit - $: log-index=@ud - transaction-index=@ud - transaction-hash=@ux - block-number=@ud - block-hash=@ux - removed=? - == - :: - address=@ux - data=@t - event=@ux - topics=(list @t) - == - :: - :: alternative event location. += event-id [block=@ud log=@ud] :: - :: data for eth_call. - ++ call - $: from=(unit address) - to=address - gas=(unit @ud) - gas-price=(unit @ud) - value=(unit @ud) - data=tape - == - :: - :: minimum data needed to construct a read call - ++ proto-read-request - $: id=(unit @t) - to=address - call-data - == - :: - :: raw call data - ++ call-data - $: function=@t - arguments=(list data) - == - :: - :: block to operate on. - ++ block - $% [%number n=@ud] - [%label l=?(%earliest %latest %pending)] - == - :: - :: - ++ azimuth - |% - ++ point - $: $= own :: ownership - $: owner=address - management-proxy=address - voting-proxy=address - transfer-proxy=address - == + ++ events (set event-id) + -- +:: :::: +:::: ++azimuth-types :: az surs for jael + :: :::: +++ azimuth-types + =, ethereum-types + |% + ++ point + $: :: ownership :: - $= net :: networking - %- unit - $: =life - =pass - continuity-number=@ud - sponsor=(unit @p) ::TODO doesn't 100% reflect chain state - escape=(unit @p) - == - :: - $= kid :: spawning - %- unit - $: spawn-proxy=address - spawned=(set @p) ::TODO sparse range, pile, see old jael ++py - == - == - :: - ++ complete-ship - $: state=point - history=(list diff-point) ::TODO maybe block/event nr? :: newest first - keys=(map life pass) - == - :: - ++ fleet (map @p complete-ship) - :: - += dnses [pri=@t sec=@t ter=@t] - :: - ++ events (set event-id) - :: - ++ eth-type - |% - ++ point - :~ [%bytes-n 32] :: encryptionKey - [%bytes-n 32] :: authenticationKey - %bool :: hasSponsor - %bool :: active - %bool :: escapeRequested - %uint :: sponsor - %uint :: escapeRequestedTo - %uint :: cryptoSuiteVersion - %uint :: keyRevisionNumber - %uint :: continuityNumber - == - ++ deed - :~ %address :: owner - %address :: managementProxy - %address :: spawnProxy - %address :: votingProxy - %address :: transferProxy - == - -- - :: - ++ eth-noun - |% - ++ point - $: encryption-key=octs - authentication-key=octs - has-sponsor=? - active=? - escape-requested=? - sponsor=@ud - escape-to=@ud - crypto-suite=@ud - key-revision=@ud - continuity-number=@ud - == - ++ deed + $= own $: owner=address management-proxy=address - spawn-proxy=address voting-proxy=address transfer-proxy=address == - -- - :: - ++ function - |% - ++ azimuth - $% [%points who=@p] - [%rights who=@p] - [%get-spawned who=@p] - [%dns-domains ind=@ud] + :: + :: networking + :: + $= net + %- unit + $: =life + =pass + continuity-number=@ud + sponsor=(unit @p) ::TODO doesn't 100% reflect chain state + escape=(unit @p) == - -- - :: - :: # diffs - :: - ++ update - $% [%full ships=(map ship point) dns=dnses heard=events] ::TODO keys - [%difs dis=(list (pair event-id diff-azimuth))] - == - :: - ++ diff-azimuth - $% [%point who=@p dif=diff-point] - [%dns pri=@t sec=@t ter=@t] - == - :: - ++ diff-point - $% [%full new=point] :: - [%owner new=address] :: OwnerChanged - [%activated who=@p] :: Activated - [%spawned who=@p] :: Spawned - [%keys =life =pass] :: ChangedKeys - [%continuity new=@ud] :: BrokeContinuity - [%sponsor new=(unit @p)] :: EscapeAcc/LostSpons - [%escape new=(unit @p)] :: EscapeReq/Can - [%management-proxy new=address] :: ChangedManagementPro - [%voting-proxy new=address] :: ChangedVotingProxy - [%spawn-proxy new=address] :: ChangedSpawnProxy - [%transfer-proxy new=address] :: ChangedTransferProxy - == - :: - :: # constants - :: - :: contract addresses - ::TODO values below are for ropsten, update for mainnet - ++ contracts - |% - :: azimuth: data contract :: - ++ azimuth 0x308a.b6a6.024c.f198.b57e.008d.0ac9.ad02.1988.6579 - :: - :: launch: block number of azimuth deploy - :: - ++ launch 4.601.630 - -- - :: - :: hashes of ship event signatures - ++ azimuth-events - |% - :: - :: OwnerChanged(uint32,address) - ++ owner-changed - 0x16d0.f539.d49c.6cad.822b.767a.9445.bfb1. - cf7e.a6f2.a6c2.b120.a7ea.4cc7.660d.8fda - :: - :: Activated(uint32) - ++ activated - 0xe74c.0380.9d07.69e1.b1f7.06cc.8414.258c. - d1f3.b6fe.020c.d15d.0165.c210.ba50.3a0f - :: - :: Spawned(uint32,uint32) - ++ spawned - 0xb2d3.a6e7.a339.f5c8.ff96.265e.2f03.a010. - a854.1070.f374.4a24.7090.9644.1508.1546 - :: - :: EscapeRequested(uint32,uint32) - ++ escape-requested - 0xb4d4.850b.8f21.8218.141c.5665.cba3.79e5. - 3e9b.b015.b51e.8d93.4be7.0210.aead.874a - :: - :: EscapeCanceled(uint32,uint32) - ++ escape-canceled - 0xd653.bb0e.0bb7.ce83.93e6.24d9.8fbf.17cd. - a590.2c83.28ed.0cd0.9988.f368.90d9.932a - :: - :: EscapeAccepted(uint32,uint32) - ++ escape-accepted - 0x7e44.7c9b.1bda.4b17.4b07.96e1.00bf.7f34. - ebf3.6dbb.7fe6.6549.0b1b.fce6.246a.9da5 - :: - :: LostSponsor(uint32,uint32) - ++ lost-sponsor - 0xd770.4f9a.2519.3dbd.0b0c.b4a8.09fe.ffff. - a7f1.9d1a.ae88.17a7.1346.c194.4482.10d5 - :: - :: ChangedKeys(uint32,bytes32,bytes32,uint32,uint32) - ++ changed-keys - 0xaa10.e7a0.117d.4323.f1d9.9d63.0ec1.69be. - bb3a.988e.8957.70e3.5198.7e01.ff54.23d5 - :: - :: BrokeContinuity(uint32,uint32) - ++ broke-continuity - 0x2929.4799.f1c2.1a37.ef83.8e15.f79d.d91b. - cee2.df99.d63c.d1c1.8ac9.68b1.2951.4e6e - :: - :: ChangedSpawnProxy(uint32,address) - ++ changed-spawn-proxy - 0x9027.36af.7b3c.efe1.0d9e.840a.ed0d.687e. - 35c8.4095.122b.2505.1a20.ead8.866f.006d - :: - :: ChangedTransferProxy(uint32,address) - ++ changed-transfer-proxy - 0xcfe3.69b7.197e.7f0c.f067.93ae.2472.a9b1. - 3583.fecb.ed2f.78df.a14d.1f10.796b.847c - :: - :: ChangedManagementProxy(uint32,address) - ++ changed-management-proxy - 0xab9c.9327.cffd.2acc.168f.afed.be06.139f. - 5f55.cb84.c761.df05.e051.1c25.1e2e.e9bf - :: - :: ChangedVotingProxy(uint32,address) - ++ changed-voting-proxy - 0xcbd6.269e.c714.57f2.c7b1.a227.74f2.46f6. - c5a2.eae3.795e.d730.0db5.1768.0c61.c805 - :: - :: ChangedDns(string,string,string) - ++ changed-dns - 0xfafd.04ad.e1da.ae2e.1fdb.0fc1.cc6a.899f. - d424.063e.d5c9.2120.e67e.0730.53b9.4898 - -- - -- :: azimuth - -- :: ethe + :: spawning + :: + $= kid + %- unit + $: spawn-proxy=address + spawned=(set @p) ::TODO sparse range, pile, see old jael ++py + == + == + :: + += dnses [pri=@t sec=@t ter=@t] + :: + ++ diff-azimuth + $% [%point who=@p dif=diff-point] + [%dns dnses] + == + :: + ++ diff-point + $% [%full new=point] :: + [%owner new=address] :: OwnerChanged + [%activated who=@p] :: Activated + [%spawned who=@p] :: Spawned + [%keys =life =pass] :: ChangedKeys + [%continuity new=@ud] :: BrokeContinuity + [%sponsor new=(unit @p)] :: EscapeAcc/LostSpons + [%escape new=(unit @p)] :: EscapeReq/Can + [%management-proxy new=address] :: ChangedManagementPro + [%voting-proxy new=address] :: ChangedVotingProxy + [%spawn-proxy new=address] :: ChangedSpawnProxy + [%transfer-proxy new=address] :: ChangedTransferProxy + == + -- :: :::: :::: ++ames :: (1a) network :: :::: @@ -2028,7 +1757,6 @@ ++ able ^? =, pki =, rights - ::TODO =, eth:jael |% :: %jael has two general kinds of task: changes :: and change subscriptions. @@ -2050,8 +1778,8 @@ :: through %ames and use %behn timers. :: ++ logs :: on-chain changes - %+ map event-id:ethe :: per event log - diff-azimuth:azimuth:ethe :: the change + %+ map event-id:ethereum-types :: per event log + diff-azimuth:azimuth-types :: the change ++ action :: balance change %+ pair ship :: partner %+ each bump :: &/liability change @@ -2168,7 +1896,7 @@ poll-timer=@da :: next filter poll == :: ++ snapshot :: rewind point - =, azimuth:ethe :: + =, azimuth-types :: $: kyz=(map ship public:able) :: public key state $= eth :: $: dns=dnses :: on-chain dns state @@ -2179,7 +1907,7 @@ :: +eth-bookmark: cursor into the ethereum chain :: ++ eth-bookmark - $: heard=(set event-id:ethe) + $: heard=(set event-id:ethereum-types) latest-block=@ud == :: +state-eth-node: state of a connection to an ethereum node @@ -7373,48 +7101,448 @@ {$wake ~} :: behn: wakeup == :: :: +:::: ++azimuth :: (2az) azimuth + :: :::: +++ azimuth + !: + =* address address:rpc:ethereum + :: types + :: + => => [azimuth-types ethereum-types .] + |% + ++ complete-ship + $: state=point + history=(list diff-point) ::TODO maybe block/event nr? :: newest first + keys=(map life pass) + == + :: + ++ fleet (map @p complete-ship) + :: + ++ eth-type + |% + ++ point + :~ [%bytes-n 32] :: encryptionKey + [%bytes-n 32] :: authenticationKey + %bool :: hasSponsor + %bool :: active + %bool :: escapeRequested + %uint :: sponsor + %uint :: escapeRequestedTo + %uint :: cryptoSuiteVersion + %uint :: keyRevisionNumber + %uint :: continuityNumber + == + ++ deed + :~ %address :: owner + %address :: managementProxy + %address :: spawnProxy + %address :: votingProxy + %address :: transferProxy + == + -- + :: + ++ eth-noun + |% + ++ point + $: encryption-key=octs + authentication-key=octs + has-sponsor=? + active=? + escape-requested=? + sponsor=@ud + escape-to=@ud + crypto-suite=@ud + key-revision=@ud + continuity-number=@ud + == + ++ deed + $: owner=address + management-proxy=address + spawn-proxy=address + voting-proxy=address + transfer-proxy=address + == + -- + :: + ++ function + |% + ++ azimuth + $% [%points who=@p] + [%rights who=@p] + [%get-spawned who=@p] + [%dns-domains ind=@ud] + == + -- + :: + :: # diffs + :: + ++ update + $% [%full ships=(map ship point) dns=dnses heard=events] ::TODO keys + [%difs dis=(list (pair event-id diff-azimuth))] + == + :: + :: # constants + :: + :: contract addresses + ::TODO values below are for ropsten, update for mainnet + ++ contracts + |% + :: azimuth: data contract + :: + ++ azimuth 0x308a.b6a6.024c.f198.b57e.008d.0ac9.ad02.1988.6579 + :: + :: launch: block number of azimuth deploy + :: + ++ launch 4.601.630 + -- + :: + :: hashes of ship event signatures + ++ azimuth-events + |% + :: + :: OwnerChanged(uint32,address) + ++ owner-changed + 0x16d0.f539.d49c.6cad.822b.767a.9445.bfb1. + cf7e.a6f2.a6c2.b120.a7ea.4cc7.660d.8fda + :: + :: Activated(uint32) + ++ activated + 0xe74c.0380.9d07.69e1.b1f7.06cc.8414.258c. + d1f3.b6fe.020c.d15d.0165.c210.ba50.3a0f + :: + :: Spawned(uint32,uint32) + ++ spawned + 0xb2d3.a6e7.a339.f5c8.ff96.265e.2f03.a010. + a854.1070.f374.4a24.7090.9644.1508.1546 + :: + :: EscapeRequested(uint32,uint32) + ++ escape-requested + 0xb4d4.850b.8f21.8218.141c.5665.cba3.79e5. + 3e9b.b015.b51e.8d93.4be7.0210.aead.874a + :: + :: EscapeCanceled(uint32,uint32) + ++ escape-canceled + 0xd653.bb0e.0bb7.ce83.93e6.24d9.8fbf.17cd. + a590.2c83.28ed.0cd0.9988.f368.90d9.932a + :: + :: EscapeAccepted(uint32,uint32) + ++ escape-accepted + 0x7e44.7c9b.1bda.4b17.4b07.96e1.00bf.7f34. + ebf3.6dbb.7fe6.6549.0b1b.fce6.246a.9da5 + :: + :: LostSponsor(uint32,uint32) + ++ lost-sponsor + 0xd770.4f9a.2519.3dbd.0b0c.b4a8.09fe.ffff. + a7f1.9d1a.ae88.17a7.1346.c194.4482.10d5 + :: + :: ChangedKeys(uint32,bytes32,bytes32,uint32,uint32) + ++ changed-keys + 0xaa10.e7a0.117d.4323.f1d9.9d63.0ec1.69be. + bb3a.988e.8957.70e3.5198.7e01.ff54.23d5 + :: + :: BrokeContinuity(uint32,uint32) + ++ broke-continuity + 0x2929.4799.f1c2.1a37.ef83.8e15.f79d.d91b. + cee2.df99.d63c.d1c1.8ac9.68b1.2951.4e6e + :: + :: ChangedSpawnProxy(uint32,address) + ++ changed-spawn-proxy + 0x9027.36af.7b3c.efe1.0d9e.840a.ed0d.687e. + 35c8.4095.122b.2505.1a20.ead8.866f.006d + :: + :: ChangedTransferProxy(uint32,address) + ++ changed-transfer-proxy + 0xcfe3.69b7.197e.7f0c.f067.93ae.2472.a9b1. + 3583.fecb.ed2f.78df.a14d.1f10.796b.847c + :: + :: ChangedManagementProxy(uint32,address) + ++ changed-management-proxy + 0xab9c.9327.cffd.2acc.168f.afed.be06.139f. + 5f55.cb84.c761.df05.e051.1c25.1e2e.e9bf + :: + :: ChangedVotingProxy(uint32,address) + ++ changed-voting-proxy + 0xcbd6.269e.c714.57f2.c7b1.a227.74f2.46f6. + c5a2.eae3.795e.d730.0db5.1768.0c61.c805 + :: + :: ChangedDns(string,string,string) + ++ changed-dns + 0xfafd.04ad.e1da.ae2e.1fdb.0fc1.cc6a.899f. + d424.063e.d5c9.2120.e67e.0730.53b9.4898 + -- + -- + :: + :: logic + :: + |% + ++ pass-from-eth + |= [enc=octs aut=octs sut=@ud] + ^- (unit pass) + ?. &(=(1 sut) =(p.enc 32) =(p.aut 32)) + ~ + `(cat 3 'b' (cat 8 q.aut q.enc)) + :: + ++ point-from-eth + |= [who=@p point:eth-noun deed:eth-noun] + ^- point + :: + :: ownership + :: + :+ :* owner + management-proxy + voting-proxy + transfer-proxy + == + :: + :: network state + :: + ::TODO doesn't match semantics of %activated diff, and + :: setting ~ here will cause a crash on the next networking diff + ?: =(0 key-revision) ~ + :- ~ + :* key-revision + :: + %- need + (pass-from-eth encryption-key authentication-key crypto-suite) + :: + continuity-number + :: + ?. has-sponsor ~ + ``@p`sponsor + :: + ?. escape-requested ~ + ``@p`escape-to + == + :: + :: spawn state + :: + ?. ?=(?(%czar %king) (clan:title who)) ~ + :- ~ + :* spawn-proxy + ~ ::TODO call getSpawned to fill this + == + :: + ++ event-log-to-point-diff + =, azimuth-events + =, abi:ethereum + |= log=event-log:rpc:ethereum + ^- (unit (pair ship diff-point)) + ~? ?=(~ mined.log) %processing-unmined-event + :: + ?: =(event.log owner-changed) + =+ ^- [who=@ wer=address] + (decode-topics topics.log ~[%uint %address]) + `[who %owner wer] + :: + ?: =(event.log activated) + =/ who=@ + (decode-topics topics.log ~[%uint]) + `[who %activated who] + :: + ?: =(event.log spawned) + =/ pre=@ (decode-topics topics.log ~[%uint]) + =/ who=@ (decode-results data.log ~[%uint]) + `[pre %spawned who] + :: + ?: =(event.log escape-requested) + =+ ^- [who=@ wer=@] + (decode-topics topics.log ~[%uint %uint]) + `[who %escape `wer] + :: + ?: =(event.log escape-canceled) + =/ who=@ (decode-topics topics.log ~[%uint]) + `[who %escape ~] + :: + ?: =(event.log escape-accepted) + =+ ^- [who=@ wer=@] + (decode-topics topics.log ~[%uint %uint]) + `[who %sponsor `wer] + :: + ?: =(event.log lost-sponsor) + =/ who=@ (decode-topics topics.log ~[%uint]) + `[who %sponsor ~] + :: + ?: =(event.log changed-keys) + =/ who=@ (decode-topics topics.log ~[%uint]) + =+ ^- [enc=octs aut=octs sut=@ud rev=@ud] + %+ decode-results data.log + ~[[%bytes-n 32] [%bytes-n 32] %uint %uint] + `[who %keys rev (need (pass-from-eth enc aut sut))] + :: + ?: =(event.log broke-continuity) + =/ who=@ (decode-topics topics.log ~[%uint]) + =/ num=@ (decode-results data.log ~[%uint]) + `[who %continuity num] + :: + ?: =(event.log changed-management-proxy) + =+ ^- [who=@ sox=address] + (decode-topics topics.log ~[%uint %address]) + `[who %management-proxy sox] + :: + ?: =(event.log changed-voting-proxy) + =+ ^- [who=@ tox=address] + (decode-topics topics.log ~[%uint %address]) + `[who %voting-proxy tox] + :: + ?: =(event.log changed-spawn-proxy) + =+ ^- [who=@ sox=address] + (decode-topics topics.log ~[%uint %address]) + `[who %spawn-proxy sox] + :: + ?: =(event.log changed-transfer-proxy) + =+ ^- [who=@ tox=address] + (decode-topics topics.log ~[%uint %address]) + `[who %transfer-proxy tox] + :: + :: warn about unimplemented events, but ignore + :: the ones we know are harmless. + ~? ?! .= event.log + :: OwnershipTransferred(address,address) + 0x8be0.079c.5316.5914.1344.cd1f.d0a4.f284. + 1949.7f97.22a3.daaf.e3b4.186f.6b64.57e0 + [%unimplemented-event event.log] + ~ + :: + ++ apply-point-diff + |= [pot=point dif=diff-point] + ^- point + ?- -.dif + %full new.dif + :: + %activated + %_ pot + net `[0 0 0 `(^sein:title who.dif) ~] + kid ?. ?=(?(%czar %king) (clan:title who.dif)) ~ + `[0x0 ~] + == + :: + :: ownership + :: + %owner pot(owner.own new.dif) + %transfer-proxy pot(transfer-proxy.own new.dif) + %management-proxy pot(management-proxy.own new.dif) + %voting-proxy pot(voting-proxy.own new.dif) + :: + :: networking + :: + ?(%keys %continuity %sponsor %escape) + ?> ?=(^ net.pot) + ?- -.dif + %keys + pot(life.u.net life.dif, pass.u.net pass.dif) + :: + %sponsor + ?~ new.dif pot(sponsor.u.net ~) + pot(sponsor.u.net new.dif, escape.u.net ~) + :: + %continuity pot(continuity-number.u.net new.dif) + %escape pot(escape.u.net new.dif) + == + :: + :: spawning + :: + ?(%spawned %spawn-proxy) + ?> ?=(^ kid.pot) + ?- -.dif + %spawned + =- pot(spawned.u.kid -) + (~(put in spawned.u.kid.pot) who.dif) + :: + %spawn-proxy pot(spawn-proxy.u.kid new.dif) + == + == + :: + ++ parse-id + |= id=@t + ^- azimuth:function + |^ + ~| id + %+ rash id + ;~ pose + (function %points 'points' shipname) + (function %get-spawned 'getSpawned' shipname) + (function %dns-domains 'dnsDomains' dem:ag) + == + :: + ++ function + |* [tag=@tas fun=@t rul=rule] + ;~(plug (cold tag (jest fun)) (ifix [lit rit] rul)) + :: + ++ shipname + ;~(pfix sig fed:ag) + -- + :: + ++ function-to-call + |% + ++ azimuth + |= cal=azimuth:function + ^- [id=@t dat=call-data:rpc:ethereum] + ?- -.cal + %points + :- (crip "points({(scow %p who.cal)})") + ['points(uint32)' ~[uint+`@`who.cal]] + :: + %rights + :- (crip "rights({(scow %p who.cal)})") + ['rights(uint32)' ~[uint+`@`who.cal]] + :: + %get-spawned + :- (crip "getSpawned({(scow %p who.cal)})") + ['getSpawned(uint32)' ~[uint+`@`who.cal]] + :: + %dns-domains + :- (crip "dnsDomains({(scow %ud ind.cal)})") + ['dnsDomains(uint256)' ~[uint+ind.cal]] + == + -- + -- +:: :: :::: ++ethereum :: (2eth) ethereum :: :::: ++ ethereum !: - =, mimes:html - =, ethe + => [ethereum-types .] |% - ++ address-from-pub - =, keccak:crypto - |= pub=@ - %^ end 3 20 - %+ keccak-256 64 - (rev 3 64 pub) + :: deriving and using ethereum keys :: - ++ address-from-prv - (cork pub-from-prv address-from-pub) - :: - ++ pub-from-prv - =, secp256k1:secp:crypto - |= prv=@ - %- serialize-point - (priv-to-pub prv) - :: - ++ sign-transaction - =, crypto - |= [tx=transaction pk=@] - ^- @ux - :: hash the raw transaction data - =/ hash=@ - =/ dat=@ - %- encode-atoms:rlp - :: with v=chain-id, r=0, s=0 - tx(chain-id [chain-id.tx 0 0 ~]) - =+ wid=(met 3 dat) - %- keccak-256:keccak - [wid (rev 3 wid dat)] - :: sign transaction hash with private key - =+ (ecdsa-raw-sign:secp256k1:secp hash pk) - :: complete transaction is raw data, with r and s - :: taken from the signature, and v as per eip-155 - %- encode-atoms:rlp - tx(chain-id [:(add (mul chain-id.tx 2) 35 v) r s ~]) + ++ key + |% + ++ address-from-pub + =, keccak:crypto + |= pub=@ + %^ end 3 20 + %+ keccak-256 64 + (rev 3 64 pub) + :: + ++ address-from-prv + (cork pub-from-prv address-from-pub) + :: + ++ pub-from-prv + =, secp256k1:secp:crypto + |= prv=@ + %- serialize-point + (priv-to-pub prv) + :: + ++ sign-transaction + =, crypto + |= [tx=transaction:rpc pk=@] + ^- @ux + :: hash the raw transaction data + =/ hash=@ + =/ dat=@ + %- encode-atoms:rlp + :: with v=chain-id, r=0, s=0 + tx(chain-id [chain-id.tx 0 0 ~]) + =+ wid=(met 3 dat) + %- keccak-256:keccak + [wid (rev 3 wid dat)] + :: sign transaction hash with private key + =+ (ecdsa-raw-sign:secp256k1:secp hash pk) + :: complete transaction is raw data, with r and s + :: taken from the signature, and v as per eip-155 + %- encode-atoms:rlp + tx(chain-id [:(add (mul chain-id.tx 2) 35 v) r s ~]) + -- :: :: rlp en/decoding ::NOTE https://github.com/ethereum/wiki/wiki/RLP @@ -7467,153 +7595,564 @@ :: -- :: - :: making calls to nodes + :: abi en/decoding + ::NOTE https://solidity.readthedocs.io/en/develop/abi-spec.html :: - :: see also the json rpc api spec: - :: https://ethereum.gitbooks.io/frontier-guide/content/rpc.html - :: - ++ json-request - =, eyre - |= [url=purl jon=json] - ^- hiss - :^ url %post - %- ~(gas in *math) - ~['Content-Type'^['application/json']~] - (some (as-octt (en-json:html jon))) - :: - ++ batch-read-request - |= req=(list proto-read-request) - ^- json - a+(turn req read-request) - :: - ++ read-request - |= proto-read-request - ^- json - %+ request-to-json id - :+ %eth-call - ^- call - [~ to ~ ~ ~ `tape`(encode-call function arguments)] - [%label %latest] - :: - ++ request-to-json - =, enjs:format - |= [riq=(unit @t) req=request] - ^- json - %- pairs - =; r=[met=@t pas=(list json)] - :* jsonrpc+s+'2.0' - method+s+met.r - params+a+pas.r - ::TODO would just jamming the req noun for id be a bad idea? - ?~ riq ~ - [id+s+u.riq]~ - == - ?- -.req - %eth-block-number - ['eth_blockNumber' ~] + ++ abi + => |% + :: solidity types. integer bitsizes ignored + ++ etyp + $% :: static + %address %bool + %int %uint + %real %ureal + [%bytes-n n=@ud] + :: dynamic + [%array-n t=etyp n=@ud] + [%array t=etyp] + %bytes %string + == + :: + :: solidity-style typed data. integer bitsizes ignored + ++ data + $% [%address p=address] + [%string p=tape] + [%bool p=?] + [%int p=@sd] + [%uint p=@ud] + [%real p=@rs] + [%ureal p=@urs] + [%array-n p=(list data)] + [%array p=(list data)] + [%bytes-n p=octs] ::TODO just @, because context knows length? + [%bytes p=octs] + == + -- + =, mimes:html + |% + :: encoding :: - %eth-call - :- 'eth_call' - :~ (eth-call-to-json cal.req) - (block-to-json deb.req) + ++ encode-args + :: encode list of arguments. + :: + |= das=(list data) + ^- tape + (encode-data [%array-n das]) + :: + ++ encode-data + :: encode typed data into ABI bytestring. + :: + |= dat=data + ^- tape + ?+ -.dat + ~| [%unsupported-type -.dat] + !! + :: + %array-n + :: enc(X) = head(X[0]) ... head(X[k-1]) tail(X[0]) ... tail(X[k-1]) + :: where head and tail are defined for X[i] being of a static type as + :: head(X[i]) = enc(X[i]) and tail(X[i]) = "" (the empty string), or as + :: head(X[i]) = enc(len( head(X[0])..head(X[k-1]) + :: tail(X[0])..tail(X[i-1]) )) + :: and tail(X[i]) = enc(X[i]) otherwise. + :: + :: so: if it's a static type, data goes in the head. if it's a dynamic + :: type, a reference goes into the head and data goes into the tail. + :: + :: in the head, we first put a placeholder where references need to go. + =+ hol=(reap 64 'x') + =/ hes=(list tape) + %+ turn p.dat + |= d=data + ?. (is-dynamic-type d) ^$(dat d) + hol + =/ tas=(list tape) + %+ turn p.dat + |= d=data + ?. (is-dynamic-type d) "" + ^$(dat d) + :: once we know the head and tail, we can fill in the references in head. + =- (weld nes `tape`(zing tas)) + ^- [@ud nes=tape] + =+ led=(lent (zing hes)) + %+ roll hes + |= [t=tape i=@ud nes=tape] + :- +(i) + :: if no reference needed, just put the data. + ?. =(t hol) (weld nes t) + :: calculate byte offset of data we need to reference. + =/ ofs/@ud + =- (div - 2) :: two hex digits per byte. + %+ add led :: count head, and + %- lent %- zing :: count all tail data + (scag i tas) :: preceding ours. + =+ ref=^$(dat [%uint ofs]) + :: shouldn't hit this unless we're sending over 2gb of data? + ~| [%weird-ref-lent (lent ref)] + ?> =((lent ref) (lent hol)) + (weld nes ref) + :: + %array :: where X has k elements (k is assumed to be of type uint256): + :: enc(X) = enc(k) enc([X[1], ..., X[k]]) + :: i.e. it is encoded as if it were an array of static size k, prefixed + :: with the number of elements. + %+ weld $(dat [%uint (lent p.dat)]) + $(dat [%array-n p.dat]) + :: + %bytes-n + :: enc(X) is the sequence of bytes in X padded with zero-bytes to a + :: length of 32. + :: Note that for any X, len(enc(X)) is a multiple of 32. + ?> (lte p.p.dat 32) + (pad-to-multiple (render-hex-bytes p.dat) 64 %right) + :: + %bytes :: of length k (which is assumed to be of type uint256) + :: enc(X) = enc(k) pad_right(X), i.e. the number of bytes is encoded as a + :: uint256 followed by the actual value of X as a byte sequence, followed + :: by the minimum number of zero-bytes such that len(enc(X)) is a + :: multiple of 32. + %+ weld $(dat [%uint p.p.dat]) + $(dat [%bytes-n p.dat]) + :: + %string + :: enc(X) = enc(enc_utf8(X)), i.e. X is utf-8 encoded and this value is + :: interpreted as of bytes type and encoded further. Note that the length + :: used in this subsequent encoding is the number of bytes of the utf-8 + :: encoded string, not its number of characters. + $(dat [%bytes (lent p.dat) (swp 3 (crip p.dat))]) + :: + %uint + :: enc(X) is the big-endian encoding of X, padded on the higher-order + :: (left) side with zero-bytes such that the length is a multiple of 32 + :: bytes. + (pad-to-multiple (render-hex-bytes (as-octs p.dat)) 64 %left) + :: + %bool + :: as in the uint8 case, where 1 is used for true and 0 for false + $(dat [%uint ?:(p.dat 1 0)]) + :: + %address + :: as in the uint160 case + $(dat [%uint `@ud`p.dat]) == :: - %eth-new-filter - :- 'eth_newFilter' - :_ ~ + ++ is-dynamic-type + |= a=data + ?. ?=(%array-n -.a) + ?=(?(%string %bytes %array) -.a) + &(!=((lent p.a) 0) (lien p.a is-dynamic-type)) + :: + :: decoding + :: + ++ decode-topics + :: tox: list of hex words + |* [tox=(list @t) tys=(list etyp)] + =- (decode-arguments - tys) + %+ roll tox + |= [top=@t tos=@t] + (cat 3 tos (rsh 3 2 top)) + :: + ++ decode-results + :: rex: string of hex bytes with leading 0x. + |* [rex=@t tys=(list etyp)] + (decode-arguments (rsh 3 2 rex) tys) + :: + ++ decode-arguments + |* [res=@t tys=(list etyp)] + =| win=@ud + =/ wos=(list @t) (rip 9 res) + =< (decode-from 0 tys) + |% + ++ decode-from + |* [win=@ud tys=(list etyp)] + ?~ tys !! + =- ?~ t.tys dat + [dat $(win nin, tys t.tys)] + (decode-one win ~[i.tys]) + :: + ++ decode-one + ::NOTE we take (list etyp) even though we only operate on + :: a single etyp as a workaround for urbit/arvo#673 + |* [win=@ud tys=(list etyp)] + =- [nin dat]=- ::NOTE ^= regular form broken + ?~ tys !! + =* typ i.tys + =+ wor=(snag win wos) + ?+ typ + ~| [%unsupported-type typ] + !! + :: + ?(%address %bool %uint) :: %int %real %ureal + :- +(win) + ?- typ + %address `@ux`(rash wor hex) + %uint `@ud`(rash wor hex) + %bool =(1 (rash wor hex)) + == + :: + %string + =+ $(tys ~[%bytes]) + ~! - + [nin (trip (swp 3 q.dat))] + :: + %bytes + :- +(win) + :: find the word index of the actual data. + =/ lic=@ud (div (rash wor hex) 32) + :: learn the bytelength of the data. + =/ len=@ud (rash (snag lic wos) hex) + (decode-bytes-n +(lic) len) + :: + [%bytes-n *] + :- (add win +((div (dec n.typ) 32))) + (decode-bytes-n win n.typ) + :: + [%array *] + :- +(win) + :: find the word index of the actual data. + =. win (div (rash wor hex) 32) + :: read the elements from their location. + %- tail + %^ decode-array-n ~[t.typ] +(win) + (rash (snag win wos) hex) + :: + [%array-n *] + (decode-array-n ~[t.typ] win n.typ) + == + :: + ++ decode-bytes-n + |= [fro=@ud bys=@ud] + ^- octs + :: parse {bys} bytes from {fro}. + =- [bys (rash - hex)] + %^ end 3 (mul 2 bys) + %+ can 9 + %+ turn + (swag [fro +((div (dec bys) 32))] wos) + |=(a=@t [1 a]) + :: + ++ decode-array-n + ::NOTE we take (list etyp) even though we only operate on + :: a single etyp as a workaround for urbit/arvo#673 + =| res=(list) + ~& %watch-out--arrays-without-typeinfo + |* [tys=(list etyp) fro=@ud len=@ud] + ^- [@ud (list)] + ?~ tys !! + ?: =(len 0) [fro (flop `(list)`res)] + =+ (decode-one fro ~[i.tys]) :: [nin=@ud dat=*] + $(res ^+(res [dat res]), fro nin, len (dec len)) + -- + -- + :: + :: communicating with rpc nodes + ::NOTE https://github.com/ethereum/wiki/wiki/JSON-RPC + :: + ++ rpc + :: types + :: + => =, abi + =, format + |% + :: raw call data + ++ call-data + $: function=@t + arguments=(list data) + == + :: + :: raw transaction data + +$ transaction + $: nonce=@ud + gas-price=@ud + gas=@ud + to=address + value=@ud + data=@ux + chain-id=@ux + == + :: + :: ethereum json rpc api + :: + :: supported requests. + ++ request + $% [%eth-block-number ~] + [%eth-call cal=call deb=block] + $: %eth-new-filter + fro=(unit block) + tob=(unit block) + adr=(list address) + top=(list octs) + == + [%eth-get-filter-logs fid=@ud] + $: %eth-get-logs + fro=(unit block) + tob=(unit block) + adr=(list address) + top=(list octs) + == + [%eth-get-filter-changes fid=@ud] + [%eth-send-raw-transaction dat=@ux] + == + :: + ::TODO clean up & actually use + ++ response + $% ::TODO + [%eth-new-filter fid=@ud] + [%eth-get-filter-logs los=(list event-log)] + [%eth-get-logs los=(list event-log)] + [%eth-got-filter-changes los=(list event-log)] + [%eth-transaction-hash haz=@ux] + == + :: + ++ event-log + $: :: null for pending logs + $= mined %- unit + $: log-index=@ud + transaction-index=@ud + transaction-hash=@ux + block-number=@ud + block-hash=@ux + removed=? + == + :: + address=@ux + data=@t + event=@ux + topics=(list @t) + == + :: + :: data for eth_call. + ++ call + $: from=(unit address) + to=address + gas=(unit @ud) + gas-price=(unit @ud) + value=(unit @ud) + data=tape + == + :: + :: minimum data needed to construct a read call + ++ proto-read-request + $: id=(unit @t) + to=address + call-data + == + :: + :: block to operate on. + ++ block + $% [%number n=@ud] + [%label l=?(%earliest %latest %pending)] + == + -- + :: + :: logic + :: + |% + ++ encode-call + |= call-data + ^- tape + ::TODO should this check to see if the data matches the function signature? + =- :(weld "0x" - (encode-args arguments)) + %+ scag 8 + %+ render-hex-bytes 32 + %- keccak-256:keccak:crypto + (as-octs:mimes:html function) + :: + :: building requests + :: + ++ json-request + =, eyre + |= [url=purl jon=json] + ^- hiss + :^ url %post + %- ~(gas in *math) + ~['Content-Type'^['application/json']~] + (some (as-octt (en-json:html jon))) + :: + ++ batch-read-request + |= req=(list proto-read-request) + ^- json + a+(turn req read-request) + :: + ++ read-request + |= proto-read-request + ^- json + %+ request-to-json id + :+ %eth-call + ^- call + [~ to ~ ~ ~ `tape`(encode-call function arguments)] + [%label %latest] + :: + ++ request-to-json + =, enjs:format + |= [riq=(unit @t) req=request] + ^- json + %- pairs + =; r=[met=@t pas=(list json)] + :* jsonrpc+s+'2.0' + method+s+met.r + params+a+pas.r + ::TODO would just jamming the req noun for id be a bad idea? + ?~ riq ~ + [id+s+u.riq]~ + == + ?- -.req + %eth-block-number + ['eth_blockNumber' ~] + :: + %eth-call + :- 'eth_call' + :~ (eth-call-to-json cal.req) + (block-to-json deb.req) + == + :: + %eth-new-filter + :- 'eth_newFilter' + :_ ~ + :- %o %- ~(gas by *(map @t json)) + =- (murn - same) + ^- (list (unit (pair @t json))) + :~ ?~ fro.req ~ + `['fromBlock' (block-to-json u.fro.req)] + :: + ?~ tob.req ~ + `['toBlock' (block-to-json u.tob.req)] + :: + ::TODO fucking tmi + ?: =(0 (lent adr.req)) ~ + :+ ~ 'address' + ?: =(1 (lent adr.req)) (tape (address-to-hex (snag 0 adr.req))) + :- %a + (turn adr.req (cork address-to-hex tape)) + :: + ?~ top.req ~ + :^ ~ 'topics' %a + (turn `(list octs)`top.req :(cork render-hex-bytes prefix-hex tape)) + == + :: + %eth-get-filter-logs + ['eth_getFilterLogs' (tape (num-to-hex fid.req)) ~] + :: + %eth-get-logs + :- 'eth_getLogs' + :_ ~ + :- %o %- ~(gas by *(map @t json)) + =- (murn - same) + ^- (list (unit (pair @t json))) + :~ ?~ fro.req ~ + `['fromBlock' (block-to-json u.fro.req)] + :: + ?~ tob.req ~ + `['toBlock' (block-to-json u.tob.req)] + :: + ::TODO fucking tmi + ?: =(0 (lent adr.req)) ~ + :+ ~ 'address' + ?: =(1 (lent adr.req)) (tape (address-to-hex (snag 0 adr.req))) + :- %a + (turn adr.req (cork address-to-hex tape)) + :: + ?~ top.req ~ + :^ ~ 'topics' %a + (turn `(list octs)`top.req :(cork render-hex-bytes prefix-hex tape)) + == + :: + %eth-get-filter-changes + ['eth_getFilterChanges' (tape (num-to-hex fid.req)) ~] + :: + %eth-send-raw-transaction + ['eth_sendRawTransaction' (tape (num-to-hex dat.req)) ~] + == + :: + ++ eth-call-to-json + =, enjs:format + |= cal=call + ^- json :- %o %- ~(gas by *(map @t json)) =- (murn - same) ^- (list (unit (pair @t json))) - :~ ?~ fro.req ~ - `['fromBlock' (block-to-json u.fro.req)] + :~ ?~ from.cal ~ + `['from' (tape (address-to-hex u.from.cal))] :: - ?~ tob.req ~ - `['toBlock' (block-to-json u.tob.req)] + `['to' (tape (address-to-hex to.cal))] :: - ::TODO fucking tmi - ?: =(0 (lent adr.req)) ~ - :+ ~ 'address' - ?: =(1 (lent adr.req)) (tape (address-to-hex (snag 0 adr.req))) - :- %a - (turn adr.req (cork address-to-hex tape)) + ?~ gas.cal ~ + `['gas' (tape (num-to-hex u.gas.cal))] :: - ?~ top.req ~ - :^ ~ 'topics' %a - (turn `(list octs)`top.req :(cork render-hex-bytes prefix-hex tape)) + ?~ gas-price.cal ~ + `['gasPrice' (tape (num-to-hex u.gas-price.cal))] + :: + ?~ value.cal ~ + `['value' (tape (num-to-hex u.value.cal))] + :: + ?~ data.cal ~ + `['data' (tape data.cal)] == :: - %eth-get-filter-logs - ['eth_getFilterLogs' (tape (num-to-hex fid.req)) ~] - :: - %eth-get-logs - :- 'eth_getLogs' - :_ ~ - :- %o %- ~(gas by *(map @t json)) - =- (murn - same) - ^- (list (unit (pair @t json))) - :~ ?~ fro.req ~ - `['fromBlock' (block-to-json u.fro.req)] - :: - ?~ tob.req ~ - `['toBlock' (block-to-json u.tob.req)] - :: - ::TODO fucking tmi - ?: =(0 (lent adr.req)) ~ - :+ ~ 'address' - ?: =(1 (lent adr.req)) (tape (address-to-hex (snag 0 adr.req))) - :- %a - (turn adr.req (cork address-to-hex tape)) - :: - ?~ top.req ~ - :^ ~ 'topics' %a - (turn `(list octs)`top.req :(cork render-hex-bytes prefix-hex tape)) + ++ block-to-json + |= dob=block + ^- json + ?- -.dob + %number s+(crip '0' 'x' ((x-co:co 1) n.dob)) + %label s+l.dob == :: - %eth-get-filter-changes - ['eth_getFilterChanges' (tape (num-to-hex fid.req)) ~] + :: parsing responses :: - %eth-send-raw-transaction - ['eth_sendRawTransaction' (tape (num-to-hex dat.req)) ~] - == + ::TODO ++ parse-response |= json ^- response + :: + ++ parse-hex-result + |= j=json + ^- @ + ?> ?=(%s -.j) + (hex-to-num p.j) + :: + ++ parse-eth-new-filter-res parse-hex-result + :: + ++ parse-eth-block-number parse-hex-result + :: + ++ parse-transaction-hash parse-hex-result + :: + ++ parse-event-logs + (ar:dejs:format parse-event-log) + :: + ++ parse-event-log + =, dejs:format + |= log=json + ^- event-log + =- ((ot -) log) + :~ =- ['logIndex'^(cu - (mu so))] + |= li=(unit @t) + ?~ li ~ + =- `((ou -) log) ::TODO not sure if elegant or hacky. + :~ 'logIndex'^(un (cu hex-to-num so)) + 'transactionIndex'^(un (cu hex-to-num so)) + 'transactionHash'^(un (cu hex-to-num so)) + 'blockNumber'^(un (cu hex-to-num so)) + 'blockHash'^(un (cu hex-to-num so)) + 'removed'^(uf | bo) + == + :: + address+(cu hex-to-num so) + data+so + :: + ::TODO doesn't account for the anonymous event case, which has no hash. + =- topics+(cu - (ar so)) + |= r=(list @t) + ?> ?=([@t *] r) + [(hex-to-num i.r) t.r] + == + -- :: - ++ eth-call-to-json - =, enjs:format - |= cal=call - ^- json - :- %o %- ~(gas by *(map @t json)) - =- (murn - same) - ^- (list (unit (pair @t json))) - :~ ?~ from.cal ~ - `['from' (tape (address-to-hex u.from.cal))] - :: - `['to' (tape (address-to-hex to.cal))] - :: - ?~ gas.cal ~ - `['gas' (tape (num-to-hex u.gas.cal))] - :: - ?~ gas-price.cal ~ - `['gasPrice' (tape (num-to-hex u.gas-price.cal))] - :: - ?~ value.cal ~ - `['value' (tape (num-to-hex u.value.cal))] - :: - ?~ data.cal ~ - `['data' (tape data.cal)] - == - :: - ++ block-to-json - |= dob=block - ^- json - ?- -.dob - %number s+(crip '0' 'x' ((x-co:co 1) n.dob)) - %label s+l.dob - == + :: utilities + ::TODO give them better homes! :: ++ num-to-hex |= n=@ ^- tape %- prefix-hex - (render-hex-bytes (as-octs n)) + %- render-hex-bytes + (as-octs:mimes:html n) :: ++ address-to-hex |= a=address @@ -7626,282 +8165,6 @@ ^- tape ['0' 'x' a] :: - :: parsing responses from nodes - :: - ++ parse-hex-result - |= j=json - ^- @ - ?> ?=(%s -.j) - (hex-to-num p.j) - :: - ++ parse-eth-new-filter-res parse-hex-result - :: - ++ parse-eth-block-number parse-hex-result - :: - ++ parse-transaction-hash parse-hex-result - :: - ++ parse-event-logs - (ar:dejs:format parse-event-log) - :: - ++ parse-event-log - =, dejs:format - |= log=json - ^- event-log - =- ((ot -) log) - :~ =- ['logIndex'^(cu - (mu so))] - |= li=(unit @t) - ?~ li ~ - =- `((ou -) log) ::TODO not sure if elegant or hacky. - :~ 'logIndex'^(un (cu hex-to-num so)) - 'transactionIndex'^(un (cu hex-to-num so)) - 'transactionHash'^(un (cu hex-to-num so)) - 'blockNumber'^(un (cu hex-to-num so)) - 'blockHash'^(un (cu hex-to-num so)) - 'removed'^(uf | bo) - == - :: - address+(cu hex-to-num so) - data+so - :: - ::TODO doesn't account for the anonymous event case, which has no hash. - =- topics+(cu - (ar so)) - |= r=(list @t) - ?> ?=([@t *] r) - [(hex-to-num i.r) t.r] - == - :: - ++ hex-to-num - |= a=@t - (rash (rsh 3 2 a) hex) - :: - :: decoding - :: - :: for details on encoding, see below. - :: - ++ decode-topics - :: tox: list of hex words - |* [tox=(list @t) tys=(list etyp)] - =- (decode-arguments - tys) - %+ roll tox - |= [top=@t tos=@t] - (cat 3 tos (rsh 3 2 top)) - :: - ++ decode-results - :: rex: string of hex bytes with leading 0x. - |* [rex=@t tys=(list etyp)] - (decode-arguments (rsh 3 2 rex) tys) - :: - ++ decode-arguments - |* [res=@t tys=(list etyp)] - =| win=@ud - =/ wos=(list @t) (rip 9 res) - =< (decode-from 0 tys) - |% - ++ decode-from - |* [win=@ud tys=(list etyp)] - ?~ tys !! - =- ?~ t.tys dat - [dat $(win nin, tys t.tys)] - (decode-one win ~[i.tys]) - :: - ++ decode-one - ::NOTE we take (list etyp) even though we only operate on - :: a single etyp as a workaround for urbit/arvo#673 - |* [win=@ud tys=(list etyp)] - =- [nin dat]=- ::NOTE ^= regular form broken - ?~ tys !! - =* typ i.tys - =+ wor=(snag win wos) - ?+ typ - ~| [%unsupported-type typ] - !! - :: - ?(%address %bool %uint) :: %int %real %ureal - :- +(win) - ?- typ - %address `@ux`(rash wor hex) - %uint `@ud`(rash wor hex) - %bool =(1 (rash wor hex)) - == - :: - %string - =+ $(tys ~[%bytes]) - ~! - - [nin (trip (swp 3 q.dat))] - :: - %bytes - :- +(win) - :: find the word index of the actual data. - =/ lic=@ud (div (rash wor hex) 32) - :: learn the bytelength of the data. - =/ len=@ud (rash (snag lic wos) hex) - (decode-bytes-n +(lic) len) - :: - [%bytes-n *] - :- (add win +((div (dec n.typ) 32))) - (decode-bytes-n win n.typ) - :: - [%array *] - :- +(win) - :: find the word index of the actual data. - =. win (div (rash wor hex) 32) - :: read the elements from their location. - %- tail - %^ decode-array-n ~[t.typ] +(win) - (rash (snag win wos) hex) - :: - [%array-n *] - (decode-array-n ~[t.typ] win n.typ) - == - :: - ++ decode-bytes-n - |= [fro=@ud bys=@ud] - ^- octs - :: parse {bys} bytes from {fro}. - =- [bys (rash - hex)] - %^ end 3 (mul 2 bys) - %+ can 9 - %+ turn - (swag [fro +((div (dec bys) 32))] wos) - |=(a=@t [1 a]) - :: - ++ decode-array-n - ::NOTE we take (list etyp) even though we only operate on - :: a single etyp as a workaround for urbit/arvo#673 - =| res=(list) - ~& %watch-out--arrays-without-typeinfo - |* [tys=(list etyp) fro=@ud len=@ud] - ^- [@ud (list)] - ?~ tys !! - ?: =(len 0) [fro (flop `(list)`res)] - =+ (decode-one fro ~[i.tys]) :: [nin=@ud dat=*] - $(res ^+(res [dat res]), fro nin, len (dec len)) - -- - :: - :: encoding - :: - :: ABI spec used for reference: - :: https://ethereum.gitbooks.io/frontier-guide/content/abi.html - :: - ++ encode-call - |= call-data - ^- tape - ::TODO should this check to see if the data matches the function signature? - =- :(weld "0x" - (encode-args arguments)) - %+ scag 8 - (render-hex-bytes 32 (keccak-256:keccak:crypto (as-octs function))) - :: - ++ encode-args - :: encode list of arguments. - :: - |= das=(list data) - ^- tape - (encode-data [%array-n das]) - :: - ++ encode-data - :: encode typed data into ABI bytestring. - :: - |= dat=data - ^- tape - ?+ -.dat - ~| [%unsupported-type -.dat] - !! - :: - %array-n - :: enc(X) = head(X[0]) ... head(X[k-1]) tail(X[0]) ... tail(X[k-1]) - :: where head and tail are defined for X[i] being of a static type as - :: head(X[i]) = enc(X[i]) and tail(X[i]) = "" (the empty string), or as - :: head(X[i]) = enc(len( head(X[0])..head(X[k-1]) - :: tail(X[0])..tail(X[i-1]) )) - :: and tail(X[i]) = enc(X[i]) otherwise. - :: - :: so: if it's a static type, data goes in the head. if it's a dynamic - :: type, a reference goes into the head and data goes into the tail. - :: - :: in the head, we first put a placeholder where references need to go. - =+ hol=(reap 64 'x') - =/ hes=(list tape) - %+ turn p.dat - |= d=data - ?. (is-dynamic-type d) ^$(dat d) - hol - =/ tas=(list tape) - %+ turn p.dat - |= d=data - ?. (is-dynamic-type d) "" - ^$(dat d) - :: once we know the head and tail, we can fill in the references in head. - =- (weld nes `tape`(zing tas)) - ^- [@ud nes=tape] - =+ led=(lent (zing hes)) - %+ roll hes - |= [t=tape i=@ud nes=tape] - :- +(i) - :: if no reference needed, just put the data. - ?. =(t hol) (weld nes t) - :: calculate byte offset of data we need to reference. - =/ ofs/@ud - =- (div - 2) :: two hex digits per byte. - %+ add led :: count head, and - %- lent %- zing :: count all tail data - (scag i tas) :: preceding ours. - =+ ref=^$(dat [%uint ofs]) - :: shouldn't hit this unless we're sending over 2gb of data? - ~| [%weird-ref-lent (lent ref)] - ?> =((lent ref) (lent hol)) - (weld nes ref) - :: - %array :: where X has k elements (k is assumed to be of type uint256): - :: enc(X) = enc(k) enc([X[1], ..., X[k]]) - :: i.e. it is encoded as if it were an array of static size k, prefixed - :: with the number of elements. - %+ weld $(dat [%uint (lent p.dat)]) - $(dat [%array-n p.dat]) - :: - %bytes-n - :: enc(X) is the sequence of bytes in X padded with zero-bytes to a - :: length of 32. - :: Note that for any X, len(enc(X)) is a multiple of 32. - ?> (lte p.p.dat 32) - (pad-to-multiple (render-hex-bytes p.dat) 64 %right) - :: - %bytes :: of length k (which is assumed to be of type uint256) - :: enc(X) = enc(k) pad_right(X), i.e. the number of bytes is encoded as a - :: uint256 followed by the actual value of X as a byte sequence, followed - :: by the minimum number of zero-bytes such that len(enc(X)) is a - :: multiple of 32. - %+ weld $(dat [%uint p.p.dat]) - $(dat [%bytes-n p.dat]) - :: - %string - :: enc(X) = enc(enc_utf8(X)), i.e. X is utf-8 encoded and this value is - :: interpreted as of bytes type and encoded further. Note that the length - :: used in this subsequent encoding is the number of bytes of the utf-8 - :: encoded string, not its number of characters. - $(dat [%bytes (lent p.dat) (swp 3 (crip p.dat))]) - :: - %uint - :: enc(X) is the big-endian encoding of X, padded on the higher-order - :: (left) side with zero-bytes such that the length is a multiple of 32 - :: bytes. - (pad-to-multiple (render-hex-bytes (as-octs p.dat)) 64 %left) - :: - %bool - :: as in the uint8 case, where 1 is used for true and 0 for false - $(dat [%uint ?:(p.dat 1 0)]) - :: - %address - :: as in the uint160 case - $(dat [%uint `@ud`p.dat]) - == - :: - ++ is-dynamic-type - |= a=data - ?. ?=(%array-n -.a) - ?=(?(%string %bytes %array) -.a) - &(!=((lent p.a) 0) (lien p.a is-dynamic-type)) - :: - :: ++ render-hex-bytes :: atom to string of hex bytes without 0x prefix and dots. |= a=octs @@ -7917,232 +8180,11 @@ %- weld ?:(?=(%left wer) [tad wat] [wat tad]) :: - :: - ++ azimuth - =, azimuth:ethe - |% - :: - ++ pass-from-eth - |= [enc=octs aut=octs sut=@ud] - ^- (unit pass) - ?. &(=(1 sut) =(p.enc 32) =(p.aut 32)) - ~ - `(cat 3 'b' (cat 8 q.aut q.enc)) - :: - ++ point-from-eth - |= [who=@p point:eth-noun deed:eth-noun] - ^- point - :: - :: ownership - :: - :+ :* owner - management-proxy - voting-proxy - transfer-proxy - == - :: - :: network state - :: - ::TODO doesn't match semantics of %activated diff, and - :: setting ~ here will cause a crash on the next networking diff - ?: =(0 key-revision) ~ - :- ~ - :* key-revision - :: - %- need - (pass-from-eth encryption-key authentication-key crypto-suite) - :: - continuity-number - :: - ?. has-sponsor ~ - ``@p`sponsor - :: - ?. escape-requested ~ - ``@p`escape-to - == - :: - :: spawn state - :: - ?. ?=(?(%czar %king) (clan:title who)) ~ - :- ~ - :* spawn-proxy - ~ ::TODO call getSpawned to fill this - == - :: - ++ event-log-to-point-diff - =, azimuth-events - |= log=event-log - ^- (unit (pair ship diff-point)) - ~? ?=(~ mined.log) %processing-unmined-event - :: - ?: =(event.log owner-changed) - =+ ^- [who=@ wer=address] - (decode-topics topics.log ~[%uint %address]) - `[who %owner wer] - :: - ?: =(event.log activated) - =/ who=@ - (decode-topics topics.log ~[%uint]) - `[who %activated who] - :: - ?: =(event.log spawned) - =/ pre=@ (decode-topics topics.log ~[%uint]) - =/ who=@ (decode-results data.log ~[%uint]) - `[pre %spawned who] - :: - ?: =(event.log escape-requested) - =+ ^- [who=@ wer=@] - (decode-topics topics.log ~[%uint %uint]) - `[who %escape `wer] - :: - ?: =(event.log escape-canceled) - =/ who=@ (decode-topics topics.log ~[%uint]) - `[who %escape ~] - :: - ?: =(event.log escape-accepted) - =+ ^- [who=@ wer=@] - (decode-topics topics.log ~[%uint %uint]) - `[who %sponsor `wer] - :: - ?: =(event.log lost-sponsor) - =/ who=@ (decode-topics topics.log ~[%uint]) - `[who %sponsor ~] - :: - ?: =(event.log changed-keys) - =/ who=@ (decode-topics topics.log ~[%uint]) - =+ ^- [enc=octs aut=octs sut=@ud rev=@ud] - %+ decode-results data.log - ~[[%bytes-n 32] [%bytes-n 32] %uint %uint] - `[who %keys rev (need (pass-from-eth enc aut sut))] - :: - ?: =(event.log broke-continuity) - =/ who=@ (decode-topics topics.log ~[%uint]) - =/ num=@ (decode-results data.log ~[%uint]) - `[who %continuity num] - :: - ?: =(event.log changed-management-proxy) - =+ ^- [who=@ sox=address] - (decode-topics topics.log ~[%uint %address]) - `[who %management-proxy sox] - :: - ?: =(event.log changed-voting-proxy) - =+ ^- [who=@ tox=address] - (decode-topics topics.log ~[%uint %address]) - `[who %voting-proxy tox] - :: - ?: =(event.log changed-spawn-proxy) - =+ ^- [who=@ sox=address] - (decode-topics topics.log ~[%uint %address]) - `[who %spawn-proxy sox] - :: - ?: =(event.log changed-transfer-proxy) - =+ ^- [who=@ tox=address] - (decode-topics topics.log ~[%uint %address]) - `[who %transfer-proxy tox] - :: - :: warn about unimplemented events, but ignore - :: the ones we know are harmless. - ~? ?! .= event.log - :: OwnershipTransferred(address,address) - 0x8be0.079c.5316.5914.1344.cd1f.d0a4.f284. - 1949.7f97.22a3.daaf.e3b4.186f.6b64.57e0 - [%unimplemented-event event.log] - ~ - :: - ++ apply-point-diff - |= [pot=point dif=diff-point] - ^- point - ?- -.dif - %full new.dif - :: - %activated - %_ pot - net `[0 0 0 `(^sein:title who.dif) ~] - kid ?. ?=(?(%czar %king) (clan:title who.dif)) ~ - `[0x0 ~] - == - :: - :: ownership - :: - %owner pot(owner.own new.dif) - %transfer-proxy pot(transfer-proxy.own new.dif) - %management-proxy pot(management-proxy.own new.dif) - %voting-proxy pot(voting-proxy.own new.dif) - :: - :: networking - :: - ?(%keys %continuity %sponsor %escape) - ?> ?=(^ net.pot) - ?- -.dif - %keys - pot(life.u.net life.dif, pass.u.net pass.dif) - :: - %sponsor - ?~ new.dif pot(sponsor.u.net ~) - pot(sponsor.u.net new.dif, escape.u.net ~) - :: - %continuity pot(continuity-number.u.net new.dif) - %escape pot(escape.u.net new.dif) - == - :: - :: spawning - :: - ?(%spawned %spawn-proxy) - ?> ?=(^ kid.pot) - ?- -.dif - %spawned - =- pot(spawned.u.kid -) - (~(put in spawned.u.kid.pot) who.dif) - :: - %spawn-proxy pot(spawn-proxy.u.kid new.dif) - == - == - :: - ++ parse-id - |= id=@t - ^- azimuth:function - |^ - ~| id - %+ rash id - ;~ pose - (function %points 'points' shipname) - (function %get-spawned 'getSpawned' shipname) - (function %dns-domains 'dnsDomains' dem:ag) - == - :: - ++ function - |* [tag=@tas fun=@t rul=rule] - ;~(plug (cold tag (jest fun)) (ifix [lit rit] rul)) - :: - ++ shipname - ;~(pfix sig fed:ag) - -- - :: - ++ function-to-call - |% - ++ azimuth - |= cal=azimuth:function - ^- [id=@t dat=call-data] - ?- -.cal - %points - :- (crip "points({(scow %p who.cal)})") - ['points(uint32)' ~[uint+`@`who.cal]] - :: - %rights - :- (crip "rights({(scow %p who.cal)})") - ['rights(uint32)' ~[uint+`@`who.cal]] - :: - %get-spawned - :- (crip "getSpawned({(scow %p who.cal)})") - ['getSpawned(uint32)' ~[uint+`@`who.cal]] - :: - %dns-domains - :- (crip "dnsDomains({(scow %ud ind.cal)})") - ['dnsDomains(uint256)' ~[uint+ind.cal]] - == - -- - -- + ++ hex-to-num + |= a=@t + (rash (rsh 3 2 a) hex) -- +:: :: |dawn: pre-boot request/response de/serialization and validation :: ++ dawn @@ -8167,7 +8209,9 @@ :: |give:dawn: produce requests for pre-boot validation :: ++ give - =/ tract azimuth:contracts:azimuth:ethe + =, rpc:ethereum + =, abi:ethereum + =/ tract azimuth:contracts:azimuth |% :: +bloq:give:dawn: Eth RPC for latest block number :: @@ -8175,7 +8219,7 @@ ^- octs %- as-octt:mimes:html %- en-json:html - %+ request-to-json:ethereum + %+ request-to-json `~.0 [%eth-block-number ~] :: +czar:give:dawn: Eth RPC for galaxy table @@ -8188,11 +8232,11 @@ :- %a %+ turn (gulf 0 255) |= gal=@ - %+ request-to-json:ethereum + %+ request-to-json `(cat 3 'gal-' (scot %ud gal)) :+ %eth-call =- [from=~ to=tract gas=~ price=~ value=~ data=-] - (encode-call:ethereum 'getKeys(uint32)' [%uint gal]~) + (encode-call 'getKeys(uint32)' [%uint gal]~) [%number boq] :: +point:give:dawn: Eth RPC for ship's contract state :: @@ -8201,11 +8245,11 @@ ^- octs %- as-octt:mimes:html %- en-json:html - %+ request-to-json:ethereum + %+ request-to-json `~.0 :+ %eth-call =- [from=~ to=tract gas=~ price=~ value=~ data=-] - (encode-call:ethereum 'points(uint32)' [%uint `@`who]~) + (encode-call 'points(uint32)' [%uint `@`who]~) [%number boq] :: +turf:give:dawn: Eth RPC for network domains :: @@ -8217,16 +8261,19 @@ :- %a %+ turn (gulf 0 2) |= idx=@ - %+ request-to-json:ethereum + %+ request-to-json `(cat 3 'turf-' (scot %ud idx)) :+ %eth-call =- [from=~ to=tract gas=~ price=~ value=~ data=-] - (encode-call:ethereum 'dnsDomains(uint256)' [%uint idx]~) + (encode-call 'dnsDomains(uint256)' [%uint idx]~) [%number boq] -- :: |take:dawn: parse responses for pre-boot validation :: ++ take + =, abi:ethereum + =, rpc:ethereum + =, azimuth =, dejs-soft:format |% :: +bloq:take:dawn: parse block number @@ -8265,7 +8312,7 @@ |= [id=@t result=@t] ^- [who=ship enc=octs aut=octs sut=@ud rev=@ud] :- `@p`(slav %ud (rsh 3 4 id)) - %+ decode-results:ethereum + %+ decode-results result ~[[%bytes-n 32] [%bytes-n 32] %uint %uint] ?~ dat @@ -8277,14 +8324,14 @@ == ^+ kyz =/ pub=(unit pass) - (pass-from-eth:azimuth:ethereum enc aut sut) + (pass-from-eth enc aut sut) ?~ pub kyz (~(put by kyz) who [rev u.pub]) :: +point:take:dawn: parse ship's contract state :: ++ point |= [who=ship rep=octs] - ^- (unit point:azimuth:ethe) + ^- (unit point:azimuth) =/ jon=(unit json) (de-json:html q.rep) ?~ jon ~&([%point-take-dawn %invalid-json] ~) @@ -8293,13 +8340,13 @@ ~&([%point-take-dawn %invalid-response rep] ~) ~? =(u.res '0x') :- 'bad result from node; is azimuth address correct?' - azimuth:contracts:azimuth:ethe + azimuth:contracts =/ out %- mule |. - %+ point-from-eth:azimuth:ethereum + %+ point-from-eth who - :_ *deed:eth-noun:azimuth:ethereum ::TODO call rights to fill - (decode-results:ethereum u.res point:eth-type:azimuth:ethe) + :_ *deed:eth-noun ::TODO call rights to fill + (decode-results u.res point:eth-type) ?: ?=(%& -.out) (some p.out) ~&([%point-take-dawn %invalid-point] ~) @@ -8323,7 +8370,7 @@ ^- (pair @ud ^turf) :- (slav %ud (rsh 3 5 id)) =/ dom=tape - (decode-results:ethereum result [%string]~) + (decode-results result [%string]~) =/ hot=host:eyre (scan dom thos:de-purl:html) ?>(?=(%& -.hot) p.hot) @@ -8375,7 +8422,7 @@ :: ++ point |= [who=ship snap=snapshot:jael] - ^- (unit point:azimuth:ethe) + ^- (unit point:azimuth) (~(get by pos.eth.snap) who) :: +turf:snap:dawn: extract network domains :: @@ -8397,7 +8444,7 @@ :: +veri:dawn: validate keys, life, discontinuity, &c :: ++ veri - |= [=seed:able:jael =point:azimuth:ethe =live] + |= [=seed:able:jael =point:azimuth =live] ^- (each sponsor=(unit ship) error=term) =/ rac (clan:title who.seed) =/ cub (nol:nu:crub:crypto key.seed) diff --git a/tests/sys/vane/jael.hoon b/tests/sys/vane/jael.hoon index 3f769a4a9..676d5ff6b 100644 --- a/tests/sys/vane/jael.hoon +++ b/tests/sys/vane/jael.hoon @@ -56,9 +56,9 @@ :: =^ results3 jael-gate =/ hiss-httr=hiss:eyre - %+ json-request:ethereum + %+ json-request:rpc:ethereum (need url) - %+ request-to-json:ethereum + %+ request-to-json:rpc:ethereum `'block number' [%eth-block-number ~] %- jael-take-with-comparator :* diff --git a/tests/sys/zuse/dawn.hoon b/tests/sys/zuse/dawn.hoon index 6419f61b3..d2e79462d 100644 --- a/tests/sys/zuse/dawn.hoon +++ b/tests/sys/zuse/dawn.hoon @@ -3,7 +3,7 @@ :: example point for ~zod :: ++ pot - ^- point:azimuth:ethe + ^- point:azimuth-types :+ [0x0 0x0 0x0 0x0] :* ~ life=1 @@ -27,7 +27,7 @@ ++ azimuth %- crip %+ weld "0x" - (render-hex-bytes:ethereum 20 `@`azimuth:contracts:azimuth:ethe) + (render-hex-bytes:ethereum 20 `@`azimuth:contracts:^azimuth) :: snapshot :: ++ snap @@ -328,7 +328,7 @@ =/ sed [who 1 sec:ex:cub ~] %+ expect-eq !> [%& ~] - !> (veri:dawn sed *point:azimuth:ethe ~) + !> (veri:dawn sed *point:azimuth-types ~) :: ++ test-veri-pawn-key-mismatch =/ cub (pit:nu:crub:crypto 24 %foo) @@ -336,7 +336,7 @@ =/ sed [who 1 sec:ex:(pit:nu:crub:crypto 24 %bar) ~] %+ expect-eq !> [%| %key-mismatch] - !> (veri:dawn sed *point:azimuth:ethe ~) + !> (veri:dawn sed *point:azimuth-types ~) :: ++ test-veri-pawn-invalid-life =/ cub (pit:nu:crub:crypto 24 %foo) @@ -344,7 +344,7 @@ =/ sed [who 2 sec:ex:cub ~] %+ expect-eq !> [%| %invalid-life] - !> (veri:dawn sed *point:azimuth:ethe ~) + !> (veri:dawn sed *point:azimuth-types ~) :: ++ test-veri-pawn-already-booted =/ cub (pit:nu:crub:crypto 24 %foo) @@ -352,5 +352,5 @@ =/ sed [who 1 sec:ex:cub ~] %+ expect-eq !> [%| %already-booted] - !> (veri:dawn sed *point:azimuth:ethe `[1 |]) + !> (veri:dawn sed *point:azimuth-types `[1 |]) -- diff --git a/tests/sys/zuse/ethereum/encoding.hoon b/tests/sys/zuse/ethereum/encoding.hoon index 94c6a3d61..cd819c62d 100644 --- a/tests/sys/zuse/ethereum/encoding.hoon +++ b/tests/sys/zuse/ethereum/encoding.hoon @@ -5,7 +5,7 @@ :: ++ test-static-args %+ expect-eq - !> %- encode-args:ethereum + !> %- encode-args:abi:ethereum :~ [%string "dave"] [%bool &] [%array [%uint 1] [%uint 2] [%uint 3] ~] @@ -24,7 +24,7 @@ :: ++ test-dynamic-args %+ expect-eq - !> %- encode-args:ethereum + !> %- encode-args:abi:ethereum :~ [%uint `@ud`0x123] [%array [%uint `@ud`0x456] [%uint `@ud`0x789] ~] [%bytes-n (as-octt:mimes:html (flop "1234567890"))] @@ -42,3 +42,4 @@ "48656c6c6f2c20776f726c642100000000000000000000000000000000000000" == -- +[l+~ l+[l+~ ~] l+[l+~ l+[l+~ ~] ~]] \ No newline at end of file diff --git a/tests/sys/zuse/ethereum/signing.hoon b/tests/sys/zuse/ethereum/signing.hoon index 0f5e8db02..5048d7527 100644 --- a/tests/sys/zuse/ethereum/signing.hoon +++ b/tests/sys/zuse/ethereum/signing.hoon @@ -4,7 +4,7 @@ :: ++ test-signing-transaction-1 %+ expect-eq - !> %+ sign-transaction:ethereum + !> %+ sign-transaction:key:ethereum :* 123 1.000 5.000 @@ -25,7 +25,7 @@ :: ++ test-signing-transaction-2 %+ expect-eq - !> %+ sign-transaction:ethereum + !> %+ sign-transaction:key:ethereum :* 42 1.000 5.000