From 9b62454bca5db35a3c1c6d7018ab58151ff9760b Mon Sep 17 00:00:00 2001 From: fang Date: Thu, 13 May 2021 17:21:35 +0200 Subject: [PATCH 01/21] naive: wip aggregator Includes logic for the core flow, but isn't fully hooked up to outside sources/events yet. Probably doesn't compile. Plenty of TODOs remaining. --- pkg/arvo/app/aggregator.hoon | 412 ++++++++++++++++++++++++++++++ pkg/arvo/lib/naive.hoon | 19 +- pkg/arvo/ted/aggregator/send.hoon | 100 ++++++++ 3 files changed, 524 insertions(+), 7 deletions(-) create mode 100644 pkg/arvo/app/aggregator.hoon create mode 100644 pkg/arvo/ted/aggregator/send.hoon diff --git a/pkg/arvo/app/aggregator.hoon b/pkg/arvo/app/aggregator.hoon new file mode 100644 index 000000000..ad3c9ee99 --- /dev/null +++ b/pkg/arvo/app/aggregator.hoon @@ -0,0 +1,412 @@ +:: aggregator: Azimuth L2 roll aggregator +:: +:: general flow is as described below, to ensure transactions actually go +:: through once we start sending it out, in the dumbest reasonable way. +:: +:: periodic timer fires: +:: if there are no pending l2 txs, do nothing. +:: else kick off tx submission flow: +:: "freeze" pending txs, store alongside nonce, then increment nonce, +:: kick off thread for sending the corresponding l1 tx: +:: if nonce doesn't match on-chain expected nonce, bail. +:: if we can't afford the tx fee, bail. +:: construct, sign, submit the l1 tx. +:: if thread bailed, retry in five minutes. +:: if thread succeeded, retry in five minutes with higher gas price. +:: when retrying, only do so if l2 txs remain in the "frozen" txs group. +:: on %tx diff from naive, remove the matching tx from the frozen group. +:: +::TODO remaining general work: +:: - hook up subscription to azimuth for %tx diffs +:: - hook up thread updates/results +:: - hook up timer callbacks +:: - cache state, upate after every azimuth %fact +:: - properly support private key changes +:: +::TODO questions: +:: - it's a bit weird how we just assume the raw and tx in raw-tx to match... +:: +/+ naive, ethereum +/= ttttt /tests/lib/naive ::TODO use new lib +:: +::TODO /sur file for public types +|% ++$ state-0 + $: %0 + :: pending: the next l2 txs to be sent + :: sending: the l2 txs currently sending/awaiting l2 confirmation + ::TODO should maybe key by [address nonce] instead. same for wires + :: finding: raw-tx-hash reverse lookup for sending map + :: next-nonce: next l1 nonce to use + :: + pending=(list pend-tx) + sending=(map nonce [next-gas-price=@ud txs=(list raw-tx:naive)]) + finding=(map keccak $?(%confirmed %failed l1-tx-pointer)) + next-nonce=@ud + :: + :: pk: private key to send the roll + :: frequency: time to wait between sending batches (TODO fancier) + :: endpoint: ethereum rpc endpoint to use + :: + pk=@ + frequency=@dr + endpoint=@t + == +:: ++$ keccak @ux +:: ++$ tx-status + $: status=?(%unknown %pending %sending %confirmed %failed) + pointer=(unit l1-tx-pointer) + == +:: ++$ l1-tx-pointer + $: =address:ethereum + nonce=@ud + == +:: +::TODO cache sender address? ++$ pend-tx [force=? =raw-tx:naive] +:: ++$ part-tx + $% [%raw raw=octs] + [%don =tx:naive] + [%ful raw=octs =tx:naive] ::TODO redundant? + == +:: ++$ action + $% [%submit force=? sig=@ tx=part-tx] + [%cancel sig=@ keccak=@] + :: + [%commit ~] ::TODO maybe pk=(unit @) later + [%config frequency=@dr] + [%setkey pk=@] + ::TODO configure endpoint, contract address, chain..? + == +:: ++$ card card:agent:gall +:: +::TODO config? +++ contract 0xb581.01cd.3bbb.cc6f.a40b.cdb0.4bb7.1623.b5c7.d39b +++ chain-id 0x1 +:: +++ resend-time ~m5 +:: +++ lverb & +-- +:: +=| state=state-0 +%- agent:dbug +%+ verb | +^- agent:gall +:: +=< + |_ =bowl:gall + +* this . + def ~(. (default-agent this %|) bowl) + :: + ++ on-init + ^- (quip card _this) + ::TODO set default frequency and endpoint? + =. frequency ~h1 + [~ this] + :: + ++ on-save !>(state) + ++ on-load + |= old=vase + ^- (quip card _this) + [~ this(state !<(state-0 old))] + :: + ++ on-poke + |= [=mark =vase] + ^- (quip card _this) + ?+ mark (on-poke:def mark vase) + %noun $(mark %aggregator-action) + :: + %aggregator-action + !! + ::TODO + == + :: +on-peek: scry paths + ::TODO reevaluate wrt recent flow changes + :: + :: /x/pending -> %noun (list pend-tx) + :: /x/pending/[~ship] -> %noun (list pend-tx) + :: /x/pending/[0xadd.ress] -> %noun (list pend-tx) + :: /x/tx/[0xke.ccak]/status -> %noun tx-status + :: /x/nonce/[~ship]/[0xadd.ress] -> %atom @ + :: + ++ on-peek + |= =path + ^- (unit (unit cage)) + ?+ path ~ + [%x %pending ~] ``noun+!>(pending) + :: + [%x %pending @ ~] + =* wat i.t.t.path + ?~ who=(slaw %p wat) + ?~ wer=(slaw %ux wat) + [~ ~] + %+ skim pending + |= pend-tx + ::TODO deduce address from sig.raw-tx ? + !! + %+ skim pending + |= pend-tx + =(u.who ship.from.tx.raw-tx) + :: + [%x %tx @ %status ~] + ?~ keccak=(slaw %ux i.t.t.path) + [~ ~] + :+ ~ ~ + :- %noun + !> ^- tx-status + ?^ status=(~(get by finding) u.keccak) + ?@ u.status [u.status ~] + [%sending u.status] + ::TODO potentially slow! + =; known=? + [?:(known %pending %unknown) ~] + %+ lien pending + |= [* raw-tx] + =(u.keccak (hash-tx raw)) + :: + [%x %nonce @ @ ~] + ?~ who=(slaw %p i.t.t.path) + [~ ~] + =+ proxy=i.t.t.t.path + ?. ?=(proxy:naive proxy) + [~ ~] + =^ * nas pending-state:do + ::TODO or should we ~ when !(~(has by points.nas) who) ? + =/ =point:naive (~(gut by points.nas) who *point) + =+ (proxy-from-point:naive proxy point) + ``atom+!>(nonce) + == + :: + ++ on-arvo + |= [=wire =sign-arvo] + ^- (quip card _this) + ?+ +<.sign (on-arvo:def wire sign) + %wake =^(cards state on-timer:do [cards this]) + == + :: + ++ on-fail + |= [=term =tang] + ::TODO if crashed during timer, set new timer? how to detect? + (on-fail:def term tang) + :: + ++ on-watch on-watch:def + ++ on-leave on-leave:def + ++ on-agent on-agent:def + -- +:: +|_ =bowl:gall +::TODO /lib/sys.hoon? +++ sys + |% + ++ b + |% + ++ wait + |= [=wire =time] + ^- card + [%pass wire %arvo %b %wait time] + -- + -- +::TODO /lib/spider.hoon? +++ spider + |% + ++ start-thread + |= [=wire thread=term arg=vase] + ^- (list card) + =/ tid=@ta (rap 3 thread '--' (scot %uv eny.bowl) ~) + =/ args [~ `tid thread arg] + :~ [%pass wire %agent [our.bowl %spider] %watch /thread-result/[tid]] + [%pass wire %agent [our.bowl %spider] %poke %spider-start !>(args)] + == + -- +:: +++ hash-tx keccak-256:keccak:crypto +:: +++ hash-raw-tx + |= raw-tx + (hash-tx raw) +:: +++ part-tx-to-full + |= =part-tx + ^- [octs tx:naive] + ?- -.part-tx + %raw [+.part-tx (decode-tx:naive +.part-tx)] + %don [(encode-tx:naive +.part-tx) +.part-tx] + %ful +.part-tx + == +:: +pending-state +:: +:: derives tentative state from pending txs and canonical state, +:: discarding invalid pending txs in the process. +:: +::TODO maybe want to cache locally, refresh on %fact from azimuth? +:: +++ pending-state + ^- [_pending state:naive] + :: load current, canonical state + :: + =+ .^ nas=state:naive + %gx + (scot %p our.bowl) + %azimuth + (scot %da now.bowl) + /nas/nas + == + :: apply our pending transactions + ::TODO should also apply txs from sending map! + :: + =| valid=_pending + |- ^+ nas + ?~ pending [(flop valid) nas] + :: + =^ gud=? nas (try-apply nas i.pending) + =? valid gud [i.pending valid] + $(pending t.pending) +:: +try-apply: +:: +++ try-apply + |= [nas=state:naive force=? =raw-tx:naive] + ^- [success=? _nas] + ?. (verify-sig-and-nonce:naive verifier:ttttt nas raw-tx) + [force nas] + :: + =^ * nas (increment-nonce:naive nas from.tx.raw-tx) + :: + ?~ nex=(receive-tx:naive nas tx.raw-tx) + [force nas] + [& +.u.nex] +:: +++ on-action + |= =action + ?- -.action + %commit send-roll + %config [~ state(frequency frequency.action)] + %setkey [~ state(pk pk.action)] ::TODO what about existing sending entries? + :: + %submit + =^ success state + %+ take-tx force.action + (part-tx-to-full tx.action) + ?> success + [~ state] + :: + %cancel + !! ::TODO + == +:: +take-tx: accept submitted l2 tx into the :pending list +::TODO rewrite +:: +++ take-tx + |= [force=? =raw-tx:naive] + ^- [success=? _state] + =/ [nep=_pending nas=state:naive] pending-state + =^ success nas + (try-apply nas force raw-tx) + ::TODO want to notify about dropped pendings, or no? client prolly polls... + =? pending success [[force raw-tx] nep] ::TODO probably +snoc instead? + ::TODO cache nas? + [success state] +:: +set-timer: %wait until next whole :frequency +:: +++ set-timer + ^- card + %+ wait /timer + (mul +((div now.bowl frequency)) frequency) +:: +on-timer: every :frequency, freeze :pending txs roll and start sending it +:: +++ on-timer + =^ cards state + ?~ pending [~ state] + =/ nonce=@ud next-nonce + =: pending ~ + next-nonce +(next-nonce) + :: + sending + %+ ~(put by sending) nonce + %+ turn pending + (cork tail (lead 0)) + == + [(send-roll nonce) state] + [[set-timer cards] state] +:: +send-roll: start thread to submit roll from :sending to l1 +:: +++ send-roll + |= nonce=@ud + ^- (list card) + :: if this nonce isn't in the sending queue anymore, it's done + :: + ?. (~(has by sending) nonce) + ~? lverb [dap.bowl %done-sending nonce] + ~ + :: start the thread, passing in the l2 txs to use + :: + ::TODO should go ahead and set resend timer in case thread hangs, or nah? + %+ start-thread:spider + /send/(scot %ud nonce) + :- %aggregator-send + !>([nonce ~(got by sending) nonce)]) ::TODO other args +:: +on-thread-result: await resend after thread success or failure +:: +++ on-thread-result + |= [nonce=@ud result=(each @ud term)] + ^- (quip card _state) + :: update gas price for this tx in state + :: + =? sending ?=(%& -.result) + %+ ~(jab by sending) nonce + (cork tail (lead p.result)) + :: print error if there was one + :: + ~? ?=(%| -.result) [dap.bowl %send-error p.result] + :: resend the l1 tx in five minutes + :: + :_ state + [(wait /resend/(scot %ud nonce) (add resend-time now.bowl))]~ +:: +on-naive-diff: process l2 tx confirmations +:: +++ on-naive-diff + |= =diff:naive + ^- (quip card _state) + ?. ?=(%tx -.diff) + [~ state] + =/ =keccak (hash-raw-tx raw-tx.diff) + ?~ wer=(~(get by finding) keccak) + [~ state] + :: if we had already seen the tx, no-op + :: + ?@ u.wer + ~? &(?=(%confirmed u.wer) ?=(~ err.diff)) + [dap.bowl %weird-double-confirm from.tx] + [~ state] + =* nonce nonce.u.wer + :: remove the tx from the sending map + :: + =. sending + ?~ sen=(~(get by sending) nonce) + ~& [dap.bowl %weird-double-remove] + sending + ?~ nin=(find [raw-tx.diff]~ txs.u.sen) + ~& [dap.bowl %weird-unknown] + =. txs.u.sen (oust [u.nin 1] txs.u.sen) + ?~ txs.u.sen + ~? lverb [dap.bowl %done-with-nonce nonce] + (~(del by sending) nonce) + (~(put by sending) nonce u.sen) + :: update the finding map with the new status + :: + =. finding + %+ ~(put by finding) keccak + ?~ err.diff %confirmed + :: if we kept the forced flag around for longer, we could notify of + :: unexpected tx failures here. would that be useful? probably not? + :: ~? !forced [dap.bowl %aggregated-tx-failed-anyway err.diff] + %failed + [~ state] +:: +-- diff --git a/pkg/arvo/lib/naive.hoon b/pkg/arvo/lib/naive.hoon index f4d7ade71..84208c4a2 100644 --- a/pkg/arvo/lib/naive.hoon +++ b/pkg/arvo/lib/naive.hoon @@ -333,6 +333,17 @@ [other batch] -- :: +++ proxy-from-point + |= [=proxy point] + ^- [=address =nonce] + ?- proxy + %own owner.own + %spawn spawn-proxy.own + %manage management-proxy.own + %vote voting-proxy.own + %transfer transfer-proxy.own + == +:: ++ verify-sig-and-nonce |= [=verifier chain-t=@t =state =raw-tx] ^- ? @@ -340,13 +351,7 @@ =/ point (get-point state ship.from.tx.raw-tx) ?> ?=(^ point) :: we never parse more than four bytes for a ship =/ need=[=address =nonce] - ?- proxy.from.tx.raw-tx - %own owner.own.u.point - %spawn spawn-proxy.own.u.point - %manage management-proxy.own.u.point - %vote voting-proxy.own.u.point - %transfer transfer-proxy.own.u.point - == + (proxy-from-point proxy.from.tx.raw-tx u.point) :: We include a domain separator to avoid letting signatures be :: accidentally reused with other applications. We include the name :: UrbitID, a signature format version number, and the EIP-155 chain diff --git a/pkg/arvo/ted/aggregator/send.hoon b/pkg/arvo/ted/aggregator/send.hoon new file mode 100644 index 000000000..fd16da29b --- /dev/null +++ b/pkg/arvo/ted/aggregator/send.hoon @@ -0,0 +1,100 @@ +:: aggregator/send: send rollup tx +:: +/- rpc=json-rpc +/+ naive, ethereum, ethio, strandio +:: +=/ gas-limit=@ud 30.000 ::TODO verify, maybe scale with roll size +:: +|= args=vase +=+ !< $: endpoint=@t + contract=address:ethereum + chain-id=@ + pk=@ + :: + nonce=@ud + next-gas-price=@ud + txs=(list raw-tx:naive) + == + args +=/ m (strand:strandio ,vase) +|^ +^- form:m +=* not-sent (pure:m !>(next-gas-price)) +:: +=/ =address:ethereum + (address-from-pub:key:ethereum pk) +;< expected-nonce=@ud bind:m + (get-next-nonce:ethio endpoint address) +:: if chain expects a different nonce, don't send this transaction +:: +?. =(nonce expected-nonce) + not-sent +:: if a gas-price of 0 was specified, fetch the recommended one +:: +;< use-gas-price=@ud bind:m + ?: =(0 next-gas-price) fetch-gas-price + (pure:(strand:strandio @ud) next-gas-price) +:: if we cannot pay for the transaction, don't bother sending it out +:: +=/ max-cost=@ud (mul gas-limit use-gas-price) +;< balance=@ud bind:m + ::TODO implement %eth-get-balance in /lib/ethio and /lib/ethereum + !! +?: (gth max-cost balance) + ~& [%insufficient-aggregator-balance address] + not-sent +:: +=/ tx=@ux + =; tx=transaction:rpc:ethereum + (sign-transaction:key:ethereum tx pk) + :* nonce + use-gas-price + gas-limit + contract + 0 + roll ::TODO tx data + chain-id + == +:: +::NOTE this fails the thread if sending fails, which in the app gives us +:: the "retry with same gas price" behavior we want +;< jon=json bind:m + %+ request-rpc:ethio endpoint + [~ %eth-send-raw-transaction tx] +::TODO check that tx-hash in jon is non-zero? +::TODO enforce max here, or in app? +:: add five gwei to gas price of next attempt +:: +(pure:m !>((add use-gas-price 5.000.000.000))) +:: +::TODO should be distilled further, partially added to strandio? +++ fetch-gas-price + =/ m (strand:strandio @ud) ::NOTE return in wei + ^- form:m + =/ =request:http + :* method=%'GET' + url='https://api.etherscan.io/api?module=gastracker&action=gasoracle' + header-list=~ + ~ + == + ;< ~ bind:m + (send-request:strandio request) + ;< rep=(unit client-response:iris) bind:m + take-maybe-response:strandio + =* fallback + ~& %fallback-gas-price + (pure:m 40.000.000.000) ::TODO maybe even lower, considering we increment? + ?. ?& ?=([~ %finished *] rep) + ?=(^ full-file.u.rep) + == + fallback + ?~ jon=(de-json:html q.data.u.full-file.u.rep) + fallback + =; res=(unit @ud) + ?~ res fallback + %- pure:m + (mul 1.000.000.000 u.res) ::NOTE gwei to wei + %. u.jon + =, dejs-soft:format + (ot 'result'^(ot 'FastGasPrice'^ni) ~) +-- From 31cc219997d9092cbae8218e983014b534ef71e5 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Sun, 25 Apr 2021 15:37:01 +0200 Subject: [PATCH 02/21] naive: support "get point" scry --- pkg/arvo/app/azimuth.hoon | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/pkg/arvo/app/azimuth.hoon b/pkg/arvo/app/azimuth.hoon index 70fdd8bcd..45e165469 100644 --- a/pkg/arvo/app/azimuth.hoon +++ b/pkg/arvo/app/azimuth.hoon @@ -256,11 +256,19 @@ ++ on-leave on-leave:def ++ on-peek |= =path - ?: =(/x/nas path) - ``nas+!>(nas.state) - ?: =(/x/logs path) + ^- (unit (unit cage)) + ?+ path (on-peek:def path) + [%x %logs ~] ``logs+!>(logs.state) - ~ + :: + [%x %nas ~] + ``nas+!>(nas.state) + :: + [%x %nas @t ~] + ?~ ship=(rush i.t.t.path ;~(pfix sig fed:ag)) + ``noun+!>(*(unit point:naive)) + ``noun+!>((~(get by points.nas.state) u.ship)) + == :: ++ on-agent |= [=wire =sign:agent:gall] From de3007dc06842406475724799c27cb9f74bd54e6 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Sun, 25 Apr 2021 15:37:16 +0200 Subject: [PATCH 03/21] json-rpc: add jsonrpc key to request --- pkg/arvo/sur/json/rpc.hoon | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/arvo/sur/json/rpc.hoon b/pkg/arvo/sur/json/rpc.hoon index 350f2cae1..809c1935a 100644 --- a/pkg/arvo/sur/json/rpc.hoon +++ b/pkg/arvo/sur/json/rpc.hoon @@ -3,6 +3,7 @@ |% +$ request $: id=@t + jsonrpc=@t method=@t params=request-params == From afd3c9b85e172f22cd465590c332fdc380420bef Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Sun, 25 Apr 2021 15:37:40 +0200 Subject: [PATCH 04/21] naive: add azimuth rpc api Currently supports one endpoint 'get-point' that returns Azimuth Point data (see +point in %/lib/naive.hoon), for a given ship. To run it: curl -X POST --data '{ "jsonrpc": "2.0", "method": "get-point", "params": {"ship": "~sampel-palnet"}, "id": 1234 }' http://localhost:8080/v1/azimuth --- pkg/arvo/app/azimuth-rpc.hoon | 243 +++++++++++++++++++++++ pkg/arvo/gen/azimuth-rpc/disconnect.hoon | 4 + 2 files changed, 247 insertions(+) create mode 100644 pkg/arvo/app/azimuth-rpc.hoon create mode 100644 pkg/arvo/gen/azimuth-rpc/disconnect.hoon diff --git a/pkg/arvo/app/azimuth-rpc.hoon b/pkg/arvo/app/azimuth-rpc.hoon new file mode 100644 index 000000000..4911ae362 --- /dev/null +++ b/pkg/arvo/app/azimuth-rpc.hoon @@ -0,0 +1,243 @@ +:: Azimuth RPC API +:: +/- rpc=json-rpc +/+ naive, *server, default-agent, verb, dbug, version +|% ++$ card card:agent:gall +:: ++$ state-0 [%0 ~] +-- +:: +%+ verb | +%- agent:dbug +:: +=| state-0 +=* state - +:: +^- agent:gall +=< + |_ =bowl:gall + +* this . + do ~(. +> bowl) + def ~(. (default-agent this %|) bowl) + :: + ++ on-init + ^- (quip card _this) + ~& > 'init' + :_ this + [%pass /bind %arvo %e %connect [~ [%v1 %azimuth ~]] dap.bowl]~ + :: + ++ on-save !>(state) + ++ on-load + |= old=vase + ^- (quip card _this) + [~ this(state !<(state-0 old))] + :: + ++ on-poke + |= [=mark =vase] + ^- (quip card _this) + |^ + ?> (team:title our.bowl src.bowl) + ?+ mark (on-poke:def mark vase) + %handle-http-request + =+ !<([id=@ta req=inbound-request:eyre] vase) + :_ this + %+ give-simple-payload:app id + (handle-http-request req) + :: + %azimuth-action + =+ !<([%disconnect bind=binding:eyre] vase) + ~& >>> "disconnecting at {}" + :_ this + [[%pass /bind %arvo %e %disconnect bind]]~ + == + :: + ++ handle-http-request + |= =inbound-request:eyre + ^- simple-payload:http + |^ + =* req request.inbound-request + =* headers header-list.req + =/ req-line (parse-request-line url.req) + ?. =(method.req %'POST') + :: TODO: method not supported + :: + not-found:gen + ?~ json-rpc=(validate-json-rpc body.req) + :: TODO: malformed request + :: + not-found:gen + (process-rpc-request:do u.json-rpc) + :: TODO: validate that format is e.g. 'get-point' + :: TODO: maybe replace with getPoint and translate to %term + :: + ++ parse-method |=(t=@t t) + :: TODO: move to library + :: + ++ validate-json-rpc + |= body=(unit octs) + ^- (unit request:rpc) + ?~ body ~ + ?~ jon=(de-json:html q.u.body) ~ + :: ignores non-object responses + :: + :: ?. ?=([%o *] json) ~|([%format-not-valid json] !!) + ?. ?=([%o *] u.jon) ~ + %- some + %. u.jon + =, dejs:format + %- ot + :~ ['id' no] + ['jsonrpc' so] + ['method' (cu parse-method so)] + :: + :- 'params' + |= =json + ^- request-params:rpc + ?: =(%a -.json) + [%list ((ar same) json)] + ?. =(%o -.json) + !! + [%object ~(tap by ((om same) json))] + == + -- + -- + :: + ++ on-watch + |= =path + ^- (quip card _this) + ?> (team:title our.bowl src.bowl) + ?+ path (on-watch:def path) + [%http-response *] [~ this] + == + :: + ++ on-arvo + |= [=wire =sign-arvo] + ^- (quip card _this) + ?+ sign-arvo (on-arvo:def wire sign-arvo) + [%eyre %bound *] + ~? !accepted.sign-arvo + [dap.bowl 'bind rejected!' binding.sign-arvo] + [~ this] + == + :: + ++ on-leave on-leave:def + ++ on-peek on-peek:def + ++ on-agent on-agent:def + ++ on-fail on-fail:def + -- +:: +|_ =bowl:gall +++ process-rpc-request + |= req=request:rpc + ^- simple-payload:http + |^ + ?+ method.req ~|([%unsupported-azimuth-request method.req] !!) + %get-point (get-point id.req params.req) + == + :: TODO: move this to a library + :: TODO: handle rpc error responses properly + :: + ++ get-point + |= [id=@t params=request-params:rpc] + %- json-response:gen + %- rpc-response-to-json + ?. ?=([%object *] params) + [%error id 'X' 'RPC params must be an object'] + ?> ?=(^ +.params) + ?. =('ship' p.i.+.params) + [%error id 'X' 'A "ship" key must exist'] + =/ ship=(unit ship) + (rush (so:dejs:format q.i.+.params) ;~(pfix sig fed:ag)) + ?~ ship + [%error id 'X' 'Ship @p invalid'] + ?~ point=(scry-point u.ship) + [%error id 'X' 'Ship @p not found'] + [%result id (point-to-json u.point)] + :: + ++ point-to-json + |= =point:naive + ^- json + |^ + :: :+ %result id + :- %o + %- molt + ^- (list [@t json]) + :~ ['dominion' s+dominion.point] + :: + :- 'ownership' + :- %o + %- molt + =* own own.point + ^- (list [@t json]) + :~ ['owner' (own-to-json owner.own)] + ['spawnProxy' (own-to-json spawn-proxy.own)] + ['managementProxy' (own-to-json spawn-proxy.own)] + ['votingProxy' (own-to-json management-proxy.own)] + ['transferProxy' (own-to-json transfer-proxy.own)] + == + :: + :- 'network' + :- %o + =, enjs:format + %- molt + =* net net.point + ^- (list [@t json]) + :* ['life' (numb life.net)] + ['pass' s+(crip ((x-co:co 20) pass.net))] + ['rift' (numb rift.net)] + :- 'sponsor' + :- %o + %- molt ^- (list [@t json]) + ~[['has' b+has.sponsor.net] ['who' (ship who.sponsor.net)]] + :: + ?~ escape.net ~ + ['escape' (ship u.escape.net)]~ + == == + :: + ++ own-to-json + |= [=address:naive =nonce:naive] + ^- json + :- %o + %- molt ^- (list [@t json]) + :~ ['address' s+(crip "0x{((x-co:co 20) address)}")] + ['nonce' (numb:enjs:format nonce)] + == + -- + :: TODO: move to rpc library + :: + ++ rpc-response-to-json + |= =response:rpc + ^- json + :: TODO: consider all cases + :: + ?+ -.response ~|([%unsupported-rpc-response response] !!) + %result + :- %o + %- molt + ^- (list [@t json]) + ~[['id' s+id.response] ['res' res.response]] + :: + %error + :- %o + %- molt + ^- (list [@t json]) + :~ ['id' s+id.response] + ['code' s+code.response] + ['message' s+message.response] + == + == + -- +:: +++ scry-point + |= =ship + .^ (unit point:naive) + %gx + (scot %p our.bowl) + %naive + (scot %da now.bowl) + %nas + (scot %p ship) + /noun + == +-- diff --git a/pkg/arvo/gen/azimuth-rpc/disconnect.hoon b/pkg/arvo/gen/azimuth-rpc/disconnect.hoon new file mode 100644 index 000000000..7b3214713 --- /dev/null +++ b/pkg/arvo/gen/azimuth-rpc/disconnect.hoon @@ -0,0 +1,4 @@ +:: +:- %say +|= [* [=binding:eyre ~] ~] +[%azimuth-action %disconnect binding] From 0c704bb145a9a35a808e2b737149ba41d93b9b8f Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Thu, 29 Apr 2021 10:56:29 +0200 Subject: [PATCH 05/21] json-rpc: add response-to-json --- pkg/arvo/app/azimuth-rpc.hoon | 27 ++------------------------- pkg/arvo/lib/json/rpc.hoon | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/pkg/arvo/app/azimuth-rpc.hoon b/pkg/arvo/app/azimuth-rpc.hoon index 4911ae362..5c26790f2 100644 --- a/pkg/arvo/app/azimuth-rpc.hoon +++ b/pkg/arvo/app/azimuth-rpc.hoon @@ -1,7 +1,7 @@ :: Azimuth RPC API :: /- rpc=json-rpc -/+ naive, *server, default-agent, verb, dbug, version +/+ naive, json-rpc, *server, default-agent, verb, dbug, version |% +$ card card:agent:gall :: @@ -141,7 +141,7 @@ ++ get-point |= [id=@t params=request-params:rpc] %- json-response:gen - %- rpc-response-to-json + %- response-to-json:json-rpc ?. ?=([%object *] params) [%error id 'X' 'RPC params must be an object'] ?> ?=(^ +.params) @@ -204,29 +204,6 @@ ['nonce' (numb:enjs:format nonce)] == -- - :: TODO: move to rpc library - :: - ++ rpc-response-to-json - |= =response:rpc - ^- json - :: TODO: consider all cases - :: - ?+ -.response ~|([%unsupported-rpc-response response] !!) - %result - :- %o - %- molt - ^- (list [@t json]) - ~[['id' s+id.response] ['res' res.response]] - :: - %error - :- %o - %- molt - ^- (list [@t json]) - :~ ['id' s+id.response] - ['code' s+code.response] - ['message' s+message.response] - == - == -- :: ++ scry-point diff --git a/pkg/arvo/lib/json/rpc.hoon b/pkg/arvo/lib/json/rpc.hoon index e44ad1d68..c5ead16c7 100644 --- a/pkg/arvo/lib/json/rpc.hoon +++ b/pkg/arvo/lib/json/rpc.hoon @@ -28,4 +28,26 @@ %object [%o (~(gas by *(map @t json)) +.params)] == == +:: +++ response-to-json + |= =response + ^- json + :: TODO: consider all cases + :: + ?+ -.response ~|([%unsupported-rpc-response response] !!) + %result + :- %o + %- molt + ^- (list [@t json]) + ~[['id' s+id.response] ['res' res.response]] + :: + %error + :- %o + %- molt + ^- (list [@t json]) + :~ ['id' s+id.response] + ['code' s+code.response] + ['message' s+message.response] + == + == -- From d8a24d7d6b660cb5c28d90c9b314d45e23f2cbbe Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Thu, 29 Apr 2021 11:14:32 +0200 Subject: [PATCH 06/21] naive: add json library for rpc responses --- pkg/arvo/app/azimuth-rpc.hoon | 62 +++++------------------------------ pkg/arvo/lib/azimuth-rpc.hoon | 53 ++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 53 deletions(-) create mode 100644 pkg/arvo/lib/azimuth-rpc.hoon diff --git a/pkg/arvo/app/azimuth-rpc.hoon b/pkg/arvo/app/azimuth-rpc.hoon index 5c26790f2..ed1d0dedf 100644 --- a/pkg/arvo/app/azimuth-rpc.hoon +++ b/pkg/arvo/app/azimuth-rpc.hoon @@ -1,7 +1,14 @@ :: Azimuth RPC API :: /- rpc=json-rpc -/+ naive, json-rpc, *server, default-agent, verb, dbug, version +/+ naive, + azimuth-rpc, + json-rpc, + *server, + default-agent, + verb, + dbug, + version |% +$ card card:agent:gall :: @@ -135,7 +142,6 @@ ?+ method.req ~|([%unsupported-azimuth-request method.req] !!) %get-point (get-point id.req params.req) == - :: TODO: move this to a library :: TODO: handle rpc error responses properly :: ++ get-point @@ -153,57 +159,7 @@ [%error id 'X' 'Ship @p invalid'] ?~ point=(scry-point u.ship) [%error id 'X' 'Ship @p not found'] - [%result id (point-to-json u.point)] - :: - ++ point-to-json - |= =point:naive - ^- json - |^ - :: :+ %result id - :- %o - %- molt - ^- (list [@t json]) - :~ ['dominion' s+dominion.point] - :: - :- 'ownership' - :- %o - %- molt - =* own own.point - ^- (list [@t json]) - :~ ['owner' (own-to-json owner.own)] - ['spawnProxy' (own-to-json spawn-proxy.own)] - ['managementProxy' (own-to-json spawn-proxy.own)] - ['votingProxy' (own-to-json management-proxy.own)] - ['transferProxy' (own-to-json transfer-proxy.own)] - == - :: - :- 'network' - :- %o - =, enjs:format - %- molt - =* net net.point - ^- (list [@t json]) - :* ['life' (numb life.net)] - ['pass' s+(crip ((x-co:co 20) pass.net))] - ['rift' (numb rift.net)] - :- 'sponsor' - :- %o - %- molt ^- (list [@t json]) - ~[['has' b+has.sponsor.net] ['who' (ship who.sponsor.net)]] - :: - ?~ escape.net ~ - ['escape' (ship u.escape.net)]~ - == == - :: - ++ own-to-json - |= [=address:naive =nonce:naive] - ^- json - :- %o - %- molt ^- (list [@t json]) - :~ ['address' s+(crip "0x{((x-co:co 20) address)}")] - ['nonce' (numb:enjs:format nonce)] - == - -- + [%result id (point-to-json:azimuth-rpc u.point)] -- :: ++ scry-point diff --git a/pkg/arvo/lib/azimuth-rpc.hoon b/pkg/arvo/lib/azimuth-rpc.hoon new file mode 100644 index 000000000..284134987 --- /dev/null +++ b/pkg/arvo/lib/azimuth-rpc.hoon @@ -0,0 +1,53 @@ +/- rpc=json-rpc +/+ naive +:: +|% +++ point-to-json + |= =point:naive + ^- json + |^ + :- %o + %- molt + ^- (list [@t json]) + :~ ['dominion' s+dominion.point] + :: + :- 'ownership' + :- %o + %- molt + =* own own.point + ^- (list [@t json]) + :~ ['owner' (own-to-json owner.own)] + ['spawnProxy' (own-to-json spawn-proxy.own)] + ['managementProxy' (own-to-json management-proxy.own)] + ['votingProxy' (own-to-json voting-proxy.own)] + ['transferProxy' (own-to-json transfer-proxy.own)] + == + :: + :- 'network' + :- %o + =, enjs:format + %- molt + =* net net.point + ^- (list [@t json]) + :* ['life' (numb life.net)] + ['pass' s+(crip ((x-co:co 20) pass.net))] + ['rift' (numb rift.net)] + :- 'sponsor' + :- %o + %- molt ^- (list [@t json]) + ~[['has' b+has.sponsor.net] ['who' (ship who.sponsor.net)]] + :: + ?~ escape.net ~ + ['escape' (ship u.escape.net)]~ + == == + :: + ++ own-to-json + |= [=address:naive =nonce:naive] + ^- json + :- %o + %- molt ^- (list [@t json]) + :~ ['address' s+(crip "0x{((x-co:co 20) address)}")] + ['nonce' (numb:enjs:format nonce)] + == + -- +-- \ No newline at end of file From 843fe4ce386a732d86dbab476f1245fdd961cfdb Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Thu, 29 Apr 2021 11:23:50 +0200 Subject: [PATCH 07/21] json-rpc: add validation for json-rpc request --- pkg/arvo/app/azimuth-rpc.hoon | 36 ++++------------------------------- pkg/arvo/lib/json/rpc.hoon | 27 ++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 32 deletions(-) diff --git a/pkg/arvo/app/azimuth-rpc.hoon b/pkg/arvo/app/azimuth-rpc.hoon index ed1d0dedf..35b9a4ad0 100644 --- a/pkg/arvo/app/azimuth-rpc.hoon +++ b/pkg/arvo/app/azimuth-rpc.hoon @@ -70,43 +70,15 @@ :: TODO: method not supported :: not-found:gen - ?~ json-rpc=(validate-json-rpc body.req) + ?~ rpc-request=(validate-request:json-rpc body.req parse-method) :: TODO: malformed request :: not-found:gen - (process-rpc-request:do u.json-rpc) - :: TODO: validate that format is e.g. 'get-point' - :: TODO: maybe replace with getPoint and translate to %term + (process-rpc-request:do u.rpc-request) + :: TODO: validate that format is e.g. 'getPoint' + :: TODO: maybe use getPoint and translate to %get-point :: ++ parse-method |=(t=@t t) - :: TODO: move to library - :: - ++ validate-json-rpc - |= body=(unit octs) - ^- (unit request:rpc) - ?~ body ~ - ?~ jon=(de-json:html q.u.body) ~ - :: ignores non-object responses - :: - :: ?. ?=([%o *] json) ~|([%format-not-valid json] !!) - ?. ?=([%o *] u.jon) ~ - %- some - %. u.jon - =, dejs:format - %- ot - :~ ['id' no] - ['jsonrpc' so] - ['method' (cu parse-method so)] - :: - :- 'params' - |= =json - ^- request-params:rpc - ?: =(%a -.json) - [%list ((ar same) json)] - ?. =(%o -.json) - !! - [%object ~(tap by ((om same) json))] - == -- -- :: diff --git a/pkg/arvo/lib/json/rpc.hoon b/pkg/arvo/lib/json/rpc.hoon index c5ead16c7..89f100b81 100644 --- a/pkg/arvo/lib/json/rpc.hoon +++ b/pkg/arvo/lib/json/rpc.hoon @@ -50,4 +50,31 @@ ['message' s+message.response] == == +:: +++ validate-request + |= [body=(unit octs) parse-method=$-(@t term)] + ^- (unit request) + ?~ body ~ + ?~ jon=(de-json:html q.u.body) ~ + :: ignores non-object responses + :: + :: ?. ?=([%o *] json) ~|([%format-not-valid json] !!) + ?. ?=([%o *] u.jon) ~ + %- some + %. u.jon + =, dejs:format + %- ot + :~ ['id' no] + ['jsonrpc' so] + ['method' (cu parse-method so)] + :: + :- 'params' + |= =json + ^- request-params + ?: =(%a -.json) + [%list ((ar same) json)] + ?. =(%o -.json) + !! + [%object ~(tap by ((om same) json))] + == -- From fe8c36dd3f82845ef8d655a43f61e1c3aded5a1f Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Thu, 29 Apr 2021 12:10:58 +0200 Subject: [PATCH 08/21] naive: use agentio for scry point --- pkg/arvo/app/azimuth-rpc.hoon | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/pkg/arvo/app/azimuth-rpc.hoon b/pkg/arvo/app/azimuth-rpc.hoon index 35b9a4ad0..857a58ec5 100644 --- a/pkg/arvo/app/azimuth-rpc.hoon +++ b/pkg/arvo/app/azimuth-rpc.hoon @@ -8,7 +8,8 @@ default-agent, verb, dbug, - version + version, + agentio |% +$ card card:agent:gall :: @@ -136,13 +137,8 @@ :: ++ scry-point |= =ship - .^ (unit point:naive) - %gx - (scot %p our.bowl) - %naive - (scot %da now.bowl) - %nas - (scot %p ship) - /noun + .^ (unit point:naive) + %gx + (~(scry agentio bowl) %naive /nas/[(scot %p ship)]/noun) == -- From fe6f189e33372b9f18ee703cd07d9aaed7bc59b8 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Mon, 3 May 2021 13:21:16 +0200 Subject: [PATCH 09/21] json-rpc: add support for params as map object --- pkg/arvo/lib/json/rpc.hoon | 30 +++++++++++++++++------------- pkg/arvo/sur/json/rpc.hoon | 1 + 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/pkg/arvo/lib/json/rpc.hoon b/pkg/arvo/lib/json/rpc.hoon index 89f100b81..22d4d9536 100644 --- a/pkg/arvo/lib/json/rpc.hoon +++ b/pkg/arvo/lib/json/rpc.hoon @@ -24,10 +24,10 @@ :- %params ^- json ?- -.params - %list [%a +.params] - %object [%o (~(gas by *(map @t json)) +.params)] - == - == + %list [%a +.params] + %map [%o +.params] + %object [%o (~(gas by *(map @t json)) +.params)] + == == :: ++ response-to-json |= =response @@ -45,7 +45,9 @@ :- %o %- molt ^- (list [@t json]) - :~ ['id' s+id.response] + :~ :: FIXME: return 'id' as string, number or NULL + :: + ['id' s+id.response] ['code' s+code.response] ['message' s+message.response] == @@ -63,18 +65,20 @@ %- some %. u.jon =, dejs:format + :: TODO: If parsing fails, return a proper error (not 500) + :: %- ot - :~ ['id' no] - ['jsonrpc' so] + :~ :: FIXME: parse 'id' as string, number or NULL + :: + ['id' so] + ['jsonrpc' (su (jest '2.0'))] ['method' (cu parse-method so)] :: :- 'params' |= =json ^- request-params - ?: =(%a -.json) - [%list ((ar same) json)] - ?. =(%o -.json) - !! - [%object ~(tap by ((om same) json))] - == + ?+ -.json !! + %a [%list ((ar same) json)] + %o [%map ((om same) json)] + == == -- diff --git a/pkg/arvo/sur/json/rpc.hoon b/pkg/arvo/sur/json/rpc.hoon index 809c1935a..63f5a06f1 100644 --- a/pkg/arvo/sur/json/rpc.hoon +++ b/pkg/arvo/sur/json/rpc.hoon @@ -10,6 +10,7 @@ :: +$ request-params $% [%list (list json)] + [%map (map @t json)] [%object (list (pair @t json))] == +$ response From 36cdb9493d8870a8eb80ef52bbf58acca324324b Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Mon, 3 May 2021 13:35:21 +0200 Subject: [PATCH 10/21] naive: add jsonrpc parsing for naive txs --- pkg/arvo/app/azimuth-rpc.hoon | 70 ++++----- pkg/arvo/lib/azimuth-rpc.hoon | 258 ++++++++++++++++++++++++++++------ 2 files changed, 251 insertions(+), 77 deletions(-) diff --git a/pkg/arvo/app/azimuth-rpc.hoon b/pkg/arvo/app/azimuth-rpc.hoon index 857a58ec5..911d3abf6 100644 --- a/pkg/arvo/app/azimuth-rpc.hoon +++ b/pkg/arvo/app/azimuth-rpc.hoon @@ -50,8 +50,7 @@ %handle-http-request =+ !<([id=@ta req=inbound-request:eyre] vase) :_ this - %+ give-simple-payload:app id - (handle-http-request req) + (handle-http-request id req) :: %azimuth-action =+ !<([%disconnect bind=binding:eyre] vase) @@ -61,8 +60,8 @@ == :: ++ handle-http-request - |= =inbound-request:eyre - ^- simple-payload:http + |= [id=@ta =inbound-request:eyre] + ^- (list card) |^ =* req request.inbound-request =* headers header-list.req @@ -70,16 +69,23 @@ ?. =(method.req %'POST') :: TODO: method not supported :: - not-found:gen + (give-simple-payload:app id not-found:gen) ?~ rpc-request=(validate-request:json-rpc body.req parse-method) :: TODO: malformed request :: - not-found:gen - (process-rpc-request:do u.rpc-request) + (give-simple-payload:app id not-found:gen) + =/ [data=(unit cage) response=simple-payload:http] + (process-rpc-request:do u.rpc-request) + %+ weld + (give-simple-payload:app id response) + ?~ data ~ + :_ ~ + ^- card + [%pass / %agent [our.bowl %dice] %poke u.data] :: TODO: validate that format is e.g. 'getPoint' :: TODO: maybe use getPoint and translate to %get-point :: - ++ parse-method |=(t=@t t) + ++ parse-method |=(t=@t `term`t) -- -- :: @@ -109,36 +115,34 @@ :: |_ =bowl:gall ++ process-rpc-request - |= req=request:rpc - ^- simple-payload:http - |^ - ?+ method.req ~|([%unsupported-azimuth-request method.req] !!) - %get-point (get-point id.req params.req) - == - :: TODO: handle rpc error responses properly - :: - ++ get-point - |= [id=@t params=request-params:rpc] + |= request:rpc + ^- [(unit cage) simple-payload:http] + =; [data=(unit cage) =response:rpc] + :- data %- json-response:gen - %- response-to-json:json-rpc - ?. ?=([%object *] params) - [%error id 'X' 'RPC params must be an object'] - ?> ?=(^ +.params) - ?. =('ship' p.i.+.params) - [%error id 'X' 'A "ship" key must exist'] - =/ ship=(unit ship) - (rush (so:dejs:format q.i.+.params) ;~(pfix sig fed:ag)) - ?~ ship - [%error id 'X' 'Ship @p invalid'] - ?~ point=(scry-point u.ship) - [%error id 'X' 'Ship @p not found'] - [%result id (point-to-json:azimuth-rpc u.point)] - -- + (response-to-json:json-rpc response) + ?. ?=([%map *] params) + [~ [%error id 'X' 'RPC params must be an object']] + =, azimuth-rpc + ?+ method [~ [%error id 'X' 'Unsupported Azimuth RPC']] + %get-point [~ (get-point id +.params scry-point)] + %transfer-point (transfer-point id +.params) + %configure-keys (configure-keys id +.params) + %spawn (spawn id +.params) + %escape (escape id +.params) + %cancel-escape (cancel-escape id +.params) + %adopt (adopt id +.params) + %detach (detach id +.params) + %reject (reject id +.params) + %set-management-proxy (management-proxy id +.params) + %set-spawn-proxy (spawn-proxy id +.params) + %set-transfer-proxy (transfer-proxy id +.params) + == :: ++ scry-point |= =ship .^ (unit point:naive) %gx - (~(scry agentio bowl) %naive /nas/[(scot %p ship)]/noun) + (~(scry agentio bowl) %azimuth /nas/[(scot %p ship)]/noun) == -- diff --git a/pkg/arvo/lib/azimuth-rpc.hoon b/pkg/arvo/lib/azimuth-rpc.hoon index 284134987..e9a58fc56 100644 --- a/pkg/arvo/lib/azimuth-rpc.hoon +++ b/pkg/arvo/lib/azimuth-rpc.hoon @@ -1,53 +1,223 @@ +:: azimuth-rpc: command parsing and utilities +:: /- rpc=json-rpc /+ naive :: -|% -++ point-to-json - |= =point:naive - ^- json - |^ - :- %o - %- molt - ^- (list [@t json]) - :~ ['dominion' s+dominion.point] - :: - :- 'ownership' - :- %o - %- molt - =* own own.point - ^- (list [@t json]) - :~ ['owner' (own-to-json owner.own)] - ['spawnProxy' (own-to-json spawn-proxy.own)] - ['managementProxy' (own-to-json management-proxy.own)] - ['votingProxy' (own-to-json voting-proxy.own)] - ['transferProxy' (own-to-json transfer-proxy.own)] +=> :: Utilities + :: + |% + ++ extract + |% + ++ keys + |= params=(map @t json) + ^- (unit [encrypt=@ auth=@ crypto-suite=@ breach=?]) + ?~ data=(~(get by params) 'data') ~ + =, dejs:format + %- some + %. u.data + %- ot + :~ ['encrypt' so] + ['auth' so] + ['crypto-suite' so] + ['breach' bo] == :: - :- 'network' - :- %o - =, enjs:format - %- molt - =* net net.point - ^- (list [@t json]) - :* ['life' (numb life.net)] - ['pass' s+(crip ((x-co:co 20) pass.net))] - ['rift' (numb rift.net)] - :- 'sponsor' - :- %o - %- molt ^- (list [@t json]) - ~[['has' b+has.sponsor.net] ['who' (ship who.sponsor.net)]] - :: - ?~ escape.net ~ - ['escape' (ship u.escape.net)]~ - == == + ++ address-ship + |= params=(map @t json) + ^- (unit [@ux ship]) + ?~ data=(~(get by params) 'data') ~ + =, dejs:format + =; [add=(unit @ux) =ship] + ?~ add ~ + (some [u.add ship]) + %. u.data + %- ot + :~ ['address' (cu to-hex so)] + ['ship' (su ;~(pfix sig fed:ag))] + == + :: + ++ address + |= params=(map @t json) + ^- (unit @ux) + ?~ data=(~(get by params) 'data') ~ + =, dejs:format + %. u.data + (ot ['address' (cu to-hex so)]~) + :: + ++ sig + |= params=(map @t json) + ^- (unit @) + ?~ sig=(~(get by params) 'sig') ~ + (some (so:dejs:format u.sig)) + :: + ++ from + |= params=(map @t json) + ^- (unit [ship @t]) + ?~ from=(~(get by params) 'from') ~ + %- some + =, dejs:format + %. u.from + %- ot + :~ ['ship' (su ;~(pfix sig fed:ag))] + ['proxy' so] + == + -- :: - ++ own-to-json - |= [=address:naive =nonce:naive] + ++ point-to-json + |= =point:naive ^- json + |^ :- %o - %- molt ^- (list [@t json]) - :~ ['address' s+(crip "0x{((x-co:co 20) address)}")] - ['nonce' (numb:enjs:format nonce)] - == + %- molt + ^- (list [@t json]) + :~ ['dominion' s+dominion.point] + :: + :- 'ownership' + :- %o + %- molt + =* own own.point + ^- (list [@t json]) + :~ ['owner' (own-to-json owner.own)] + ['spawnProxy' (own-to-json spawn-proxy.own)] + ['managementProxy' (own-to-json management-proxy.own)] + ['votingProxy' (own-to-json voting-proxy.own)] + ['transferProxy' (own-to-json transfer-proxy.own)] + == + :: + :- 'network' + :- %o + =, enjs:format + %- molt ^- (list [@t json]) + =* net net.point + :* ['rift' (numb rift.net)] + :: + :- 'keys' + :- %o + %- molt ^- (list [@t json]) + :~ ['life' (numb life.keys.net)] + ['suite' (numb suite.keys.net)] + ['auth' (numb auth.keys.net)] + ['crypt' (numb crypt.keys.net)] + == + :: + ['rift' (numb rift.net)] + :- 'sponsor' + :- %o + %- molt ^- (list [@t json]) + ~[['has' b+has.sponsor.net] ['who' (ship who.sponsor.net)]] + :: + ?~ escape.net ~ + ['escape' (ship u.escape.net)]~ + == == + :: + ++ own-to-json + |= [=address:naive =nonce:naive] + ^- json + :- %o + %- molt ^- (list [@t json]) + :~ ['address' s+(crip "0x{((x-co:co 20) address)}")] + ['nonce' (numb:enjs:format nonce)] + == + -- + :: + ++ to-hex + |= =cord + ^- (unit @ux) + =/ parsed=(unit (pair @ud @ux)) (de:base16:mimes:html cord) + ?~ parsed + ::~|(%non-hex-cord !!) + ~ + (some q.u.parsed) + :: + ++ sponsor-call + |= [id=@t params=(map @t json)] + ?. =((lent ~(tap by params)) 3) + [~ [%error id 'X' 'Params missing']] + ?> =((lent ~(tap by params)) 3) + =/ sig=(unit @) (sig:extract params) + =/ from=(unit [ship @t]) (from:extract params) + =/ data=(unit [@ux ship]) (address-ship:extract params) + ?. &(?=(^ sig) ?=(^ from) ?=(^ data)) + + [~ [%error id 'X' 'Failed to parsed']] + :_ [%result id s+'ok'] + %- some + noun+!>([u.sig u.from u.data]) + :: + ++ proxy-call + |= [id=@t params=(map @t json)] + ^- [(unit cage) response:rpc] + ?. =((lent ~(tap by params)) 3) + [~ [%error id 'X' 'Params missing']] + =/ sig=(unit @) (sig:extract params) + =/ from=(unit [ship @t]) (from:extract params) + =/ data=(unit @ux) (address:extract params) + ?. &(?=(^ sig) ?=(^ from) ?=(^ data)) + [~ [%error id 'X' 'Failed to parsed']] + :_ [%result id s+'ok'] + %- some + noun+!>([u.sig u.from u.data]) -- --- \ No newline at end of file +|% +:: TODO: move error handling to separate core +:: +++ get-point + |= [id=@t params=(map @t json) scry=$-(ship (unit point:naive))] + ^- response:rpc + ?. =((lent ~(tap by params)) 1) + [%error id 'X' 'Params missing'] + ?~ ship=(~(get by params) 'ship') + [%error id 'X' 'A "ship" key must exist'] + ?~ ship=(rush (so:dejs:format u.ship) ;~(pfix sig fed:ag)) + [%error id 'X' 'Ship @p invalid'] + ?~ point=(scry u.ship) + [%error id 'X' 'Ship @p not found'] + [%result id (point-to-json u.point)] +:: +++ transfer-point + |= [id=@t params=(map @t json)] + ^- [(unit cage) response:rpc] + ?. =((lent ~(tap by params)) 3) + [~ [%error id 'X' 'Params missing']] + =/ sig=(unit @) (sig:extract params) + =/ from=(unit [ship @t]) (from:extract params) + =/ data=(unit [@ux ?]) + ?~ data=(~(get by params) 'data') ~ + =, dejs:format + =; [add=(unit @ux) r=?] + ?~ add ~ + (some [u.add r]) + %. u.data + %- ot + ~[['address' (cu to-hex so)] ['reset' bo]] + ?. &(?=(^ sig) ?=(^ from) ?=(^ data)) + [~ [%error id 'X' 'Failed to parsed']] + :_ [%result id s+'ok'] + %- some + noun+!>([u.sig u.from u.data]) +:: +++ configure-keys + |= [id=@t params=(map @t json)] + ^- [(unit cage) response:rpc] + ?. =((lent ~(tap by params)) 3) + [~ [%error id 'X' 'Params missing']] + =/ sig=(unit @) (sig:extract params) + =/ from=(unit [ship @t]) (from:extract params) + =/ data=(unit [encrypt=@ auth=@ crypto-suite=@ breach=?]) + (keys:extract params) + ?. &(?=(^ sig) ?=(^ from) ?=(^ data)) + [~ [%error id 'X' 'Failed to parsed']] + :_ [%result id s+'ok'] + %- some + noun+!>([u.sig u.from u.data]) +:: +++ spawn sponsor-call +++ escape sponsor-call +++ cancel-escape sponsor-call +++ adopt sponsor-call +++ detach sponsor-call +++ reject sponsor-call +++ management-proxy proxy-call +++ spawn-proxy proxy-call +++ transfer-proxy proxy-call +-- From 0380d1873558bc85755509f52c0c85c8e7fe0a67 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Tue, 4 May 2021 10:08:44 +0200 Subject: [PATCH 11/21] naive: add rpc response error codes --- pkg/arvo/app/azimuth-rpc.hoon | 8 +-- pkg/arvo/lib/azimuth-rpc.hoon | 94 ++++++++++++++++++++--------------- pkg/arvo/lib/json/rpc.hoon | 14 ++++-- 3 files changed, 66 insertions(+), 50 deletions(-) diff --git a/pkg/arvo/app/azimuth-rpc.hoon b/pkg/arvo/app/azimuth-rpc.hoon index 911d3abf6..135827dbc 100644 --- a/pkg/arvo/app/azimuth-rpc.hoon +++ b/pkg/arvo/app/azimuth-rpc.hoon @@ -121,10 +121,10 @@ :- data %- json-response:gen (response-to-json:json-rpc response) - ?. ?=([%map *] params) - [~ [%error id 'X' 'RPC params must be an object']] =, azimuth-rpc - ?+ method [~ [%error id 'X' 'Unsupported Azimuth RPC']] + ?. ?=([%map *] params) + [~ ~(parse error id)] + ?+ method [~ ~(method error id)] %get-point [~ (get-point id +.params scry-point)] %transfer-point (transfer-point id +.params) %configure-keys (configure-keys id +.params) @@ -136,7 +136,7 @@ %reject (reject id +.params) %set-management-proxy (management-proxy id +.params) %set-spawn-proxy (spawn-proxy id +.params) - %set-transfer-proxy (transfer-proxy id +.params) + %set-transfer-proxy (transfer-proxy id +.params) == :: ++ scry-point diff --git a/pkg/arvo/lib/azimuth-rpc.hoon b/pkg/arvo/lib/azimuth-rpc.hoon index e9a58fc56..3045658ed 100644 --- a/pkg/arvo/lib/azimuth-rpc.hoon +++ b/pkg/arvo/lib/azimuth-rpc.hoon @@ -12,9 +12,8 @@ |= params=(map @t json) ^- (unit [encrypt=@ auth=@ crypto-suite=@ breach=?]) ?~ data=(~(get by params) 'data') ~ - =, dejs:format - %- some %. u.data + =, dejs-soft:format %- ot :~ ['encrypt' so] ['auth' so] @@ -26,11 +25,12 @@ |= params=(map @t json) ^- (unit [@ux ship]) ?~ data=(~(get by params) 'data') ~ - =, dejs:format - =; [add=(unit @ux) =ship] - ?~ add ~ - (some [u.add ship]) + =; ans=(unit [add=(unit @ux) =ship]) + ?~ ans ~ + ?~ add.u.ans ~ + (some [u.add.u.ans ship.u.ans]) %. u.data + =, dejs-soft:format %- ot :~ ['address' (cu to-hex so)] ['ship' (su ;~(pfix sig fed:ag))] @@ -40,22 +40,26 @@ |= params=(map @t json) ^- (unit @ux) ?~ data=(~(get by params) 'data') ~ - =, dejs:format + =; ans=(unit (unit @ux)) + ?~ ans ~ + ?~ u.ans ~ + (some u.u.ans) + =, dejs-soft:format %. u.data (ot ['address' (cu to-hex so)]~) - :: + :: ++ sig |= params=(map @t json) ^- (unit @) + =, dejs-soft:format ?~ sig=(~(get by params) 'sig') ~ - (some (so:dejs:format u.sig)) + (so:dejs-soft:format u.sig) :: ++ from |= params=(map @t json) ^- (unit [ship @t]) ?~ from=(~(get by params) 'from') ~ - %- some - =, dejs:format + =, dejs-soft:format %. u.from %- ot :~ ['ship' (su ;~(pfix sig fed:ag))] @@ -131,15 +135,14 @@ :: ++ sponsor-call |= [id=@t params=(map @t json)] - ?. =((lent ~(tap by params)) 3) - [~ [%error id 'X' 'Params missing']] - ?> =((lent ~(tap by params)) 3) + ^- [(unit cage) response:rpc] + ?. =((lent ~(tap by params)) 3) + [~ ~(params error id)] =/ sig=(unit @) (sig:extract params) =/ from=(unit [ship @t]) (from:extract params) =/ data=(unit [@ux ship]) (address-ship:extract params) - ?. &(?=(^ sig) ?=(^ from) ?=(^ data)) - - [~ [%error id 'X' 'Failed to parsed']] + ?. &(?=(^ sig) ?=(^ from) ?=(^ data)) + [~ ~(parse error id)] :_ [%result id s+'ok'] %- some noun+!>([u.sig u.from u.data]) @@ -147,51 +150,60 @@ ++ proxy-call |= [id=@t params=(map @t json)] ^- [(unit cage) response:rpc] - ?. =((lent ~(tap by params)) 3) - [~ [%error id 'X' 'Params missing']] + ?. =((lent ~(tap by params)) 3) + [~ ~(params error id)] =/ sig=(unit @) (sig:extract params) =/ from=(unit [ship @t]) (from:extract params) =/ data=(unit @ux) (address:extract params) - ?. &(?=(^ sig) ?=(^ from) ?=(^ data)) - [~ [%error id 'X' 'Failed to parsed']] + ?. &(?=(^ sig) ?=(^ from) ?=(^ data)) + [~ ~(parse error id)] :_ [%result id s+'ok'] %- some noun+!>([u.sig u.from u.data]) + :: + ++ error + |_ id=@t + :: https://www.jsonrpc.org/specification#error_object + :: + ++ parse [%error id '-32700' 'Failed to parsed'] + ++ request [%error id '-32600' 'Invalid Request'] + ++ method [%error id '-32601' 'Method not found'] + ++ params [%error id '-32602' 'Invalid params'] + ++ internal [%error id '-32603' 'Internal error'] + -- -- |% -:: TODO: move error handling to separate core -:: ++ get-point |= [id=@t params=(map @t json) scry=$-(ship (unit point:naive))] ^- response:rpc - ?. =((lent ~(tap by params)) 1) - [%error id 'X' 'Params missing'] - ?~ ship=(~(get by params) 'ship') - [%error id 'X' 'A "ship" key must exist'] + ?. =((lent ~(tap by params)) 1) + ~(params error id) + ?~ ship=(~(get by params) 'ship') + ~(params error id) ?~ ship=(rush (so:dejs:format u.ship) ;~(pfix sig fed:ag)) - [%error id 'X' 'Ship @p invalid'] - ?~ point=(scry u.ship) - [%error id 'X' 'Ship @p not found'] + ~(params error id) + ?~ point=(scry u.ship) + ~(params error id) [%result id (point-to-json u.point)] :: ++ transfer-point |= [id=@t params=(map @t json)] ^- [(unit cage) response:rpc] - ?. =((lent ~(tap by params)) 3) - [~ [%error id 'X' 'Params missing']] - =/ sig=(unit @) (sig:extract params) - =/ from=(unit [ship @t]) (from:extract params) + ?. =((lent ~(tap by params)) 3) + [~ ~(params error id)] + =/ sig=(unit @) (sig:extract params) + =/ from=(unit [ship @t]) (from:extract params) =/ data=(unit [@ux ?]) ?~ data=(~(get by params) 'data') ~ - =, dejs:format =; [add=(unit @ux) r=?] ?~ add ~ (some [u.add r]) %. u.data + =, dejs:format %- ot ~[['address' (cu to-hex so)] ['reset' bo]] - ?. &(?=(^ sig) ?=(^ from) ?=(^ data)) - [~ [%error id 'X' 'Failed to parsed']] + ?: |(?=(~ sig) ?=(~ from) ?=(~ data)) + [~ ~(parse error id)] :_ [%result id s+'ok'] %- some noun+!>([u.sig u.from u.data]) @@ -199,14 +211,14 @@ ++ configure-keys |= [id=@t params=(map @t json)] ^- [(unit cage) response:rpc] - ?. =((lent ~(tap by params)) 3) - [~ [%error id 'X' 'Params missing']] + ?. =((lent ~(tap by params)) 3) + [~ ~(params error id)] =/ sig=(unit @) (sig:extract params) =/ from=(unit [ship @t]) (from:extract params) =/ data=(unit [encrypt=@ auth=@ crypto-suite=@ breach=?]) (keys:extract params) - ?. &(?=(^ sig) ?=(^ from) ?=(^ data)) - [~ [%error id 'X' 'Failed to parsed']] + ?. &(?=(^ sig) ?=(^ from) ?=(^ data)) + [~ ~(parse error id)] :_ [%result id s+'ok'] %- some noun+!>([u.sig u.from u.data]) diff --git a/pkg/arvo/lib/json/rpc.hoon b/pkg/arvo/lib/json/rpc.hoon index 22d4d9536..97543c704 100644 --- a/pkg/arvo/lib/json/rpc.hoon +++ b/pkg/arvo/lib/json/rpc.hoon @@ -39,16 +39,20 @@ :- %o %- molt ^- (list [@t json]) - ~[['id' s+id.response] ['res' res.response]] + :: FIXME: return 'id' as string, number or NULL + :: + :~ ['jsonrpc' s+'2.0'] + ['id' s+id.response] + ['res' res.response] + == :: %error :- %o %- molt ^- (list [@t json]) - :~ :: FIXME: return 'id' as string, number or NULL - :: - ['id' s+id.response] - ['code' s+code.response] + :~ ['jsonrpc' s+'2.0'] + ['id' ?~(id.response ~ s+id.response)] + ['code' n+code.response] ['message' s+message.response] == == From 00334d582eeaa604e2fa2a5921708c9eb89a8b91 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Tue, 4 May 2021 10:36:50 +0200 Subject: [PATCH 12/21] naive: use +pairs:enjs for point-to-json reponse --- pkg/arvo/lib/azimuth-rpc.hoon | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/pkg/arvo/lib/azimuth-rpc.hoon b/pkg/arvo/lib/azimuth-rpc.hoon index 3045658ed..7ad8763df 100644 --- a/pkg/arvo/lib/azimuth-rpc.hoon +++ b/pkg/arvo/lib/azimuth-rpc.hoon @@ -70,15 +70,13 @@ ++ point-to-json |= =point:naive ^- json + =, enjs:format |^ - :- %o - %- molt - ^- (list [@t json]) + %- pairs :~ ['dominion' s+dominion.point] :: :- 'ownership' - :- %o - %- molt + %- pairs =* own own.point ^- (list [@t json]) :~ ['owner' (own-to-json owner.own)] @@ -89,15 +87,12 @@ == :: :- 'network' - :- %o - =, enjs:format - %- molt ^- (list [@t json]) + %- pairs =* net net.point :* ['rift' (numb rift.net)] :: :- 'keys' - :- %o - %- molt ^- (list [@t json]) + %- pairs :~ ['life' (numb life.keys.net)] ['suite' (numb suite.keys.net)] ['auth' (numb auth.keys.net)] @@ -106,8 +101,7 @@ :: ['rift' (numb rift.net)] :- 'sponsor' - :- %o - %- molt ^- (list [@t json]) + %- pairs ~[['has' b+has.sponsor.net] ['who' (ship who.sponsor.net)]] :: ?~ escape.net ~ @@ -117,8 +111,7 @@ ++ own-to-json |= [=address:naive =nonce:naive] ^- json - :- %o - %- molt ^- (list [@t json]) + %- pairs :~ ['address' s+(crip "0x{((x-co:co 20) address)}")] ['nonce' (numb:enjs:format nonce)] == From c150da0372d7bb21c2ccc7182ecbb1b5fffa715e Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Thu, 6 May 2021 08:14:04 +0200 Subject: [PATCH 13/21] naive: validate proxy in from is one of proxy:naive --- pkg/arvo/lib/azimuth-rpc.hoon | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/arvo/lib/azimuth-rpc.hoon b/pkg/arvo/lib/azimuth-rpc.hoon index 7ad8763df..5c62f61c1 100644 --- a/pkg/arvo/lib/azimuth-rpc.hoon +++ b/pkg/arvo/lib/azimuth-rpc.hoon @@ -57,13 +57,13 @@ :: ++ from |= params=(map @t json) - ^- (unit [ship @t]) + ^- (unit [ship proxy:naive]) ?~ from=(~(get by params) 'from') ~ =, dejs-soft:format %. u.from %- ot :~ ['ship' (su ;~(pfix sig fed:ag))] - ['proxy' so] + ['proxy' (cu proxy:naive so)] == -- :: From 66d0c7d47b52d3607731763f84a066cbfce3be33 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Thu, 6 May 2021 08:22:08 +0200 Subject: [PATCH 14/21] naive: handle malformed data in transfer-point --- pkg/arvo/lib/azimuth-rpc.hoon | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/pkg/arvo/lib/azimuth-rpc.hoon b/pkg/arvo/lib/azimuth-rpc.hoon index 5c62f61c1..960aaac05 100644 --- a/pkg/arvo/lib/azimuth-rpc.hoon +++ b/pkg/arvo/lib/azimuth-rpc.hoon @@ -21,6 +21,19 @@ ['breach' bo] == :: + ++ address-transfer + |= params=(map @t json) + ^- (unit [@ux ?]) + ?~ data=(~(get by params) 'data') ~ + =; ans=(unit [add=(unit @ux) r=?]) + ?~ ans ~ + ?~ add.u.ans ~ + (some [u.add.u.ans r.u.ans]) + %. u.data + =, dejs-soft:format + %- ot + ~[['address' (cu to-hex so)] ['reset' bo]] + :: ++ address-ship |= params=(map @t json) ^- (unit [@ux ship]) @@ -186,15 +199,7 @@ [~ ~(params error id)] =/ sig=(unit @) (sig:extract params) =/ from=(unit [ship @t]) (from:extract params) - =/ data=(unit [@ux ?]) - ?~ data=(~(get by params) 'data') ~ - =; [add=(unit @ux) r=?] - ?~ add ~ - (some [u.add r]) - %. u.data - =, dejs:format - %- ot - ~[['address' (cu to-hex so)] ['reset' bo]] + =/ data=(unit [@ux ?]) (address-transfer:extract params) ?: |(?=(~ sig) ?=(~ from) ?=(~ data)) [~ ~(parse error id)] :_ [%result id s+'ok'] From ae8d98c467e08c8cf4059f3c29f1e14ce882ec13 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Thu, 6 May 2021 13:20:13 +0200 Subject: [PATCH 15/21] naive: add jsonrpc parsing for sending pending rolls --- pkg/arvo/app/azimuth-rpc.hoon | 27 ++++++- pkg/arvo/lib/azimuth-rpc.hoon | 136 ++++++++++++++++++++++++++++++---- 2 files changed, 147 insertions(+), 16 deletions(-) diff --git a/pkg/arvo/app/azimuth-rpc.hoon b/pkg/arvo/app/azimuth-rpc.hoon index 135827dbc..7eb82ccca 100644 --- a/pkg/arvo/app/azimuth-rpc.hoon +++ b/pkg/arvo/app/azimuth-rpc.hoon @@ -136,7 +136,10 @@ %reject (reject id +.params) %set-management-proxy (management-proxy id +.params) %set-spawn-proxy (spawn-proxy id +.params) - %set-transfer-proxy (transfer-proxy id +.params) + %set-transfer-proxy (transfer-proxy id +.params) + %pending (pending id +.params all:pending-rolls) + %pending-by-ship (pending-ship id +.params ship:pending-rolls) + %pending-by-address (pending-address id +.params addr:pending-rolls) == :: ++ scry-point @@ -145,4 +148,26 @@ %gx (~(scry agentio bowl) %azimuth /nas/[(scot %p ship)]/noun) == +:: +++ pending-rolls + |% + ++ all + .^ (list tx:naive) + %gx + (~(scry agentio bowl) %dice /pending/all/noun) + == + ++ ship + |= =^ship + .^ (list tx:naive) + %gx + (~(scry agentio bowl) %dice /pending/ship/[(scot %p ship)]/noun) + == + ++ addr + |= =address:naive + .^ (list tx:naive) + %gx + %+ ~(scry agentio bowl) %dice + /pending/address/[(scot %ux address)]/noun + == + -- -- diff --git a/pkg/arvo/lib/azimuth-rpc.hoon b/pkg/arvo/lib/azimuth-rpc.hoon index 960aaac05..a9af00cb2 100644 --- a/pkg/arvo/lib/azimuth-rpc.hoon +++ b/pkg/arvo/lib/azimuth-rpc.hoon @@ -36,9 +36,9 @@ :: ++ address-ship |= params=(map @t json) - ^- (unit [@ux ship]) + ^- (unit [@ux @p]) ?~ data=(~(get by params) 'data') ~ - =; ans=(unit [add=(unit @ux) =ship]) + =; ans=(unit [add=(unit @ux) ship=@p]) ?~ ans ~ ?~ add.u.ans ~ (some [u.add.u.ans ship.u.ans]) @@ -60,7 +60,15 @@ =, dejs-soft:format %. u.data (ot ['address' (cu to-hex so)]~) - :: + :: + ++ ship + |= params=(map @t json) + ^- (unit @p) + ?~ data=(~(get by params) 'data') ~ + =, dejs-soft:format + %. u.data + (ot ['ship' (su ;~(pfix sig fed:ag))]~) + :: ++ sig |= params=(map @t json) ^- (unit @) @@ -70,7 +78,7 @@ :: ++ from |= params=(map @t json) - ^- (unit [ship proxy:naive]) + ^- (unit [@p proxy:naive]) ?~ from=(~(get by params) 'from') ~ =, dejs-soft:format %. u.from @@ -80,6 +88,60 @@ == -- :: + ++ pending-to-json + |= pending=(list tx:naive) + ^- json + =, enjs:format + :- %a + %+ turn pending + |= =tx:naive + ^- json + |^ + =, enjs:format + %- pairs + :~ ['tx' (parse-tx +.tx)] + :: + :- 'from' + %- pairs + ~[['ship' (ship ship.from.tx)] ['proxy' s+proxy.from.tx]] + == + :: + ++ parse-tx + |= tx=skim-tx:naive + ^- json + %- pairs + :~ ['type' s+-.tx] + :: + :- 'data' + %- pairs + ?- -.tx + %transfer-point (en-transfer +.tx) + %spawn (en-spawn +.tx) + %configure-keys (en-keys +.tx) + %escape ~[(en-ship parent.tx)] + %cancel-escape ~[(en-ship parent.tx)] + %adopt ~[(en-ship ship.tx)] + %reject ~[(en-ship ship.tx)] + %detach ~[(en-ship ship.tx)] + %set-management-proxy ~[(en-address address.tx)] + %set-spawn-proxy ~[(en-address address.tx)] + %set-transfer-proxy ~[(en-address address.tx)] + == == + :: + ++ en-ship |=(s=@p ship+(ship s)) + ++ en-address |=(a=@ux address+s+(crip "0x{((x-co:co 20) a)}")) + ++ en-spawn |=([s=@p a=@ux] ~[(en-ship s) (en-address a)]) + ++ en-transfer |=([a=@ux r=?] ~[(en-address a) reset+b+r]) + ++ en-keys + |= [encrypt=@ auth=@ crypto-suite=@ breach=?] + ^- (list [@t json]) + :~ ['encrypt' (numb encrypt)] + ['auth' (numb auth)] + ['crypto-suite' (numb crypto-suite)] + ['breach' b+breach] + == + -- + :: ++ point-to-json |= =point:naive ^- json @@ -144,9 +206,9 @@ ^- [(unit cage) response:rpc] ?. =((lent ~(tap by params)) 3) [~ ~(params error id)] - =/ sig=(unit @) (sig:extract params) - =/ from=(unit [ship @t]) (from:extract params) - =/ data=(unit [@ux ship]) (address-ship:extract params) + =/ sig=(unit @) (sig:extract params) + =/ from=(unit [@p proxy:naive]) (from:extract params) + =/ data=(unit [@ux @p]) (address-ship:extract params) ?. &(?=(^ sig) ?=(^ from) ?=(^ data)) [~ ~(parse error id)] :_ [%result id s+'ok'] @@ -158,9 +220,9 @@ ^- [(unit cage) response:rpc] ?. =((lent ~(tap by params)) 3) [~ ~(params error id)] - =/ sig=(unit @) (sig:extract params) - =/ from=(unit [ship @t]) (from:extract params) - =/ data=(unit @ux) (address:extract params) + =/ sig=(unit @) (sig:extract params) + =/ from=(unit [@p proxy:naive]) (from:extract params) + =/ data=(unit @ux) (address:extract params) ?. &(?=(^ sig) ?=(^ from) ?=(^ data)) [~ ~(parse error id)] :_ [%result id s+'ok'] @@ -171,11 +233,12 @@ |_ id=@t :: https://www.jsonrpc.org/specification#error_object :: - ++ parse [%error id '-32700' 'Failed to parsed'] - ++ request [%error id '-32600' 'Invalid Request'] - ++ method [%error id '-32601' 'Method not found'] - ++ params [%error id '-32602' 'Invalid params'] - ++ internal [%error id '-32603' 'Internal error'] + ++ parse [%error id '-32700' 'Failed to parsed'] + ++ request [%error id '-32600' 'Invalid Request'] + ++ method [%error id '-32601' 'Method not found'] + ++ params [%error id '-32602' 'Invalid params'] + ++ internal [%error id '-32603' 'Internal error'] + ++ not-found [%error id '-32000' 'Resource not found'] -- -- |% @@ -230,4 +293,47 @@ ++ management-proxy proxy-call ++ spawn-proxy proxy-call ++ transfer-proxy proxy-call +:: - readNonce(from=[ship proxy]) -> @ :: automatically increment for pending wraps +:: +++ read-nonce + |= [id=@t params=(map @t json) scry=$-([ship proxy:naive] (unit @))] + ^- response:rpc + ?. =((lent ~(tap by params)) 3) + ~(params error id) + ?~ from=(from:extract params) + ~(parse error id) + ?~ nonce=(scry u.from) + ~(params error id) + [%result id (numb:enjs:format u.nonce)] +:: +:: - readPendingRoll() -> (list tx) +:: +++ pending + |= [id=@t params=(map @t json) pending=(list tx:naive)] + ^- response:rpc + ?. =((lent ~(tap by params)) 0) + ~(params error id) + [%result id (pending-to-json pending)] +:: +:: - readPendingByShip(ship) -> (list tx) +:: +++ pending-by-ship + |= [id=@t params=(map @t json) scry=$-(ship (list tx:naive))] + ^- response:rpc + ?. =((lent ~(tap by params)) 1) + ~(params error id) + ?~ ship=(ship:extract params) + ~(parse error id) + [%result id (pending-to-json (scry u.ship))] +:: +:: - readPendingByAddress(address) -> (list tx) +:: +++ pending-by-address + |= [id=@t params=(map @t json) scry=$-(@ux (list tx:naive))] + ^- response:rpc + ?. =((lent ~(tap by params)) 1) + ~(params error id) + ?~ address=(address:extract params) + ~(parse error id) + [%result id (pending-to-json (scry u.address))] -- From 7ede24c3ccbf429d1db06f1ee5b5a206c6725e95 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Thu, 6 May 2021 16:47:38 +0200 Subject: [PATCH 16/21] naive: first pass at tx history RPC --- pkg/arvo/app/azimuth-rpc.hoon | 19 +++++++-- pkg/arvo/lib/azimuth-rpc.hoon | 74 +++++++++++++++++++++++------------ 2 files changed, 65 insertions(+), 28 deletions(-) diff --git a/pkg/arvo/app/azimuth-rpc.hoon b/pkg/arvo/app/azimuth-rpc.hoon index 7eb82ccca..80a8ceb5a 100644 --- a/pkg/arvo/app/azimuth-rpc.hoon +++ b/pkg/arvo/app/azimuth-rpc.hoon @@ -137,9 +137,10 @@ %set-management-proxy (management-proxy id +.params) %set-spawn-proxy (spawn-proxy id +.params) %set-transfer-proxy (transfer-proxy id +.params) - %pending (pending id +.params all:pending-rolls) - %pending-by-ship (pending-ship id +.params ship:pending-rolls) - %pending-by-address (pending-address id +.params addr:pending-rolls) + %pending [~ (all:pending id +.params all:pending-rolls)] + %pending-by-ship [~ (ship:pending id +.params ship:pending-rolls)] + %pending-by-address [~ (addr:pending id +.params addr:pending-rolls)] + %history [~ (history id +.params scry-history)] == :: ++ scry-point @@ -149,7 +150,7 @@ (~(scry agentio bowl) %azimuth /nas/[(scot %p ship)]/noun) == :: -++ pending-rolls +++ pending-rolls |% ++ all .^ (list tx:naive) @@ -170,4 +171,14 @@ /pending/address/[(scot %ux address)]/noun == -- +:: +++ scry-history + |= [=ship =proxy:naive] + :: FIXME: use proper type from aggregator/index + :: + .^ (list [tx:naive ?]) + %gx + %+ ~(scry agentio bowl) %dice + /history/[(scot %p ship)]/proxy/noun + == -- diff --git a/pkg/arvo/lib/azimuth-rpc.hoon b/pkg/arvo/lib/azimuth-rpc.hoon index a9af00cb2..dbb30511b 100644 --- a/pkg/arvo/lib/azimuth-rpc.hoon +++ b/pkg/arvo/lib/azimuth-rpc.hoon @@ -192,6 +192,13 @@ == -- :: + ++ txs-to-json + :: TODO: implement me! + :: + |= txs=(list [tx:naive success=?]) + ^- json + ~ + :: ++ to-hex |= =cord ^- (unit @ux) @@ -306,34 +313,53 @@ ~(params error id) [%result id (numb:enjs:format u.nonce)] :: -:: - readPendingRoll() -> (list tx) -:: ++ pending - |= [id=@t params=(map @t json) pending=(list tx:naive)] - ^- response:rpc - ?. =((lent ~(tap by params)) 0) - ~(params error id) - [%result id (pending-to-json pending)] + :: FIXME: send raw-tx (i.e. tx with signature) instead? + :: + |% + :: - readPendingRoll() -> (list tx) + :: + ++ all + |= [id=@t params=(map @t json) pending=(list tx:naive)] + ^- response:rpc + ?. =((lent ~(tap by params)) 0) + ~(params error id) + [%result id (pending-to-json pending)] + :: + :: - readPendingByShip(ship) -> (list tx) + :: + ++ ship + |= [id=@t params=(map @t json) scry=$-(@p (list tx:naive))] + ^- response:rpc + ?. =((lent ~(tap by params)) 1) + ~(params error id) + ?~ ship=(ship:extract params) + ~(parse error id) + [%result id (pending-to-json (scry u.ship))] + :: + :: - readPendingByAddress(address) -> (list tx) + :: + ++ addr + |= [id=@t params=(map @t json) scry=$-(@ux (list tx:naive))] + ^- response:rpc + ?. =((lent ~(tap by params)) 1) + ~(params error id) + ?~ address=(address:extract params) + ~(parse error id) + [%result id (pending-to-json (scry u.address))] + -- :: -:: - readPendingByShip(ship) -> (list tx) -:: -++ pending-by-ship - |= [id=@t params=(map @t json) scry=$-(ship (list tx:naive))] +++ history + |= $: id=@t + params=(map @t json) + :: FIXME: use proper type from aggregator/index + :: + scry=$-([@p proxy:naive] (list [tx:naive success=?])) + == ^- response:rpc ?. =((lent ~(tap by params)) 1) ~(params error id) - ?~ ship=(ship:extract params) + ?~ from=(from:extract params) ~(parse error id) - [%result id (pending-to-json (scry u.ship))] -:: -:: - readPendingByAddress(address) -> (list tx) -:: -++ pending-by-address - |= [id=@t params=(map @t json) scry=$-(@ux (list tx:naive))] - ^- response:rpc - ?. =((lent ~(tap by params)) 1) - ~(params error id) - ?~ address=(address:extract params) - ~(parse error id) - [%result id (pending-to-json (scry u.address))] + [%result id (txs-to-json (scry u.from))] -- From 8ebb5e2d6ce6a25345f5c795b27b44664b8b3e25 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Tue, 11 May 2021 13:28:26 +0200 Subject: [PATCH 17/21] naive: add pending and tx status RPCs --- pkg/arvo/app/azimuth-rpc.hoon | 127 ++++++++---- pkg/arvo/lib/azimuth-rpc.hoon | 379 +++++++++++++++++++--------------- 2 files changed, 304 insertions(+), 202 deletions(-) diff --git a/pkg/arvo/app/azimuth-rpc.hoon b/pkg/arvo/app/azimuth-rpc.hoon index 80a8ceb5a..88a2e3fd1 100644 --- a/pkg/arvo/app/azimuth-rpc.hoon +++ b/pkg/arvo/app/azimuth-rpc.hoon @@ -1,4 +1,4 @@ -:: Azimuth RPC API +:: Azimuth JSON-RPC API :: /- rpc=json-rpc /+ naive, @@ -11,6 +11,15 @@ version, agentio |% +:: FIXME: import tx-status, pend-tx from aggregator +:: ++$ tx-status + $: status=?(%unknown %pending %sent %confirmed %failed) + tx=(unit @ux) + == +:: ++$ pend-tx [force=? =raw-tx:naive] +:: +$ card card:agent:gall :: +$ state-0 [%0 ~] @@ -125,7 +134,7 @@ ?. ?=([%map *] params) [~ ~(parse error id)] ?+ method [~ ~(method error id)] - %get-point [~ (get-point id +.params scry-point)] + %get-point [~ (get-point id +.params point:scry)] %transfer-point (transfer-point id +.params) %configure-keys (configure-keys id +.params) %spawn (spawn id +.params) @@ -137,48 +146,90 @@ %set-management-proxy (management-proxy id +.params) %set-spawn-proxy (spawn-proxy id +.params) %set-transfer-proxy (transfer-proxy id +.params) - %pending [~ (all:pending id +.params all:pending-rolls)] - %pending-by-ship [~ (ship:pending id +.params ship:pending-rolls)] - %pending-by-address [~ (addr:pending id +.params addr:pending-rolls)] - %history [~ (history id +.params scry-history)] + %pending [~ (all:pending id +.params all:pending:scry)] + %pending-by-ship [~ (ship:pending id +.params ship:pending:scry)] + %pending-by-address [~ (addr:pending id +.params addr:pending:scry)] + %status [~ (status id +.params tx-status:scry)] + :: %history [~ (history id +.params all:history:scry)] == :: -++ scry-point - |= =ship - .^ (unit point:naive) - %gx - (~(scry agentio bowl) %azimuth /nas/[(scot %p ship)]/noun) - == -:: -++ pending-rolls +++ scry |% - ++ all - .^ (list tx:naive) - %gx - (~(scry agentio bowl) %dice /pending/all/noun) - == - ++ ship - |= =^ship - .^ (list tx:naive) + ++ point + |= =ship + .^ (unit point:naive) %gx - (~(scry agentio bowl) %dice /pending/ship/[(scot %p ship)]/noun) + (~(scry agentio bowl) %azimuth /nas/[(scot %p ship)]/noun) == - ++ addr - |= =address:naive - .^ (list tx:naive) + :: + ++ pending + |% + ++ all + .^ (list pend-tx) + %gx + (~(scry agentio bowl) %dice /pending/noun) + == + :: + ++ ship + |= =^ship + .^ (list pend-tx) + %gx + (~(scry agentio bowl) %dice /pending/[(scot %p ship)]/noun) + == + :: + ++ addr + |= =address:naive + .^ (list pend-tx) + %gx + %+ ~(scry agentio bowl) %dice + /pending/[(scot %ux address)]/noun + == + -- + :: + ++ history + |% + ++ all + :: FIXME: use proper type from aggregator/index + :: + .^ (list tx:naive) + %gx + (~(scry agentio bowl) %dice /history/noun) + == + :: + ++ ship + |= =^ship + :: FIXME: use proper type from aggregator/index + :: + .^ (list tx:naive) + %gx + (~(scry agentio bowl) %dice /history/[(scot %p ship)]/noun) + == + :: + ++ addr + |= =address:naive + :: FIXME: use proper type from aggregator/index + :: + .^ (list tx:naive) + %gx + (~(scry agentio bowl) %dice /history/[(scot %ux address)]/noun) + == + -- + :: + ++ tx-status + |= keccak=@ux + .^ ^tx-status %gx - %+ ~(scry agentio bowl) %dice - /pending/address/[(scot %ux address)]/noun + (~(scry agentio bowl) %dice /tx/[(scot %ux keccak)]/status/noun) + == + :: + ++ nonce + |= [=ship =address:naive] + :: FIXME: use proper type from aggregator/index + .^ @ + %gx + %+ ~(scry agentio bowl) + %dice + /nonce/[(scot %p ship)]/[(scot %ux address)]/atom == -- -:: -++ scry-history - |= [=ship =proxy:naive] - :: FIXME: use proper type from aggregator/index - :: - .^ (list [tx:naive ?]) - %gx - %+ ~(scry agentio bowl) %dice - /history/[(scot %p ship)]/proxy/noun - == -- diff --git a/pkg/arvo/lib/azimuth-rpc.hoon b/pkg/arvo/lib/azimuth-rpc.hoon index dbb30511b..9c20de491 100644 --- a/pkg/arvo/lib/azimuth-rpc.hoon +++ b/pkg/arvo/lib/azimuth-rpc.hoon @@ -6,7 +6,16 @@ => :: Utilities :: |% - ++ extract + :: FIXME: import tx-status, pend-tx from aggregator + :: + +$ tx-status + $: status=?(%unknown %pending %sent %confirmed %failed) + tx=(unit @ux) + == + :: + +$ pend-tx [force=? =raw-tx:naive] + :: + ++ from-json |% ++ keys |= params=(map @t json) @@ -54,9 +63,7 @@ ^- (unit @ux) ?~ data=(~(get by params) 'data') ~ =; ans=(unit (unit @ux)) - ?~ ans ~ - ?~ u.ans ~ - (some u.u.ans) + ?~(ans ~ u.ans) =, dejs-soft:format %. u.data (ot ['address' (cu to-hex so)]~) @@ -72,7 +79,6 @@ ++ sig |= params=(map @t json) ^- (unit @) - =, dejs-soft:format ?~ sig=(~(get by params) 'sig') ~ (so:dejs-soft:format u.sig) :: @@ -86,119 +92,153 @@ :~ ['ship' (su ;~(pfix sig fed:ag))] ['proxy' (cu proxy:naive so)] == + :: + ++ keccak + |= params=(map @t json) + ^- (unit @ux) + ?~ keccak=(~(get by params) 'keccak') ~ + =; ans=(unit (unit @ux)) + ?~(ans ~ u.ans) + =, dejs-soft:format + ((cu to-hex so) u.keccak) -- :: - ++ pending-to-json - |= pending=(list tx:naive) - ^- json - =, enjs:format - :- %a - %+ turn pending - |= =tx:naive - ^- json - |^ - =, enjs:format - %- pairs - :~ ['tx' (parse-tx +.tx)] - :: - :- 'from' - %- pairs - ~[['ship' (ship ship.from.tx)] ['proxy' s+proxy.from.tx]] - == - :: - ++ parse-tx - |= tx=skim-tx:naive + ++ to-json + |% + ++ pending + |= pending=(list pend-tx) ^- json + =, enjs:format + :- %a + %+ turn pending + |= pend-tx + ^- json + =, enjs:format %- pairs - :~ ['type' s+-.tx] + :~ ['force' b+force] :: - :- 'data' + :- 'raw-tx' %- pairs - ?- -.tx - %transfer-point (en-transfer +.tx) - %spawn (en-spawn +.tx) - %configure-keys (en-keys +.tx) - %escape ~[(en-ship parent.tx)] - %cancel-escape ~[(en-ship parent.tx)] - %adopt ~[(en-ship ship.tx)] - %reject ~[(en-ship ship.tx)] - %detach ~[(en-ship ship.tx)] - %set-management-proxy ~[(en-address address.tx)] - %set-spawn-proxy ~[(en-address address.tx)] - %set-transfer-proxy ~[(en-address address.tx)] + :~ ['sig' (numb sig.raw-tx)] + ['tx' (tx:to-json tx.raw-tx)] == == :: - ++ en-ship |=(s=@p ship+(ship s)) - ++ en-address |=(a=@ux address+s+(crip "0x{((x-co:co 20) a)}")) - ++ en-spawn |=([s=@p a=@ux] ~[(en-ship s) (en-address a)]) - ++ en-transfer |=([a=@ux r=?] ~[(en-address a) reset+b+r]) - ++ en-keys - |= [encrypt=@ auth=@ crypto-suite=@ breach=?] - ^- (list [@t json]) - :~ ['encrypt' (numb encrypt)] - ['auth' (numb auth)] - ['crypto-suite' (numb crypto-suite)] - ['breach' b+breach] + ++ tx + |= =tx:naive + ^- json + =, enjs:format + |^ + %- pairs + :~ ['tx' (parse-tx +.tx)] + :: + :- 'from' + %- pairs + ~[['ship' (ship ship.from.tx)] ['proxy' s+proxy.from.tx]] == - -- - :: - ++ point-to-json - |= =point:naive - ^- json - =, enjs:format - |^ - %- pairs - :~ ['dominion' s+dominion.point] :: - :- 'ownership' + ++ parse-tx + |= tx=skim-tx:naive + ^- json %- pairs - =* own own.point + :~ ['type' s+-.tx] + :: + :- 'data' + %- pairs + ?- -.tx + %transfer-point (en-transfer +.tx) + %spawn (en-spawn +.tx) + %configure-keys (en-keys +.tx) + %escape ~[(en-ship parent.tx)] + %cancel-escape ~[(en-ship parent.tx)] + %adopt ~[(en-ship ship.tx)] + %reject ~[(en-ship ship.tx)] + %detach ~[(en-ship ship.tx)] + %set-management-proxy ~[(en-address address.tx)] + %set-spawn-proxy ~[(en-address address.tx)] + %set-transfer-proxy ~[(en-address address.tx)] + == == + :: + ++ en-ship |=(s=@p ship+(ship s)) + ++ en-address |=(a=@ux address+s+(crip "0x{((x-co:co 20) a)}")) + ++ en-spawn |=([s=@p a=@ux] ~[(en-ship s) (en-address a)]) + ++ en-transfer |=([a=@ux r=?] ~[(en-address a) reset+b+r]) + ++ en-keys + |= [encrypt=@ auth=@ crypto-suite=@ breach=?] ^- (list [@t json]) - :~ ['owner' (own-to-json owner.own)] - ['spawnProxy' (own-to-json spawn-proxy.own)] - ['managementProxy' (own-to-json management-proxy.own)] - ['votingProxy' (own-to-json voting-proxy.own)] - ['transferProxy' (own-to-json transfer-proxy.own)] + :~ ['encrypt' (numb encrypt)] + ['auth' (numb auth)] + ['crypto-suite' (numb crypto-suite)] + ['breach' b+breach] == - :: - :- 'network' - %- pairs - =* net net.point - :* ['rift' (numb rift.net)] - :: - :- 'keys' - %- pairs - :~ ['life' (numb life.keys.net)] - ['suite' (numb suite.keys.net)] - ['auth' (numb auth.keys.net)] - ['crypt' (numb crypt.keys.net)] - == - :: - ['rift' (numb rift.net)] - :- 'sponsor' - %- pairs - ~[['has' b+has.sponsor.net] ['who' (ship who.sponsor.net)]] - :: - ?~ escape.net ~ - ['escape' (ship u.escape.net)]~ - == == + -- + :: + ++ txs + |= txs=(list tx:naive) + ^- json + a+(turn txs |=(=tx:naive (tx:to-json tx))) + :: + ++ point + |= =point:naive + ^- json + =, enjs:format + %- pairs + :~ ['dominion' s+dominion.point] + :: + :- 'ownership' + %- pairs + =* own own.point + ^- (list [@t json]) + :~ ['owner' (ownership owner.own)] + ['spawnProxy' (ownership spawn-proxy.own)] + ['managementProxy' (ownership management-proxy.own)] + ['votingProxy' (ownership voting-proxy.own)] + ['transferProxy' (ownership transfer-proxy.own)] + == + :: + :- 'network' + %- pairs + =* net net.point + :* ['rift' (numb rift.net)] + :: + :- 'keys' + %- pairs + :~ ['life' (numb life.keys.net)] + ['suite' (numb suite.keys.net)] + ['auth' (numb auth.keys.net)] + ['crypt' (numb crypt.keys.net)] + == + :: + ['rift' (numb rift.net)] + :- 'sponsor' + %- pairs + ~[['has' b+has.sponsor.net] ['who' (ship who.sponsor.net)]] + :: + ?~ escape.net ~ + ['escape' (ship u.escape.net)]~ + == == :: - ++ own-to-json + ++ ownership |= [=address:naive =nonce:naive] ^- json + =, enjs:format %- pairs :~ ['address' s+(crip "0x{((x-co:co 20) address)}")] - ['nonce' (numb:enjs:format nonce)] + ['nonce' (numb nonce)] + == + :: + ++ tx-status + |= =^tx-status + ^- json + =, enjs:format + %- pairs + :~ ['status' s+status.tx-status] + :: + :- 'tx' + ?~ tx.tx-status ~ + s+(crip "0x{((x-co:co 20) u.tx.tx-status)}") == -- :: - ++ txs-to-json - :: TODO: implement me! - :: - |= txs=(list [tx:naive success=?]) - ^- json - ~ - :: ++ to-hex |= =cord ^- (unit @ux) @@ -208,33 +248,37 @@ ~ (some q.u.parsed) :: - ++ sponsor-call - |= [id=@t params=(map @t json)] - ^- [(unit cage) response:rpc] - ?. =((lent ~(tap by params)) 3) - [~ ~(params error id)] - =/ sig=(unit @) (sig:extract params) - =/ from=(unit [@p proxy:naive]) (from:extract params) - =/ data=(unit [@ux @p]) (address-ship:extract params) - ?. &(?=(^ sig) ?=(^ from) ?=(^ data)) - [~ ~(parse error id)] - :_ [%result id s+'ok'] - %- some - noun+!>([u.sig u.from u.data]) - :: - ++ proxy-call - |= [id=@t params=(map @t json)] - ^- [(unit cage) response:rpc] - ?. =((lent ~(tap by params)) 3) - [~ ~(params error id)] - =/ sig=(unit @) (sig:extract params) - =/ from=(unit [@p proxy:naive]) (from:extract params) - =/ data=(unit @ux) (address:extract params) - ?. &(?=(^ sig) ?=(^ from) ?=(^ data)) - [~ ~(parse error id)] - :_ [%result id s+'ok'] - %- some - noun+!>([u.sig u.from u.data]) + ++ rpc-res + |% + ++ sponsor + |= [id=@t params=(map @t json)] + ^- [(unit cage) response:rpc] + ?. =((lent ~(tap by params)) 3) + [~ ~(params error id)] + =/ sig=(unit @) (sig:from-json params) + =/ from=(unit [@p proxy:naive]) (from:from-json params) + =/ data=(unit [@ux @p]) (address-ship:from-json params) + ?. &(?=(^ sig) ?=(^ from) ?=(^ data)) + [~ ~(parse error id)] + :_ [%result id s+'ok'] + %- some + noun+!>([u.sig u.from u.data]) + :: + ++ proxy + |= [id=@t params=(map @t json)] + ^- [(unit cage) response:rpc] + ?. =((lent ~(tap by params)) 3) + [~ ~(params error id)] + =/ sig=(unit @) (sig:from-json params) + =/ from=(unit [@p proxy:naive]) (from:from-json params) + =/ data=(unit @ux) (address:from-json params) + ?. &(?=(^ sig) ?=(^ from) ?=(^ data)) + [~ ~(parse error id)] + :_ [%result id s+'ok'] + %- some + noun+!>([u.sig u.from u.data]) + :: + -- :: ++ error |_ id=@t @@ -260,16 +304,16 @@ ~(params error id) ?~ point=(scry u.ship) ~(params error id) - [%result id (point-to-json u.point)] + [%result id (point:to-json u.point)] :: ++ transfer-point |= [id=@t params=(map @t json)] ^- [(unit cage) response:rpc] ?. =((lent ~(tap by params)) 3) [~ ~(params error id)] - =/ sig=(unit @) (sig:extract params) - =/ from=(unit [ship @t]) (from:extract params) - =/ data=(unit [@ux ?]) (address-transfer:extract params) + =/ sig=(unit @) (sig:from-json params) + =/ from=(unit [ship @t]) (from:from-json params) + =/ data=(unit [@ux ?]) (address-transfer:from-json params) ?: |(?=(~ sig) ?=(~ from) ?=(~ data)) [~ ~(parse error id)] :_ [%result id s+'ok'] @@ -281,25 +325,25 @@ ^- [(unit cage) response:rpc] ?. =((lent ~(tap by params)) 3) [~ ~(params error id)] - =/ sig=(unit @) (sig:extract params) - =/ from=(unit [ship @t]) (from:extract params) + =/ sig=(unit @) (sig:from-json params) + =/ from=(unit [ship @t]) (from:from-json params) =/ data=(unit [encrypt=@ auth=@ crypto-suite=@ breach=?]) - (keys:extract params) + (keys:from-json params) ?. &(?=(^ sig) ?=(^ from) ?=(^ data)) [~ ~(parse error id)] :_ [%result id s+'ok'] %- some noun+!>([u.sig u.from u.data]) :: -++ spawn sponsor-call -++ escape sponsor-call -++ cancel-escape sponsor-call -++ adopt sponsor-call -++ detach sponsor-call -++ reject sponsor-call -++ management-proxy proxy-call -++ spawn-proxy proxy-call -++ transfer-proxy proxy-call +++ spawn sponsor:rpc-res +++ escape sponsor:rpc-res +++ cancel-escape sponsor:rpc-res +++ adopt sponsor:rpc-res +++ detach sponsor:rpc-res +++ reject sponsor:rpc-res +++ management-proxy proxy:rpc-res +++ spawn-proxy proxy:rpc-res +++ transfer-proxy proxy:rpc-res :: - readNonce(from=[ship proxy]) -> @ :: automatically increment for pending wraps :: ++ read-nonce @@ -307,7 +351,7 @@ ^- response:rpc ?. =((lent ~(tap by params)) 3) ~(params error id) - ?~ from=(from:extract params) + ?~ from=(from:from-json params) ~(parse error id) ?~ nonce=(scry u.from) ~(params error id) @@ -317,49 +361,56 @@ :: FIXME: send raw-tx (i.e. tx with signature) instead? :: |% - :: - readPendingRoll() -> (list tx) + :: - readPendingRoll() -> (list pend-tx) :: - ++ all - |= [id=@t params=(map @t json) pending=(list tx:naive)] + ++ all + |= [id=@t params=(map @t json) pending=(list pend-tx)] ^- response:rpc ?. =((lent ~(tap by params)) 0) ~(params error id) - [%result id (pending-to-json pending)] - :: - :: - readPendingByShip(ship) -> (list tx) + [%result id (pending:to-json pending)] + :: - readPendingByShip(ship) -> (list pend-tx) :: ++ ship - |= [id=@t params=(map @t json) scry=$-(@p (list tx:naive))] + |= [id=@t params=(map @t json) scry=$-(@p (list pend-tx))] ^- response:rpc ?. =((lent ~(tap by params)) 1) ~(params error id) - ?~ ship=(ship:extract params) + ?~ ship=(ship:from-json params) ~(parse error id) - [%result id (pending-to-json (scry u.ship))] - :: - :: - readPendingByAddress(address) -> (list tx) + [%result id (pending:to-json (scry u.ship))] + :: - readPendingByAddress(address) -> (list pend-tx) :: ++ addr - |= [id=@t params=(map @t json) scry=$-(@ux (list tx:naive))] + |= [id=@t params=(map @t json) scry=$-(@ux (list pend-tx))] ^- response:rpc ?. =((lent ~(tap by params)) 1) ~(params error id) - ?~ address=(address:extract params) + ?~ address=(address:from-json params) ~(parse error id) - [%result id (pending-to-json (scry u.address))] + [%result id (pending:to-json (scry u.address))] -- :: -++ history - |= $: id=@t - params=(map @t json) - :: FIXME: use proper type from aggregator/index - :: - scry=$-([@p proxy:naive] (list [tx:naive success=?])) - == +++ status + |= [id=@t params=(map @t json) scry=$-(@ tx-status)] ^- response:rpc ?. =((lent ~(tap by params)) 1) ~(params error id) - ?~ from=(from:extract params) + ?~ keccak=(keccak:from-json params) ~(parse error id) - [%result id (txs-to-json (scry u.from))] + [%result id (tx-status:to-json (scry u.keccak))] +:: +:: ++ history +:: |= $: id=@t +:: params=(map @t json) +:: :: FIXME: use proper type from aggregator/index +:: :: +:: scry=$-([@p proxy:naive] (list tx:naive)) +:: == +:: ^- response:rpc +:: ?. =((lent ~(tap by params)) 1) +:: ~(params error id) +:: ?~ from=(from:from-json params) +:: ~(parse error id) +:: [%result id (txs:to-json (scry u.from))] -- From c5d61b7076950835ebef772a60266b3465ac1300 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Tue, 11 May 2021 13:28:55 +0200 Subject: [PATCH 18/21] json-rpc: fix result key in rpc response --- pkg/arvo/lib/json/rpc.hoon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/arvo/lib/json/rpc.hoon b/pkg/arvo/lib/json/rpc.hoon index 97543c704..2cc0c7ff0 100644 --- a/pkg/arvo/lib/json/rpc.hoon +++ b/pkg/arvo/lib/json/rpc.hoon @@ -43,7 +43,7 @@ :: :~ ['jsonrpc' s+'2.0'] ['id' s+id.response] - ['res' res.response] + ['result' res.response] == :: %error From 154baceb8be8a0740f9f06c8011020f9f9c75819 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Fri, 14 May 2021 09:46:36 +0200 Subject: [PATCH 19/21] Merge branch 'yu/azimuth-rpc' into naive/aggregator --- pkg/arvo/app/azimuth-rpc.hoon | 235 ++++++++ pkg/arvo/app/azimuth.hoon | 16 +- pkg/arvo/gen/azimuth-rpc/disconnect.hoon | 4 + pkg/arvo/lib/azimuth-rpc.hoon | 416 +++++++++++++ pkg/arvo/lib/json/rpc.hoon | 63 +- pkg/arvo/lib/naive-transactions.hoon | 177 ++++++ pkg/arvo/sur/json/rpc.hoon | 2 + pkg/arvo/tests/lib/naive.hoon | 709 +++++++++++++++-------- 8 files changed, 1381 insertions(+), 241 deletions(-) create mode 100644 pkg/arvo/app/azimuth-rpc.hoon create mode 100644 pkg/arvo/gen/azimuth-rpc/disconnect.hoon create mode 100644 pkg/arvo/lib/azimuth-rpc.hoon create mode 100644 pkg/arvo/lib/naive-transactions.hoon diff --git a/pkg/arvo/app/azimuth-rpc.hoon b/pkg/arvo/app/azimuth-rpc.hoon new file mode 100644 index 000000000..88a2e3fd1 --- /dev/null +++ b/pkg/arvo/app/azimuth-rpc.hoon @@ -0,0 +1,235 @@ +:: Azimuth JSON-RPC API +:: +/- rpc=json-rpc +/+ naive, + azimuth-rpc, + json-rpc, + *server, + default-agent, + verb, + dbug, + version, + agentio +|% +:: FIXME: import tx-status, pend-tx from aggregator +:: ++$ tx-status + $: status=?(%unknown %pending %sent %confirmed %failed) + tx=(unit @ux) + == +:: ++$ pend-tx [force=? =raw-tx:naive] +:: ++$ card card:agent:gall +:: ++$ state-0 [%0 ~] +-- +:: +%+ verb | +%- agent:dbug +:: +=| state-0 +=* state - +:: +^- agent:gall +=< + |_ =bowl:gall + +* this . + do ~(. +> bowl) + def ~(. (default-agent this %|) bowl) + :: + ++ on-init + ^- (quip card _this) + ~& > 'init' + :_ this + [%pass /bind %arvo %e %connect [~ [%v1 %azimuth ~]] dap.bowl]~ + :: + ++ on-save !>(state) + ++ on-load + |= old=vase + ^- (quip card _this) + [~ this(state !<(state-0 old))] + :: + ++ on-poke + |= [=mark =vase] + ^- (quip card _this) + |^ + ?> (team:title our.bowl src.bowl) + ?+ mark (on-poke:def mark vase) + %handle-http-request + =+ !<([id=@ta req=inbound-request:eyre] vase) + :_ this + (handle-http-request id req) + :: + %azimuth-action + =+ !<([%disconnect bind=binding:eyre] vase) + ~& >>> "disconnecting at {}" + :_ this + [[%pass /bind %arvo %e %disconnect bind]]~ + == + :: + ++ handle-http-request + |= [id=@ta =inbound-request:eyre] + ^- (list card) + |^ + =* req request.inbound-request + =* headers header-list.req + =/ req-line (parse-request-line url.req) + ?. =(method.req %'POST') + :: TODO: method not supported + :: + (give-simple-payload:app id not-found:gen) + ?~ rpc-request=(validate-request:json-rpc body.req parse-method) + :: TODO: malformed request + :: + (give-simple-payload:app id not-found:gen) + =/ [data=(unit cage) response=simple-payload:http] + (process-rpc-request:do u.rpc-request) + %+ weld + (give-simple-payload:app id response) + ?~ data ~ + :_ ~ + ^- card + [%pass / %agent [our.bowl %dice] %poke u.data] + :: TODO: validate that format is e.g. 'getPoint' + :: TODO: maybe use getPoint and translate to %get-point + :: + ++ parse-method |=(t=@t `term`t) + -- + -- + :: + ++ on-watch + |= =path + ^- (quip card _this) + ?> (team:title our.bowl src.bowl) + ?+ path (on-watch:def path) + [%http-response *] [~ this] + == + :: + ++ on-arvo + |= [=wire =sign-arvo] + ^- (quip card _this) + ?+ sign-arvo (on-arvo:def wire sign-arvo) + [%eyre %bound *] + ~? !accepted.sign-arvo + [dap.bowl 'bind rejected!' binding.sign-arvo] + [~ this] + == + :: + ++ on-leave on-leave:def + ++ on-peek on-peek:def + ++ on-agent on-agent:def + ++ on-fail on-fail:def + -- +:: +|_ =bowl:gall +++ process-rpc-request + |= request:rpc + ^- [(unit cage) simple-payload:http] + =; [data=(unit cage) =response:rpc] + :- data + %- json-response:gen + (response-to-json:json-rpc response) + =, azimuth-rpc + ?. ?=([%map *] params) + [~ ~(parse error id)] + ?+ method [~ ~(method error id)] + %get-point [~ (get-point id +.params point:scry)] + %transfer-point (transfer-point id +.params) + %configure-keys (configure-keys id +.params) + %spawn (spawn id +.params) + %escape (escape id +.params) + %cancel-escape (cancel-escape id +.params) + %adopt (adopt id +.params) + %detach (detach id +.params) + %reject (reject id +.params) + %set-management-proxy (management-proxy id +.params) + %set-spawn-proxy (spawn-proxy id +.params) + %set-transfer-proxy (transfer-proxy id +.params) + %pending [~ (all:pending id +.params all:pending:scry)] + %pending-by-ship [~ (ship:pending id +.params ship:pending:scry)] + %pending-by-address [~ (addr:pending id +.params addr:pending:scry)] + %status [~ (status id +.params tx-status:scry)] + :: %history [~ (history id +.params all:history:scry)] + == +:: +++ scry + |% + ++ point + |= =ship + .^ (unit point:naive) + %gx + (~(scry agentio bowl) %azimuth /nas/[(scot %p ship)]/noun) + == + :: + ++ pending + |% + ++ all + .^ (list pend-tx) + %gx + (~(scry agentio bowl) %dice /pending/noun) + == + :: + ++ ship + |= =^ship + .^ (list pend-tx) + %gx + (~(scry agentio bowl) %dice /pending/[(scot %p ship)]/noun) + == + :: + ++ addr + |= =address:naive + .^ (list pend-tx) + %gx + %+ ~(scry agentio bowl) %dice + /pending/[(scot %ux address)]/noun + == + -- + :: + ++ history + |% + ++ all + :: FIXME: use proper type from aggregator/index + :: + .^ (list tx:naive) + %gx + (~(scry agentio bowl) %dice /history/noun) + == + :: + ++ ship + |= =^ship + :: FIXME: use proper type from aggregator/index + :: + .^ (list tx:naive) + %gx + (~(scry agentio bowl) %dice /history/[(scot %p ship)]/noun) + == + :: + ++ addr + |= =address:naive + :: FIXME: use proper type from aggregator/index + :: + .^ (list tx:naive) + %gx + (~(scry agentio bowl) %dice /history/[(scot %ux address)]/noun) + == + -- + :: + ++ tx-status + |= keccak=@ux + .^ ^tx-status + %gx + (~(scry agentio bowl) %dice /tx/[(scot %ux keccak)]/status/noun) + == + :: + ++ nonce + |= [=ship =address:naive] + :: FIXME: use proper type from aggregator/index + .^ @ + %gx + %+ ~(scry agentio bowl) + %dice + /nonce/[(scot %p ship)]/[(scot %ux address)]/atom + == + -- +-- diff --git a/pkg/arvo/app/azimuth.hoon b/pkg/arvo/app/azimuth.hoon index 70fdd8bcd..45e165469 100644 --- a/pkg/arvo/app/azimuth.hoon +++ b/pkg/arvo/app/azimuth.hoon @@ -256,11 +256,19 @@ ++ on-leave on-leave:def ++ on-peek |= =path - ?: =(/x/nas path) - ``nas+!>(nas.state) - ?: =(/x/logs path) + ^- (unit (unit cage)) + ?+ path (on-peek:def path) + [%x %logs ~] ``logs+!>(logs.state) - ~ + :: + [%x %nas ~] + ``nas+!>(nas.state) + :: + [%x %nas @t ~] + ?~ ship=(rush i.t.t.path ;~(pfix sig fed:ag)) + ``noun+!>(*(unit point:naive)) + ``noun+!>((~(get by points.nas.state) u.ship)) + == :: ++ on-agent |= [=wire =sign:agent:gall] diff --git a/pkg/arvo/gen/azimuth-rpc/disconnect.hoon b/pkg/arvo/gen/azimuth-rpc/disconnect.hoon new file mode 100644 index 000000000..7b3214713 --- /dev/null +++ b/pkg/arvo/gen/azimuth-rpc/disconnect.hoon @@ -0,0 +1,4 @@ +:: +:- %say +|= [* [=binding:eyre ~] ~] +[%azimuth-action %disconnect binding] diff --git a/pkg/arvo/lib/azimuth-rpc.hoon b/pkg/arvo/lib/azimuth-rpc.hoon new file mode 100644 index 000000000..9c20de491 --- /dev/null +++ b/pkg/arvo/lib/azimuth-rpc.hoon @@ -0,0 +1,416 @@ +:: azimuth-rpc: command parsing and utilities +:: +/- rpc=json-rpc +/+ naive +:: +=> :: Utilities + :: + |% + :: FIXME: import tx-status, pend-tx from aggregator + :: + +$ tx-status + $: status=?(%unknown %pending %sent %confirmed %failed) + tx=(unit @ux) + == + :: + +$ pend-tx [force=? =raw-tx:naive] + :: + ++ from-json + |% + ++ keys + |= params=(map @t json) + ^- (unit [encrypt=@ auth=@ crypto-suite=@ breach=?]) + ?~ data=(~(get by params) 'data') ~ + %. u.data + =, dejs-soft:format + %- ot + :~ ['encrypt' so] + ['auth' so] + ['crypto-suite' so] + ['breach' bo] + == + :: + ++ address-transfer + |= params=(map @t json) + ^- (unit [@ux ?]) + ?~ data=(~(get by params) 'data') ~ + =; ans=(unit [add=(unit @ux) r=?]) + ?~ ans ~ + ?~ add.u.ans ~ + (some [u.add.u.ans r.u.ans]) + %. u.data + =, dejs-soft:format + %- ot + ~[['address' (cu to-hex so)] ['reset' bo]] + :: + ++ address-ship + |= params=(map @t json) + ^- (unit [@ux @p]) + ?~ data=(~(get by params) 'data') ~ + =; ans=(unit [add=(unit @ux) ship=@p]) + ?~ ans ~ + ?~ add.u.ans ~ + (some [u.add.u.ans ship.u.ans]) + %. u.data + =, dejs-soft:format + %- ot + :~ ['address' (cu to-hex so)] + ['ship' (su ;~(pfix sig fed:ag))] + == + :: + ++ address + |= params=(map @t json) + ^- (unit @ux) + ?~ data=(~(get by params) 'data') ~ + =; ans=(unit (unit @ux)) + ?~(ans ~ u.ans) + =, dejs-soft:format + %. u.data + (ot ['address' (cu to-hex so)]~) + :: + ++ ship + |= params=(map @t json) + ^- (unit @p) + ?~ data=(~(get by params) 'data') ~ + =, dejs-soft:format + %. u.data + (ot ['ship' (su ;~(pfix sig fed:ag))]~) + :: + ++ sig + |= params=(map @t json) + ^- (unit @) + ?~ sig=(~(get by params) 'sig') ~ + (so:dejs-soft:format u.sig) + :: + ++ from + |= params=(map @t json) + ^- (unit [@p proxy:naive]) + ?~ from=(~(get by params) 'from') ~ + =, dejs-soft:format + %. u.from + %- ot + :~ ['ship' (su ;~(pfix sig fed:ag))] + ['proxy' (cu proxy:naive so)] + == + :: + ++ keccak + |= params=(map @t json) + ^- (unit @ux) + ?~ keccak=(~(get by params) 'keccak') ~ + =; ans=(unit (unit @ux)) + ?~(ans ~ u.ans) + =, dejs-soft:format + ((cu to-hex so) u.keccak) + -- + :: + ++ to-json + |% + ++ pending + |= pending=(list pend-tx) + ^- json + =, enjs:format + :- %a + %+ turn pending + |= pend-tx + ^- json + =, enjs:format + %- pairs + :~ ['force' b+force] + :: + :- 'raw-tx' + %- pairs + :~ ['sig' (numb sig.raw-tx)] + ['tx' (tx:to-json tx.raw-tx)] + == == + :: + ++ tx + |= =tx:naive + ^- json + =, enjs:format + |^ + %- pairs + :~ ['tx' (parse-tx +.tx)] + :: + :- 'from' + %- pairs + ~[['ship' (ship ship.from.tx)] ['proxy' s+proxy.from.tx]] + == + :: + ++ parse-tx + |= tx=skim-tx:naive + ^- json + %- pairs + :~ ['type' s+-.tx] + :: + :- 'data' + %- pairs + ?- -.tx + %transfer-point (en-transfer +.tx) + %spawn (en-spawn +.tx) + %configure-keys (en-keys +.tx) + %escape ~[(en-ship parent.tx)] + %cancel-escape ~[(en-ship parent.tx)] + %adopt ~[(en-ship ship.tx)] + %reject ~[(en-ship ship.tx)] + %detach ~[(en-ship ship.tx)] + %set-management-proxy ~[(en-address address.tx)] + %set-spawn-proxy ~[(en-address address.tx)] + %set-transfer-proxy ~[(en-address address.tx)] + == == + :: + ++ en-ship |=(s=@p ship+(ship s)) + ++ en-address |=(a=@ux address+s+(crip "0x{((x-co:co 20) a)}")) + ++ en-spawn |=([s=@p a=@ux] ~[(en-ship s) (en-address a)]) + ++ en-transfer |=([a=@ux r=?] ~[(en-address a) reset+b+r]) + ++ en-keys + |= [encrypt=@ auth=@ crypto-suite=@ breach=?] + ^- (list [@t json]) + :~ ['encrypt' (numb encrypt)] + ['auth' (numb auth)] + ['crypto-suite' (numb crypto-suite)] + ['breach' b+breach] + == + -- + :: + ++ txs + |= txs=(list tx:naive) + ^- json + a+(turn txs |=(=tx:naive (tx:to-json tx))) + :: + ++ point + |= =point:naive + ^- json + =, enjs:format + %- pairs + :~ ['dominion' s+dominion.point] + :: + :- 'ownership' + %- pairs + =* own own.point + ^- (list [@t json]) + :~ ['owner' (ownership owner.own)] + ['spawnProxy' (ownership spawn-proxy.own)] + ['managementProxy' (ownership management-proxy.own)] + ['votingProxy' (ownership voting-proxy.own)] + ['transferProxy' (ownership transfer-proxy.own)] + == + :: + :- 'network' + %- pairs + =* net net.point + :* ['rift' (numb rift.net)] + :: + :- 'keys' + %- pairs + :~ ['life' (numb life.keys.net)] + ['suite' (numb suite.keys.net)] + ['auth' (numb auth.keys.net)] + ['crypt' (numb crypt.keys.net)] + == + :: + ['rift' (numb rift.net)] + :- 'sponsor' + %- pairs + ~[['has' b+has.sponsor.net] ['who' (ship who.sponsor.net)]] + :: + ?~ escape.net ~ + ['escape' (ship u.escape.net)]~ + == == + :: + ++ ownership + |= [=address:naive =nonce:naive] + ^- json + =, enjs:format + %- pairs + :~ ['address' s+(crip "0x{((x-co:co 20) address)}")] + ['nonce' (numb nonce)] + == + :: + ++ tx-status + |= =^tx-status + ^- json + =, enjs:format + %- pairs + :~ ['status' s+status.tx-status] + :: + :- 'tx' + ?~ tx.tx-status ~ + s+(crip "0x{((x-co:co 20) u.tx.tx-status)}") + == + -- + :: + ++ to-hex + |= =cord + ^- (unit @ux) + =/ parsed=(unit (pair @ud @ux)) (de:base16:mimes:html cord) + ?~ parsed + ::~|(%non-hex-cord !!) + ~ + (some q.u.parsed) + :: + ++ rpc-res + |% + ++ sponsor + |= [id=@t params=(map @t json)] + ^- [(unit cage) response:rpc] + ?. =((lent ~(tap by params)) 3) + [~ ~(params error id)] + =/ sig=(unit @) (sig:from-json params) + =/ from=(unit [@p proxy:naive]) (from:from-json params) + =/ data=(unit [@ux @p]) (address-ship:from-json params) + ?. &(?=(^ sig) ?=(^ from) ?=(^ data)) + [~ ~(parse error id)] + :_ [%result id s+'ok'] + %- some + noun+!>([u.sig u.from u.data]) + :: + ++ proxy + |= [id=@t params=(map @t json)] + ^- [(unit cage) response:rpc] + ?. =((lent ~(tap by params)) 3) + [~ ~(params error id)] + =/ sig=(unit @) (sig:from-json params) + =/ from=(unit [@p proxy:naive]) (from:from-json params) + =/ data=(unit @ux) (address:from-json params) + ?. &(?=(^ sig) ?=(^ from) ?=(^ data)) + [~ ~(parse error id)] + :_ [%result id s+'ok'] + %- some + noun+!>([u.sig u.from u.data]) + :: + -- + :: + ++ error + |_ id=@t + :: https://www.jsonrpc.org/specification#error_object + :: + ++ parse [%error id '-32700' 'Failed to parsed'] + ++ request [%error id '-32600' 'Invalid Request'] + ++ method [%error id '-32601' 'Method not found'] + ++ params [%error id '-32602' 'Invalid params'] + ++ internal [%error id '-32603' 'Internal error'] + ++ not-found [%error id '-32000' 'Resource not found'] + -- + -- +|% +++ get-point + |= [id=@t params=(map @t json) scry=$-(ship (unit point:naive))] + ^- response:rpc + ?. =((lent ~(tap by params)) 1) + ~(params error id) + ?~ ship=(~(get by params) 'ship') + ~(params error id) + ?~ ship=(rush (so:dejs:format u.ship) ;~(pfix sig fed:ag)) + ~(params error id) + ?~ point=(scry u.ship) + ~(params error id) + [%result id (point:to-json u.point)] +:: +++ transfer-point + |= [id=@t params=(map @t json)] + ^- [(unit cage) response:rpc] + ?. =((lent ~(tap by params)) 3) + [~ ~(params error id)] + =/ sig=(unit @) (sig:from-json params) + =/ from=(unit [ship @t]) (from:from-json params) + =/ data=(unit [@ux ?]) (address-transfer:from-json params) + ?: |(?=(~ sig) ?=(~ from) ?=(~ data)) + [~ ~(parse error id)] + :_ [%result id s+'ok'] + %- some + noun+!>([u.sig u.from u.data]) +:: +++ configure-keys + |= [id=@t params=(map @t json)] + ^- [(unit cage) response:rpc] + ?. =((lent ~(tap by params)) 3) + [~ ~(params error id)] + =/ sig=(unit @) (sig:from-json params) + =/ from=(unit [ship @t]) (from:from-json params) + =/ data=(unit [encrypt=@ auth=@ crypto-suite=@ breach=?]) + (keys:from-json params) + ?. &(?=(^ sig) ?=(^ from) ?=(^ data)) + [~ ~(parse error id)] + :_ [%result id s+'ok'] + %- some + noun+!>([u.sig u.from u.data]) +:: +++ spawn sponsor:rpc-res +++ escape sponsor:rpc-res +++ cancel-escape sponsor:rpc-res +++ adopt sponsor:rpc-res +++ detach sponsor:rpc-res +++ reject sponsor:rpc-res +++ management-proxy proxy:rpc-res +++ spawn-proxy proxy:rpc-res +++ transfer-proxy proxy:rpc-res +:: - readNonce(from=[ship proxy]) -> @ :: automatically increment for pending wraps +:: +++ read-nonce + |= [id=@t params=(map @t json) scry=$-([ship proxy:naive] (unit @))] + ^- response:rpc + ?. =((lent ~(tap by params)) 3) + ~(params error id) + ?~ from=(from:from-json params) + ~(parse error id) + ?~ nonce=(scry u.from) + ~(params error id) + [%result id (numb:enjs:format u.nonce)] +:: +++ pending + :: FIXME: send raw-tx (i.e. tx with signature) instead? + :: + |% + :: - readPendingRoll() -> (list pend-tx) + :: + ++ all + |= [id=@t params=(map @t json) pending=(list pend-tx)] + ^- response:rpc + ?. =((lent ~(tap by params)) 0) + ~(params error id) + [%result id (pending:to-json pending)] + :: - readPendingByShip(ship) -> (list pend-tx) + :: + ++ ship + |= [id=@t params=(map @t json) scry=$-(@p (list pend-tx))] + ^- response:rpc + ?. =((lent ~(tap by params)) 1) + ~(params error id) + ?~ ship=(ship:from-json params) + ~(parse error id) + [%result id (pending:to-json (scry u.ship))] + :: - readPendingByAddress(address) -> (list pend-tx) + :: + ++ addr + |= [id=@t params=(map @t json) scry=$-(@ux (list pend-tx))] + ^- response:rpc + ?. =((lent ~(tap by params)) 1) + ~(params error id) + ?~ address=(address:from-json params) + ~(parse error id) + [%result id (pending:to-json (scry u.address))] + -- +:: +++ status + |= [id=@t params=(map @t json) scry=$-(@ tx-status)] + ^- response:rpc + ?. =((lent ~(tap by params)) 1) + ~(params error id) + ?~ keccak=(keccak:from-json params) + ~(parse error id) + [%result id (tx-status:to-json (scry u.keccak))] +:: +:: ++ history +:: |= $: id=@t +:: params=(map @t json) +:: :: FIXME: use proper type from aggregator/index +:: :: +:: scry=$-([@p proxy:naive] (list tx:naive)) +:: == +:: ^- response:rpc +:: ?. =((lent ~(tap by params)) 1) +:: ~(params error id) +:: ?~ from=(from:from-json params) +:: ~(parse error id) +:: [%result id (txs:to-json (scry u.from))] +-- diff --git a/pkg/arvo/lib/json/rpc.hoon b/pkg/arvo/lib/json/rpc.hoon index e44ad1d68..2cc0c7ff0 100644 --- a/pkg/arvo/lib/json/rpc.hoon +++ b/pkg/arvo/lib/json/rpc.hoon @@ -24,8 +24,65 @@ :- %params ^- json ?- -.params - %list [%a +.params] - %object [%o (~(gas by *(map @t json)) +.params)] - == + %list [%a +.params] + %map [%o +.params] + %object [%o (~(gas by *(map @t json)) +.params)] + == == +:: +++ response-to-json + |= =response + ^- json + :: TODO: consider all cases + :: + ?+ -.response ~|([%unsupported-rpc-response response] !!) + %result + :- %o + %- molt + ^- (list [@t json]) + :: FIXME: return 'id' as string, number or NULL + :: + :~ ['jsonrpc' s+'2.0'] + ['id' s+id.response] + ['result' res.response] + == + :: + %error + :- %o + %- molt + ^- (list [@t json]) + :~ ['jsonrpc' s+'2.0'] + ['id' ?~(id.response ~ s+id.response)] + ['code' n+code.response] + ['message' s+message.response] + == == +:: +++ validate-request + |= [body=(unit octs) parse-method=$-(@t term)] + ^- (unit request) + ?~ body ~ + ?~ jon=(de-json:html q.u.body) ~ + :: ignores non-object responses + :: + :: ?. ?=([%o *] json) ~|([%format-not-valid json] !!) + ?. ?=([%o *] u.jon) ~ + %- some + %. u.jon + =, dejs:format + :: TODO: If parsing fails, return a proper error (not 500) + :: + %- ot + :~ :: FIXME: parse 'id' as string, number or NULL + :: + ['id' so] + ['jsonrpc' (su (jest '2.0'))] + ['method' (cu parse-method so)] + :: + :- 'params' + |= =json + ^- request-params + ?+ -.json !! + %a [%list ((ar same) json)] + %o [%map ((om same) json)] + == == -- diff --git a/pkg/arvo/lib/naive-transactions.hoon b/pkg/arvo/lib/naive-transactions.hoon new file mode 100644 index 000000000..82d4cc9dc --- /dev/null +++ b/pkg/arvo/lib/naive-transactions.hoon @@ -0,0 +1,177 @@ +/+ naive, ethereum +:: Types +|% ++$ address address:ethereum ++$ nonce @ud ++$ proxy ?(%own %spawn %manage %vote %transfer) ++$ skp [=ship pk=@ =proxy] +:: ++$ l2-tx + $% [%spawn child=ship =address] + [%transfer-point =address reset=?] + [%configure-keys suite=@ud encrypt=@ auth=@ breach=?] + [%escape parent=ship] + [%cancel-escape parent=ship] + [%adopt child=ship] + [%reject child=ship] + [%detach child=ship] + [%set-management-proxy =address] + [%set-spawn-proxy =address] + [%set-transfer-proxy =address] + == +-- +:: +|% +:: +++ gen-tx + |= [=nonce =skp tx=l2-tx] ^- octs + =/ raw=octs + ?- -.tx + %spawn (get-spawn:bits ship.skp proxy.skp +.tx) + %transfer-point (get-transfer:bits ship.skp proxy.skp +.tx) + %configure-keys (get-keys:bits ship.skp proxy.skp +.tx) + %escape (get-escape:bits %escape ship.skp proxy.skp +.tx) + %cancel-escape (get-escape:bits %cancel-escape ship.skp proxy.skp +.tx) + %adopt (get-escape:bits %adopt ship.skp proxy.skp +.tx) + %reject (get-escape:bits %reject ship.skp proxy.skp +.tx) + %detach (get-escape:bits %detach ship.skp proxy.skp +.tx) + %set-management-proxy (get-ship-address:bits %set-management-proxy ship.skp proxy.skp +.tx) + %set-spawn-proxy (get-ship-address:bits %set-spawn-proxy ship.skp proxy.skp +.tx) + %set-transfer-proxy (get-ship-address:bits %set-transfer-proxy ship.skp proxy.skp +.tx) + == + %^ sign-tx pk.skp nonce raw +:: +:: 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 (keccak-256:keccak:crypto dat) v r s) + ?- -.result + %| ~ + %& `p.result + == +:: +++ sign-tx + |= [pk=@ =nonce tx=octs] ^- octs + =/ prepared-data (prepare-for-sig 1.337 nonce tx) + =/ sign-data + =/ len (rsh [3 2] (scot %ui p.prepared-data)) + %- keccak-256:keccak:crypto + %: cad:naive 3 + 26^'\19Ethereum Signed Message:\0a' + (met 3 len)^len + prepared-data + ~ + == + =+ (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 + ~ + == +:: +++ bits + :: + |% + :: + :: TODO: Shouldn't need to pass all these arguments along - they should already be in the subject somewhere + :: + ++ get-spawn + |= [=ship =proxy child=ship =address] ^- octs + %: cad:naive 3 + (from-proxy:bits proxy) + 4^ship + 1^%1 :: %spawn + 4^child + 20^address + ~ + == + :: + ++ get-transfer + |= [=ship =proxy =address reset=?] ^- octs + %: cad:naive 3 + (from-proxy:bits proxy) + 4^ship + 1^(can 0 7^%0 1^reset ~) :: %transfer-point + 20^address + ~ + == + :: + ++ get-keys + |= [=ship =proxy suite=@ud encrypt=@ auth=@ breach=?] ^- octs + %: cad:naive 3 + (from-proxy:bits proxy) + 4^ship + 1^(can 0 7^%2 1^breach ~) :: %configure-keys + 32^encrypt + 32^auth + 4^suite + ~ + == + :: + ++ get-escape + |= [action=@tas from=ship proxy=@tas other=ship] ^- octs + =/ op + ?+ action !! + %escape %3 + %cancel-escape %4 + %adopt %5 + %reject %6 + %detach %7 + == + %: cad:naive 3 + (from-proxy proxy) + 4^from + 1^(can 0 7^op 1^0 ~) + 4^other + ~ + == + :: + ++ get-ship-address + |= [action=@tas from=ship proxy=@tas =address] ^- octs + =/ op + ?+ action !! + %set-management-proxy %8 + %set-spawn-proxy %9 + %set-transfer-proxy %10 + == + %: cad:naive 3 + (from-proxy proxy) + 4^from + 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 ~) + :: + -- +:: +-- diff --git a/pkg/arvo/sur/json/rpc.hoon b/pkg/arvo/sur/json/rpc.hoon index 350f2cae1..63f5a06f1 100644 --- a/pkg/arvo/sur/json/rpc.hoon +++ b/pkg/arvo/sur/json/rpc.hoon @@ -3,12 +3,14 @@ |% +$ request $: id=@t + jsonrpc=@t method=@t params=request-params == :: +$ request-params $% [%list (list json)] + [%map (map @t json)] [%object (list (pair @t json))] == +$ response diff --git a/pkg/arvo/tests/lib/naive.hoon b/pkg/arvo/tests/lib/naive.hoon index 27db42bf7..da5de9b71 100644 --- a/pkg/arvo/tests/lib/naive.hoon +++ b/pkg/arvo/tests/lib/naive.hoon @@ -1,24 +1,7 @@ -/+ *test, naive, ethereum -|% -++ address @ux -++ n |=([=^state:naive =^input:naive] (%*(. naive lac |) verifier 1.337 +<)) -:: TODO: does this uniquely produce the pubkey? +/+ *test, naive, ethereum, azimuth, *naive-transactions :: -++ 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 (keccak-256:keccak:crypto dat) v r s) - ?- -.result - %| ~ - %& `p.result - == +|% +++ n |=([=^state:naive =^input:naive] (%*(. naive lac |) verifier 1.337 +<)) :: ++ addr address-from-prv:key:ethereum :: @@ -32,7 +15,14 @@ ++ init-bud |= =^state:naive ^- [effects:naive ^state:naive] - (n state (owner-changed:l1 ~bud (addr ~bud))) + (n state (owner-changed:l1 ~bud (addr %bud-key-0))) +:: +:: ~wes is for testing sponsors of stars +:: +++ init-wes + |= =^state:naive + ^- [effects:naive ^state:naive] + (n state (owner-changed:l1 ~wes (addr %wes-key-0))) :: :: ~dopbud is for testing L1 ownership with L2 spawn proxy :: @@ -54,7 +44,18 @@ =^ f3 state (n state (owner-changed:l1 ~marbud deposit-address:naive)) [:(welp f1 f2 f3) state] :: -:: ~sambud is for testing L1 stars attempting L2 actions +:: ~litbud is for testing L2 sponsorship +:: +++ init-litbud + |= =^state:naive + ^- [effects:naive ^state:naive] + :: ~bud should already be spawned, though trying to init ~bud again shouldn't matter i think? + :: =^ f1 state (init-bud state) + =^ f2 state (n state (owner-changed:l1 ~litbud (addr %litbud-key-0))) + =^ f3 state (n state (owner-changed:l1 ~litbud deposit-address:naive)) + [:(welp f2 f3) state] +:: +:: ~sambud is for testing L1 stars :: ++ init-sambud |= =^state:naive @@ -63,34 +64,6 @@ =^ f2 state (n state (owner-changed:l1 ~sambud (addr %sambud-key-0))) [:(welp f1 f2) state] :: -++ sign-tx - |= [pk=@ nonce=@ud tx=octs] ^- octs - =/ prepared-data (prepare-for-sig 1.337 nonce tx) - =/ sign-data - =/ len (rsh [3 2] (scot %ui p.prepared-data)) - %- keccak-256:keccak:crypto - %: cad:naive 3 - 26^'\19Ethereum Signed Message:\0a' - (met 3 len)^len - prepared-data - ~ - == - =+ (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=@ud 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 - ~ - == -:: ++ l1 |% :: @@ -121,7 +94,7 @@ (log lost-sponsor:log-names:naive *@ux lost parent ~) :: ++ changed-keys - |= [=ship encr=@ auth=@ suite=@ life=@] + |= [=ship suite=@ encr=@ auth=@ life=@] =/ keys=@ux %: can 8 1^life @@ -162,162 +135,44 @@ :: -- :: -++ l2 - :: - |% - :: - ++ spawn - |= [nonce=@ud parent=ship pk=@ proxy=@tas child=ship =address] ^- octs - %^ sign-tx pk nonce - %: cad:naive 3 - (from-proxy:bits proxy) - 4^parent - 1^%1 :: %spawn - 4^child - 20^address - ~ - == - :: - ++ transfer-point - |= [nonce=@ud =ship pk=@ =address proxy=@tas reset=?] ^- octs - %^ sign-tx pk nonce - %: cad:naive 3 - (from-proxy:bits proxy) - 4^ship - 1^(can 0 7^%0 1^reset ~) :: %transfer-point - 20^address - ~ - == - :: - ++ configure-keys - |= $: nonce=@ud =ship pk=@ proxy=@tas - breach=@ encrypt=@ auth=@ crypto-suite=@ - == - ^- octs - %^ sign-tx pk nonce - %: cad:naive 3 - (from-proxy:bits proxy) - 4^ship - 1^(can 0 7^%2 1^breach ~) :: %configure-keys - 32^encrypt - 32^auth - 4^crypto-suite - ~ - == - :: - ++ escape - |= [nonce=@ud child=ship pk=@ proxy=@tas parent=ship] ^- octs - %^ sign-tx pk nonce - (take-escape:bits %escape child proxy parent) - :: - ++ cancel-escape - |= [nonce=@ud child=ship pk=@ proxy=@tas parent=ship] ^- octs - %^ sign-tx pk nonce - (take-escape:bits %cancel-escape child proxy parent) - :: - ++ adopt - |= [nonce=@ud child=ship pk=@ proxy=@tas parent=ship] ^- octs - %^ sign-tx pk nonce - (take-escape:bits %adopt parent proxy child) - :: - ++ reject - |= [nonce=@ud child=ship pk=@ proxy=@tas parent=ship] ^- octs - %^ sign-tx pk nonce - (take-escape:bits %reject parent proxy child) - :: - ++ detach - |= [nonce=@ud child=ship pk=@ proxy=@tas parent=ship] ^- octs - %^ sign-tx pk nonce - (take-escape:bits %detach parent proxy child) - :: - ++ set-management-proxy - |= [nonce=@ud =ship pk=@ proxy=@tas =address] ^- octs - %^ sign-tx pk nonce - ^- octs - (take-ship-address:bits %set-management-proxy ship proxy address) - :: - ++ set-spawn-proxy - |= [nonce=@ud =ship pk=@ proxy=@tas =address] ^- octs - %^ sign-tx pk nonce - (take-ship-address:bits %set-spawn-proxy ship proxy address) - :: - ++ set-transfer-proxy - |= [nonce=@ud =ship pk=@ proxy=@tas =address] ^- octs - %^ sign-tx pk nonce - (take-ship-address:bits %set-transfer-proxy ship proxy address) - :: - ++ bits - :: - |% - :: - :: TODO: Shouldn't need to pass all these arguments along - they should already be in the subject somewhere - :: - ++ take-escape - |= [action=@tas from=ship proxy=@tas other=ship] ^- octs - =/ op - ?+ action !! - %escape %3 - %cancel-escape %4 - %adopt %5 - %reject %6 - %detach %7 - == - %: cad:naive 3 - (from-proxy proxy) - 4^from - 1^(can 0 7^op 1^0 ~) - 4^other - ~ - == - :: - ++ take-ship-address - |= [action=@tas from=ship proxy=@tas =address] ^- octs - =/ op - ?+ action !! - %set-management-proxy %8 - %set-spawn-proxy %9 - %set-transfer-proxy %10 - == - %: cad:naive 3 - (from-proxy proxy) - 4^from - 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 ~) - :: - -- - :: - -- -:: -- :: +:: Common values used for tests +:: |% +:: +++ encr (shax 'You will forget that you ever read this sentence.') +++ auth (shax 'You cant know that this sentence is true.') +++ suit 1 +:: +++ marbud-own [~marbud %marbud-key-0 %own] +++ marbud-spn [~marbud %marbud-skey %spawn] +++ marbud-mgt [~marbud %marbud-mkey %manage] +:: +++ dopbud-own [~dopbud %dopbud-key-0 %own] +:: +++ litbud-own [~litbud %litbud-key-0 %own] +:: +++ lt-own [~linnup-torsyx %lt-key-0 %own] +++ lt-xfr [~linnup-torsyx %lt-key-0 %transfer] +-- +:: +:: Tests +:: +|% +:: ++ test-log ^- tang %+ expect-eq !> - :- [%point ~bud %owner 0x123]~ + :- [%point ~bud %owner (addr %bud-key-0)]~ :_ [~ ~] :_ [~ ~] :- ~bud - %*(. *point:naive dominion %l1, owner.own 0x123^0, who.sponsor.net ~bud) + %*(. *point:naive dominion %l1, owner.own (addr %bud-key-0)^0, who.sponsor.net ~bud) :: !> %^ naive verifier 1.337 :- *^state:naive :* %log *@ux *@ux - owner-changed:log-names:naive (@ux ~bud) 0x123 ~ + owner-changed:log-names:naive (@ux ~bud) (addr %bud-key-0) ~ == :: ++ test-deposit ^- tang @@ -330,84 +185,153 @@ dominion:(~(got by points.state) ~marbud) :: ++ test-batch ^- tang + =/ marbud-transfer [%transfer-point (addr %marbud-key-0) |] + =/ marbud-transfer-2 [%transfer-point (addr %marbud-key-1) |] + :: %+ expect-eq - !> [0x234 2] + !> [(addr %marbud-key-1) 2] :: !> =| =^state:naive =^ f state (init-marbud state) - =^ f state (n state %bat q:(transfer-point:l2 0 ~marbud %marbud-key-0 (addr %marbud-key-0) %own |)) - =^ f state (n state %bat q:(transfer-point:l2 1 ~marbud %marbud-key-0 0x234 %own |)) + =^ f state (n state %bat q:(gen-tx 0 marbud-own marbud-transfer)) + =^ f state (n state %bat q:(gen-tx 1 marbud-own marbud-transfer-2)) owner.own:(~(got by points.state) ~marbud) :: ++ test-l1-changed-spawn-proxy ^- tang %+ expect-eq - !> [0x123 0] + !> [(addr %bud-skey) 0] :: !> =| =^state:naive =^ f state (init-bud state) - =^ f state (n state (changed-spawn-proxy:l1 ~bud 0x123)) + =^ f state (n state (changed-spawn-proxy:l1 ~bud (addr %bud-skey))) spawn-proxy.own:(~(got by points.state) ~bud) :: ++ test-l1-changed-transfer-proxy ^- tang %+ expect-eq - !> [0x123 0] + !> [(addr %bud-key-1) 0] :: !> =| =^state:naive =^ f state (init-bud state) - =^ f state (n state (changed-transfer-proxy:l1 ~bud 0x123)) + =^ f state (n state (changed-transfer-proxy:l1 ~bud (addr %bud-key-1))) transfer-proxy.own:(~(got by points.state) ~bud) :: ++ test-l1-changed-management-proxy ^- tang %+ expect-eq - !> [0x123 0] + !> [(addr %bud-mkey) 0] :: !> =| =^state:naive =^ f state (init-bud state) - =^ f state (n state (changed-management-proxy:l1 ~bud 0x123)) + =^ f state (n state (changed-management-proxy:l1 ~bud (addr %bud-mkey))) management-proxy.own:(~(got by points.state) ~bud) :: ++ test-l1-changed-voting-proxy ^- tang %+ expect-eq - !> [0x123 0] + !> [(addr %bud-vkey) 0] :: !> =| =^state:naive =^ f state (init-bud state) - =^ f state (n state (changed-voting-proxy:l1 ~bud 0x123)) + =^ f state (n state (changed-voting-proxy:l1 ~bud (addr %bud-vkey))) voting-proxy.own:(~(got by points.state) ~bud) :: -++ test-l2-set-spawn-proxy ^- tang +++ test-l1-changed-keys ^- tang + =/ life 1 + =/ new-keys [~bud suit encr auth life] + :: %+ expect-eq - !> [0x123 0] + !> [suit auth encr] + :: + !> + =| =^state:naive + =^ f state (init-bud state) + =^ f state (n state (changed-keys:l1 new-keys)) + |1:keys.net:(~(got by points.state) ~bud) +:: +++ test-l1-star-escape-requested ^- tang + %+ expect-eq + !> [~ ~wes] + :: + !> + =| =^state:naive + =^ f state (init-wes state) + =^ f state (init-sambud state) + =^ f state (n state (escape-requested:l1 ~sambud ~wes)) + escape.net:(~(got by points.state) ~sambud) +:: +++ test-l1-star-escape-canceled ^- tang + %+ expect-eq + !> ~ + :: + !> + =| =^state:naive + =^ f state (init-wes state) + =^ f state (init-sambud state) + =^ f state (n state (escape-requested:l1 ~sambud ~wes)) + =^ f state (n state (escape-canceled:l1 ~sambud ~wes)) + escape.net:(~(got by points.state) ~sambud) +:: +++ test-l1-star-adopt-accept ^- tang + %+ expect-eq + !> [~ %.y ~wes] + :: + !> + =| =^state:naive + =^ f state (init-wes state) + =^ f state (init-sambud state) + =^ f state (n state (escape-requested:l1 ~sambud ~wes)) + =^ f state (n state (escape-accepted:l1 ~sambud ~wes)) + [escape.net sponsor.net]:(~(got by points.state) ~sambud) +:: +++ test-l1-star-lost-sponsor ^- tang + %+ expect-eq + !> [~ %.n ~bud] + :: + !> + =| =^state:naive + =^ f state (init-sambud state) + =^ f state (n state (lost-sponsor:l1 ~sambud ~bud)) + [escape.net sponsor.net]:(~(got by points.state) ~sambud) +:: +:: TODO: sponsorship tests for l1 planets, and L1/L2 sponsorship tests +:: +++ test-l2-set-spawn-proxy ^- tang + =/ marbud-sproxy [%set-spawn-proxy (addr %marbud-skey)] + :: + %+ expect-eq + !> [(addr %marbud-skey) 0] :: !> =| =^state:naive =^ f state (init-marbud state) - =^ f state (n state %bat q:(set-spawn-proxy:l2 0 ~marbud %marbud-key-0 %own 0x123)) + =^ f state (n state %bat q:(gen-tx 0 marbud-own marbud-sproxy)) spawn-proxy.own:(~(got by points.state) ~marbud) :: ++ test-l2-set-transfer-proxy ^- tang + =/ marbud-tproxy [%set-transfer-proxy (addr %marbud-tkey)] + :: %+ expect-eq - !> [0x123 0] + !> [(addr %marbud-tkey) 0] :: !> =| =^state:naive =^ f state (init-marbud state) - =^ f state (n state %bat q:(set-transfer-proxy:l2 0 ~marbud %marbud-key-0 %own 0x123)) + =^ f state (n state %bat q:(gen-tx 0 marbud-own marbud-tproxy)) transfer-proxy.own:(~(got by points.state) ~marbud) :: ++ test-l2-set-management-proxy ^- tang + =/ marbud-mproxy [%set-management-proxy (addr %marbud-mkey)] + :: %+ expect-eq - !> [0x123 0] + !> [(addr %marbud-mkey) 0] :: !> =| =^state:naive =^ f state (init-marbud state) - =^ f state (n state %bat q:(set-management-proxy:l2 0 ~marbud %marbud-key-0 %own 0x123)) + =^ f state (n state %bat q:(gen-tx 0 marbud-own marbud-mproxy)) management-proxy.own:(~(got by points.state) ~marbud) :: ++ test-l2-spawn-proxy-deposit ^- tang @@ -420,46 +344,271 @@ dominion:(~(got by points.state) ~dopbud) :: ++ test-marbud-l2-spawn ^- tang - %+ expect-eq - !> [`@ux`(addr %ll-key-0) 0] + =/ marbud-sproxy [%set-spawn-proxy (addr %marbud-skey)] + =/ lt-spawn [%spawn ~linnup-torsyx (addr %lt-key-0)] :: - !> - =| =^state:naive - =^ f state (init-marbud state) - =^ f state (n state %bat q:(spawn:l2 0 ~marbud %marbud-key-0 %own ~linnup-torsyx (addr %ll-key-0))) - transfer-proxy.own:(~(got by points.state) ~linnup-torsyx) + ;: weld + %+ expect-eq + :: Tests l2 spawning with ownership + !> [`@ux`(addr %lt-key-0) 0] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (n state %bat q:(gen-tx 0 marbud-own lt-spawn)) + transfer-proxy.own:(~(got by points.state) ~linnup-torsyx) + :: + %+ expect-eq + :: Tests l2 spawning with spawn proxy + !> [`@ux`(addr %lt-key-0) 0] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (n state %bat q:(gen-tx 0 marbud-own marbud-sproxy)) + =^ f state (n state %bat q:(gen-tx 0 marbud-spn lt-spawn)) + transfer-proxy.own:(~(got by points.state) ~linnup-torsyx) + == :: -++ test-marbud-l2-spawn-w-proxy ^- tang - %+ expect-eq - !> [`@ux`(addr %ll-key-0) 0] +++ test-marbud-l2-double-spawn ^- tang + :: Attempts to spawn the same planet twice, once with ownership and once with spawn proxy + =/ marbud-sproxy [%set-spawn-proxy (addr %marbud-skey)] + =/ lt-spawn-0 [%spawn ~linnup-torsyx (addr %lt-key-0)] + =/ lt-spawn-1 [%spawn ~linnup-torsyx (addr %lt-key-1)] :: - !> + %- expect-fail + |. =| =^state:naive =^ f state (init-marbud state) - =^ f state (n state %bat q:(set-spawn-proxy:l2 0 ~marbud %marbud-key-0 %own (addr %marbud-spawn-0))) - =^ f state (n state %bat q:(spawn:l2 0 ~marbud %marbud-spawn-0 %spawn ~linnup-torsyx (addr %ll-key-0))) - transfer-proxy.own:(~(got by points.state) ~linnup-torsyx) + =^ f state (n state %bat q:(gen-tx 0 marbud-own marbud-sproxy)) + =^ f state (n state %bat q:(gen-tx 1 marbud-own lt-spawn-0)) + =^ f state (n state %bat q:(gen-tx 0 marbud-spn lt-spawn-1)) + state +:: +++ test-marbud-l2-change-keys ^- tang + =/ new-keys [%configure-keys suit encr auth |] + =/ marbud-mproxy [%set-management-proxy (addr %marbud-mkey)] + :: + ;: weld + %+ expect-eq + !> [suit auth encr] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (n state %bat q:(gen-tx 0 marbud-own new-keys)) + |1:keys.net:(~(got by points.state) ~marbud) + :: + %+ expect-eq + !> [suit auth encr] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (n state %bat q:(gen-tx 0 marbud-own marbud-mproxy)) + =^ f state (n state %bat q:(gen-tx 0 marbud-mgt new-keys)) + |1:keys.net:(~(got by points.state) ~marbud) + :: + :: TODO: make sure nobody else can change these keys + == +:: +:: TODO: transfer breach via transfer proxy +++ test-marbud-l2-proxies-transfer ^- tang + =/ marbud-t1 [~marbud %marbud-key-1 %transfer] + =/ new-keys [%configure-keys suit encr auth |] + =/ marbud-sproxy [%set-spawn-proxy (addr %marbud-skey)] + =/ marbud-mproxy [%set-management-proxy (addr %marbud-mkey)] + =/ marbud-tproxy [%set-transfer-proxy (addr %marbud-key-1)] + =/ marbud-transfer-breach [%transfer-point (addr %marbud-key-1) &] + =/ marbud-transfer-no-breach [%transfer-point (addr %marbud-key-1) |] + :: + ;: weld + %+ expect-eq + :: Tests that proxies are reset on transfer with breach + :: + !> + :* [(addr %marbud-key-1) 3] :: ownership + [0 0] :: spawn-proxy + [0 0] :: management-proxy + [0 0] :: voting-proxy + [0 1] :: transfer-proxy + == + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (n state %bat q:(gen-tx 0 marbud-own marbud-sproxy)) + =^ f state (n state %bat q:(gen-tx 1 marbud-own marbud-mproxy)) + =^ f state (n state %bat q:(gen-tx 2 marbud-own marbud-tproxy)) + =^ f state (n state %bat q:(gen-tx 0 marbud-t1 marbud-transfer-breach)) + ^- [[@ @] [@ @] [@ @] [@ @] [@ @]] + own:(~(got by points.state) ~marbud) + :: + %+ expect-eq + :: Tests that networking keys are reset on transfer with breach + !> + [0 0 0] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (n state %bat q:(gen-tx 0 marbud-own new-keys)) + =^ f state (n state %bat q:(gen-tx 1 marbud-own [%transfer-point (addr %marbud-key-0) &])) + |1:keys.net:(~(got by points.state) ~marbud) + :: + %+ expect-eq + :: Tests that proxies are not reset when transfering without breach + !> + :* [(addr %marbud-key-1) 3] :: ownership + [(addr %marbud-skey) 0] :: spawn-proxy + [(addr %marbud-mkey) 0] :: management-proxy + [0 0] :: voting-proxy + [0 1] :: transfer-proxy + == + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (n state %bat q:(gen-tx 0 marbud-own marbud-sproxy)) + =^ f state (n state %bat q:(gen-tx 1 marbud-own marbud-mproxy)) + =^ f state (n state %bat q:(gen-tx 2 marbud-own marbud-tproxy)) + =^ f state (n state %bat q:(gen-tx 0 marbud-t1 marbud-transfer-no-breach)) + ^- [[@ @] [@ @] [@ @] [@ @] [@ @]] + own:(~(got by points.state) ~marbud) + :: + %+ expect-eq + :: Tests that networking keys are not reset when transfering without breach + !> + [suit auth encr] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (n state %bat q:(gen-tx 0 marbud-own new-keys)) + =^ f state (n state %bat q:(gen-tx 1 marbud-own [%transfer-point (addr %marbud-key-0) |])) + |1:keys.net:(~(got by points.state) ~marbud) + == +:: +:: TODO: life+rift changes via transfer proxy +:: +++ test-marbud-keys-life-rift ^- tang + =/ new-keys-no-reset [%configure-keys suit encr auth |] + =/ new-keys-yes-reset [%configure-keys suit encr auth &] + =/ zero-keys-no-reset [%configure-keys 0 0 0 |] + =/ zero-keys-yes-reset [%configure-keys 0 0 0 &] + :: + ;: weld + %+ expect-eq + :: breach=%.n + !> [0 1] :: [rift life] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (n state %bat q:(gen-tx 0 marbud-own new-keys-no-reset)) + [rift.net life.keys.net]:(~(got by points.state) ~marbud) + :: + %+ expect-eq + :: breach=%.y + !> [1 1] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (n state %bat q:(gen-tx 0 marbud-own new-keys-yes-reset)) + [rift.net life.keys.net]:(~(got by points.state) ~marbud) + :: + %+ expect-eq + :: networking keys set incremenets life, reset=%.y + :: then zero keys and transfer, should increment rift but not life + :: + !> [2 2] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (n state %bat q:(gen-tx 0 marbud-own new-keys-yes-reset)) :: inc life and rift + =^ f state (n state %bat q:(gen-tx 1 marbud-own zero-keys-no-reset)) :: inc life + =^ f state (n state %bat q:(gen-tx 2 marbud-own zero-keys-yes-reset)) :: inc rift + [rift.net life.keys.net]:(~(got by points.state) ~marbud) + :: + == +:: +++ test-marbud-transfer-life-rift ^- tang + =/ new-keys-no-reset [%configure-keys suit encr auth |] + =/ new-keys-yes-reset [%configure-keys suit encr auth &] + =/ zero-keys-no-reset [%configure-keys 0 0 0 |] + =/ zero-keys-yes-reset [%configure-keys 0 0 0 &] + =/ marbud-transfer-no-breach [%transfer-point (addr %marbud-key-1) |] + =/ marbud-transfer-yes-breach [%transfer-point (addr %marbud-key-1) &] + :: + ;: weld + %+ expect-eq + :: networking keys not set, reset=%.n + :: + !> [0 0] :: [rift life] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (n state %bat q:(gen-tx 0 marbud-own marbud-transfer-no-breach)) + [rift.net life.keys.net]:(~(got by points.state) ~marbud) + :: + %+ expect-eq + :: networking keys not set, reset=%.y + :: + !> [0 0] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (n state %bat q:(gen-tx 0 marbud-own marbud-transfer-no-breach)) + [rift.net life.keys.net]:(~(got by points.state) ~marbud) + :: + %+ expect-eq + :: networking keys set incremenets life, reset=%.y + :: then zero keys and transfer, should increment rift but not life + :: TODO: transferring and reset with already zeroed keys ought to incr rift but not life, right? + :: but currently the transfer w/ reset increments both life and rift, despite keys already being 0 + :: + !> [2 2] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (n state %bat q:(gen-tx 0 marbud-own new-keys-yes-reset)) :: inc life and rift + =^ f state (n state %bat q:(gen-tx 1 marbud-own zero-keys-no-reset)) :: inc life + =^ f state (n state %bat q:(gen-tx 2 marbud-own marbud-transfer-yes-breach)) :: inc rift + [rift.net life.keys.net]:(~(got by points.state) ~marbud) + :: + == :: ++ test-dopbud-l2-spawn ^- tang + =/ pp-spawn [%spawn ~palsep-picdun (addr %pp-key-0)] + :: %+ expect-eq !> [`@ux`(addr %pp-key-0) 0] :: !> =| =^state:naive =^ f state (init-dopbud state) - =^ f state (n state %bat q:(spawn:l2 0 ~dopbud %dopbud-key-0 %own ~palsep-picdun (addr %pp-key-0))) + =^ f state (n state %bat q:(gen-tx 0 dopbud-own pp-spawn)) transfer-proxy.own:(~(got by points.state) ~palsep-picdun) :: ++ test-dopbud-l2-spawn-after-transfer ^- tang + =/ pp-spawn [%spawn ~palsep-picdun (addr %pp-key-0)] + =/ lr-spawn [%spawn ~laclur-rachul (addr %lr-key-0)] + =/ dopbud-own-1 [~dopbud %dopbud-key-1 %own] + :: %+ expect-eq !> [`@ux`(addr %lr-key-0) 0] :: !> =| =^state:naive =^ f state (init-dopbud state) - =^ f state (n state %bat q:(spawn:l2 0 ~dopbud %dopbud-key-0 %own ~palsep-picdun (addr %pp-key-0))) + =^ f state (n state %bat q:(gen-tx 0 dopbud-own pp-spawn)) =^ f state (n state (owner-changed:l1 ~dopbud (addr %dopbud-key-1))) - =^ f state (n state %bat q:(spawn:l2 1 ~dopbud %dopbud-key-1 %own ~laclur-rachul (addr %lr-key-0))) + =^ f state (n state %bat q:(gen-tx 1 dopbud-own-1 lr-spawn)) transfer-proxy.own:(~(got by points.state) ~laclur-rachul) :: :: ++ test-sambud-double-spawn ^- tang @@ -493,27 +642,119 @@ :: state :: ++ test-linnup-torsyx-l2-transfer-ownership ^- tang + =/ lt-spawn [%spawn ~linnup-torsyx (addr %lt-key-0)] + =/ lt-transfer-yes-breach [%transfer-point (addr %lt-key-0) &] + :: %+ expect-eq !> [`@ux`(addr %lt-key-0) 0] :: !> =| =^state:naive =^ f state (init-marbud state) - =^ f state (n state %bat q:(spawn:l2 0 ~marbud %marbud-key-0 %own ~linnup-torsyx (addr %lt-key-0))) - =^ f state (n state %bat q:(transfer-point:l2 0 ~linnup-torsyx %lt-key-0 (addr %lt-key-0) %transfer &)) + =^ f state (n state %bat q:(gen-tx 0 marbud-own lt-spawn)) + =^ f state (n state %bat q:(gen-tx 0 lt-xfr lt-transfer-yes-breach)) owner.own:(~(got by points.state) ~linnup-torsyx) :: ++ test-palsep-picdun-l2-transfer-ownership ^- tang + =/ pp-xfr [~palsep-picdun %pp-key-0 %transfer] + =/ pp-spawn [%spawn ~palsep-picdun (addr %pp-key-0)] + =/ pp-transfer-yes-breach [%transfer-point (addr %pp-key-0) &] %+ expect-eq !> [`@ux`(addr %pp-key-0) 0] :: !> =| =^state:naive =^ f state (init-dopbud state) - =^ f state (n state %bat q:(spawn:l2 0 ~dopbud %dopbud-key-0 %own ~palsep-picdun (addr %pp-key-0))) - =^ f state (n state %bat q:(transfer-point:l2 0 ~palsep-picdun %pp-key-0 (addr %pp-key-0) %transfer &)) + =^ f state (n state %bat q:(gen-tx 0 dopbud-own pp-spawn)) + =^ f state (n state %bat q:(gen-tx 0 pp-xfr pp-transfer-yes-breach)) owner.own:(~(got by points.state) ~palsep-picdun) :: +++ test-linnup-torsyx-l2-escape-request ^- tang + :: TODO: Are you supposed to be able to request escape to a non-existent star? + =/ lt-spawn [%spawn ~linnup-torsyx (addr %lt-key-0)] + =/ lt-transfer-yes-breach [%transfer-point (addr %lt-key-0) &] + :: + %+ expect-eq + !> [~ ~litbud] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (init-litbud state) + =^ f state (n state %bat q:(gen-tx 0 marbud-own lt-spawn)) + =^ f state (n state %bat q:(gen-tx 0 lt-xfr lt-transfer-yes-breach)) + =^ f state (n state %bat q:(gen-tx 0 lt-own [%escape ~litbud])) + escape.net:(~(got by points.state) ~linnup-torsyx) +:: +++ test-linnup-torsyx-l2-cancel-escape-request ^- tang + =/ lt-spawn [%spawn ~linnup-torsyx (addr %lt-key-0)] + =/ lt-transfer-yes-breach [%transfer-point (addr %lt-key-0) &] + :: + %+ expect-eq + !> ~ + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (init-litbud state) + =^ f state (n state %bat q:(gen-tx 0 marbud-own lt-spawn)) + =^ f state (n state %bat q:(gen-tx 0 lt-xfr lt-transfer-yes-breach)) + =^ f state (n state %bat q:(gen-tx 0 lt-own [%escape ~litbud])) + =^ f state (n state %bat q:(gen-tx 1 lt-own [%cancel-escape ~litbud])) + escape.net:(~(got by points.state) ~linnup-torsyx) +:: +++ test-linnup-torsyx-l2-adopt-accept ^- tang + =/ lt-spawn [%spawn ~linnup-torsyx (addr %lt-key-0)] + =/ lt-transfer-yes-breach [%transfer-point (addr %lt-key-0) &] + :: + %+ expect-eq + !> [~ %.y ~litbud] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (init-litbud state) + =^ f state (n state %bat q:(gen-tx 0 marbud-own lt-spawn)) + =^ f state (n state %bat q:(gen-tx 0 lt-xfr lt-transfer-yes-breach)) + =^ f state (n state %bat q:(gen-tx 0 lt-own [%escape ~litbud])) + =^ f state (n state %bat q:(gen-tx 0 litbud-own [%adopt ~linnup-torsyx])) + [escape.net sponsor.net]:(~(got by points.state) ~linnup-torsyx) +:: +++ test-linnup-torsyx-l2-adopt-reject ^- tang + :: TODO: at the moment the default sponsor is always ~zod, but it should probably + :: be ~marbud here + =/ lt-spawn [%spawn ~linnup-torsyx (addr %lt-key-0)] + =/ lt-transfer-yes-breach [%transfer-point (addr %lt-key-0) &] + :: + %+ expect-eq + !> ~ + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (init-litbud state) + =^ f state (n state %bat q:(gen-tx 0 marbud-own lt-spawn)) + =^ f state (n state %bat q:(gen-tx 0 lt-xfr lt-transfer-yes-breach)) + =^ f state (n state %bat q:(gen-tx 0 lt-own [%escape ~litbud])) + =^ f state (n state %bat q:(gen-tx 0 litbud-own [%reject ~linnup-torsyx])) + escape.net:(~(got by points.state) ~linnup-torsyx) +:: +++ test-linnup-torsyx-l2-detach ^- tang + =/ lt-spawn [%spawn ~linnup-torsyx (addr %lt-key-0)] + =/ lt-transfer-yes-breach [%transfer-point (addr %lt-key-0) &] + :: + %+ expect-eq + !> [~ %.n ~marbud] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (init-litbud state) + =^ f state (n state %bat q:(gen-tx 0 marbud-own lt-spawn)) + =^ f state (n state %bat q:(gen-tx 0 lt-xfr lt-transfer-yes-breach)) + =^ f state (n state %bat q:(gen-tx 1 marbud-own [%detach ~linnup-torsyx])) + [escape.net sponsor.net]:(~(got by points.state) ~linnup-torsyx) +:: :: TODO: signature format changed; regenerate :: :: ++ test-metamask-signature ^- tang From 7c57a35ccc327102d3793acc19d4a18879af2b26 Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Mon, 17 May 2021 17:48:49 +0200 Subject: [PATCH 20/21] naive: wip aggregator compiles got it to compile and tested poke and scry from /app/azimuth-rpc.hoon --- pkg/arvo/app/aggregator.hoon | 142 +++++++++++++++++++++++------------ 1 file changed, 92 insertions(+), 50 deletions(-) diff --git a/pkg/arvo/app/aggregator.hoon b/pkg/arvo/app/aggregator.hoon index ad3c9ee99..6250ef2dc 100644 --- a/pkg/arvo/app/aggregator.hoon +++ b/pkg/arvo/app/aggregator.hoon @@ -26,8 +26,8 @@ ::TODO questions: :: - it's a bit weird how we just assume the raw and tx in raw-tx to match... :: -/+ naive, ethereum -/= ttttt /tests/lib/naive ::TODO use new lib +/+ naive, default-agent, ethereum, dbug, verb +/= ttttt /tests/lib/naive ::TODO use new lib :: ::TODO /sur file for public types |% @@ -40,7 +40,7 @@ :: next-nonce: next l1 nonce to use :: pending=(list pend-tx) - sending=(map nonce [next-gas-price=@ud txs=(list raw-tx:naive)]) + sending=(map nonce:naive [next-gas-price=@ud txs=(list raw-tx:naive)]) finding=(map keccak $?(%confirmed %failed l1-tx-pointer)) next-nonce=@ud :: @@ -88,14 +88,16 @@ :: ::TODO config? ++ contract 0xb581.01cd.3bbb.cc6f.a40b.cdb0.4bb7.1623.b5c7.d39b -++ chain-id 0x1 +++ chain-id '1' :: ++ resend-time ~m5 :: ++ lverb & -- :: -=| state=state-0 +=| state-0 +=* state - +:: %- agent:dbug %+ verb | ^- agent:gall @@ -103,6 +105,7 @@ =< |_ =bowl:gall +* this . + do ~(. +> bowl) def ~(. (default-agent this %|) bowl) :: ++ on-init @@ -120,13 +123,13 @@ ++ on-poke |= [=mark =vase] ^- (quip card _this) - ?+ mark (on-poke:def mark vase) - %noun $(mark %aggregator-action) - :: - %aggregator-action - !! - ::TODO - == + =^ cards state + ?+ mark (on-poke:def mark vase) + %aggregator-action + =+ !<(poke=action vase) + (on-action:do poke) + == + [cards this] :: +on-peek: scry paths ::TODO reevaluate wrt recent flow changes :: @@ -145,12 +148,20 @@ [%x %pending @ ~] =* wat i.t.t.path ?~ who=(slaw %p wat) + :: by-address + :: ?~ wer=(slaw %ux wat) [~ ~] + =; pending=(list pend-tx) + ``noun+!>(pending) %+ skim pending |= pend-tx ::TODO deduce address from sig.raw-tx ? !! + :: by-ship + :: + =; pending=(list pend-tx) + ``noun+!>(pending) %+ skim pending |= pend-tx =(u.who ship.from.tx.raw-tx) @@ -163,12 +174,12 @@ !> ^- tx-status ?^ status=(~(get by finding) u.keccak) ?@ u.status [u.status ~] - [%sending u.status] + [%sending status] ::TODO potentially slow! =; known=? [?:(known %pending %unknown) ~] %+ lien pending - |= [* raw-tx] + |= [* raw-tx:naive] =(u.keccak (hash-tx raw)) :: [%x %nonce @ @ ~] @@ -177,9 +188,9 @@ =+ proxy=i.t.t.t.path ?. ?=(proxy:naive proxy) [~ ~] - =^ * nas pending-state:do + =/ [* nas=^state:naive] pending-state:do ::TODO or should we ~ when !(~(has by points.nas) who) ? - =/ =point:naive (~(gut by points.nas) who *point) + =/ =point:naive (~(gut by points.nas) u.who *point:naive) =+ (proxy-from-point:naive proxy point) ``atom+!>(nonce) == @@ -187,7 +198,7 @@ ++ on-arvo |= [=wire =sign-arvo] ^- (quip card _this) - ?+ +<.sign (on-arvo:def wire sign) + ?+ +<.sign-arvo (on-arvo:def wire sign-arvo) %wake =^(cards state on-timer:do [cards this]) == :: @@ -220,24 +231,38 @@ |= [=wire thread=term arg=vase] ^- (list card) =/ tid=@ta (rap 3 thread '--' (scot %uv eny.bowl) ~) - =/ args [~ `tid thread arg] - :~ [%pass wire %agent [our.bowl %spider] %watch /thread-result/[tid]] - [%pass wire %agent [our.bowl %spider] %poke %spider-start !>(args)] + :~ (poke wire %spider-start !>([~ `tid thread arg])) + (watch wire %spider-start /thread-result/[tid]) == + :: + ++ poke + |= [=path =cage] + ^- card + [%pass path %agent [our.bowl %spider] %poke cage] + :: + ++ watch + |= [=path =sub=path] + ^- card + [%pass path %agent [our.bowl %spider] %watch sub-path] + :: + ++ leave + |= =path + ^- card + [%pass path %agent [our.bowl %spider] %leave ~] -- :: ++ hash-tx keccak-256:keccak:crypto :: ++ hash-raw-tx - |= raw-tx - (hash-tx raw) + |= =raw-tx:naive + (hash-tx raw.raw-tx) :: ++ part-tx-to-full |= =part-tx ^- [octs tx:naive] - ?- -.part-tx - %raw [+.part-tx (decode-tx:naive +.part-tx)] - %don [(encode-tx:naive +.part-tx) +.part-tx] + ?+ -.part-tx !! + :: %raw [+.part-tx (decode-tx:naive +.part-tx)] + :: %don [(encode-tx:naive +.part-tx) +.part-tx] %ful +.part-tx == :: +pending-state @@ -248,21 +273,21 @@ ::TODO maybe want to cache locally, refresh on %fact from azimuth? :: ++ pending-state - ^- [_pending state:naive] + ^- (quip pend-tx ^state:naive) :: load current, canonical state :: - =+ .^ nas=state:naive - %gx - (scot %p our.bowl) - %azimuth - (scot %da now.bowl) - /nas/nas - == + =+ .^ nas=^state:naive + %gx + (scot %p our.bowl) + %azimuth + (scot %da now.bowl) + /nas/nas + == :: apply our pending transactions ::TODO should also apply txs from sending map! :: =| valid=_pending - |- ^+ nas + |- ^+ [valid nas] ?~ pending [(flop valid) nas] :: =^ gud=? nas (try-apply nas i.pending) @@ -271,12 +296,12 @@ :: +try-apply: :: ++ try-apply - |= [nas=state:naive force=? =raw-tx:naive] + |= [nas=^state:naive force=? =raw-tx:naive] ^- [success=? _nas] - ?. (verify-sig-and-nonce:naive verifier:ttttt nas raw-tx) + ?. (verify-sig-and-nonce:naive verifier:ttttt chain-id nas raw-tx) [force nas] :: - =^ * nas (increment-nonce:naive nas from.tx.raw-tx) + =^ out points.nas (increment-nonce:naive nas from.tx.raw-tx) :: ?~ nex=(receive-tx:naive nas tx.raw-tx) [force nas] @@ -284,15 +309,20 @@ :: ++ on-action |= =action + ^- (quip card _state) ?- -.action - %commit send-roll + %commit !! :: TODO send-roll %config [~ state(frequency frequency.action)] %setkey [~ state(pk pk.action)] ::TODO what about existing sending entries? :: %submit =^ success state - %+ take-tx force.action + ^- [? _state] + %^ take-tx + force.action + sig.action (part-tx-to-full tx.action) + :: TODO: consider failure case ?> success [~ state] :: @@ -305,32 +335,36 @@ ++ take-tx |= [force=? =raw-tx:naive] ^- [success=? _state] - =/ [nep=_pending nas=state:naive] pending-state - =^ success nas - (try-apply nas force raw-tx) + =/ [nep=_pending nas=^state:naive] pending-state + =| success=? + :: TODO: actually use try-apply when proper Tx signing in place + :: + :: =^ success nas + :: (try-apply nas force raw-tx) ::TODO want to notify about dropped pendings, or no? client prolly polls... - =? pending success [[force raw-tx] nep] ::TODO probably +snoc instead? + =? pending success (snoc nep [force raw-tx]) ::TODO cache nas? [success state] :: +set-timer: %wait until next whole :frequency :: ++ set-timer ^- card - %+ wait /timer + %+ wait:b:sys /timer (mul +((div now.bowl frequency)) frequency) :: +on-timer: every :frequency, freeze :pending txs roll and start sending it :: ++ on-timer + ^- (quip card _state) =^ cards state ?~ pending [~ state] =/ nonce=@ud next-nonce - =: pending ~ + =: :: FIXME: what's up with this? `pending ~` also fails + :: pending *(list pend-tx) next-nonce +(next-nonce) :: sending %+ ~(put by sending) nonce - %+ turn pending - (cork tail (lead 0)) + [0 (turn pending tail)] == [(send-roll nonce) state] [[set-timer cards] state] @@ -350,7 +384,14 @@ %+ start-thread:spider /send/(scot %ud nonce) :- %aggregator-send - !>([nonce ~(got by sending) nonce)]) ::TODO other args + !> + :* endpoint + contract + chain-id + 0x1234.5678 + nonce + (~(got by sending) nonce) + == :: +on-thread-result: await resend after thread success or failure :: ++ on-thread-result @@ -367,7 +408,7 @@ :: resend the l1 tx in five minutes :: :_ state - [(wait /resend/(scot %ud nonce) (add resend-time now.bowl))]~ + [(wait:b:sys /resend/(scot %ud nonce) (add resend-time now.bowl))]~ :: +on-naive-diff: process l2 tx confirmations :: ++ on-naive-diff @@ -382,7 +423,7 @@ :: ?@ u.wer ~? &(?=(%confirmed u.wer) ?=(~ err.diff)) - [dap.bowl %weird-double-confirm from.tx] + [dap.bowl %weird-double-confirm from.tx.raw-tx.diff] [~ state] =* nonce nonce.u.wer :: remove the tx from the sending map @@ -393,6 +434,7 @@ sending ?~ nin=(find [raw-tx.diff]~ txs.u.sen) ~& [dap.bowl %weird-unknown] + sending =. txs.u.sen (oust [u.nin 1] txs.u.sen) ?~ txs.u.sen ~? lverb [dap.bowl %done-with-nonce nonce] From 152cf894ff0dee035b229d739a5c88ad6283848c Mon Sep 17 00:00:00 2001 From: yosoyubik Date: Mon, 17 May 2021 17:49:41 +0200 Subject: [PATCH 21/21] naive: hook rpc-api with aggregator --- pkg/arvo/app/azimuth-rpc.hoon | 34 +++--- pkg/arvo/lib/azimuth-rpc.hoon | 207 ++++++++++++++++++++++++---------- 2 files changed, 164 insertions(+), 77 deletions(-) diff --git a/pkg/arvo/app/azimuth-rpc.hoon b/pkg/arvo/app/azimuth-rpc.hoon index 88a2e3fd1..7320530f9 100644 --- a/pkg/arvo/app/azimuth-rpc.hoon +++ b/pkg/arvo/app/azimuth-rpc.hoon @@ -90,7 +90,7 @@ ?~ data ~ :_ ~ ^- card - [%pass / %agent [our.bowl %dice] %poke u.data] + [%pass / %agent [our.bowl %aggregator] %poke u.data] :: TODO: validate that format is e.g. 'getPoint' :: TODO: maybe use getPoint and translate to %get-point :: @@ -138,14 +138,14 @@ %transfer-point (transfer-point id +.params) %configure-keys (configure-keys id +.params) %spawn (spawn id +.params) - %escape (escape id +.params) - %cancel-escape (cancel-escape id +.params) - %adopt (adopt id +.params) - %detach (detach id +.params) - %reject (reject id +.params) - %set-management-proxy (management-proxy id +.params) - %set-spawn-proxy (spawn-proxy id +.params) - %set-transfer-proxy (transfer-proxy id +.params) + %escape (escape id +.params method) + %cancel-escape (cancel-escape id +.params method) + %adopt (adopt id +.params method) + %detach (detach id +.params method) + %reject (reject id +.params method) + %set-management-proxy (management-proxy id +.params method) + %set-spawn-proxy (spawn-proxy id +.params method) + %set-transfer-proxy (transfer-proxy id +.params method) %pending [~ (all:pending id +.params all:pending:scry)] %pending-by-ship [~ (ship:pending id +.params ship:pending:scry)] %pending-by-address [~ (addr:pending id +.params addr:pending:scry)] @@ -167,21 +167,21 @@ ++ all .^ (list pend-tx) %gx - (~(scry agentio bowl) %dice /pending/noun) + (~(scry agentio bowl) %aggregator /pending/noun) == :: ++ ship |= =^ship .^ (list pend-tx) %gx - (~(scry agentio bowl) %dice /pending/[(scot %p ship)]/noun) + (~(scry agentio bowl) %aggregator /pending/[(scot %p ship)]/noun) == :: ++ addr |= =address:naive .^ (list pend-tx) %gx - %+ ~(scry agentio bowl) %dice + %+ ~(scry agentio bowl) %aggregator /pending/[(scot %ux address)]/noun == -- @@ -193,7 +193,7 @@ :: .^ (list tx:naive) %gx - (~(scry agentio bowl) %dice /history/noun) + (~(scry agentio bowl) %aggregator /history/noun) == :: ++ ship @@ -202,7 +202,7 @@ :: .^ (list tx:naive) %gx - (~(scry agentio bowl) %dice /history/[(scot %p ship)]/noun) + (~(scry agentio bowl) %aggregator /history/[(scot %p ship)]/noun) == :: ++ addr @@ -211,7 +211,7 @@ :: .^ (list tx:naive) %gx - (~(scry agentio bowl) %dice /history/[(scot %ux address)]/noun) + (~(scry agentio bowl) %aggregator /history/[(scot %ux address)]/noun) == -- :: @@ -219,7 +219,7 @@ |= keccak=@ux .^ ^tx-status %gx - (~(scry agentio bowl) %dice /tx/[(scot %ux keccak)]/status/noun) + (~(scry agentio bowl) %aggregator /tx/[(scot %ux keccak)]/status/noun) == :: ++ nonce @@ -228,7 +228,7 @@ .^ @ %gx %+ ~(scry agentio bowl) - %dice + %aggregator /nonce/[(scot %p ship)]/[(scot %ux address)]/atom == -- diff --git a/pkg/arvo/lib/azimuth-rpc.hoon b/pkg/arvo/lib/azimuth-rpc.hoon index 9c20de491..78167fa37 100644 --- a/pkg/arvo/lib/azimuth-rpc.hoon +++ b/pkg/arvo/lib/azimuth-rpc.hoon @@ -6,6 +6,19 @@ => :: Utilities :: |% + +$ spawn-action + $? %escape + %cancel-escape + %adopt + %reject + %detach + == + :: + +$ proxy-action + $? %set-management-proxy + %set-spawn-proxy + %set-transfer-proxy + == :: FIXME: import tx-status, pend-tx from aggregator :: +$ tx-status @@ -30,52 +43,72 @@ ['breach' bo] == :: - ++ address-transfer - |= params=(map @t json) - ^- (unit [@ux ?]) - ?~ data=(~(get by params) 'data') ~ - =; ans=(unit [add=(unit @ux) r=?]) - ?~ ans ~ - ?~ add.u.ans ~ - (some [u.add.u.ans r.u.ans]) - %. u.data - =, dejs-soft:format - %- ot - ~[['address' (cu to-hex so)] ['reset' bo]] - :: - ++ address-ship - |= params=(map @t json) - ^- (unit [@ux @p]) - ?~ data=(~(get by params) 'data') ~ - =; ans=(unit [add=(unit @ux) ship=@p]) - ?~ ans ~ - ?~ add.u.ans ~ - (some [u.add.u.ans ship.u.ans]) - %. u.data - =, dejs-soft:format - %- ot - :~ ['address' (cu to-hex so)] - ['ship' (su ;~(pfix sig fed:ag))] - == - :: - ++ address - |= params=(map @t json) - ^- (unit @ux) - ?~ data=(~(get by params) 'data') ~ - =; ans=(unit (unit @ux)) - ?~(ans ~ u.ans) - =, dejs-soft:format - %. u.data - (ot ['address' (cu to-hex so)]~) - :: + ++ data + |% + ++ address-transfer + |= params=(map @t json) + ^- (unit [@ux ?]) + ?~ data=(~(get by params) 'data') ~ + =; ans=(unit [add=(unit @ux) r=?]) + ?~ ans ~ + ?~ add.u.ans ~ + (some [u.add.u.ans r.u.ans]) + %. u.data + =, dejs-soft:format + %- ot + ~[['address' (cu to-hex so)] ['reset' bo]] + :: + ++ address-ship + |= params=(map @t json) + ^- (unit [@p @ux]) + ?~ data=(~(get by params) 'data') ~ + =; ans=(unit [ship=@p add=(unit @ux)]) + ?~ ans ~ + ?~ add.u.ans ~ + (some [ship.u.ans u.add.u.ans]) + %. u.data + =, dejs-soft:format + %- ot + :~ ['ship' (su ;~(pfix sig fed:ag))] + ['address' (cu to-hex so)] + == + :: + ++ address + |= params=(map @t json) + ^- (unit @ux) + ?~ data=(~(get by params) 'data') ~ + =; ans=(unit (unit @ux)) + ?~(ans ~ u.ans) + =, dejs-soft:format + %. u.data + (ot ['address' (cu to-hex so)]~) + :: + ++ ship + |= params=(map @t json) + ^- (unit @p) + ?~ data=(~(get by params) 'data') ~ + =, dejs-soft:format + %. u.data + (ot ['ship' (su ;~(pfix sig fed:ag))]~) + -- + :: ++ ship |= params=(map @t json) ^- (unit @p) - ?~ data=(~(get by params) 'data') ~ + ?~ data=(~(get by params) 'ship') ~ =, dejs-soft:format %. u.data - (ot ['ship' (su ;~(pfix sig fed:ag))]~) - :: + (su ;~(pfix sig fed:ag)) + :: + ++ address + |= params=(map @t json) + ^- (unit @ux) + ?~ data=(~(get by params) 'address') ~ + =; ans=(unit (unit @ux)) + ?~(ans ~ u.ans) + =, dejs-soft:format + ((cu to-hex so) u.data) + :: ++ sig |= params=(map @t json) ^- (unit @) @@ -101,6 +134,17 @@ ?~(ans ~ u.ans) =, dejs-soft:format ((cu to-hex so) u.keccak) + :: + ++ raw + |= params=(map @t json) + ^- (unit octs) + ?~ raw=(~(get by params) 'raw') ~ + =; ans=(unit (unit @ux)) + ?~ ans ~ + ?~ u.ans ~ + (some (as-octs:mimes:html u.u.ans)) + =, dejs-soft:format + ((cu to-hex so) u.raw) -- :: ++ to-json @@ -251,33 +295,52 @@ ++ rpc-res |% ++ sponsor - |= [id=@t params=(map @t json)] + |= [id=@t params=(map @t json) action=spawn-action] ^- [(unit cage) response:rpc] - ?. =((lent ~(tap by params)) 3) + ?. (params:validate params) [~ ~(params error id)] =/ sig=(unit @) (sig:from-json params) =/ from=(unit [@p proxy:naive]) (from:from-json params) - =/ data=(unit [@ux @p]) (address-ship:from-json params) - ?. &(?=(^ sig) ?=(^ from) ?=(^ data)) + =/ raw=(unit octs) (raw:from-json params) + =/ data=(unit @p) (ship:data:from-json params) + ?. &(?=(^ sig) ?=(^ from) ?=(^ raw) ?=(^ data)) [~ ~(parse error id)] - :_ [%result id s+'ok'] + :_ [%result id s+'ok'] %- some - noun+!>([u.sig u.from u.data]) + :- %aggregator-action + !> + =; =skim-tx:naive + [%submit | u.sig %ful u.raw u.from skim-tx] + ?- action + %escape [%escape u.data] + %cancel-escape [%cancel-escape u.data] + %adopt [%adopt u.data] + %reject [%reject u.data] + %detach [%detach u.data] + == :: ++ proxy - |= [id=@t params=(map @t json)] + |= [id=@t params=(map @t json) action=proxy-action] ^- [(unit cage) response:rpc] - ?. =((lent ~(tap by params)) 3) + ?. (params:validate params) [~ ~(params error id)] =/ sig=(unit @) (sig:from-json params) =/ from=(unit [@p proxy:naive]) (from:from-json params) - =/ data=(unit @ux) (address:from-json params) - ?. &(?=(^ sig) ?=(^ from) ?=(^ data)) + =/ raw=(unit octs) (raw:from-json params) + =/ data=(unit @ux) (address:data:from-json params) + ?. &(?=(^ sig) ?=(^ from) ?=(^ raw) ?=(^ data)) [~ ~(parse error id)] :_ [%result id s+'ok'] %- some - noun+!>([u.sig u.from u.data]) - :: + :- %aggregator-action + !> + =; =skim-tx:naive + [%submit | u.sig %ful u.raw u.from skim-tx] + ?- action + %set-management-proxy [%set-management-proxy u.data] + %set-spawn-proxy [%set-spawn-proxy u.data] + %set-transfer-proxy [%set-transfer-proxy u.data] + == -- :: ++ error @@ -291,6 +354,14 @@ ++ internal [%error id '-32603' 'Internal error'] ++ not-found [%error id '-32000' 'Resource not found'] -- + :: + ++ validate + |% + ++ params + |= params=(map @t json) + ^- ? + =((lent ~(tap by params)) 4) + -- -- |% ++ get-point @@ -309,12 +380,13 @@ ++ transfer-point |= [id=@t params=(map @t json)] ^- [(unit cage) response:rpc] - ?. =((lent ~(tap by params)) 3) + ?. (params:validate params) [~ ~(params error id)] =/ sig=(unit @) (sig:from-json params) =/ from=(unit [ship @t]) (from:from-json params) - =/ data=(unit [@ux ?]) (address-transfer:from-json params) - ?: |(?=(~ sig) ?=(~ from) ?=(~ data)) + =/ raw=(unit octs) (raw:from-json params) + =/ data=(unit [@ux ?]) (address-transfer:data:from-json params) + ?: |(?=(~ sig) ?=(~ from) ?=(~ raw) ?=(~ data)) [~ ~(parse error id)] :_ [%result id s+'ok'] %- some @@ -323,19 +395,34 @@ ++ configure-keys |= [id=@t params=(map @t json)] ^- [(unit cage) response:rpc] - ?. =((lent ~(tap by params)) 3) + ?. (params:validate params) [~ ~(params error id)] =/ sig=(unit @) (sig:from-json params) =/ from=(unit [ship @t]) (from:from-json params) + =/ raw=(unit octs) (raw:from-json params) =/ data=(unit [encrypt=@ auth=@ crypto-suite=@ breach=?]) - (keys:from-json params) - ?. &(?=(^ sig) ?=(^ from) ?=(^ data)) + (keys:data:from-json params) + ?. &(?=(^ sig) ?=(^ from) ?=(^ raw) ?=(^ data)) [~ ~(parse error id)] :_ [%result id s+'ok'] %- some noun+!>([u.sig u.from u.data]) :: -++ spawn sponsor:rpc-res +++ spawn + |= [id=@t params=(map @t json)] + ^- [(unit cage) response:rpc] + ?. (params:validate params) + [~ ~(params error id)] + =/ sig=(unit @) (sig:from-json params) + =/ from=(unit [@p proxy:naive]) (from:from-json params) + =/ raw=(unit octs) (raw:from-json params) + =/ data=(unit [@p @ux]) (address-ship:data:from-json params) + ?. &(?=(^ sig) ?=(^ from) ?=(^ raw) ?=(^ data)) + [~ ~(parse error id)] + :_ [%result id s+'ok'] + %- some + aggregator-action+!>([%submit | u.sig %ful u.raw u.from %spawn u.data]) +:: ++ escape sponsor:rpc-res ++ cancel-escape sponsor:rpc-res ++ adopt sponsor:rpc-res