mirror of
https://github.com/urbit/shrub.git
synced 2024-12-15 04:22:48 +03:00
574 lines
15 KiB
Plaintext
574 lines
15 KiB
Plaintext
/- constitution, ethereum, json-rpc
|
|
/+ constitution, ethereum
|
|
::TODO =, ethereum / constitution causes bail fail. find minimal repro
|
|
=> [. constitution ^constitution ethereum]
|
|
=, eyre
|
|
|%
|
|
++ state
|
|
$: ships=fleet
|
|
checking=(map @p hull)
|
|
dns=dnses
|
|
heard=events
|
|
latest-block=@ud :: last heard
|
|
filter=@ud :: our filter id
|
|
config=configuration
|
|
==
|
|
::
|
|
++ configuration
|
|
$: src=source
|
|
poll-time=@dr
|
|
==
|
|
::
|
|
++ source
|
|
$% [%ship who=@p]
|
|
[%rpc url=purl]
|
|
==
|
|
::
|
|
::
|
|
+= move [bone card] :: [target side-effect]
|
|
++ card :: side-effect
|
|
$% [%peer wire gill:gall path]
|
|
[%pull wire gill:gall ~]
|
|
[%diff %constitution-update update]
|
|
[%hiss wire (unit user:eyre) mark [%hiss hiss]]
|
|
[%wait wire @da]
|
|
==
|
|
--
|
|
::
|
|
|_ {bol=bowl:gall state}
|
|
::
|
|
++ prep
|
|
|= old=(unit state)
|
|
^- (quip move _+>)
|
|
:: ?~ old
|
|
ta-save:ta-init:ta
|
|
:: [~ ..prep(+<+ u.old)]
|
|
::
|
|
++ ta
|
|
|_ $: moves=(list move) :: side-effects
|
|
diffs=(jar [@ud @ud] diff-constitution) :: changes per event
|
|
reqs=(list (pair (unit @t) request)) :: rpc requests
|
|
wir=wire :: wire for reqs
|
|
==
|
|
::
|
|
++ ta-save
|
|
^- (quip move _+>)
|
|
:_ ..ta
|
|
=- (weld - (flop moves))
|
|
%+ weld
|
|
^- (list move)
|
|
?~ reqs ~
|
|
=- [ost.bol -]~
|
|
%+ rpc-request:ca wir
|
|
a+(turn (flop reqs) request-to-json)
|
|
^- (list move)
|
|
%- zing
|
|
%+ turn ~(tap by diffs)
|
|
|= [cause=[@ud @ud] dis=(list diff-constitution)]
|
|
=. dis (flop dis)
|
|
^- (list move)
|
|
%+ murn ~(tap by sup.bol)
|
|
|= [b=bone s=ship p=path]
|
|
^- (unit move)
|
|
?. ?=([%state *] p) ~
|
|
`[b (updates:ca cause dis)]
|
|
::
|
|
++ ta-move
|
|
|= mov=move
|
|
%_(+> moves [mov moves])
|
|
::
|
|
++ ta-moves
|
|
|= mos=(list move)
|
|
%_(+> moves (weld (flop mos) moves))
|
|
::
|
|
++ ta-card
|
|
|= car=card
|
|
(ta-move [ost.bol car])
|
|
::
|
|
++ ta-to-all
|
|
|= upd=update
|
|
%- ta-moves
|
|
%+ murn ~(tap by sup.bol)
|
|
|= [b=bone s=ship p=path]
|
|
^- (unit move)
|
|
?. ?=([%state *] p) ~
|
|
`[b %diff %constitution-update upd]
|
|
::
|
|
++ ta-change
|
|
|= [cause=[@ud @ud] dif=diff-constitution]
|
|
(da(diffs (~(add ja diffs) cause dif)) cause [dif]~)
|
|
::
|
|
++ ta-changes
|
|
|= [cause=[@ud @ud] dis=(list diff-constitution)]
|
|
=- (da(diffs -) cause dis)
|
|
%+ ~(put by diffs) cause
|
|
(weld (flop dis) (~(get ja diffs) cause))
|
|
::
|
|
++ ta-request
|
|
|= [id=(unit @t) req=request]
|
|
%_(+> reqs [[id req] reqs])
|
|
::
|
|
++ ta-request-single
|
|
|= [wir=wire id=(unit @t) req=request]
|
|
%- ta-card
|
|
%+ rpc-request:ca wir
|
|
(request-to-json id req)
|
|
::
|
|
++ ta-read
|
|
|= cal=ships:function
|
|
=+ (ships:function-to-call cal)
|
|
%+ ta-request `id
|
|
:+ %eth-call
|
|
[~ ships:contracts ~ ~ ~ (encode-call dat)]
|
|
::NOTE we can't make read calls to not the latest block. however,
|
|
:: you risk getting data that filter polling hasn't yet seen,
|
|
:: so probably kick the filter before doing any important reads.
|
|
[%label %latest]
|
|
::
|
|
++ ta-read-ships
|
|
|= who=(list @p)
|
|
?~ who +>
|
|
=. +> (ta-read %ships i.who)
|
|
$(who t.who)
|
|
::
|
|
++ ta-read-dns
|
|
=+ inx=(gulf 0 2)
|
|
|-
|
|
?~ inx ..ta-read-dns
|
|
=. ..ta-read-dns (ta-read %dns-domains i.inx)
|
|
$(inx t.inx)
|
|
::
|
|
::
|
|
++ ta-new-filter
|
|
%- ta-request-single
|
|
:+ /filter/new `'new filter'
|
|
:* %eth-new-filter
|
|
`[%number +(latest-block)] ::TODO or Ships origin block when 0
|
|
~
|
|
~[ships:contracts]
|
|
~
|
|
==
|
|
::
|
|
++ ta-read-filter
|
|
%- ta-request-single
|
|
:+ /filter `'filter logs'
|
|
[%eth-get-filter-logs filter]
|
|
::
|
|
++ ta-poll-filter
|
|
%- ta-request-single
|
|
:+ /filter `'poll filter'
|
|
[%eth-get-filter-changes filter]
|
|
::
|
|
++ ta-wait-poll
|
|
%- ta-card
|
|
[%wait /poll (add now.bol poll-time.config)]
|
|
::
|
|
::
|
|
++ ta-init
|
|
=. poll-time.config ~m4
|
|
=+ bos=(sein:title our.bol)
|
|
?. =(our.bol bos)
|
|
=. src.config [%ship bos]
|
|
(ta-card (subscribe-to:ca bos))
|
|
=+ (need (de-purl:html 'http://localhost:8545'))
|
|
=. src.config [%rpc -(p.p |)]
|
|
ta-new-filter
|
|
::
|
|
++ ta-run-check
|
|
|= save=?
|
|
=. wir (weld /read ?:(save /reset /verify))
|
|
=< ta-read-dns
|
|
(ta-read-ships (gulf ~zod ~nec)) ::TODO ~fes
|
|
::
|
|
::
|
|
++ ta-serve (ta-card full-state:ca)
|
|
::
|
|
++ ta-assume
|
|
|= [s=fleet d=dnses h=events]
|
|
?: &(=(s ships) =(d dns) =(h heard)) +>
|
|
~& [%ta-assume ~(wyt by s) ~(wyt in h)]
|
|
(ta-to-all(ships s, dns d, heard h) %full s d h)
|
|
::
|
|
++ ta-accept
|
|
|= [cause=[@ud @ud] dis=(list diff-constitution)]
|
|
?: &(!=([0 0] cause) (~(has in heard) cause))
|
|
~& %ta-accept-ignoring-duplicate-event
|
|
+>.$
|
|
~& [%ta-accept (lent dis)]
|
|
(ta-changes cause dis)
|
|
::
|
|
::
|
|
++ ta-take-filter
|
|
|= rep=response:json-rpc
|
|
^+ +>
|
|
?< ?=(%batch -.rep)
|
|
?: ?=(%error -.rep)
|
|
~& [%filter-error--retrying message.rep]
|
|
ta-new-filter
|
|
=- ta-read-filter(filter -)
|
|
(parse-eth-new-filter-res res.rep)
|
|
::
|
|
++ ta-take-filter-results
|
|
|= rep=response:json-rpc
|
|
^+ +>
|
|
?< ?=(%batch -.rep)
|
|
?: ?=(%error -.rep)
|
|
?. =('filter not found' message.rep)
|
|
~& [%unhandled-filter-error message.rep]
|
|
+>
|
|
~& %filter-timed-out--recreating
|
|
ta-new-filter
|
|
=. +> ta-wait-poll
|
|
?> ?=(%a -.res.rep)
|
|
=* changes p.res.rep
|
|
~& [%filter-changes (lent changes)]
|
|
|- ^+ +>.^$
|
|
?~ changes +>.^$
|
|
=. +>.^$
|
|
(ta-take-event-log (parse-event-log i.changes))
|
|
$(changes t.changes)
|
|
::
|
|
++ ta-take-event-log
|
|
|= log=event-log
|
|
^+ +>
|
|
?~ mined.log
|
|
~& %ignoring-unmined-event
|
|
+>
|
|
::
|
|
::TODO if the block number is less than latest, that means we got
|
|
:: events out of order somehow and should probably reset.
|
|
::
|
|
=* place u.mined.log
|
|
?: (~(has in heard) block-number.place log-index.place)
|
|
~& %ignoring-duplicate-event
|
|
+>
|
|
=+ cuz=[block-number.place log-index.place]
|
|
::
|
|
?: =(event.log changed-dns:ships-events)
|
|
=+ ^- [pri=tape sec=tape ter=tape]
|
|
(decode-results data.log ~[%string %string %string])
|
|
=? +>.$ !=(pri.dns (crip pri))
|
|
(ta-change cuz %dns 0 (crip pri))
|
|
=? +>.$ !=(sec.dns (crip sec))
|
|
(ta-change cuz %dns 1 (crip sec))
|
|
=? +>.$ !=(ter.dns (crip ter))
|
|
(ta-change cuz %dns 2 (crip ter))
|
|
+>.$
|
|
::
|
|
=+ dis=(event-log-to-hull-diffs log)
|
|
?~ dis +>.$
|
|
(ta-change cuz %hull i.dis)
|
|
::
|
|
::
|
|
++ ta-take-read-results
|
|
|= [rep=response:json-rpc save=?]
|
|
^+ +>
|
|
?> ?=(%batch -.rep)
|
|
=. wir (weld /read ?:(save /reset /verify))
|
|
|- ^+ +>.^$
|
|
?~ bas.rep +>.^$
|
|
=. +>.^$
|
|
(ta-take-read-result i.bas.rep save)
|
|
$(bas.rep t.bas.rep)
|
|
::
|
|
++ ta-take-read-result
|
|
|= [rep=response:json-rpc save=?]
|
|
^+ +>
|
|
?< ?=(%batch -.rep)
|
|
?: ?=(%error -.rep)
|
|
~& [%unhandled-read-error id.rep message.rep]
|
|
+>
|
|
=/ cal=ships:function (parse-id id.rep)
|
|
::TODO think about a better way to structure the comparison code below
|
|
?- -.cal :: ~&([%unhandled-read-result -.cal] +>.$)
|
|
%ships
|
|
?> ?=(%s -.res.rep)
|
|
=/ hul=hull:eth-noun
|
|
~| [id.rep p.res.rep]
|
|
(decode-results p.res.rep hull:eth-type)
|
|
:: ignore inactive ships
|
|
?. active.hul +>.$
|
|
:: we store the read data for now, and only compare with state once we
|
|
:: have completed it by learning the spawned ships.
|
|
=. checking (~(put by checking) who.cal (hull-from-eth hul))
|
|
(ta-read %get-spawned who.cal)
|
|
::
|
|
%get-spawned
|
|
?> ?=(%s -.res.rep)
|
|
=+ hul=(~(got by checking) who.cal)
|
|
=/ kis=(list @p)
|
|
::TODO can we let this be if we're cool with just @ ?
|
|
%- (list @p) ::NOTE because arrays are still typeless
|
|
(decode-results p.res.rep [%array %uint]~)
|
|
=. hul hul(spawned (~(gas in *(set @p)) kis))
|
|
::
|
|
=+ have=(~(get by ships) who.cal)
|
|
=. +>.$
|
|
?~ have
|
|
~& [%completely-missing who.cal]
|
|
?. save +>.$
|
|
~& [%storing-chain-version-of who.cal]
|
|
(ta-change [0 0] %hull who.cal %full hul)
|
|
::
|
|
=* huv state.u.have
|
|
?: =(huv hul) +>.$
|
|
~& [%differs-from-chain-version who.cal]
|
|
~& [%what %have %chain]
|
|
::TODO can we maybe re-use some ++redo code to simplify this?
|
|
~? !=(owner.huv owner.hul)
|
|
:- %owner-differs
|
|
[owner.huv owner.hul]
|
|
~? !=(encryption-key.huv encryption-key.hul)
|
|
:- %encryption-key-differs
|
|
[encryption-key.huv encryption-key.hul]
|
|
~? !=(authentication-key.huv authentication-key.hul)
|
|
:- %authentication-key-differs
|
|
[authentication-key.huv authentication-key.hul]
|
|
~? !=(key-revision.huv key-revision.hul)
|
|
:- %key-revision-differs
|
|
[key-revision.huv key-revision.hul]
|
|
~? !=(spawn-count.huv spawn-count.hul)
|
|
:- %spawn-count-differs
|
|
[spawn-count.huv spawn-count.hul]
|
|
~? !=(spawned.huv spawned.hul)
|
|
:- %spawned-differs
|
|
[spawned.huv spawned.hul]
|
|
~? !=(sponsor.huv sponsor.hul)
|
|
:- %sponsor-differs
|
|
[sponsor.huv sponsor.hul]
|
|
~? !=(escape.huv escape.hul)
|
|
:- %escape-differs
|
|
[escape.huv escape.hul]
|
|
~? !=(spawn-proxy.huv spawn-proxy.hul)
|
|
:- %spawn-proxy-differs
|
|
[spawn-proxy.huv spawn-proxy.hul]
|
|
~? !=(transfer-proxy.huv transfer-proxy.hul)
|
|
:- %transfer-proxy-differs
|
|
[transfer-proxy.huv transfer-proxy.hul]
|
|
::
|
|
~& %$
|
|
?. save +>.$
|
|
~& [%storing-chain-version-of who.cal]
|
|
(ta-change [0 0] %hull who.cal %full hul)
|
|
::
|
|
=. checking (~(del by checking) who.cal)
|
|
(ta-read-ships kis)
|
|
::
|
|
%dns-domains
|
|
?> ?=(%s -.res.rep)
|
|
=+ dom=(crip (decode-results p.res.rep ~[%string]))
|
|
?: =(0 ind.cal)
|
|
?: =(pri.dns dom) +>.$
|
|
~& [%primary-dns-differs pri.dns dom]
|
|
?. save +>.$
|
|
(ta-change [0 0] %dns 0 dom)
|
|
?: =(1 ind.cal)
|
|
?: =(sec.dns dom) +>.$
|
|
~& [%secondary-dns-differs sec.dns dom]
|
|
?. save +>.$
|
|
(ta-change [0 0] %dns 1 dom)
|
|
?: =(2 ind.cal)
|
|
?: =(ter.dns dom) +>.$
|
|
~& [%tertiary-dns-differs ter.dns dom]
|
|
?. save +>.$
|
|
(ta-change [0 0] %dns 2 dom)
|
|
!!
|
|
==
|
|
::
|
|
::
|
|
++ da
|
|
|= [[block=@ud log=@ud] dis=(list diff-constitution)]
|
|
^+ +>
|
|
=. heard (~(put in heard) block log)
|
|
=. latest-block (max latest-block block)
|
|
|^ ?~ dis +>.^$
|
|
=. ..da
|
|
=* dif i.dis
|
|
?- -.dif
|
|
%hull (da-hull +.dif)
|
|
%dns (da-dns +.dif)
|
|
==
|
|
$(dis t.dis)
|
|
::
|
|
++ da-hull
|
|
|= [who=@p dif=diff-hull]
|
|
=- ..da(ships -)
|
|
:: if new, first dif must be %full
|
|
?> |((~(has by ships) who) ?=(%full -.dif))
|
|
=+ old=(fall (~(get by ships) who) *complete-ship)
|
|
:: catch key changes, store them in the key map
|
|
=? keys.old ?=(%keys -.dif)
|
|
~? &((gth rev.dif 0) !(~(has by keys.old) (dec rev.dif)))
|
|
[%missing-previous-key-rev who (dec rev.dif)]
|
|
(~(put by keys.old) rev.dif enc.dif aut.dif)
|
|
:: for full, store the new keys in case we don't have them yet
|
|
=? keys.old ?=(%full -.dif)
|
|
=, new.dif
|
|
~? &((gth key-revision 0) !(~(has by keys.old) (dec key-revision)))
|
|
[%missing-previous-key-rev who (dec key-revision)]
|
|
%+ ~(put by keys.old) key-revision
|
|
[encryption-key authentication-key]
|
|
=. state.old (apply-hull-diff state.old dif)
|
|
=. history.old [dif history.old]
|
|
:: apply dif to ship state
|
|
(~(put by ships) who old)
|
|
::
|
|
++ da-dns
|
|
|= [ind=@ud new=@t]
|
|
?: =(0 ind) ..da(pri.dns new)
|
|
?: =(1 ind) ..da(sec.dns new)
|
|
?: =(2 ind) ..da(ter.dns new)
|
|
!!
|
|
::
|
|
++ da-heard
|
|
|= [block=@ud log=@ud]
|
|
=- ..da(heard har, latest-block las)
|
|
^- [har=(set (pair @ud @ud)) las=@ud]
|
|
:- (~(put in heard) block log)
|
|
(max latest-block block)
|
|
--
|
|
--
|
|
::
|
|
:: arms for card generation
|
|
++ ca
|
|
|%
|
|
++ rpc-request
|
|
|= [w=wire j=json]
|
|
^- card
|
|
:^ %hiss w ~
|
|
:+ %json-rpc-response %hiss
|
|
=- (json-request - j)
|
|
?> ?=(%rpc -.src.config)
|
|
url.src.config
|
|
::
|
|
++ subscribe-to
|
|
|= who=@p
|
|
^- card
|
|
:* %peer
|
|
/source/(scot %p who)
|
|
[who dap.bol]
|
|
/state
|
|
==
|
|
::
|
|
++ unsubscribe-from
|
|
|= who=@p
|
|
^- card
|
|
:* %pull
|
|
/source/(scot %p who)
|
|
[who dap.bol]
|
|
~
|
|
==
|
|
::
|
|
++ full-state
|
|
^- card
|
|
:+ %diff %constitution-update
|
|
[%full ships dns heard]
|
|
::
|
|
++ updates
|
|
|= [cause=[@ud @ud] dis=(list diff-constitution)]
|
|
^- card
|
|
[%diff %constitution-update %diff cause dis]
|
|
--
|
|
::
|
|
++ hull-from-eth
|
|
|= hul=hull:eth-noun
|
|
^- hull
|
|
=, hul
|
|
:* owner
|
|
::
|
|
?> =(32 p.encryption-key)
|
|
`@`q.encryption-key
|
|
::
|
|
?> =(32 p.authentication-key)
|
|
`@`q.authentication-key
|
|
::
|
|
key-revision
|
|
::
|
|
spawn-count
|
|
::
|
|
~
|
|
::
|
|
`@p`sponsor
|
|
::
|
|
?. escape-requested ~
|
|
``@p`escape-to
|
|
::
|
|
spawn-proxy
|
|
transfer-proxy
|
|
==
|
|
::
|
|
++ poke-noun
|
|
|= a/@
|
|
^- (quip move _+>)
|
|
?> =(src.bol our.bol)
|
|
=< ta-save
|
|
?: =(a 0)
|
|
~& [%have-ships ~(key by ships)]
|
|
~& [%zod (~(get by ships) ~zod)]
|
|
ta
|
|
?: =(a 1) ta-poll-filter:ta
|
|
?: =(a 2) ta-new-filter:ta
|
|
?: =(a 3) ta-read-filter:ta
|
|
?: =(a 4) (ta-run-check:ta |)
|
|
?: =(a 5) (ta-run-check:ta &)
|
|
ta
|
|
::
|
|
::
|
|
++ peer-state
|
|
|= p=path
|
|
^- (quip move _+>)
|
|
~& %peer-state
|
|
~? ?=(^ p) [%ignoring-specific-state p]
|
|
ta-save:ta-serve:ta
|
|
::
|
|
++ diff-constitution-update
|
|
|= [w=wire u=update]
|
|
^- (quip move _+>)
|
|
=< ta-save
|
|
?- -.u
|
|
%full (ta-assume:ta +.u)
|
|
%diff (ta-accept:ta +.u)
|
|
==
|
|
::
|
|
::
|
|
:: when we get the timer: poll filter
|
|
++ wake-poll
|
|
|= [w=wire ~]
|
|
^- (quip move _+>)
|
|
?. ?=(%rpc -.src.config) [~ +>]
|
|
~& [%waking-for-poll ost.bol now.bol]
|
|
::TODO maybe we need a way to get rid of double timers if they ever occur?
|
|
ta-save:ta-poll-filter:ta
|
|
::
|
|
++ sigh-tang
|
|
|= [w=wire t=tang]
|
|
^- (quip move _+>)
|
|
~& [%failed-sigh w]
|
|
~& (turn t (cury wash [0 80]))
|
|
::TODO actually do error handling, be sure to continue the thing the request
|
|
:: was trying to do.
|
|
[~ +>.$]
|
|
::
|
|
:: when we get a new filter: read it, kick timer
|
|
:: when we get log or poll results: apply them
|
|
++ sigh-json-rpc-response-filter
|
|
|= [w=wire r=response:json-rpc]
|
|
^- (quip move _+>)
|
|
?. ?=(%rpc -.src.config) [~ +>]
|
|
=< ta-save
|
|
?: ?=([%new *] w)
|
|
(ta-take-filter:ta r)
|
|
(ta-take-filter-results:ta r)
|
|
::
|
|
:: when we get read results: verify/reset
|
|
++ sigh-json-rpc-response-read
|
|
|= [w=wire r=response:json-rpc]
|
|
^- (quip move _+>)
|
|
?. ?=(%rpc -.src.config) [~ +>]
|
|
=< ta-save
|
|
?+ w ~&(%unknown-read-reason ta)
|
|
[%verify ~] (ta-take-read-results:ta r |)
|
|
[%reset ~] (ta-take-read-results:ta r &)
|
|
==
|
|
--
|