diff --git a/.gitattributes b/.gitattributes index cc987fbdb..27a039ad1 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,9 +1,11 @@ bin/* filter=lfs diff=lfs merge=lfs -text bin/*/* filter=lfs diff=lfs merge=lfs -text pkg/arvo/**/*.css binary +pkg/arvo/app/naive/logs.eth-logs filter=lfs diff=lfs merge=lfs -text **/package-lock.json binary merge=theirs pkg/arvo/tmp/garden.jam filter=lfs diff=lfs merge=lfs -text pkg/arvo/tmp/landscape.jam filter=lfs diff=lfs merge=lfs -text pkg/arvo/tmp/base.jam filter=lfs diff=lfs merge=lfs -text pkg/arvo/tmp/bitcoin.jam filter=lfs diff=lfs merge=lfs -text pkg/arvo/tmp/webterm.jam filter=lfs diff=lfs merge=lfs -text + diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 02ce63901..afdc9188e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -74,15 +74,15 @@ jobs: # for the docker build. We don't want in on Mac, where it isn't but # it breaks the nix install. The two `if` clauses should be mutually # exclusive - - uses: cachix/install-nix-action@v12 + - uses: cachix/install-nix-action@v13 with: extra_nix_config: | system-features = nixos-test benchmark big-parallel kvm if: ${{ matrix.os == 'ubuntu-latest' }} - - uses: cachix/install-nix-action@v12 + - uses: cachix/install-nix-action@v13 if: ${{ matrix.os != 'ubuntu-latest' }} - - uses: cachix/cachix-action@v8 + - uses: cachix/cachix-action@v10 with: name: ares authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} @@ -107,8 +107,8 @@ jobs: steps: - uses: actions/checkout@v2 - - uses: cachix/install-nix-action@v12 - - uses: cachix/cachix-action@v8 + - uses: cachix/install-nix-action@v13 + - uses: cachix/cachix-action@v10 with: name: ares authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} diff --git a/.github/workflows/ops-group-timer.yml b/.github/workflows/ops-group-timer.yml deleted file mode 100644 index f28a615ab..000000000 --- a/.github/workflows/ops-group-timer.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: group-timer -on: - push: - branches: - - 'ops/group-timer' -jobs: - glob: - runs-on: ubuntu-latest - name: "Create and deploy a glob to ~difmex-passed" - steps: - - uses: actions/checkout@v2 - with: - lfs: true - - uses: ./.github/actions/glob - with: - ship: 'difmex-passed' - credentials: ${{ secrets.JANEWAY_SERVICE_KEY }} - ssh-sec-key: ${{ secrets.JANEWAY_SSH_SEC_KEY }} - ssh-pub-key: ${{ secrets.JANEWAY_SSH_PUB_KEY }} - diff --git a/.github/workflows/release-docker.yml b/.github/workflows/release-docker.yml index bae515601..8f49b6d03 100644 --- a/.github/workflows/release-docker.yml +++ b/.github/workflows/release-docker.yml @@ -16,11 +16,11 @@ jobs: steps: - uses: actions/checkout@v2 - - uses: cachix/install-nix-action@v12 + - uses: cachix/install-nix-action@v13 with: extra_nix_config: | system-features = nixos-test benchmark big-parallel kvm - - uses: cachix/cachix-action@v8 + - uses: cachix/cachix-action@v10 with: name: ares authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index db22e4b8d..e42e79dc4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,8 +17,8 @@ jobs: steps: - uses: actions/checkout@v2 - - uses: cachix/install-nix-action@v12 - - uses: cachix/cachix-action@v8 + - uses: cachix/install-nix-action@v13 + - uses: cachix/cachix-action@v10 with: name: ${{ secrets.CACHIX_NAME }} authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} @@ -35,7 +35,8 @@ jobs: - name: Run upload to bootstrap.urbit.org run: | version="$(cat ./pkg/urbit/version)" - system="$(nix eval --raw '(builtins.currentSystem)')" + system="$(nix-instantiate --eval --expr 'builtins.currentSystem')" + system=${system:1:${#system}-2} target="gs://bootstrap.urbit.org/ci/urbit-v${version}-${system}-${GITHUB_SHA:0:9}.tgz" gsutil cp -n ./result "$target" diff --git a/.vercel/README.txt b/.vercel/README.txt deleted file mode 100644 index 525d8ce8e..000000000 --- a/.vercel/README.txt +++ /dev/null @@ -1,11 +0,0 @@ -> Why do I have a folder named ".vercel" in my project? -The ".vercel" folder is created when you link a directory to a Vercel project. - -> What does the "project.json" file contain? -The "project.json" file contains: -- The ID of the Vercel project that you linked ("projectId") -- The ID of the user or team your Vercel project is owned by ("orgId") - -> Should I commit the ".vercel" folder? -No, you should not share the ".vercel" folder with anyone. -Upon creation, it will be automatically added to your ".gitignore" file. diff --git a/.vercel/project.json b/.vercel/project.json deleted file mode 100644 index 3ffe22dfc..000000000 --- a/.vercel/project.json +++ /dev/null @@ -1 +0,0 @@ -{"orgId":"EDiU8DZExvM9N4unZGYQbG3d","projectId":"prj_fbAU5smemBgtr5t8lsk5ZoT9zNtI"} \ No newline at end of file diff --git a/bin/ivory.pill b/bin/ivory.pill index 703d7d9dc..33b0f0a2c 100644 --- a/bin/ivory.pill +++ b/bin/ivory.pill @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f50aee74e4f3dd6685d36520bbc924ab94d3d47a7bc86e649882e58ab069e7dd -size 991930 +oid sha256:f59ec4eaf907227a1fd64e1d54810b769b5d39f6811c6bb254b2e89de528ca04 +size 1209494 diff --git a/bin/multi-brass.pill b/bin/multi-brass.pill index 05a99aec6..12abdd5f0 100644 --- a/bin/multi-brass.pill +++ b/bin/multi-brass.pill @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:049801d388b4cb7203854b4668826688c21089f90430bd547d276e7b59386e8d -size 5588170 +oid sha256:6f48518fe49584a6532a20018f4ac4eae3817b25d85d60536a99643eb5d65b2b +size 22872573 diff --git a/bin/solid.pill b/bin/solid.pill index 8b7f8682c..1da0adbc3 100644 --- a/bin/solid.pill +++ b/bin/solid.pill @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d8d387759fe4830fcc09a1fc7b80d52e61327d518f7eb0713697aec1819eacf7 -size 5608210 +oid sha256:c29577dc949ac0689ba3c97ad13b812ea6c3c6cc9d255b770d2da95fd9af84b9 +size 23121802 diff --git a/nix/lib/boot-fake-ship.nix b/nix/lib/boot-fake-ship.nix index 610f9f0e7..9a5d01ea9 100644 --- a/nix/lib/boot-fake-ship.nix +++ b/nix/lib/boot-fake-ship.nix @@ -41,6 +41,10 @@ in stdenvNoCC.mkDerivation { if check && sleep 10 && check; then header "boot success" herb ./pier -p hood -d '+hood/exit' + while [ -f ./pier/.vere.lock ]; do + echo "waiting for pier to shut down" + sleep 5 + done else header "boot failure" kill $(< ./pier/.vere.lock) || true @@ -49,6 +53,8 @@ in stdenvNoCC.mkDerivation { ''; installPhase = '' + ls + ls -a ./pier mv ./pier $out ''; } diff --git a/pkg/arvo/app/acme.hoon b/pkg/arvo/app/acme.hoon index 7d64a69f3..cd2a2a09b 100644 --- a/pkg/arvo/app/acme.hoon +++ b/pkg/arvo/app/acme.hoon @@ -588,7 +588,7 @@ :: =/ =purl :- [sec=| por=~ host=[%& turf.next]] - [[ext=`~.udon path=/static] query=~] + [[ext=~ path=/'~debug'] query=~] =/ =wire (acme-wire try %validate-domain /idx/(scot %ud idx.next)) (emit (request wire purl %get ~ ~)) @@ -1300,11 +1300,11 @@ ~& [%failed-order-history fal.hit] this :: - :: install privkey and cert .pem from /=home=/acme, ignores app state + :: install privkey and cert .pem from /=base=/acme, ignores app state ::TODO refactor this out of %acme, see also arvo#1151 :: %install-from-clay - =/ bas=path /(scot %p our.bow)/home/(scot %da now.bow)/acme + =/ bas=path /(scot %p our.bow)/base/(scot %da now.bow)/acme =/ key=wain .^(wain %cx (weld bas /privkey/pem)) =/ cer=wain .^(wain %cx (weld bas /cert/pem)) (emit %pass /install %arvo %e %rule %cert `[key cer]) diff --git a/pkg/arvo/app/azimuth-rpc.hoon b/pkg/arvo/app/azimuth-rpc.hoon new file mode 100644 index 000000000..832971233 --- /dev/null +++ b/pkg/arvo/app/azimuth-rpc.hoon @@ -0,0 +1,182 @@ +:: Azimuth JSON-RPC API +:: +/- rpc=json-rpc +/+ naive, + azimuth-roll-rpc, + json-rpc, + *server, + default-agent, + verb, + dbug, + agentio +|% +:: ++$ 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) + :: TODO: malformed request + :: + (give-simple-payload:app id not-found:gen) + =/ [data=(list cage) response=simple-payload:http] + (process-rpc-request:do u.rpc-request) + %+ weld + (give-simple-payload:app id response) + |- + ?~ data ~ + :_ $(data t.data) + ^- card + [%pass / %agent [our.bowl %azimuth] %poke i.data] + -- + -- + :: + ++ 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=batch-request:rpc + ^- [(list cage) simple-payload:http] + |^ + ?- -.req + %o + =/ [data=(unit cage) =response:rpc] + (process p.req) + [(drop data) (render response)] + :: + %a + =| data=(list cage) + =| resp=(list response:rpc) + |- + ?~ p.req + [(flop data) (render %batch (flop resp))] + =/ [dat=(unit cage) res=response:rpc] + (process i.p.req) + =? data ?=(^ dat) [u.dat data] + $(p.req t.p.req, resp [res resp]) + == + :: + ++ render + |= res=response:rpc + %- json-response:gen + (response-to-json:json-rpc res) + :: + ++ process + |= request:rpc + =, azimuth-roll-rpc + ?. ?=([%map *] params) + [~ ~(parse error:json-rpc id)] + =/ method=@tas (enkebab method) + ?+ method [~ ~(method error:json-rpc id)] + %get-point `(get-point id +.params point:scry) + %get-dns `(get-dns id +.params dns:scry) + %get-naive-state `(get-naive id +.params naive-state:scry) + %get-refresh `(get-refresh id +.params refresh:scry) + == + -- +:: +++ scry + |% + ++ point + |= =ship + .^ (unit point:naive) + %gx + (~(scry agentio bowl) %azimuth /point/(scot %p ship)/noun) + == + :: + ++ dns + .^ (list @t) + %gx + (~(scry agentio bowl) %azimuth /dns/noun) + == + :: + ++ naive-state + .^ ^state:naive + %gx + (~(scry agentio bowl) %azimuth /nas/noun) + == + :: + ++ refresh + .^ @dr + %gx + (~(scry agentio bowl) %azimuth /refresh/noun) + == + -- +-- diff --git a/pkg/arvo/app/azimuth-tracker.hoon b/pkg/arvo/app/azimuth-tracker.hoon index 4b6766e4d..3bb450579 100644 --- a/pkg/arvo/app/azimuth-tracker.hoon +++ b/pkg/arvo/app/azimuth-tracker.hoon @@ -94,6 +94,7 @@ :* url.state =(%czar (clan:title our)) ~m5 ~m30 launch:contracts:azimuth ~[azimuth:contracts:azimuth] + ~ (topics whos.state) == [%pass /wa %agent [our %eth-watcher] %poke %eth-watcher-poke args] diff --git a/pkg/arvo/app/azimuth.hoon b/pkg/arvo/app/azimuth.hoon new file mode 100644 index 000000000..634505fde --- /dev/null +++ b/pkg/arvo/app/azimuth.hoon @@ -0,0 +1,419 @@ +/- eth-watcher, *dice +/+ ethereum, + azimuth, + naive, + dice, + default-agent, + verb, + dbug +:: Generally don't update the snapshot until we have clay tombstoning. +:: To update, run: +:: =e -build-file %/lib/ethereum/hoon +:: =l .^((list event-log:rpc:e) %gx /=azimuth=/logs/noun) +:: */app/azimuth/logs/eth-logs ð-logs l +:: +/* snap %eth-logs /app/azimuth/logs/eth-logs +:: +=/ last-snap :: maybe just use the last one? + %+ roll `(list event-log:rpc:ethereum)`snap ::~ + |= [log=event-log:rpc:ethereum last=@ud] + ?~ mined.log + last + (max block-number.u.mined.log last) +:: +=, jael +|% ++$ app-state + $: %2 + url=@ta + =net + whos=(set ship) + nas=^state:naive + own=owners + spo=sponsors + logs=(list =event-log:rpc:ethereum) + == +:: ++$ poke-data + $% :: %listen + :: + [%listen whos=(list ship) =source:jael] + :: %watch: configure node url and network + :: + [%watch url=@ta =net] + == +:: ++$ tagged-diff [=id:block diff:naive] ++$ card card:agent:gall +:: TODO: add to state? +:: +++ refresh ~m5 +-- +:: +=| state=app-state +%- agent:dbug +%+ verb | +^- agent:gall +=< + |_ =bowl:gall + +* this . + do ~(. +> bowl) + def ~(. (default-agent this %|) bowl) + :: + ++ on-init + ^- (quip card _this) + =: net.state %default + logs.state snap + url.state 'http://eth-mainnet.urbit.org:8545' + == + :_ this + ?: .^(? %j /(scot %p our.bowl)/fake/(scot %da now.bowl)) + ~ + :~ :* %pass /old-tracker %agent [our.bowl %hood] + %poke %kiln-nuke !>([%azimuth-tracker %|]) + == + :: + [%pass /init %arvo %b %wait now.bowl] + == + :: + ++ on-save !>(state) + ++ on-load + |= old=vase + ^- (quip card _this) + |^ + =+ !<(old-state=app-states old) + =? old-state ?=(%0 -.old-state) + =, old-state + [%1 url net whos nas own *sponsors logs] + =^ cards-1 old-state + ?. ?=(%1 -.old-state) + `old-state + %- %- slog :_ ~ + leaf+"azimuth: loading snapshot with {<(lent logs.old-state)>} events" + =. +.state +.old-state + =^ cards state + (%*(run-logs do nas.state *^state:naive) logs.state) + [(jael-update:do (to-udiffs:do cards)) state] + ?> ?=(%2 -.old-state) + [cards-1 this(state old-state)] + :: + ++ app-states $%(state-0 state-1 app-state) + :: + +$ state-1 + $: %1 + url=@ta + =net + whos=(set ship) + nas=^state:naive + own=owners + spo=sponsors + logs=(list =event-log:rpc:ethereum) + == + :: + ++ state-0 + $: %0 + url=@ta + =net + whos=(set ship) + nas=^state:naive + own=owners + logs=(list =event-log:rpc:ethereum) + == + -- + :: + ++ on-poke + |= [=mark =vase] + ^- (quip card _this) + ?: =(%noun mark) + ?+ q.vase !! + %rerun + ~& [%rerunning (lent logs.state)] + =. points.nas.state ~ + =. own.state ~ + =^ * state (run-logs:do logs.state) + `this + :: + %resub + :_ this :_ ~ + :* %pass /eth-watcher %agent [our.bowl %eth-watcher] + %watch /logs/[dap.bowl] + == + :: + %resnap + =. logs.state snap + $(mark %noun, vase !>(%rerun)) + == + ?: =(%eth-logs mark) + =+ !<(logs=(list event-log:rpc:ethereum) vase) + =. logs.state logs + $(mark %noun, vase !>(%rerun)) + :: + ?. ?=(%azimuth-poke mark) + (on-poke:def mark vase) + =+ !<(poke=poke-data vase) + ?- -.poke + %listen + [[%pass /lo %arvo %j %listen (silt whos.poke) source.poke]~ this] + :: + %watch + :: TODO: only wipe out state when switching networks? + :: ?: =(net.state net.poke) + :: [~ this] + =: nas.state *^state:naive + net.state net.poke + url.state url.poke + own.state ~ + spo.state ~ + logs.state ?:(?=(%default net.poke) snap ~) + == + [start:do this] + == + :: + ++ on-watch + |= =path + ^- (quip card _this) + ?< =(/sole/drum path) + ?: =(/event path) + :_ this + [%give %fact ~ %naive-state !>([nas.state own.state spo.state])]~ + =/ who=(unit ship) + ?~ path ~ + ?: ?=([@ ~] path) ~ + `(slav %p i.path) + =. whos.state + ?~ who + ~ + (~(put in whos.state) u.who) + ^- (quip card _this) + :: Slow to recalculate all the diffs, but this is necessary to make + :: sure Jael gets the updates from the snapshot + :: + %- %- slog :_ ~ + leaf+"azimuth: loading snapshot with {<(lent logs.state)>} events" + =^ snap-cards state + (%*(run-logs do nas.state *^state:naive) logs.state) + [(weld (jael-update:do (to-udiffs:do snap-cards)) start:do) this] + :: + ++ on-leave on-leave:def + ++ on-peek + |= =path + ^- (unit (unit cage)) + |^ + ?+ path (on-peek:def path) + [%x %logs ~] ``noun+!>(logs.state) + [%x %nas ~] ``noun+!>(nas.state) + [%x %dns ~] ``noun+!>(dns.nas.state) + [%x %own ~] ``noun+!>(own.state) + [%x %spo ~] ``noun+!>(spo.state) + [%x %refresh ~] ``atom+!>(refresh) + [%x %point @ ~] ``noun+(point i.t.t.path) + == + :: + ++ point + |= wat=@t + ^- vase + !> ^- (unit point:naive) + ?~ ship=(rush wat ;~(pfix sig fed:ag)) + ~ + (get:orm:naive points.nas.state u.ship) + -- + :: + ++ on-agent + |= [=wire =sign:agent:gall] + ^- (quip card _this) + ?. ?=([%eth-watcher ~] wire) + (on-agent:def wire sign) + ?. ?=(%fact -.sign) + (on-agent:def wire sign) + ?. ?=(%eth-watcher-diff p.cage.sign) + (on-agent:def wire sign) + =+ !<(diff=diff:eth-watcher q.cage.sign) + ?: ?=(%disavow -.diff) + [(jael-update:do [*ship id.diff %disavow ~]~) this] + :: + =. logs.state + ?- -.diff + :: %history loglist.diff + %history (welp logs.state loglist.diff) + %logs (welp logs.state loglist.diff) + == + =? nas.state ?=(%history -.diff) *^state:naive + =^ effects state (run-logs:do loglist.diff) + :: + :_ this + %+ weld + (event-update:do effects) + (jael-update:do (to-udiffs:do effects)) + :: + ++ on-arvo + |= [=wire =sign-arvo] + ?. &(=(/init wire) ?=(%wake +<.sign-arvo)) + (on-arvo:def wire sign-arvo) + ?^ error.sign-arvo + %- (slog 'azimuth: failed to initialize!' ~) + `this + :_ this + :~ :* %pass /eth-watcher %agent [our.bowl %eth-watcher] + %watch /logs/[dap.bowl] + == + :: + [%pass /lo %arvo %j %listen ~ [%| dap.bowl]] + == + :: + ++ on-fail on-fail:def + -- +|_ =bowl:gall +:: TODO: maybe flop the endianness here so metamask signs it in normal +:: order? +:: +++ 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 + == +:: +++ topics + |= ships=(set ship) + ^- (list ?(@ux (list @ux))) + ~ +:: +++ data-to-hex + |= data=@t + ?~ data *@ux + ?: =(data '0x') *@ux + (hex-to-num:ethereum data) +:: +++ run-logs + |= [logs=(list event-log:rpc:ethereum)] + ^- (quip tagged-diff _state) + =+ net=(get-network net.state) + =| effects=(list tagged-diff) + !. :: saves 700MB replaying snapshot + =- =/ res (mule -) + ?- -.res + %& p.res + %| (mean 'naive: fail!' p.res) + == + |. + ?~ logs + [(flop effects) state] + ?~ mined.i.logs + $(logs t.logs) + =/ [raw-effects=effects:naive new-nas=_nas.state] + =/ =^input:naive + :- block-number.u.mined.i.logs + ?: =(azimuth.net address.i.logs) + =/ data (data-to-hex data.i.logs) + =/ =event-log:naive + [address.i.logs data topics.i.logs] + [%log event-log] + ?~ input.u.mined.i.logs + [%bat *@] + [%bat u.input.u.mined.i.logs] + (%*(. naive lac |) verifier chain-id.net nas.state input) + :: TODO: move to /lib/dice ? + :: + =/ [new-own=_own.state new-spo=_spo.state] + =< [own spo] + ?. =(azimuth.net address.i.logs) + %: apply-effects:dice + chain-id.net + raw-effects + nas.state + own.state + spo.state + == + %: update-indices:dice + raw-effects + nas.state + new-nas + own.state + spo.state + == + =: nas.state new-nas + own.state new-own + spo.state new-spo + == + =/ effects-1 + =/ =id:block [block-hash block-number]:u.mined.i.logs + (turn raw-effects |=(=diff:naive [id diff])) + =. effects (welp (flop effects-1) effects) + $(logs t.logs) +:: +++ to-udiffs + |= effects=(list tagged-diff) + ^- =udiffs:point + %+ murn effects + |= tag=tagged-diff + ^- (unit [=ship =udiff:point]) + ?. ?=(%point +<.tag) ~ + ?+ +>+<.tag ~ + %rift `[ship.tag id.tag %rift rift.tag] + %sponsor `[ship.tag id.tag %spon sponsor.tag] + %keys + =/ =pass + (pass-from-eth:azimuth 32^crypt.keys.tag 32^auth.keys.tag suite.keys.tag) + `[ship.tag id.tag %keys life.keys.tag suite.keys.tag pass] + == +:: +++ jael-update + |= =udiffs:point + ^- (list card) + :: ?: & ~ :: XX + :- [%give %fact ~[/] %azimuth-udiffs !>(udiffs)] + |- ^- (list card) + ?~ udiffs + ~ + =/ =path /(scot %p ship.i.udiffs) + :: Should really give all diffs involving each ship at the same time + :: + :- [%give %fact ~[path] %azimuth-udiffs !>(~[i.udiffs])] + $(udiffs t.udiffs) +:: +++ event-update + |= effects=(list tagged-diff) + ^- (list card) + %+ murn effects + |= tag=tagged-diff + ^- (unit card) + ?. |(?=(%tx +<.tag) ?=(%point +<.tag)) ~ + %- some + ^- card + [%give %fact ~[/event] %naive-diffs !>(+.tag)] +:: +++ get-network + |= =net + ^- [azimuth=@ux naive=@ux chain-id=@ launch=@] + =< [azimuth naive chain-id launch] + =, azimuth + ?- net + %mainnet mainnet-contracts + %ropsten ropsten-contracts + %local local-contracts + %default contracts + == +:: +++ start + ^- (list card) + =+ net=(get-network net.state) + =/ args=vase !> + :+ %watch /[dap.bowl] + ^- config:eth-watcher + :* url.state =(%czar (clan:title our.bowl)) refresh ~h30 + (max launch.net ?:(=(net.state %default) last-snap 0)) + ~[azimuth.net] + ~[naive.net] + (topics whos.state) + == + [%pass /wa %agent [our.bowl %eth-watcher] %poke %eth-watcher-poke args]~ +-- diff --git a/pkg/arvo/app/azimuth/logs.eth-logs b/pkg/arvo/app/azimuth/logs.eth-logs new file mode 100644 index 000000000..1a6f1d9b0 Binary files /dev/null and b/pkg/arvo/app/azimuth/logs.eth-logs differ diff --git a/pkg/arvo/app/eth-watcher.hoon b/pkg/arvo/app/eth-watcher.hoon index cb4c358c1..18aefdd9c 100644 --- a/pkg/arvo/app/eth-watcher.hoon +++ b/pkg/arvo/app/eth-watcher.hoon @@ -8,7 +8,7 @@ => |% +$ card card:agent:gall +$ app-state - $: %4 + $: %5 dogs=(map path watchdog) == :: @@ -23,7 +23,7 @@ == :: :: history: newest block first, oldest event first - +$ history (list loglist) + +$ history (list loglist) -- :: :: Helpers @@ -112,14 +112,16 @@ :: =? old-state ?=(%3 -.old-state) %- (slog leaf+"upgrading eth-watcher from %3" ~) - ^- app-state + ^- app-state-4 %= old-state - %4 dogs %- ~(run by dogs.old-state) |= dog=watchdog-3 + ^- watchdog-4 %= dog - + ^- config-4 =, -.dog [url eager refresh-rate (mul refresh-rate 6) from contracts topics] :: @@ -129,10 +131,80 @@ == == :: - [cards-1 this(state ?>(?=(%4 -.old-state) old-state))] + =? old-state ?=(%4 -.old-state) + %- (slog leaf+"upgrading eth-watcher from %4" ~) + ^- app-state + %= old-state + - %5 + dogs + %- ~(run by dogs.old-state) + |= dog=watchdog-4 + %= dog + - + =, -.dog + [url eager refresh-rate timeout-time from contracts ~ topics] + :: + pending-logs-4 + %- ~(run by pending-logs-4.dog) + |= =loglist-4 + %+ turn loglist-4 + |= =event-log-4 + event-log-4(mined ?~(mined.event-log-4 ~ `mined.event-log-4)) + :: + history-4 + %+ turn history-4.dog + |= =loglist-4 + %+ turn loglist-4 + |= =event-log-4 + event-log-4(mined ?~(mined.event-log-4 ~ `mined.event-log-4)) + == + == + :: + [cards-1 this(state ?>(?=(%5 -.old-state) old-state))] :: +$ app-states - $%(app-state-0 app-state-1 app-state-2 app-state-3 app-state) + $%(app-state-0 app-state-1 app-state-2 app-state-3 app-state-4 app-state) + :: + +$ app-state-4 + $: %4 + dogs=(map path watchdog-4) + == + :: + +$ watchdog-4 + $: config-4 + running=(unit [since=@da =tid:spider]) + =number:block + =pending-logs-4 + =history-4 + blocks=(list block) + == + :: + +$ config-4 + $: url=@ta + eager=? + refresh-rate=@dr + timeout-time=@dr + from=number:block + contracts=(list address:ethereum) + =topics + == + +$ pending-logs-4 (map number:block loglist-4) + +$ history-4 (list loglist-4) + +$ loglist-4 (list event-log-4) + +$ event-log-4 + $: $= mined %- unit + $: log-index=@ud + transaction-index=@ud + transaction-hash=@ux + block-number=@ud + block-hash=@ux + removed=? + == + :: + address=@ux + data=@t + topics=(lest @ux) + == :: +$ app-state-3 $: %3 @@ -143,8 +215,8 @@ $: config-3 running=(unit =tid:spider) =number:block - =pending-logs - =history + =pending-logs-4 + =history-4 blocks=(list block) == :: @@ -171,8 +243,8 @@ $: config-1 running=(unit =tid:spider) =number:block - =pending-logs - =history + =pending-logs-4 + =history-4 blocks=(list block) == :: @@ -193,8 +265,8 @@ $: config-0 running=(unit =tid:spider) =number:block - =pending-logs - =history + =pending-logs-4 + =history-4 blocks=(list block) == :: @@ -390,9 +462,9 @@ ++ release-logs |= [=path dog=watchdog] ^- (quip card watchdog) - ?: (lth number.dog 30) + ?: (lth number.dog 0) :: TODO: 30! `dog - =/ rel-number (sub number.dog 30) + =/ rel-number (sub number.dog 0) :: TODO: 30! =/ numbers=(list number:block) ~(tap in ~(key by pending-logs.dog)) =. numbers (sort numbers lth) =^ logs=(list event-log:rpc:ethereum) dog diff --git a/pkg/arvo/app/gaze.hoon b/pkg/arvo/app/gaze.hoon index 52046d358..18f154e47 100644 --- a/pkg/arvo/app/gaze.hoon +++ b/pkg/arvo/app/gaze.hoon @@ -212,6 +212,7 @@ public:mainnet-contracts ~[azimuth delegated-sending]:mainnet-contracts ~ + ~ == :: :: see also comment in +setup-cards diff --git a/pkg/arvo/app/roller-rpc.hoon b/pkg/arvo/app/roller-rpc.hoon new file mode 100644 index 000000000..cca6d7af2 --- /dev/null +++ b/pkg/arvo/app/roller-rpc.hoon @@ -0,0 +1,365 @@ +:: Roller JSON-RPC API +:: +/- rpc=json-rpc, *dice +/+ naive, + azimuth-roll-rpc, + json-rpc, + *server, + default-agent, + verb, + dbug, + agentio +|% +:: ++$ 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/roller] 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) + :: TODO: malformed request + :: + (give-simple-payload:app id not-found:gen) + =/ [data=(list cage) response=simple-payload:http] + (process-rpc-request:do u.rpc-request) + %+ weld + (give-simple-payload:app id response) + |- + ?~ data ~ + :_ $(data t.data) + ^- card + [%pass / %agent [our.bowl %roller] %poke i.data] + -- + -- + :: + ++ 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=batch-request:rpc + ^- [(list cage) simple-payload:http] + |^ + ?- -.req + %o + =/ [data=(unit cage) =response:rpc] + (process p.req) + [(drop data) (render response)] + :: + %a + =| data=(list cage) + =| resp=(list response:rpc) + |- + ?~ p.req + [(flop data) (render %batch (flop resp))] + =/ [dat=(unit cage) res=response:rpc] + (process i.p.req) + =? data ?=(^ dat) [u.dat data] + $(p.req t.p.req, resp [res resp]) + == + :: + ++ render + |= res=response:rpc + %- json-response:gen + (response-to-json:json-rpc res) + :: + ++ process + |= request:rpc + ?. ready:scry + :: TODO: move to lib + :: + `[%error id '-32003' 'Roller is not ready'] + =, azimuth-roll-rpc + ?. ?=([%map *] params) + [~ ~(parse error:json-rpc id)] + =/ method=@tas (enkebab method) + ?: ?=(l2-tx method) + (process-rpc id +.params method over-quota:scry) + ?+ method [~ ~(method error:json-rpc id)] + %get-point `(get-point id +.params point:scry) + %get-ships `(get-ships id +.params ships:scry) + %cancel-transaction (cancel-tx id +.params) + %get-spawned `(get-spawned id +.params spawned:scry) + %get-unspawned `(get-spawned id +.params unspawned:scry) + %spawns-remaining `(spawns-remaining id +.params unspawned:scry) + %get-sponsored-points `(sponsored-points id +.params sponsored:scry) + %get-owned-points `(get-ships id +.params owned:scry) + %get-transferring-for `(get-ships id +.params transfers:scry) + %get-manager-for `(get-ships id +.params manager:scry) + %get-voting-for `(get-ships id +.params voting:scry) + %get-spawning-for `(get-ships id +.params spawning:scry) + %get-all-pending `(all:pending id +.params all:pending:scry) + %get-pending-by-ship `(ship:pending id +.params ship:pending:scry) + %get-pending-by-address `(addr:pending id +.params addr:pending:scry) + %get-pending-tx `(hash:pending id +.params hash:pending:scry) + %get-transaction-status `(status id +.params tx-status:scry) + %when-next-batch `(next-batch id +.params next-batch:scry) + %get-nonce `(nonce id +.params nonce:scry) + %get-history `(history id +.params addr:history:scry) + %get-roller-config `(get-config id +.params config:scry) + %prepare-for-signing `(hash-transaction id +.params chain:scry | &) + %get-unsigned-tx `(hash-transaction id +.params chain:scry & |) + %get-predicted-state `(get-naive id +.params predicted:scry) + %hash-raw-transaction `(hash-raw-transaction id +.params) + :: TODO: deprecated, remove (used together with personal_sign) + :: + %hash-transaction ::`(hash-transaction id +.params chain:scry | &) + `(hash-transaction id +.params chain:scry & |) + == + -- +:: +++ scry + |% + ++ point + |= =ship + .^ (unit point:naive) + %gx + (~(scry agentio bowl) %roller /point/(scot %p ship)/noun) + == + :: + ++ ships + |= =address:naive + .^ (list ship) + %gx + (~(scry agentio bowl) %roller /ships/(scot %ux address)/noun) + == + :: + ++ spawned + |= =ship + .^ (list @p) + %gx + (~(scry agentio bowl) %roller /spawned/(scot %p ship)/noun) + == + :: + ++ unspawned + |= =ship + .^ (list @p) + %gx + (~(scry agentio bowl) %roller /unspawned/(scot %p ship)/noun) + == + :: + ++ owned + |= =address:naive + .^ (list ship) + %gx + (~(scry agentio bowl) %roller /owned/(scot %ux address)/noun) + == + :: + ++ sponsored + |= parent=ship + .^ [residents=(list ship) requests=(list ship)] + %gx + (~(scry agentio bowl) %roller /sponsored/(scot %p parent)/noun) + == + :: + ++ transfers + |= =address:naive + .^ (list ship) + %gx + (~(scry agentio bowl) %roller /transfers/(scot %ux address)/noun) + == + :: + ++ manager + |= =address:naive + .^ (list ship) + %gx + (~(scry agentio bowl) %roller /manager/(scot %ux address)/noun) + == + :: + ++ voting + |= =address:naive + .^ (list ship) + %gx + (~(scry agentio bowl) %roller /voting/(scot %ux address)/noun) + == + :: + ++ spawning + |= =address:naive + .^ (list ship) + %gx + (~(scry agentio bowl) %roller /spawning/(scot %ux address)/noun) + == + :: + ++ pending + |% + ++ all + .^ (list pend-tx) + %gx + (~(scry agentio bowl) %roller /pending/noun) + == + :: + ++ ship + |= =^ship + .^ (list pend-tx) + %gx + (~(scry agentio bowl) %roller /pending/(scot %p ship)/noun) + == + :: + ++ addr + |= =address:naive + .^ (list pend-tx) + %gx + %+ ~(scry agentio bowl) %roller + /pending/[(scot %ux address)]/noun + == + :: + ++ hash + |= keccak=@ux + .^ (unit pend-tx) + %gx + %+ ~(scry agentio bowl) %roller + /pending-tx/[(scot %ux keccak)]/noun + == + -- + :: + ++ history + |% + ++ addr + |= =address:naive + .^ (list hist-tx) + %gx + (~(scry agentio bowl) %roller /history/(scot %ux address)/noun) + == + -- + :: + ++ tx-status + |= keccak=@ux + .^ ^tx-status + %gx + (~(scry agentio bowl) %roller /tx/(scot %ux keccak)/status/noun) + == + :: + ++ next-batch + .^ time + %gx + (~(scry agentio bowl) %roller /next-batch/noun) + == + :: + ++ nonce + |= [=ship =proxy:naive] + .^ (unit @) + %gx + %+ ~(scry agentio bowl) + %roller + /nonce/(scot %p ship)/[proxy]/noun + == + :: + ++ config + ^- [azimuth-config roller-config] + :- refresh + .^ roller-config + %gx + %+ ~(scry agentio bowl) + %roller + /config/noun + == + :: + ++ chain + .^ @ + %gx + %+ ~(scry agentio bowl) + %roller + /chain-id/noun + == + :: + ++ predicted + .^ ^state:naive + %gx + (~(scry agentio bowl) %roller /predicted/noun) + == + :: + ++ refresh + .^ @dr + %gx + (~(scry agentio bowl) %azimuth /refresh/noun) + == + :: + ++ over-quota + |= =ship + .^ ? + %gx + (~(scry agentio bowl) %roller /over-quota/(scot %p ship)/atom) + == + :: + ++ ready + .^ ? + %gx + (~(scry agentio bowl) %roller /ready/atom) + == + -- +-- diff --git a/pkg/arvo/app/roller.hoon b/pkg/arvo/app/roller.hoon new file mode 100644 index 000000000..4a3bd7202 --- /dev/null +++ b/pkg/arvo/app/roller.hoon @@ -0,0 +1,1338 @@ +:: roller: 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 questions: +:: - it's a bit weird how we just assume the raw and tx in raw-tx to match... +:: +/- *dice +/+ azimuth, + naive, + dice, + lib=naive-transactions, + default-agent, + ethereum, + dbug, + verb +:: +|% ++$ app-state + $: %2 + :: pending: the next l2 txs to be sent + :: sending: l2 txs awaiting l2 confirmation, ordered by nonce + :: finding: sig+raw-tx hash reverse lookup for txs in sending map + :: history: status of l2 txs by ethereum address, timestamp sorted + :: ship-quota: number of txs submited per ship in the current slice + :: next-nonce: next l1 nonce to use + :: next-batch: when then next l2 batch will be sent + :: pre: predicted l2 state + :: own: ownership of azimuth points + :: spo: residents and escapees, per sponsor + :: + pending=(list pend-tx) + sending=(tree [l1-tx-pointer send-tx]) + finding=(map keccak ?(%confirmed %failed [=time l1-tx-pointer])) + history=(map address:ethereum (tree hist-tx)) + ship-quota=(map ship @ud) + next-nonce=(unit @ud) + next-batch=time + pre=^state:naive + own=owners + spo=sponsors + :: + :: pk: private key to send the roll + :: quota: max numbers of transactions per unit of time (slice) + :: slice: unit of time where txs are allowed to be added to pending + :: derive: defer derivation of predicted/ownership state + :: frequency: time to wait between sending batches (TODO fancier) + :: endpoint: ethereum rpc endpoint to use + :: contract: ethereum contract address + :: chain-id: mainnet, ropsten, local (https://chainid.network/) + :: resend-time: time to resend a batch with higher gas prie + :: update-rate: frequency to update the roller's predicted state + :: + pk=@ + slice=@dr + quota=@ud + derive=? + frequency=@dr + endpoint=(unit @t) + contract=@ux + chain-id=@ + resend-time=@dr + update-rate=@dr + == +:: orp: ordered points in naive state by parent ship +:: +++ orp ((on ship point:naive) por:naive) +:: ors: ordered sending map by (increasing) L1 nonce +:: +++ ors ((on l1-tx-pointer send-tx) nonce-order:dice) +:: orh: ordered tx history by (decreasing) timestamp +:: +++ orh ((on time roll-tx) gth) +:: ++$ action + $% :: we need to include the address in submit so pending txs show up + :: in the tx history, but because users can send the wrong + :: address, in +apply-tx:predicted state, we just replace + :: the provided address, with the one used when the message was signed; + :: + :: we need to do it there to know the correct nonce that the signed + :: message should have included. + :: + [%submit force=? =address:naive sig=@ tx=part-tx] + [%cancel sig=@ keccak=@ =l2-tx =ship] + [%commit ~] ::TODO maybe pk=(unit @) later + [%config config] + == +:: ++$ card card:agent:gall +:: +++ lverb & +-- +:: +=| app-state +=* state - +:: +%- agent:dbug +%+ verb | +^- agent:gall +:: +=< + |_ =bowl:gall + +* this . + do ~(. +> bowl) + def ~(. (default-agent this %|) bowl) + :: + ++ on-init + ^- (quip card _this) + =: frequency ~h1 + quota 7 + slice ~d7 + resend-time ~m5 + update-rate ~m5 + contract naive:local-contracts:azimuth + chain-id chain-id:local-contracts:azimuth + == + =^ card next-batch set-roller:timer + :_ this + :~ card + (set-quota:timer slice) + [%pass /azimuth-events %agent [our.bowl %azimuth] %watch /event] + == + :: + ++ on-save !>(state) + ++ on-load + |= old=vase + ^- (quip card _this) + =| cards=(list card) + :: new additions to app-state + :: + =| spo=(map ship [residents=(set ship) requests=(set ship)]) + |^ + =+ !<(old-state=app-states old) + =? cards ?=(%0 -.old-state) + [(set-quota:timer slice)]~ + =? old-state ?=(%0 -.old-state) + ^- state-1 + =, old-state + :* %1 + pending sending finding history + ship-quota next-nonce next-batch + pre own pk slice quota derive + frequency endpoint contract chain-id + resend-time update-rate + == + =? old-state ?=(%1 -.old-state) + ^- app-state + =, old-state + :* %2 + pending sending finding history + ship-quota next-nonce next-batch + pre own spo pk slice quota derive + frequency endpoint contract chain-id + resend-time update-rate + == + ?> ?=(%2 -.old-state) + [cards this(state old-state)] + :: + ++ app-states $%(state-0 state-1 app-state) + ++ state-0 + $: %0 + pending=(list pend-tx) + sending=(tree [l1-tx-pointer send-tx]) + finding=(map keccak ?(%confirmed %failed [=time l1-tx-pointer])) + history=(map address:ethereum (tree hist-tx)) + next-nonce=(unit @ud) + next-batch=time + pre=^state:naive + own=owners + derive=? + pk=@ + frequency=@dr + endpoint=(unit @t) + contract=@ux + chain-id=@ + == + :: + ++ state-1 + $: %1 + pending=(list pend-tx) + sending=(tree [l1-tx-pointer send-tx]) + finding=(map keccak ?(%confirmed %failed [=time l1-tx-pointer])) + history=(map address:ethereum (tree hist-tx)) + ship-quota=(map ship @ud) + next-nonce=(unit @ud) + next-batch=time + pre=^state:naive + own=owners + pk=@ + slice=@dr + quota=@ud + derive=? + frequency=@dr + endpoint=(unit @t) + contract=@ux + chain-id=@ + resend-time=@dr + update-rate=@dr + == + -- + :: + ++ on-poke + |= [=mark =vase] + ^- (quip card _this) + =^ cards state + ?+ mark (on-poke:def mark vase) + %roller-action + =+ !<(poke=action vase) + (on-action:do poke) + == + [cards this] + :: +on-peek: scry paths + :: + :: /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]/[@ud]status -> %noun tx-status + :: /x/history/[0xadd.ress] -> %noun (list hist-tx) + :: /x/nonce/[~ship]/[proxy] -> %noun (unit @) + :: /x/spawned/[~star] -> %noun (list ship) + :: /x/unspawned/[~star] -> %noun (list ship) + :: /x/sponsored/[~point] -> %noun [(list ship) (list ship)] + :: /x/next-batch -> %atom time + :: /x/point/[~ship] -> %noun point:naive + :: /x/ships/[0xadd.ress] -> %noun (list ship) + :: /x/config -> %noun config + :: /x/chain-id -> %atom @ + :: /x/owned/[0xadd.ress] -> %noun (list ship) + :: /x/transfers/[0xadd.ress] -> %noun (list ship) + :: /x/manager/[0xadd.ress] -> %noun (list ship) + :: /x/voting/[0xadd.ress] -> %noun (list ship) + :: /x/spawning/[0xadd.ress] -> %noun (list ship) + :: /x/predicted -> %noun state:naive + :: /x/quota -> %atom @ud + :: /x/slice -> %atom @dr + :: /x/over-quota/[~ship] -> %atom ? + :: /x/ready -> %atom ? + :: + ++ on-peek + |= =path + ^- (unit (unit cage)) + |^ + ?+ path ~ + [%x %pending ~] ``noun+!>(pending) + [%x %pending @ ~] (pending-by i.t.t.path) + [%x %tx @ %status ~] (status i.t.t.path) + [%x %pending-tx @ ~] (transaction i.t.t.path) + [%x %history @ ~] (history i.t.t.path) + [%x %nonce @ @ ~] (nonce i.t.t.path i.t.t.t.path) + [%x %spawned @ ~] (spawned i.t.t.path) + [%x %unspawned @ ~] (unspawned i.t.t.path) + [%x %sponsored @ ~] (sponsored i.t.t.path) + [%x %next-batch ~] ``atom+!>(next-batch) + [%x %point @ ~] (point i.t.t.path) + [%x %ships @ ~] (ships i.t.t.path) + [%x %config ~] config + [%x %chain-id ~] ``atom+!>(chain-id) + [%x %owned @ ~] (points-proxy %own i.t.t.path) + [%x %transfers @ ~] (points-proxy %transfer i.t.t.path) + [%x %manager @ ~] (points-proxy %manage i.t.t.path) + [%x %voting @ ~] (points-proxy %vote i.t.t.path) + [%x %spawning @ ~] (points-proxy %spawn i.t.t.path) + [%x %predicted ~] ``noun+!>(pre) + [%x %quota ~] ``atom+!>(quota) + [%x %slice ~] ``atom+!>(slice) + [%x %over-quota @ ~] (over-quota i.t.t.path) + [%x %ready ~] ``atom+!>(?=(^ points.pre)) + == + :: + ++ pending-by + |= wat=@t + ?~ who=(slaw %p wat) + :: by-address + :: + ?~ wer=(slaw %ux wat) + [~ ~] + =; pending=(list pend-tx) + ``noun+!>(pending) + %+ skim pending + |= pend-tx + :: TODO: use this instead? =(u.wer address) + :: + ?~ addr=(get-l1-address tx.raw-tx pre) | + =(u.wer u.addr) + :: by-ship + :: + =; pending=(list pend-tx) + ``noun+!>(pending) + %+ skim pending + |= pend-tx + =(u.who ship.from.tx.raw-tx) + :: + ++ status + |= wat=@t + ?~ keccak=(slaw %ux wat) + [~ ~] + :+ ~ ~ + :- %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 + |= pend-tx + =(u.keccak (hash-raw-tx:lib raw-tx)) + :: + ++ transaction + |= wat=@t + ?~ keccak=(slaw %ux wat) + [~ ~] + :+ ~ ~ + :- %noun + !> ^- (unit pend-tx) + :: TODO: potentially slow! + |- + ?~ pending ~ + =* tx i.pending + ?: =(u.keccak (hash-tx:lib raw.raw-tx.tx)) + `tx + $(pending t.pending) + :: + ++ history + |= wat=@t + :+ ~ ~ + :- %noun + !> ^- (list hist-tx) + ?~ addr=(slaw %ux wat) ~ + ?~ hist=(~(get by ^history) u.addr) ~ + (tap:orh u.hist) + :: + ++ nonce + |= [who=@t proxy=@t] + ?~ who=(slaw %p who) + [~ ~] + ?. ?=(proxy:naive proxy) + [~ ~] + :+ ~ ~ + :- %noun + !> ^- (unit @) + ?~ point=(get:orp points.pre u.who) + ~ + =< `nonce + (proxy-from-point:naive proxy u.point) + :: + ++ spawned + |= wat=@t + :+ ~ ~ + :- %noun + !> ^- (list @p) + ?~ star=(slaw %p wat) ~ + =; range + (turn range head) + :: range exclusive [star first-moon-last-planet] + :: + %- tap:orp + (lot:orp points.pre [`u.star `(cat 3 u.star 0x1.ffff)]) + :: + ++ unspawned + |= wat=@t + :+ ~ ~ + :- %noun + !> ^- (list @p) + ?~ star=(slaw %p wat) ~ + =/ spawned=(set @p) + =; points + (~(gas in *(set @p)) (turn points head)) + %- tap:orp + (lot:orp points.pre [`u.star `(cat 3 u.star 0x1.ffff)]) + =/ children=(list @p) + (turn (gulf 0x1 0xffff) |=(a=@ (cat 3 u.star a))) + %+ murn children + |= =ship + ?: (~(has in spawned) ship) ~ + `ship + :: + ++ sponsored + |= wat=@t + :+ ~ ~ + :- %noun + !> ^- [(list ship) (list ship)] + ?~ who=(slaw %p wat) [~ ~] + ?~ sponsor=(~(get by spo) u.who) + [~ ~] + :- ~(tap in residents.u.sponsor) + ~(tap in requests.u.sponsor) + :: + ++ point + |= wat=@t + ?~ ship=(rush wat ;~(pfix sig fed:ag)) + ``noun+!>(*(unit point:naive)) + ``noun+!>((get:orp points.pre u.ship)) + :: + ++ ships + |= wat=@t + :+ ~ ~ + :- %noun + !> ^- (list ship) + ?~ addr=(slaw %ux wat) + ~ + =/ proxies=(list proxy:naive) + ~[%own %spawn %manage %vote %transfer] + %+ roll proxies + |= [=proxy:naive ships=(list ship)] + %+ weld ships + ~(tap in (~(get ju own) [proxy u.addr])) + :: + ++ config + :+ ~ ~ + :- %noun + !> ^- roller-config + :* next-batch + frequency + resend-time + update-rate + contract + chain-id + slice + quota + == + :: + ++ points-proxy + |= [=proxy:naive wat=@t] + :+ ~ ~ + :- %noun + !> ^- (list ship) + ?~ addr=(slaw %ux wat) + ~ + ~(tap in (~(get ju own) [proxy u.addr])) + :: + ++ over-quota + |= wat=@t + ?~ who=(slaw %p wat) [~ ~] + =/ [exceeded=? *] (quota-exceeded u.who) + ``atom+!>(exceeded) + :: + -- + :: + ++ on-arvo + |= [=wire =sign-arvo] + ^- (quip card _this) + ?+ wire (on-arvo:def wire sign-arvo) + [%timer ~] + ?+ +<.sign-arvo (on-arvo:def wire sign-arvo) + %wake =^(cards state on-timer:do [cards this]) + == + [%quota-timer ~] + ?+ +<.sign-arvo (on-arvo:def wire sign-arvo) + %wake =^(cards state on-quota-timer:do [cards this]) + == + :: + [%predict ~] + ?+ +<.sign-arvo (on-arvo:def wire sign-arvo) + %wake + =. own.state canonical-owners:do + =^ effects state + (predicted-state canonical-state):do + [(emit effects) this(derive &)] + == + :: + [%resend @ @ ~] + =/ [address=@ux nonce=@ud] + [(slav %ux i.t.wire) (rash i.t.t.wire dem)] + ?+ +<.sign-arvo (on-arvo:def wire sign-arvo) + %wake [(send-roll:do address nonce) this] + == + == + :: + ++ on-fail + |= [=term =tang] + ::TODO if crashed during timer, set new timer? how to detect? + (on-fail:def term tang) + :: + ++ on-watch + |= =path + ^- (quip card _this) + :_ this + |^ + ?+ path (on-watch:def path) + [%txs @ ~] [%give %fact ~ (give-txs i.t.path)]~ + [%points @ ~] [%give %fact ~ (give-points i.t.path)]~ + == + :: + ++ give-points + |= wat=@t + ^- cage + :- %points + !> ^- (list [ship point:naive]) + ?~ addr=(slaw %ux wat) ~ + =/ proxies=(list proxy:naive) + ~[%own %spawn %manage %vote %transfer] + %+ roll proxies + |= [=proxy:naive points=(list [ship point:naive])] + %+ weld points + :: + %+ roll ~(tap in (~(get ju own) [proxy u.addr])) + |= [=ship points=_points] + %+ snoc points + [ship (need (get:orp points.pre ship))] + :: + ++ give-txs + |= wat=@t + ^- cage + :- %txs + !> ^- (list hist-tx) + ?~ addr=(slaw %ux wat) ~ + ?~ hist=(~(get by history) u.addr) ~ + (tap:orh u.hist) + -- + :: + ++ on-leave on-leave:def + :: + ++ on-agent + |= [=wire =sign:agent:gall] + ^- (quip card _this) + |^ + ?+ wire (on-agent:def wire sign) + [%send @ @ *] (send-batch i.t.wire i.t.t.wire sign) + [%azimuth-events ~] (azimuth-event sign) + [%nonce ~] (nonce sign) + [%refresh-nonce @ ~] (refresh i.t.wire sign) + == + :: + ++ send-batch + |= [address=@t nonce=@t =sign:agent:gall] + ^- (quip card _this) + =/ [address=@ux nonce=@ud] + [(slav %ux address) (rash nonce dem)] + ?- -.sign + %poke-ack + ?~ p.sign + %- (slog leaf+"Send batch thread started successfully" ~) + [~ this] + %- (slog leaf+"{(trip dap.bowl)} couldn't start thread" u.p.sign) + :_ this + [(leave:spider:do wire)]~ + :: + %watch-ack + ?~ p.sign + [~ this] + =/ =tank leaf+"{(trip dap.bowl)} couldn't start listen to thread" + %- (slog tank u.p.sign) + [~ this] + :: + %kick + [~ this] + :: + %fact + ?+ p.cage.sign (on-agent:def wire sign) + %thread-fail + =+ !<([=term =tang] q.cage.sign) + %- (slog leaf+"{(trip dap.bowl)} failed" leaf+ tang) + =^ cards state + (on-batch-result:do address nonce %.n^[%error 'thread failed']) + [cards this] + :: + %thread-done + =+ !<(result=(each @ud [term @t]) q.cage.sign) + =^ cards state + (on-batch-result:do address nonce result) + [cards this] + == + == + :: + ++ azimuth-event + |= =sign:agent:gall + ^- (quip card _this) + ?+ -.sign [~ this] + %watch-ack + ?~ p.sign [~ this] + =/ =tank leaf+"{(trip dap.bowl)} couldn't start listen to %azimuth" + %- (slog tank u.p.sign) + [~ this] + :: + %fact + ?+ p.cage.sign (on-agent:def wire sign) + %naive-diffs + =+ !<(=diff:naive q.cage.sign) + =^ cards state + (on-naive-diff:do diff) + [cards this] + :: + %naive-state + ~& > %received-azimuth-state + :: cache naive and ownership state + :: + =+ !<([nas=^state:naive own=owners spo=sponsors] q.cage.sign) + =: own.state own + spo.state spo + == + =^ effects state + (predicted-state:do nas) + [(emit effects) this] + == + == + :: + ++ nonce + |= =sign:agent:gall + ^- (quip card _this) + ?- -.sign + %poke-ack + ?~ p.sign + %- (slog leaf+"Nonce thread started successfully" ~) + [~ this] + %- (slog leaf+"{(trip dap.bowl)} couldn't start thread" u.p.sign) + :_ this + [(leave:spider:do wire)]~ + :: + %watch-ack + ?~ p.sign + [~ this] + =/ =tank leaf+"{(trip dap.bowl)} couldn't start listen to thread" + %- (slog tank u.p.sign) + [~ this] + :: + %kick + [~ this] + :: + %fact + ?+ p.cage.sign (on-agent:def wire sign) + %thread-fail + =+ !<([=term =tang] q.cage.sign) + %- (slog leaf+"{(trip dap.bowl)} failed" leaf+ tang) + [~ this] + :: + %thread-done + =+ !<(nonce=@ud q.cage.sign) + [~ this(next-nonce `nonce)] + == + == + :: + ++ refresh + |= [nonce=@t =sign:agent:gall] + ^- (quip card _this) + =/ failed-nonce=@ud (rash nonce dem) + ?- -.sign + %poke-ack + ?~ p.sign + %- (slog leaf+"Refresh Nonce thread started successfully" ~) + [~ this] + %- (slog leaf+"{(trip dap.bowl)} couldn't start thread" u.p.sign) + :_ this + [(leave:spider:do wire)]~ + :: + %watch-ack + ?~ p.sign + [~ this] + =/ =tank leaf+"{(trip dap.bowl)} couldn't start listen to thread" + %- (slog tank u.p.sign) + [~ this] + :: + %kick + [~ this] + :: + %fact + ?+ p.cage.sign (on-agent:def wire sign) + %thread-fail + =+ !<([=term =tang] q.cage.sign) + %- (slog leaf+"{(trip dap.bowl)} failed" leaf+ tang) + [~ this] + :: + %thread-done + =+ !<(nonce=@ud q.cage.sign) + =^ cards state + (on-out-of-sync:do nonce failed-nonce) + [cards this] + == + == + -- + -- +:: +|_ =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) + =/ =beak byk.bowl(r da+now.bowl) + =/ tid=@ta (rap 3 thread '--' (scot %uv eny.bowl) ~) + =/ args [~ `tid beak thread arg] + :~ [%pass wire %agent [our.bowl %spider] %watch /thread-result/[tid]] + [%pass wire %agent [our.bowl %spider] %poke %spider-start !>(args)] + == + :: + ++ leave + |= =path + ^- card + [%pass path %agent [our.bowl %spider] %leave ~] + -- +:: +:: +++ emit + |= updates=(list update) + |- ^- (list card) + ?~ updates ~ + =* up i.updates + =/ [address=@t last-owner=(unit @t)] + ?- -.up + %tx + :_ ~ + (scot %ux address.up) + :: + %point + :- (scot %ux address.new.up) + ?~(old.up ~ `(scot %ux address.u.old.up)) + == + %+ weld + $(updates t.updates) + ^- (list card) + ?- -.i.updates + %tx + [%give %fact ~[/txs/[address]] tx+!>(roll-tx.up)]~ + :: + %point + %+ weld + [%give %fact ~[/points/[address]] point+!>([ship point]:up)]~ + ?~ last-owner ~ + [%give %fact ~[/points/[u.last-owner]] point+!>([ship point]:up)]~ + == +:: +++ part-tx-to-full + |= =part-tx + ^- [octs tx:naive] + ?- -.part-tx + %raw + ?~ batch=(parse-raw-tx:naive 0 q.raw.part-tx) + ~? lverb [dap.bowl %parse-failed] + :: TODO: maybe return a unit if parsing fails? + :: + !! + [raw tx]:-.u.batch + :: + %don [(gen-tx-octs:lib +.part-tx) +.part-tx] + %ful +.part-tx + == +:: +canonical-state: current l2 state from /app/azimuth +:: +++ canonical-state + .^ ^state:naive + %gx + (scot %p our.bowl) + %azimuth + (scot %da now.bowl) + /nas/noun + == +:: +canonical-owners: current azimuth point ownership +:: +++ canonical-owners + .^ owners + %gx + (scot %p our.bowl) + %azimuth + (scot %da now.bowl) + /own/noun + == +:: +canonical-sponsors: current azimuth sponsorship +:: +++ canonical-sponsors + .^ sponsors + %gx + (scot %p our.bowl) + %azimuth + (scot %da now.bowl) + /spo/noun + == +:: +predicted-state +:: +:: derives predicted state from applying pending & sending txs to +:: the provided naive state, discarding invalid txs in the process +:: +++ predicted-state + |= nas=^state:naive + ^- (quip update _state) + =: pre nas + own canonical-owners + spo canonical-sponsors + == + |^ + =^ [nes=_sending updates-1=(list update)] state + apply-sending + =^ [nep=_pending updates-2=(list update)] state + apply-pending + :- (welp updates-1 updates-2) + state(sending nes, pending nep) + :: + ++ apply-pending + (apply-txs pending %pending next-nonce.state) + :: + ++ apply-sending + =| ups=(list update) + =/ valid=_sending ~ + =+ sorted=(tap:ors sending) + |- ^+ [[valid ups] state] + ?~ sorted [[valid ups] state] + :: + =* key key.i.sorted + =* val val.i.sorted + =+ txs=(turn txs.val |=(=raw-tx:naive [| 0x0 *time raw-tx])) + =^ [new-valid=_txs nups=_ups] state + (apply-txs txs %sending `nonce.key) + :: we only hear updates for this nonce if it has been sent + :: + =. valid ::=? valid sent.val + %^ put:ors valid + key + :: TODO: too much functional hackery? + val(txs (turn new-valid (cork tail (cork tail tail)))) + $(sorted t.sorted, ups (welp ups nups)) + :: + ++ apply-txs + |= [txs=(list pend-tx) type=?(%pending %sending) nonce=(unit @ud)] + =/ valid=_txs ~ + =| ups=(list update) + |- ^+ [[valid ups] state] + ?~ txs [[(flop valid) ups] state] + :: + =* tx i.txs + =* raw-tx raw-tx.i.txs + =* ship ship.from.tx.raw-tx.i.txs + =/ =keccak (hash-raw-tx:lib raw-tx) + =/ sign-address=(unit @ux) + (extract-address:lib raw-tx pre chain-id) + =^ [gud=? nups=_ups] state + (try-apply pre force.tx raw-tx) + :: TODO: only replace address if !=(address.tx sign-address)? + :: + =? tx &(gud ?=(^ sign-address)) + tx(address u.sign-address) + =/ =roll-tx [ship type keccak (l2-tx +<.tx.raw-tx)] + =? nups !gud + %+ snoc nups + [%tx address.tx roll-tx(status %failed)] + =? valid gud [tx valid] + =? history !gud + =/ =time + ?: ?=(%pending type) time.tx + =+ wer=(~(got by finding) keccak) + ?>(?=(^ wer) time.wer) + =+ txs=(~(got by history) address.tx) + =. txs +:(del:orh txs time) + %+ ~(put by history) address.tx + %+ put:orh txs + [time roll-tx(status %failed)] + =? finding !gud (~(put by finding) keccak %failed) + $(txs t.txs, ups (weld ups nups)) + -- +:: +try-apply: maybe apply the given l2 tx to the naive state +:: +++ try-apply + |= [nas=^state:naive force=? =raw-tx:naive] + ^- [[? ups=(list update)] _state] + =/ [success=? ups=(list update) predicted=_nas owners=_own sponsors=_spo] + (apply-raw-tx:dice force chain-id raw-tx nas own spo) + :- [success ups] + state(pre predicted, own owners, spo sponsors) +:: +++ get-l1-address + |= [=tx:naive nas=^state:naive] + ^- (unit address:ethereum) + ?~ point=(get:orp points.nas ship.from.tx) ~ + =< `address + (proxy-from-point:naive proxy.from.tx u.point) +:: +++ on-action + |= =action + ^- (quip card _state) + =+ local=(team:title our.bowl src.bowl) + ?- -.action + %commit ?>(local on-timer) + %config ?>(local (on-config +.action)) + %cancel (cancel-tx +.action) + :: + %submit + :: TODO: return [~ state] instead of crashing + :: if naive state hasn't being retrieved yet? + :: + ?> ?=(^ points.pre) + %- take-tx + :* force.action + address.action + now.bowl + sig.action + (part-tx-to-full tx.action) + == + == +:: +++ on-config + |= =config + ^- (quip card _state) + ?- -.config + %frequency [~ state(frequency frequency.config)] + %resend-time [~ state(resend-time time.config)] + %update-rate [~ state(update-rate rate.config)] + %slice [~ state(slice slice.config)] + %quota [~ state(quota quota.config)] + :: + %endpoint + :- ~ + =/ [contract=@ux chain-id=@] + =< [naive chain-id] + =, azimuth + ?- net.config + %mainnet mainnet-contracts + %ropsten ropsten-contracts + %local local-contracts + %default contracts + == + %_ state + contract contract + chain-id chain-id + endpoint `endpoint.config + == + :: + %setkey + ?~ pk=(de:base16:mimes:html pk.config) + `state + [(get-nonce q.u.pk /nonce) state(pk q.u.pk)] + == +:: TODO: move address to state? +:: +++ get-address + ^- address:ethereum + (address-from-prv:key:ethereum pk) +:: +cancel-tx: cancel a pending transaction +:: +++ cancel-tx + |= [sig=@ =keccak =l2-tx =ship] + ^- (quip card _state) + ?^ status=(~(get by finding) keccak) + ~? lverb [dap.bowl %tx-not-pending status+u.status] + [~ state] + :: "cancel: 0x1234abcd" + :: + =/ message=octs + %: cad:naive 3 + 8^'cancel: ' + :: + =; hash=@t + (met 3 hash)^hash + (crip "0x{((x-co:co 65) keccak)}") + :: + ~ + == + ?~ addr=(verify-sig:lib sig message) + ~? lverb [dap.bowl %cancel-sig-fail] + [~ state] + =^ time pending + =| nep=(list pend-tx) + |- ^- [(unit time) _nep] + ?~ pending [~ (flop nep)] + ?: =(keccak (hash-raw-tx:lib raw-tx.i.pending)) + [`time.i.pending (weld (flop nep) t.pending)] + $(pending t.pending, nep [i.pending nep]) + ?~ time + ~? lverb [dap.bowl %weird-tx-not-pending] + [~ state] + :- ~ + %_ state + history + =+ txs=(~(got by history) u.addr) + =. txs +:(del:orh txs u.time) + %+ ~(put by history) u.addr + %^ put:orh txs + u.time + [ship %cancelled keccak l2-tx] + == +:: +take-tx: accept submitted l2 tx into the :pending list +:: +++ take-tx + |= =pend-tx + ^- (quip card _state) + =* ship ship.from.tx.raw-tx.pend-tx + =/ [exceeded=? next-quota=@] (quota-exceeded ship) + ?: exceeded [~ state] + =^ [gud=? cards-1=(list update)] state + (try-apply pre [force raw-tx]:pend-tx) + =^ cards-2 history + (update-history [pend-tx]~ ?:(gud %pending %failed)) + ?. gud + :_ state + :: %point and (%failed) %tx updates + :: + (emit cards-1) + =: pending (snoc pending pend-tx) + ship-quota (~(put by ship-quota) ship next-quota) + == + :: toggle derivation + :: + :_ state(derive ?:(derive | derive)) + ;: welp + (emit cards-1) :: %point updates + (emit cards-2) :: %tx updates + :: + ?. derive ~ + :: defer updating predicted naive/ownership state from canonical + :: + [(wait:b:sys /predict (add update-rate now.bowl))]~ + == +:: +++ timer + |% + :: +set-roller: %wait until next whole :frequency + :: + ++ set-roller + ^- [=card =time] + =+ time=(mul +((div now.bowl frequency)) frequency) + [(wait:b:sys /timer time) time] + :: +set-roller: %wait until next whole :slice + :: + ++ set-quota + |= slice=@dr + ^- card + =+ time=(mul +((div now.bowl slice)) slice) + (wait:b:sys /quota-timer time) + -- +:: +on-timer: every :frequency, freeze :pending txs roll and start sending it +:: +++ on-timer + ^- (quip card _state) + =^ updates-1 state + (predicted-state canonical-state) + =^ cards state + ?: =(~ pending) [~ state] + ?~ next-nonce + ~? lverb [dap.bowl %missing-roller-nonce] [~ state] + :: this guarantees that next-nonce is only incremented + :: when the thread that's sending the previous batch + :: has come back and confirms that it was sent to L1 + :: + ?: out-of-sync + :: this would postpone sending the batch for a whole "frequency" + :: TODO: set up a timer to retry this in ~mX ? + :: + ~? lverb [dap.bowl %nonce-out-sync] [~ state] + =/ nonce=@ud u.next-nonce + =^ updates-2 history (update-history pending %sending) + =: pending ~ + derive & + next-nonce `+(u.next-nonce) + :: + sending + %^ put:ors sending + [get-address nonce] + [0 | (turn pending (cork tail (cork tail tail)))] + :: + finding + %- ~(gas by finding) + %+ turn pending + |= pend-tx + (hash-raw-tx:lib raw-tx)^[time address nonce] + == + :_ state + ;: welp + (emit updates-1) + (emit updates-2) + (send-roll get-address nonce) + == + =^ card next-batch set-roller:timer + [[card cards] state] +:: +on-quota-timer: resets tx quota for all ships +:: +++ on-quota-timer + ^- (quip card _state) + :- [(set-quota:timer slice)]~ + state(ship-quota *(map ship @ud)) +:: +++ update-history + |= [txs=(list pend-tx) =status] + ^- [(list update) _history] + %+ roll txs + |= [pend-tx ups=(list update) sih=_history] + =/ =roll-tx + :* ship.from.tx.raw-tx + status + (hash-raw-tx:lib raw-tx) + (l2-tx +<.tx.raw-tx) + == + =/ txs=(tree hist-tx) + ?~ txs=(~(get by sih) address) ~ + u.txs + =? txs ?=(^ txs) +:(del:orh txs time) + :- (snoc ups tx+[address roll-tx]) + %+ ~(put by sih) address + (put:orh txs [time roll-tx]) +:: +get-nonce: retrieves the latest nonce +:: +++ get-nonce + |= [pk=@ =wire] + ^- (list card) + ?~ endpoint ~?(lverb [dap.bowl %no-endpoint] ~) + (start-thread:spider wire [%roller-nonce !>([u.endpoint pk])]) +:: +++ quota-exceeded + |= =ship + ^- [? @ud] + ?~ quota=(~(get by ship-quota) ship) + [| 1] + [(gte u.quota quota.state) +(u.quota)] +:: +out-of-sync: checks if the previous nonce has been sent +:: +++ out-of-sync + ^- ? + ?~ newest-batch=(ram:ors sending) | + !=(sent.val.u.newest-batch &) +:: +on-out-of-sync +:: +++ on-out-of-sync + |= [nonce=@ud failed-nonce=@ud] + :: we only care about nonces >= than the one that failed + :: + =/ failed-sending=(list [l1-tx-pointer send-tx]) + %- tap:ors + :: (range exclusive) + :: + (lot:ors sending [`[get-address (dec failed-nonce)] ~]) + =/ confirmed-sending=_sending + (lot:ors sending [~ `[get-address failed-nonce]]) + =/ [nes=_sending nif=_finding sih=_history] + %- tail + %+ roll failed-sending + |= $: [p=l1-tx-pointer q=send-tx] + new-nonce=_nonce + sending=_confirmed-sending + finding=_finding + history=_history + == + |^ + =* nonce nonce.p + =* txs txs.q + :: TODO: this shouldn't be needed + ?: (lth nonce.p failed-nonce) + ~& ["weird case" nonce+nonce.p] + [new-nonce sending finding history] + :+ +(new-nonce) + update-sending + process-l2-txs + :: + ++ update-sending + (put:ors sending [p(nonce new-nonce) q(sent %.n)]) + :: + ++ process-l2-txs + %+ roll txs.q + |= [=raw-tx:naive nif=_finding sih=_history] + =/ =keccak (hash-raw-tx:lib raw-tx) + |^ + ?~ val=(~(get by nif) keccak) + [nif sih] + ?. ?=(^ u.val) [nif sih] + :- (update-finding u.val) + (update-history time.u.val address.u.val) + :: + ++ update-finding + |= val=[time l1-tx-pointer] + ^+ nif + (~(put by nif) keccak val(nonce.+ new-nonce)) + :: + ++ update-history + |= [=time =address:ethereum] + ^+ sih + =* ship ship.from.tx.raw-tx + =/ l2-tx (l2-tx +<.tx.raw-tx) + =/ =roll-tx [ship %sending keccak l2-tx] + =+ txs=(~(got by sih) address) + =. txs +:(del:orh txs time) + %+ ~(put by sih) address + (put:orh txs [time roll-tx]) + -- + -- + =: sending nes + finding nif + history sih + next-nonce `+(nonce) + == + [(send-roll get-address nonce) state] +:: +send-roll: start thread to submit roll from :sending to l1 +:: +++ send-roll + |= [=address:ethereum =nonce:naive] + ^- (list card) + :: if this nonce isn't in the sending queue anymore, it's done + :: + ?. (has:ors sending [address nonce]) + ~? lverb [dap.bowl %done-sending [address nonce]] + ~ + ?~ endpoint + ~? lverb [dap.bowl %no-endpoint] + ~ + :: 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 %ux address)/(scot %ud nonce) + :- %roller-send + !> ^- rpc-send-roll + :* u.endpoint + contract + chain-id + pk + nonce + :: + =< [next-gas-price txs] + (got:ors sending [address nonce]) + == +:: +on-batch-result: await resend after thread success or failure +:: +++ on-batch-result + |= [=address:ethereum nonce=@ud result=(each @ud [term @t])] + ^- (quip card _state) + :: print error if there was one + :: + ~? ?=(%| -.result) [dap.bowl %send-error +.p.result] + =/ =send-tx (got:ors sending [address nonce]) + =? sending ?=(%& -.result) + %^ put:ors sending + [address nonce] + :: update gas price for this tx in state + :: and set it as sent to L1 + :: + send-tx(next-gas-price p.result, sent &) + :_ state + ?: ?| ?=(%& -.result) + :: a general error shouldn't innitiate + :: the out-of-sync nonce thread + :: + ?=([%| %error *] result) + :: this accounts for a resend with higher gas + :: for a previous nonce, so we shouldn't start + :: the out-of-sync nonce thread + :: + ?& sent.send-tx + ?=([%| %not-sent *] result) + == == + :_ ~ + :: resend the l1 tx in five minutes + :: + %+ wait:b:sys + /resend/(scot %ux address)/(scot %ud nonce) + (add resend-time now.bowl) + :: TODO: this only accounts for the case where the nonce is out of sync, + :: reaching this because of lower funds needs to be addressed manually + :: + ?> ?=(%not-sent -.p.result) + (get-nonce pk.state /refresh-nonce/(scot %ud nonce)) +:: +on-naive-diff: process l2 tx confirmations +:: +++ on-naive-diff + |= =diff:naive + ^- (quip card _state) + ?. |(?=(%point -.diff) ?=(%tx -.diff)) + [~ state] + =; [cards=(list card) =_state] + :_ state(derive ?:(derive | derive)) + %+ weld cards + ?. derive ~ + :: defer updating predicted naive/ownership state from canonical + :: + [(wait:b:sys /predict (add update-rate now.bowl))]~ + :: + ?: ?=(%point -.diff) [~ state] + ?> ?=(%tx -.diff) + =/ =keccak (hash-raw-tx:lib raw-tx.diff) + ?~ wer=(~(get by finding) keccak) + :: tx not submitted by this roller + :: + [~ state] + ?@ u.wer + ~? &(?=(%confirmed u.wer) ?=(~ err.diff)) + [dap.bowl %weird-double-confirm from.tx.raw-tx.diff] + [~ state] + =* nonce nonce.u.wer + =* address address.u.wer + =* ship ship.from.tx.raw-tx.diff + =* time time.u.wer + =* tx tx.raw-tx.diff + =/ l2-tx (l2-tx +<.tx) + :: remove the tx from the sending map + :: + =. sending + ?~ sen=(get:ors sending [get-address nonce]) + ~? lverb [dap.bowl %weird-double-remove nonce+nonce] + sending + ?~ nin=(find [raw-tx.diff]~ txs.u.sen) + ~? lverb [dap.bowl %weird-unknown nonce+nonce] + sending + =. txs.u.sen (oust [u.nin 1] txs.u.sen) + ?~ txs.u.sen + ~? lverb [dap.bowl %done-with-nonce [get-address nonce]] + =^ * sending + (del:ors sending [get-address nonce]) + sending + ^+ sending + (put:ors sending [get-address 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 + :: + =^ updates history + %+ update-history + [| address time raw-tx.diff]~ + ?~(err.diff %confirmed %failed) + [(emit updates) state] +:: +-- diff --git a/pkg/arvo/app/test.hoon b/pkg/arvo/app/test.hoon index b8f93b5fe..3a31d642a 100644 --- a/pkg/arvo/app/test.hoon +++ b/pkg/arvo/app/test.hoon @@ -50,7 +50,7 @@ |=(c=@tD `@tD`?:(=('/' c) '-' c)) =/ sing=card :+ %pass /build/mar/[mak] - [%arvo %c %warp our.bowl %home ~ %sing %b da+now.bowl /[mak]] + [%arvo %c %warp our.bowl q.byk.bowl ~ %sing %b da+now.bowl /[mak]] %_ $ paz t.paz fex [sing fex] @@ -72,7 +72,7 @@ $(daz t.daz) =/ sing=card :+ %pass /build/app/[i.daz] - [%arvo %c %warp our.bowl %home ~ %sing %a da+now.bowl dap-pax] + [%arvo %c %warp our.bowl q.byk.bowl ~ %sing %a da+now.bowl dap-pax] %_ $ daz t.daz fex [sing fex] @@ -92,7 +92,7 @@ $(paz t.paz) =/ sing=card :+ %pass build+i.paz - [%arvo %c %warp our.bowl %home ~ %sing %a da+now.bowl i.paz] + [%arvo %c %warp our.bowl q.byk.bowl ~ %sing %a da+now.bowl i.paz] %_ $ paz t.paz fex [sing fex] diff --git a/pkg/arvo/desk.bill b/pkg/arvo/desk.bill index bbb7fb7d3..b4d897254 100644 --- a/pkg/arvo/desk.bill +++ b/pkg/arvo/desk.bill @@ -1,5 +1,5 @@ :~ %acme - %azimuth-tracker + %azimuth %dbug %dojo %eth-watcher diff --git a/pkg/arvo/gen/azimuth-block.hoon b/pkg/arvo/gen/azimuth-block.hoon index 6b42aa8d8..e6bafea94 100644 --- a/pkg/arvo/gen/azimuth-block.hoon +++ b/pkg/arvo/gen/azimuth-block.hoon @@ -10,5 +10,5 @@ [leaf+(scow %ud block)]~ .^ @ud %gx - /(scot %p our)/eth-watcher/(scot %da now)/block/azimuth-tracker/noun + /(scot %p our)/eth-watcher/(scot %da now)/block/azimuth/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] diff --git a/pkg/arvo/gen/azimuth-tracker/kick.hoon b/pkg/arvo/gen/azimuth-tracker/kick.hoon deleted file mode 100644 index 3119ac5b4..000000000 --- a/pkg/arvo/gen/azimuth-tracker/kick.hoon +++ /dev/null @@ -1,4 +0,0 @@ -:: Kick azimuth-tracker -:- %say -|= * -[%azimuth-tracker-poke %listen ~ %| %azimuth-tracker] diff --git a/pkg/arvo/gen/azimuth-tracker/watch.hoon b/pkg/arvo/gen/azimuth-tracker/watch.hoon deleted file mode 100644 index 295db5803..000000000 --- a/pkg/arvo/gen/azimuth-tracker/watch.hoon +++ /dev/null @@ -1,4 +0,0 @@ -:: Change node url for azimuth-tracker -:- %say -|= [* [url=@ta ~] ~] -[%azimuth-tracker-poke %watch url] diff --git a/pkg/arvo/gen/azimuth/kick.hoon b/pkg/arvo/gen/azimuth/kick.hoon new file mode 100644 index 000000000..9082cfe83 --- /dev/null +++ b/pkg/arvo/gen/azimuth/kick.hoon @@ -0,0 +1,4 @@ +:: Kick azimuth +:- %say +|= * +[%azimuth-poke %listen ~ %| %azimuth] diff --git a/pkg/arvo/gen/azimuth-tracker/listen.hoon b/pkg/arvo/gen/azimuth/listen.hoon similarity index 72% rename from pkg/arvo/gen/azimuth-tracker/listen.hoon rename to pkg/arvo/gen/azimuth/listen.hoon index 5517063c3..539afebd0 100644 --- a/pkg/arvo/gen/azimuth-tracker/listen.hoon +++ b/pkg/arvo/gen/azimuth/listen.hoon @@ -1,4 +1,5 @@ -:: Add a source for azimuth-tracker +:: Add a source for azimuth +:: => |% +$ src $% [%ship =ship ~] @@ -12,4 +13,4 @@ %ship [%& ship.src] %app [%| term.src] == -[%azimuth-tracker-poke %listen whos source] +[%azimuth-poke %listen whos source] diff --git a/pkg/arvo/gen/azimuth/watch.hoon b/pkg/arvo/gen/azimuth/watch.hoon new file mode 100644 index 000000000..e85ad1470 --- /dev/null +++ b/pkg/arvo/gen/azimuth/watch.hoon @@ -0,0 +1,4 @@ +:: Change node url and network for azimuth +:- %say +|= [* [url=@ta net=?(%mainnet %ropsten %local %default) ~] ~] +[%azimuth-poke %watch url net] diff --git a/pkg/arvo/gen/hood/crunch.hoon b/pkg/arvo/gen/hood/crunch.hoon deleted file mode 100644 index 6998e7bf2..000000000 --- a/pkg/arvo/gen/hood/crunch.hoon +++ /dev/null @@ -1,30 +0,0 @@ -/- ms=metadata-store -/+ crunch -:- %say -|= [[now=@da * bec=beak] [csv-path=path from=@da ~] [to=@da groups=(list path) content=(unit ?) ~]] -=/ our=@p p.bec -:: check given path has `csv` mark -:: -?> =(%csv (snag (dec (lent csv-path)) csv-path)) -:: get all graph associations ship is a part of -:: -=/ associations=associations:ms - (~(scry-graph-associations crunch [our now])) -:: filter by input groups, if any (default: all from scry) -:: -=/ filtered-associations=associations:ms - ?~ groups - associations - %+ filter-associations-by-group-resources.crunch - associations - (paths-to-resources.crunch groups) -:: walk graphs to extract content -:: -=/ file-content=wain - %: ~(walk-graph-associations crunch [our now]) - filtered-associations - ?~ content %.n u.content - from - ?: =(*@da to) now to - == -[%helm-pass (note-write-csv-to-clay.crunch csv-path file-content)] diff --git a/pkg/arvo/gen/hood/label.hoon b/pkg/arvo/gen/hood/label.hoon index 6be85cb88..9f3cf717d 100644 --- a/pkg/arvo/gen/hood/label.hoon +++ b/pkg/arvo/gen/hood/label.hoon @@ -8,7 +8,13 @@ :: :- %say |= $: [now=@da eny=@uvJ bec=beak] - [arg=[syd=desk lab=@tas ~] ~] + [arg=[syd=desk lab=@tas ~] aeon=aeon:clay ~] == +:: handle optional aeon +:: +=/ aey=(unit aeon:clay) + ?: =(0 aeon) + ~ + `aeon :- %kiln-label -[syd lab]:arg +[syd.arg lab.arg aey] diff --git a/pkg/arvo/gen/hood/rein.hoon b/pkg/arvo/gen/hood/rein.hoon index d3477ec5e..3f777a2d3 100644 --- a/pkg/arvo/gen/hood/rein.hoon +++ b/pkg/arvo/gen/hood/rein.hoon @@ -10,7 +10,7 @@ :- desk %+ roll arg =| =rein:hood -|: [*[on=? =dude:gall] rein(liv liv)] +|: [*[on=? =dude:gall] rein=rein(liv liv)] ?: on rein(add (~(put in add.rein) dude)) rein(sub (~(put in sub.rein) dude)) diff --git a/pkg/arvo/gen/hood/start.hoon b/pkg/arvo/gen/hood/start.hoon index 2949d0044..a44b38b3d 100644 --- a/pkg/arvo/gen/hood/start.hoon +++ b/pkg/arvo/gen/hood/start.hoon @@ -10,8 +10,9 @@ |= $: [now=@da eny=@uvJ bec=beak] [arg=[@ $@(~ [@ ~])] ~] == -:- %drum-start -?> ((sane %tas) -.arg) -?@ +.arg [q.bec -.arg] -?> ((sane %tas) +<.arg) -[-.arg +<.arg] +=/ [des=@tas dap=@tas] + ?> ((sane %tas) -.arg) + ?@ +.arg [q.bec -.arg] + ?> ((sane %tas) +<.arg) + [-.arg +<.arg] +[%kiln-rein des & [dap ~ ~] ~] diff --git a/pkg/arvo/gen/roller/commit.hoon b/pkg/arvo/gen/roller/commit.hoon new file mode 100644 index 000000000..f04a62e11 --- /dev/null +++ b/pkg/arvo/gen/roller/commit.hoon @@ -0,0 +1,5 @@ +:: Submits a new L2 batch with all pending transactions +:: +:- %say +|= * +[%roller-action %commit ~] diff --git a/pkg/arvo/gen/roller/config.hoon b/pkg/arvo/gen/roller/config.hoon new file mode 100644 index 000000000..261514635 --- /dev/null +++ b/pkg/arvo/gen/roller/config.hoon @@ -0,0 +1,7 @@ +:: Updates a configuration option for /app/roller +:: +/- *dice +:: +:- %say +|= [* [=config ~] ~] +[%roller-action %config config] diff --git a/pkg/arvo/gen/roller/endpoint.hoon b/pkg/arvo/gen/roller/endpoint.hoon new file mode 100644 index 000000000..ce59f3073 --- /dev/null +++ b/pkg/arvo/gen/roller/endpoint.hoon @@ -0,0 +1,4 @@ +:: +:- %say +|= [* [url=@t net=?(%mainnet %ropsten %local) ~] ~] +[%roller-action %config %endpoint url net] diff --git a/pkg/arvo/gen/roller/frequency.hoon b/pkg/arvo/gen/roller/frequency.hoon new file mode 100644 index 000000000..b4485a309 --- /dev/null +++ b/pkg/arvo/gen/roller/frequency.hoon @@ -0,0 +1,4 @@ +:: +:- %say +|= [* [freq=@dr ~] ~] +[%roller-action %config %frequency freq] diff --git a/pkg/arvo/gen/roller/local.hoon b/pkg/arvo/gen/roller/local.hoon new file mode 100644 index 000000000..f1202a8ed --- /dev/null +++ b/pkg/arvo/gen/roller/local.hoon @@ -0,0 +1,5 @@ +:: Configures /app/roller to listen to a local Ethereum node +:: +:- %say +|= * +[%roller-action %config %endpoint 'http://0.0.0.0:8545' %local] diff --git a/pkg/arvo/gen/roller/quota.hoon b/pkg/arvo/gen/roller/quota.hoon new file mode 100644 index 000000000..a5ca7845b --- /dev/null +++ b/pkg/arvo/gen/roller/quota.hoon @@ -0,0 +1,5 @@ +:: Modifies the number of txs a ship is allowed to send, per unit of time (slice) +:: +:- %say +|= [* [quota=@ud ~] ~] +[%roller-action %config %quota quota] diff --git a/pkg/arvo/gen/roller/ropsten.hoon b/pkg/arvo/gen/roller/ropsten.hoon new file mode 100644 index 000000000..af363f0dd --- /dev/null +++ b/pkg/arvo/gen/roller/ropsten.hoon @@ -0,0 +1,10 @@ +:: Configures /app/roller to listen to a Ropsten Infura node +:: +:- %say +|= * +:* %roller-action + %config + %endpoint + 'https://ropsten.infura.io/v3/2599df54929b47099bda360958d75aaf' + %ropsten +== diff --git a/pkg/arvo/gen/roller/setkey.hoon b/pkg/arvo/gen/roller/setkey.hoon new file mode 100644 index 000000000..7e884027b --- /dev/null +++ b/pkg/arvo/gen/roller/setkey.hoon @@ -0,0 +1,5 @@ +:: Loads a private key into the roller and retrieves its L1 nonce +:: +:- %say +|= [* [pk=@t ~] ~] +[%roller-action %config %setkey pk] diff --git a/pkg/arvo/gen/roller/slice.hoon b/pkg/arvo/gen/roller/slice.hoon new file mode 100644 index 000000000..1b0de984e --- /dev/null +++ b/pkg/arvo/gen/roller/slice.hoon @@ -0,0 +1,5 @@ +:: Modifies the unit of time (e.g. ~d1) for each ship's quota +:: +:- %say +|= [* [slice=@dr ~] ~] +[%roller-action %config %slice slice] diff --git a/pkg/arvo/gen/show-vat.hoon b/pkg/arvo/gen/show-vat.hoon index 2f2e7f725..180b29eed 100644 --- a/pkg/arvo/gen/show-vat.hoon +++ b/pkg/arvo/gen/show-vat.hoon @@ -1,4 +1,3 @@ -/- *bill :- %say |= $: [now=@da eny=@uvJ bec=beak] [=desk ~] @@ -11,5 +10,5 @@ :~ 'sys.kelvin:' leaf/"[%{} %{}]" 'desk.bill:' - (sell !>(.^(bill cx+(weld pax /desk/bill)))) + (sell !>(.^((list dude:gall) cx+(weld pax /desk/bill)))) == diff --git a/pkg/arvo/gen/tx.hoon b/pkg/arvo/gen/tx.hoon new file mode 100644 index 000000000..64f3393cf --- /dev/null +++ b/pkg/arvo/gen/tx.hoon @@ -0,0 +1,56 @@ +:: ethereum.request({method: 'personal_sign', params: ['tx',count]}).then(console.log) +:: ethereum.request({method: 'eth_sendTransaction', params: [{from: count, gasPrice: '0x2540be400', to: '0xb58101cd3bbbcc6fa40bcdb04bb71623b5c7d39b', gas: '0x10000', data: 'batch', chainId: '0x3'}]}).then(console.log) +:: +/+ eth=ethereum +/= tt /tests/lib/naive +|% +:: Generated by running these commands after modifying eth-sig-util +:: such that TypedDataUtils.sign returns the domain separator instead +:: of continuing to sign. I think this is basically EIP-712 +:: compatible, but it also doesn't matter much because we're not +:: compatible with the whole EIP anyway. The main thing is to be +:: distinct from other names, versions, and chainIds. +:: +:: Alter chainId as necessary +:: +:: sig = require('eth-sig-util') +:: domain = [{ name: "name", type: "string" },{ name: "version", type: "string" },{ name: "chainId", type: "uint256" }] +:: domainData = {name: "Urbit", version: "1", chainId: 0x1} +:: sig.TypedDataUtils.sign({domain: domainData, types: {EIP712Domain: domain}, primaryType: 'EIP712Domain'}, true).toString('hex') +:: +++ domain-separator ropsten-separator +++ mainnet-separator + 0x30e4.9840.ca87.cf16.b969.f49e.4b8d.488f. + 08a6.88f9.43f5.b07e.7671.6c0d.b2fb.b44b +++ ropsten-separator + 0x77e7.083f.92f9.321e.0a71.a78d.238a.a25a. + 5689.19d4.6a58.abf6.7bed.2c83.80e1.8692 +:: +++ print-for-web3 + |= =octs + ^- @t + =/ txt (crip (render-hex-bytes:eth octs)) + ?> =(p.octs (met 4 txt)) + (cat 3 '0x' (rev 4 (met 4 txt) txt)) +:: +++ print-for-batch + |= =octs + ^- @t + (crip (render-hex-bytes:eth octs)) +-- +|= sig=(unit @t) +^- @t +=/ account (hex-to-num:eth '0xb026b0AA6e686F2386051b31A03E5fB95513e1c0') +=/ tx=octs + (gen-tx-octs:tt [~ravmun-mitbus %own] %set-spawn-proxy account) +=/ prepped=octs (prepare-for-sig:tt 3 0 tx) +?~ sig + (cat 3 'sign: ' (print-for-web3 prepped)) +=/ batch=@t + %: rap 3 + '0x26887f26' + (print-for-batch tx) + (rsh 3^2 u.sig) + ~ + == +(cat 3 'batch: ' batch) diff --git a/pkg/arvo/lib/azimuth-roll-rpc.hoon b/pkg/arvo/lib/azimuth-roll-rpc.hoon new file mode 100644 index 000000000..baf502807 --- /dev/null +++ b/pkg/arvo/lib/azimuth-roll-rpc.hoon @@ -0,0 +1,683 @@ +:: azimuth/roll rpc: command parsing and utilities +:: +/- rpc=json-rpc, *dice +/+ naive, json-rpc, lib=naive-transactions +:: +=> :: Utilities + :: + |% + +$ spawn-action + $? %escape + %cancel-escape + %adopt + %reject + %detach + == + :: + +$ proxy-action + $? %set-management-proxy + %set-spawn-proxy + %set-transfer-proxy + == + :: + ++ parse-ship + |= jon=json + ^- (unit @p) + ?: ?=([%n *] jon) + (rush p.jon dem) + ?. ?=([%s *] jon) ~ + (rush p.jon ;~(pfix sig fed:ag)) + :: TODO: from /lib/group-store (move to zuse?) + ++ enkebab + |= str=cord + ^- @tas + ~| str + =- (fall - str) + %+ rush str + =/ name + %+ cook + |= part=tape + ^- tape + ?~ part part + :- (add i.part 32) + t.part + ;~(plug hig (star low)) + %+ cook + |=(a=(list tape) (crip (zing (join "-" a)))) + ;~(plug (star low) (star name)) + :: + ++ from-json + =, dejs-soft:format + |% + ++ data + |% + ++ keys + |= params=(map @t json) + ^- (unit [encrypt=@ auth=@ crypto-suite=@ breach=?]) + ?~ data=(~(get by params) 'data') ~ + =; ans=(unit [cryp=(unit @ux) auth=(unit @ux) suit=@ brec=?]) + ?~ ans ~ + ?: |(?=(~ cryp.u.ans) ?=(~ auth.u.ans)) ~ + (some [u.cryp.u.ans u.auth.u.ans suit.u.ans brec.u.ans]) + %. u.data + %- ot + :~ ['encrypt' (cu to-hex so)] + ['auth' (cu to-hex so)] + ['cryptoSuite' (su dem)] + ['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 + %- 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 + %- ot + :~ ['ship' parse-ship] + ['address' (cu to-hex so)] + == + :: + ++ address + |= params=(map @t json) + ^- (unit @ux) + ?~ data=(~(get by params) 'data') ~ + =; ans=(unit (unit @ux)) + ?~(ans ~ u.ans) + %. u.data + (ot ['address' (cu to-hex so)]~) + :: + ++ ship + |= params=(map @t json) + ^- (unit @p) + ?~ data=(~(get by params) 'data') ~ + %. u.data + (ot ['ship' parse-ship]~) + :: + ++ cancel + |= params=(map @t json) + ^- (unit [l2-tx @p]) + ?~ data=(~(get by params) 'data') ~ + %. u.data + %- ot + :~ ['type' (cu l2-tx so)] + ['ship' parse-ship] + == + -- + :: + ++ ship + |= params=(map @t json) + ^- (unit @p) + ?~ data=(~(get by params) 'ship') ~ + (parse-ship u.data) + :: + ++ address + |= params=(map @t json) + ^- (unit @ux) + ?~ data=(~(get by params) 'address') ~ + ?~ ans=((cu to-hex so) u.data) ~ + u.ans + :: + ++ sig + |= params=(map @t json) + ^- (unit @) + ?~ sig=(~(get by params) 'sig') ~ + ?~ ans=((cu to-hex so) u.sig) ~ + u.ans + :: + ++ from + |= params=(map @t json) + ^- (unit [@p proxy:naive]) + ?~ from=(~(get by params) 'from') ~ + %. u.from + %- ot + :~ ['ship' parse-ship] + ['proxy' (cu proxy:naive so)] + == + :: + ++ hash + |= params=(map @t json) + ^- (unit @ux) + ?~ hash=(~(get by params) 'hash') ~ + ?~ ans=((cu to-hex so) u.hash) ~ + u.ans + :: + ++ raw + |= params=(map @t json) + ^- (unit octs) + ?~ raw=(~(get by params) 'raw') ~ + ?~ ans=((cu to-hex so) u.raw) ~ + ?~ u.ans ~ + (some (as-octs:mimes:html u.u.ans)) + :: + ++ tx + |= params=(map @t json) + ^- (unit l2-tx) + ?~ data=(~(get by params) 'tx') ~ + ?~ tx=(so u.data) ~ + =/ method=@tas (enkebab u.tx) + ?. ?=(l2-tx method) ~ + `method + :: + ++ nonce + |= params=(map @t json) + ^- (unit @ud) + ?~ nonce=(~(get by params) 'nonce') ~ + (ni u.nonce) + -- + :: + ++ to-json + =, enjs:format + |% + ++ pending-tx + |= pend-tx + ^- json + %- pairs + :~ ['force' b+force] + ['time' (^time time)] + ['rawTx' (^raw-tx raw-tx)] + (en-address address) + == + :: + ++ pending-txs + |= pending=(list pend-tx) + ^- json + a+(turn pending pending-tx) + :: + ++ en-address |=(a=@ux address+(hex 20 a)) + :: + ++ raw-tx + |= raw-tx:naive + ^- json + |^ + %- pairs + :~ ['tx' (parse-tx +.tx)] + ['sig' (hex (as-octs:mimes:html sig))] + :: + :- '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+(numb `@ud`s)) + ++ 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)] + ['cryptoSuite' (numb crypto-suite)] + ['breach' b+breach] + == + -- + :: + ++ hist-txs + |= txs=(list hist-tx) + ^- json + :- %a + %+ turn txs + |= hist-tx + ^- json + %- pairs + :~ ['time' (time p)] + ['status' s+status.q] + ['hash' (hex (as-octs:mimes:html hash.q))] + ['type' s+type.q] + ['ship' (ship ship.q)] + == + :: + ++ point + |= =point:naive + ^- json + %- 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' s+(json-number rift.net)] + :: + :- 'keys' + %- pairs + :~ ['life' s+(json-number life.keys.net)] + ['suite' s+(json-number suite.keys.net)] + ['auth' (hex 32 auth.keys.net)] + ['crypt' (hex 32 crypt.keys.net)] + == + :: + :- 'sponsor' + %- pairs + ~[['has' b+has.sponsor.net] ['who' (numb `@ud`who.sponsor.net)]] + :: + ?~ escape.net ~ + ['escape' (numb `@ud`u.escape.net)]~ + == == + :: + ++ json-number + |= num=@ + ^- @t + =/ jon=json (numb num) + ?>(?=([%n *] jon) p.jon) + :: + ++ points + |= points=(list [@p point:naive]) + ^- json + :- %a + %+ turn points + |= [ship=@p =point:naive] + %- pairs + :~ ['ship' (^ship ship)] + ['point' (^point point)] + == + :: + ++ ships + |= ships=(list @p) + ^- json + a+(turn ships (cork @ud numb)) + :: + ++ ownership + |= [=address:naive =nonce:naive] + ^- json + %- pairs + :~ (en-address address) + ['nonce' (numb nonce)] + == + :: + ++ spawned + |= children=(list [@p @ux]) + ^- json + :- %a + %+ turn children + |= [child=@p address=@ux] + %- pairs + :~ ['ship' (ship child)] + (en-address address) + == + :: + ++ sponsored + |= [res=(list @p) req=(list @p)] + ^- json + %- pairs + :~ ['residents' (ships res)] + ['requests' (ships req)] + == + :: + ++ tx-status |=(=^tx-status ^-(json s+status.tx-status)) + :: + ++ roller-config + |= [az=^azimuth-config ro=^roller-config] + ^- json + %- pairs + :~ ['azimuthRefreshRate' (numb (div refresh-rate.az ~s1))] + ['nextBatch' (time next-batch.ro)] + ['frequency' (numb (div frequency.ro ~s1))] + ['rollerResendTime' (numb (div resend-time.ro ~s1))] + ['rollerUpdateRate' (numb (div update-rate.ro ~s1))] + ['contract' (hex 20 contract.ro)] + ['chainId' (numb chain-id.ro)] + ['timeSlice' (numb (div slice.ro ~s1))] + ['rollerQuota' (numb quota.ro)] + == + :: + ++ azimuth-config + |= config=^azimuth-config + ^- json + %- pairs + ['refreshRate' (numb (div refresh-rate.config ~s1))]~ + :: + ++ hex + |= [p=@ q=@] + ^- json + s+(crip ['0' 'x' ((x-co:co (mul 2 p)) q)]) + :: + ++ naive-state + |= =^state:naive + ^- json + |^ + %- pairs + :~ ['points' (points (tap:orp points.state))] + ['operators' (operators operators.state)] + ['dns' a+(turn dns.state (lead %s))] + == + :: + ++ orp ((on ^ship point:naive) por:naive) + :: + ++ operators + |= =operators:naive + ^- json + :- %a + %+ turn ~(tap by operators) + |= [op=@ux addrs=(set @ux)] + ^- json + %- pairs + :~ ['operator' (hex 20 op)] + ['addresses' a+(turn ~(tap in addrs) (cury hex 20))] + == + -- + -- + :: + ++ to-hex + |= =cord + ^- (unit @ux) + ?. =((end [3 2] cord) '0x') ~ + (rush (rsh [3 2] cord) hex) + :: + ++ build-l2-tx + |= [=l2-tx from=[@p proxy:naive] params=(map @t json)] + ^- (unit tx:naive) + ?: =(l2-tx %transfer-point) + ?~ data=(address-transfer:data:from-json params) + ~ + `[from %transfer-point u.data] + ?: =(l2-tx %spawn) + ?~ data=(address-ship:data:from-json params) + ~ + `[from %spawn u.data] + ?: =(l2-tx %configure-keys) + ?~ data=(keys:data:from-json params) + ~ + `[from %configure-keys u.data] + ?: ?=(spawn-action l2-tx) + ?~ data=(ship:data:from-json params) + ~ + ?- l2-tx + %escape `[from %escape u.data] + %cancel-escape `[from %cancel-escape u.data] + %adopt `[from %adopt u.data] + %reject `[from %reject u.data] + %detach `[from %detach u.data] + == + ?. ?=(proxy-action l2-tx) + ~ + ?~ data=(address:data:from-json params) + ~ + ?- l2-tx + %set-management-proxy `[from %set-management-proxy u.data] + %set-spawn-proxy `[from %set-spawn-proxy u.data] + %set-transfer-proxy `[from %set-transfer-proxy u.data] + == + -- +|% +++ get-point + |= [id=@t params=(map @t json) scry=$-(ship (unit point:naive))] + ^- response:rpc + ?. =(~(wyt by params) 1) + ~(params error:json-rpc id) + ?~ ship=(~(get by params) 'ship') + ~(params error:json-rpc id) + ?~ ship=(parse-ship u.ship) + ~(params error:json-rpc id) + ?~ point=(scry u.ship) + ~(not-found error:json-rpc id) + [%result id (point:to-json u.point)] +:: +++ get-ships + |= [id=@t params=(map @t json) scry=$-(@ux (list @p))] + ^- response:rpc + ?. =(~(wyt by params) 1) + ~(params error:json-rpc id) + ?~ address=(address:from-json params) + ~(parse error:json-rpc id) + [%result id (ships:to-json (scry u.address))] +:: +++ get-dns + |= [id=@t params=(map @t json) dns=(list @t)] + ^- response:rpc + ?. =((lent ~(tap by params)) 0) + ~(params error:json-rpc id) + [%result id a+(turn dns (cork same (lead %s)))] +:: +++ cancel-tx + |= [id=@t params=(map @t json)] + ^- [(unit cage) response:rpc] + ?. =(~(wyt by params) 3) + [~ ~(params error:json-rpc id)] + =/ sig=(unit @) (sig:from-json params) + =/ keccak=(unit @ux) (hash:from-json params) + =/ data=(unit [l2-tx ship]) (cancel:data:from-json params) + ?. &(?=(^ sig) ?=(^ keccak) ?=(^ data)) + [~ ~(parse error:json-rpc id)] + :_ [%result id s+'ok'] + %- some + roller-action+!>([%cancel u.sig u.keccak u.data]) +:: +++ get-spawned + |= [id=@t params=(map @t json) scry=$-(@p (list @p))] + ^- response:rpc + ?. =((lent ~(tap by params)) 1) + ~(params error:json-rpc id) + ?~ ship=(ship:from-json params) + ~(params error:json-rpc id) + [%result id (ships:to-json (scry u.ship))] +:: +++ spawns-remaining + |= [id=@t params=(map @t json) scry=$-(@p (list @p))] + ^- response:rpc + ?. =((lent ~(tap by params)) 1) + ~(params error:json-rpc id) + ?~ ship=(ship:from-json params) + ~(params error:json-rpc id) + [%result id (numb:enjs:format (lent (scry u.ship)))] +:: +++ sponsored-points + |= [id=@t params=(map @t json) scry=$-(@p [(list @p) (list @p)])] + ^- response:rpc + ?. =((lent ~(tap by params)) 1) + ~(params error:json-rpc id) + ?~ ship=(ship:from-json params) + ~(params error:json-rpc id) + [%result id (sponsored:to-json (scry u.ship))] +:: +++ process-rpc + |= [id=@t params=(map @t json) action=l2-tx over-quota=$-(@p ?)] + ^- [(unit cage) response:rpc] + ?. =((lent ~(tap by params)) 4) + [~ ~(params error:json-rpc id)] + =+ ^- $: sig=(unit @) + from=(unit [=ship proxy:naive]) + addr=(unit @ux) + == + =, from-json + [(sig params) (from params) (address params)] + ?: |(?=(~ sig) ?=(~ from) ?=(~ addr)) + [~ ~(parse error:json-rpc id)] + ?: (over-quota ship.u.from) + `[%error id '-32002' 'Max tx quota exceeded'] + =/ tx=(unit tx:naive) (build-l2-tx action u.from params) + ?~ tx [~ ~(parse error:json-rpc id)] + =+ (gen-tx-octs:lib u.tx) + :_ [%result id (hex:to-json 32 (hash-tx:lib p q))] + %- some + roller-action+!>([%submit | u.addr u.sig %don u.tx]) +:: +++ nonce + |= [id=@t params=(map @t json) scry=$-([ship proxy:naive] (unit @))] + ^- response:rpc + ?. =((lent ~(tap by params)) 1) + ~(params error:json-rpc id) + ?~ from=(from:from-json params) + ~(parse error:json-rpc id) + ?~ nonce=(scry u.from) + ~(not-found error:json-rpc id) + [%result id (numb:enjs:format u.nonce)] +:: +++ pending + |% + :: + ++ all + |= [id=@t params=(map @t json) pending=(list pend-tx)] + ^- response:rpc + ?. =((lent ~(tap by params)) 0) + ~(params error:json-rpc id) + [%result id (pending-txs:to-json pending)] + :: + ++ ship + |= [id=@t params=(map @t json) scry=$-(@p (list pend-tx))] + ^- response:rpc + ?. =((lent ~(tap by params)) 1) + ~(params error:json-rpc id) + ?~ ship=(ship:from-json params) + ~(parse error:json-rpc id) + [%result id (pending-txs:to-json (scry u.ship))] + :: + ++ addr + |= [id=@t params=(map @t json) scry=$-(@ux (list pend-tx))] + ^- response:rpc + ?. =((lent ~(tap by params)) 1) + ~(params error:json-rpc id) + ?~ address=(address:from-json params) + ~(parse error:json-rpc id) + [%result id (pending-txs:to-json (scry u.address))] + :: + ++ hash + |= [id=@t params=(map @t json) scry=$-(@ux (unit pend-tx))] + ^- response:rpc + ?. =((lent ~(tap by params)) 1) + ~(params error:json-rpc id) + ?~ hash=(hash:from-json params) + ~(parse error:json-rpc id) + ?~ tx=(scry u.hash) + ~(not-found error:json-rpc id) + [%result id (pending-tx:to-json u.tx)] + -- +:: +++ status + |= [id=@t params=(map @t json) scry=$-(@ tx-status)] + ^- response:rpc + ?. =((lent ~(tap by params)) 1) + ~(params error:json-rpc id) + ?~ hash=(hash:from-json params) + ~(parse error:json-rpc id) + [%result id (tx-status:to-json (scry u.hash))] +:: +++ next-batch + |= [id=@t params=(map @t json) when=time] + ^- response:rpc + ?. =((lent ~(tap by params)) 0) + ~(params error:json-rpc id) + [%result id (time:enjs:format when)] +:: +++ history + |= [id=@t params=(map @t json) scry=$-(address:naive (list hist-tx))] + ^- response:rpc + ?. =((lent ~(tap by params)) 1) + ~(params error:json-rpc id) + ?~ address=(address:from-json params) + ~(parse error:json-rpc id) + [%result id (hist-txs:to-json (scry u.address))] +:: +++ get-config + |= [id=@t params=(map @t json) config=[azimuth-config roller-config]] + ^- response:rpc + ?. =((lent ~(tap by params)) 0) + ~(params error:json-rpc id) + [%result id (roller-config:to-json config)] +:: +++ hash-transaction + |= [id=@t params=(map @t json) chain-id=@ header=? reverse=?] + ^- response:rpc + ?. =((lent ~(tap by params)) 4) + ~(params error:json-rpc id) + =+ ^- $: l2-tx=(unit l2-tx) + nonce=(unit @ud) + from=(unit [@p proxy:naive]) + == + =, from-json + [(tx params) (nonce params) (from params)] + ?: |(?=(~ nonce) ?=(~ from) ?=(~ l2-tx)) + ~(parse error:json-rpc id) + =/ tx=(unit tx:naive) (build-l2-tx u.l2-tx u.from params) + ?~ tx ~(parse error:json-rpc id) + =/ =octs + %. [chain-id u.nonce (gen-tx-octs:lib u.tx)] + ?: header + unsigned-tx:lib + prepare-for-sig:lib + :+ %result id + %- hex:to-json + ?: reverse + p.octs^(rev 3 octs) + 32^(hash-tx:lib octs) +:: +++ hash-raw-transaction + |= [id=@t params=(map @t json)] + ^- response:rpc + ?. =((lent ~(tap by params)) 4) + ~(params error:json-rpc id) + =+ ^- $: sig=(unit @) + l2-tx=(unit l2-tx) + from=(unit [=ship proxy:naive]) + == + =, from-json + [(sig params) (tx params) (from params)] + ?: |(?=(~ sig) ?=(~ from) ?=(~ l2-tx)) + ~(parse error:json-rpc id) + =/ tx=(unit tx:naive) (build-l2-tx u.l2-tx u.from params) + ?~ tx ~(parse error:json-rpc id) + :+ %result id + %+ hex:to-json 32 + (hash-raw-tx:lib u.sig (gen-tx-octs:lib u.tx) u.tx) +:: +++ get-naive + |= [id=@t params=(map @t json) =^state:naive] + ^- response:rpc + ?. =((lent ~(tap by params)) 0) + ~(params error:json-rpc id) + [%result id (naive-state:to-json state)] +:: +++ get-refresh + |= [id=@t params=(map @t json) =azimuth-config] + ^- response:rpc + ?. =((lent ~(tap by params)) 0) + ~(params error:json-rpc id) + [%result id (azimuth-config:to-json azimuth-config)] +-- diff --git a/pkg/arvo/lib/azimuth.hoon b/pkg/arvo/lib/azimuth.hoon index e12222542..32f5c03a7 100644 --- a/pkg/arvo/lib/azimuth.hoon +++ b/pkg/arvo/lib/azimuth.hoon @@ -98,6 +98,9 @@ ++ delegated-sending 0xf790.8ab1.f1e3.52f8.3c5e.bc75.051c.0565.aeae.a5fb :: + ++ naive + 0xeb70.029c.fb3c.53c7.78ea.f68c.d28d.e725.390a.1fe9 + :: :: launch: block number of azimuth deploy :: ++ launch 6.784.800 @@ -105,6 +108,8 @@ :: public: block number of azimuth becoming independent :: ++ public 7.033.765 + :: + ++ chain-id 1 -- :: :: Testnet contract addresses @@ -126,8 +131,12 @@ ++ delegated-sending 0x3e8c.a510.354b.c2fd.bbd6.1502.52d9.3105.c9c2.7bbe :: + ++ naive + 0xe7cf.4b83.06d3.11ba.ca15.585f.e3f0.7cd0.441c.21d1 + :: ++ launch 4.601.630 ++ public launch + ++ chain-id 3 -- :: :: Local contract addresses @@ -147,8 +156,11 @@ 0x3c3.dc12.be65.8158.d1d7.f9e6.6e08.ec40.99c5.68e4 ++ conditional-star-release 0x35eb.3b10.2d9c.1b69.ac14.69c1.b1fe.1799.850c.d3eb + ++ naive + 0x6bb8.8a9b.bd82.be7a.997f.eb01.929c.6ec7.8988.fe12 ++ launch 0 ++ public 0 + ++ chain-id 1.337 -- :: :: ++ azimuth 0x863d.9c2e.5c4c.1335.96cf.ac29.d552.55f0.d0f8.6381 :: local bridge diff --git a/pkg/arvo/lib/crunch.hoon b/pkg/arvo/lib/crunch.hoon deleted file mode 100644 index 58c0cbb7f..000000000 --- a/pkg/arvo/lib/crunch.hoon +++ /dev/null @@ -1,356 +0,0 @@ -/- c=crunch, gs=graph-store, ms=metadata-store, p=post, r=resource -:: -=< - |_ [our=ship now=@da] - ++ walk-graph-associations - |= [=associations:ms content=? from=@da to=@da] - ^- wain - :: graph resources in `our`; used to avoid scrying, e.g., - :: a graph `our` has left and can no longer access - :: - =/ accessible-graphs=(set resource:r) (scry-graph-resources) - %- ~(rep by associations) - |= [[=md-resource:ms =association:ms] out=wain] - ^- wain - ?. ?=(%graph app-name.md-resource) - out - ?. ?=(%graph -.config.metadatum.association) - out - :: ensure graph, given by association, exists in `our` - :: - ?. (~(has in accessible-graphs) resource.md-resource) - out - :: scry the graph - :: - =/ graph=(unit graph:gs) (scry-graph resource.md-resource) - ?~ graph - out - :: prepare channel-info argument - :: - =/ channel-info=channel-info:c - :* group.association - resource.md-resource - module.config.metadatum.association - == - :: walk the graph - :: - ?+ module.config.metadatum.association - :: non-chat (e.g. links & notes) - :: - %+ weld out - %: walk-nested-graph-for-most-recent-entries - u.graph - content - channel-info - from - to - == - :: - %chat - %+ weld out - %: walk-chat-graph - u.graph - content - channel-info - from - to - == - == - :: - ++ scry-graph - |= graph-resource=resource:r - ^- (unit graph:gs) - =/ scry-response=update:gs - .^ update:gs - %gx - (scot %p our) - %graph-store - (scot %da now) - %graph - (scot %p entity.graph-resource) - name.graph-resource - /noun - == - ?. ?=(%add-graph -.q.scry-response) - ~ - ?~ graph.q.scry-response - ~ - [~ graph.q.scry-response] - :: - ++ scry-graph-resources - |= ~ - ^- (set resource:r) - =/ scry-response=update:gs - .^ update:gs - %gx - (scot %p our) - %graph-store - (scot %da now) - /keys/noun - == - ?. ?=(%keys -.q.scry-response) - ~ - resources.q.scry-response - :: helper arm for callers to get graph associations - :: to pass to `walk-graph-associations` - :: - ++ scry-graph-associations - |= ~ - ^- associations:ms - .^ associations:ms - %gx - (scot %p our) - %metadata-store - (scot %da now) - /app-name/graph/noun - == - -- -:: -|% -:: -:: parsing and formatting -:: -++ resource-to-cord - |= =resource:r - ^- @t - (rap 3 (scot %p entity.resource) '/' (scot %tas name.resource) ~) -:: -++ paths-to-resources - |= paxs=(list path) - ^- (set resource:r) - %- ~(gas in *(set resource:r)) - (turn paxs path-to-resource) -:: -++ path-to-resource - |= pax=path - ^- resource:r - =/ entity=@p (slav %p -.pax) - =/ name=@tas -.+.pax - [entity name] -:: -++ escape-characters-in-cord - |= =cord - ^- @t - %- crip - %- mesc - :: specific to CSVs: make sure content does not - :: contain commas (only allowed as delimiters) - :: - %- replace-tape-commas-with-semicolons - %- trip - cord -:: -++ replace-tape-commas-with-semicolons - |= string=tape - ^- tape - =/ comma-indices=(list @ud) (fand "," string) - |- - ^- tape - ?~ comma-indices - string - $(string (snap string i.comma-indices ';'), comma-indices t.comma-indices) -:: -++ contents-to-cord - |= contents=(list content:p) - ^- @t - ?~ contents - '' - %+ join-cords - ' ' - (turn contents content-to-cord) -:: -++ content-to-cord - |= =content:p - ^- @t - ?- -.content - %text (escape-characters-in-cord text.content) - %mention (scot %p ship.content) - %url url.content - %code expression.content :: TODO: also print output? - %reference (reference-content-to-cord reference.content) - == -:: -++ reference-content-to-cord - |= =reference:p - ^- @t - ?- -.reference - %group (resource-to-cord group.reference) - %graph (rap 3 (resource-to-cord group.reference) ': ' (resource-to-cord resource.uid.reference) ~) - == -:: -++ format-post-to-comma-separated-cord - |= [=post:gs =channel-info:c] - ^- @t - %+ join-cords - ',' - :~ (scot %da time-sent.post) - (scot %p author.post) - (resource-to-cord group.channel-info) - (resource-to-cord channel.channel-info) - (scot %tas channel-type.channel-info) - :: exclude content; optionally add later - :: - == -:: -++ join-cords - |= [delimiter=@t cords=(list @t)] - ^- @t - %+ roll cords - |= [cord=@t out=@t] - ^- @t - ?: =('' out) - :: don't put delimiter before first element - :: - cord - (rap 3 out delimiter cord ~) -:: -:: walking graphs -:: -++ walk-chat-graph - |= [=graph:gs content=? =channel-info:c from=@da to=@da] - ^- wain - %- flop - %+ roll - :: filter by time - :: - %+ only-nodes-older-than to - %+ only-nodes-newer-than from - ~(val by graph) - |= [=node:gs out=wain] - ^- wain - ?- -.post.node - %| - :: do not output deleted posts - :: - out - %& - ?~ contents.p.post.node - :: do not output structural nodes - :: - out - :_ out - =/ post-no-content=@t (format-post-to-comma-separated-cord p.post.node channel-info) - ?- content - %| post-no-content - %& - %+ join-cords ',' - ~[post-no-content (contents-to-cord contents.p.post.node)] - == - == -:: -++ walk-nested-graph-for-most-recent-entries - |= [=graph:gs content=? =channel-info:c from=@da to=@da] - ^- wain - =| out=wain - =| most-recent-post-content=@t - =/ nodes - :: filter by time - :: - %+ only-nodes-older-than to - %+ only-nodes-newer-than from - ~(val by graph) - %- flop - |- - ^- wain - ?~ nodes - ?: =('' most-recent-post-content) - :: don't return a cell: `['' ~]` - :: we want either an empty list `~` - :: or a list populated with actual entries - :: - out - [most-recent-post-content out] - :: - =? out ?=(%graph -.children.i.nodes) - %+ weld out - %: walk-nested-graph-for-most-recent-entries - p.children.i.nodes - content - channel-info - from - to - == - :: - ?- -.post.i.nodes - %| - :: do not keep deleted posts - :: - $(nodes t.nodes) - %& - ?~ contents.p.post.i.nodes - :: do not keep structural nodes - :: - $(nodes t.nodes) - =/ post-no-content=@t (format-post-to-comma-separated-cord p.post.i.nodes channel-info) - %= $ - nodes t.nodes - most-recent-post-content - ?- content - %| post-no-content - %& - %+ join-cords ',' - ~[post-no-content (contents-to-cord contents.p.post.i.nodes)] - == - == - == -:: -:: filters -:: -++ filter-associations-by-group-resources - |= [=associations:ms group-resources=(set resource:r)] - ^- associations:ms - %- ~(rep by associations) - |= [[=md-resource:ms =association:ms] out=associations:ms] - ^- associations:ms - ?. (~(has in group-resources) group.association) - out - (~(put by out) md-resource association) -:: wrappers for intuitive use of `filter-nodes-by-timestamp`: -:: pass `nodes` as given by the `graph-store` scry and no -:: need to worry about comparators -:: -++ only-nodes-older-than - |= [time=@da nodes=(list node:gs)] - (filter-nodes-by-timestamp nodes lte time) -:: -++ only-nodes-newer-than - |= [time=@da nodes=(list node:gs)] - %- flop - (filter-nodes-by-timestamp (flop nodes) gte time) -:: -++ filter-nodes-by-timestamp - |= [nodes=(list node:gs) comparator=$-([@ @] ?) time=@da] - =| out=(list node:gs) - :: return `out` in same time-order as `nodes` - :: - %- flop - |- - ^- (list node:gs) - ?~ nodes - out - ?- -.post.i.nodes - %| - :: skip deleted posts - :: - $(nodes t.nodes) - %& - ?. (comparator time-sent.p.post.i.nodes time) - :: assume: - :: * time is monotonic - :: * first `%.n` we hit indicates nodes further on are `%.n` - :: (i.e. `nodes` must be ordered st. they start `%.y`, - :: e.g. if want all `nodes` older than given time, - :: `nodes` must start with oldest and comparator is `lth`) - :: - out - $(nodes t.nodes, out [i.nodes out]) - == -:: -:: io -:: -++ note-write-csv-to-clay - |= [pax=path file-content=wain] - ?> =(%csv (snag (dec (lent pax)) pax)) - [%c [%info %base %& [pax %ins %csv !>(file-content)]~]] -:: --- diff --git a/pkg/arvo/lib/dice.hoon b/pkg/arvo/lib/dice.hoon new file mode 100644 index 000000000..076a5fc9a --- /dev/null +++ b/pkg/arvo/lib/dice.hoon @@ -0,0 +1,207 @@ +:: dice: helper functions for L2 Rollers +:: +/- *dice +/+ naive, *naive-transactions +:: +|% +++ nonce-order + |= [a=[* =nonce:naive] b=[* =nonce:naive]] + (lte nonce.a nonce.b) +:: +++ apply-effects + |= [chain-t=@ =effects:naive =indices] + ^+ indices + %+ roll effects + |= [=diff:naive indices=_indices] + ?. ?=([%tx *] diff) indices::[nas own spo] + =< indices + (apply-raw-tx | chain-t raw-tx.diff indices) +:: +++ apply-raw-tx + |= [force=? chain-t=@ =raw-tx:naive =indices] + ^- [? ups=(list update) indices=_indices] + =+ cache-nas=nas.indices + =/ chain-t=@t (ud-to-ascii:naive chain-t) + ?. (verify-sig-and-nonce:naive verifier chain-t nas.indices raw-tx) + ~& [%verify-sig-and-nonce %failed tx.raw-tx] + [force ~ indices] + =^ * points.nas.indices + (increment-nonce:naive nas.indices from.tx.raw-tx) + ?~ nex=(receive-tx:naive nas.indices tx.raw-tx) + ~& [%receive-tx %failed] + =? nas.indices !force cache-nas + [force ~ indices] + =* new-nas +.u.nex + =* effects -.u.nex + =/ [updates=(list update) own=_own.indices spo=_spo.indices] + (update-indices effects cache-nas new-nas [own spo]:indices) + =: nas.indices new-nas + own.indices own + spo.indices spo + == + [& updates indices] +:: +++ update-indices + |= $: =effects:naive + cache-nas=^state:naive + nas=^state:naive + =owners + =sponsors + == + ^- [(list update) own=_owners spo=_sponsors] + %+ roll effects + |= $: =diff:naive + ups=(list update) + owners=_owners + sponsors=_sponsors + == + =, orm:naive + ?. ?=([%point *] diff) [ups owners sponsors] + =* ship ship.diff + =/ old=(unit point:naive) + (get points.cache-nas ship) + =/ new=point:naive + (need (get points.nas ship)) + =* event +>.diff + |^ + =^ updates owners ownership + =+ sponsors=sponsorship + :+ (weld ups updates) + owners + sponsors + :: + ++ sponsorship + ^+ sponsors + ?+ -.event sponsors + %owner + ?^ old + :: ownership change + :: + sponsors + :: owner event with ?=(~ old) is a spawn + :: + =* parent who.sponsor.net.new + ?: =(parent ship) sponsors + %+ ~(put by sponsors) parent + ?~ sponsor=(~(get by sponsors) parent) + :_ *(set @p) + (~(put in *(set @p)) ship) + :_ requests.u.sponsor + (~(put in residents.u.sponsor) ship) + :: + %escape + ?~ old sponsors + =* from who.sponsor.net.u.old + =* to to.event + =* escape escape.net.u.old + ?~ to + :: cancel/reject escape + :: + ?~ escape sponsors + ?~ receiver=(~(get by sponsors) u.escape) + sponsors + %+ ~(put by sponsors) u.escape + :- residents.u.receiver + (~(del in requests.u.receiver) ship) + :: normal escape + :: + %+ ~(put by sponsors) u.to + ?~ receiver=(~(get by sponsors) u.to) + :- *(set @p) + (~(put in *(set @p)) ship) + :- residents.u.receiver + (~(put in requests.u.receiver) ship) + :: + %sponsor + ?~ old sponsors + =* from who.sponsor.net.u.old + =* to sponsor.event + =/ previous (~(get by sponsors) from) + ?~ to + :: detach + :: + ?~ previous sponsors + %+ ~(put by sponsors) from + :_ requests.u.previous + (~(del in residents.u.previous) ship) + :: accepted + :: + =/ receiver (~(get by sponsors) u.to) + =? sponsors ?=(^ receiver) + %+ ~(put by sponsors) u.to + :- (~(put in residents.u.receiver) ship) + (~(del in requests.u.receiver) ship) + =? sponsors ?=(^ previous) + %+ ~(put by sponsors) from + :_ requests.u.previous + (~(del in residents.u.previous) ship) + sponsors + == + :: + ++ ownership + ^- (quip update _owners) + =; [to=(unit owner) from=(unit owner)] + =? owners &(?=(^ from) !=(address.u.from 0x0)) + (~(del ju owners) u.from ship) + ?: ?| =(~ to) + &(?=(^ to) =(address.u.to 0x0)) + == + [ups owners] + ?~ to [ups owners] + :_ (~(put ju owners) u.to ship) + (snoc ups [%point ship new u.to from]) + ?+ -.event [~ ~] + %owner + :- `[%own +.event] + ?~ old ~ + `[%own address.owner.own.u.old] + :: + %management-proxy + :- `[%manage +.event] + ?~ old ~ + `[%manage address.management-proxy.own.u.old] + :: + %spawn-proxy + :- `[%spawn +.event] + ?~ old ~ + `[%spawn address.spawn-proxy.own.u.old] + :: + %voting-proxy + :- `[%vote +.event] + ?~ old ~ + `[%vote address.voting-proxy.own.u.old] + :: + %transfer-proxy + :- `[%transfer +.event] + ?~ old ~ + `[%transfer address.transfer-proxy.own.u.old] + == + -- +:: +++ get-owner + |= [=point:naive =proxy:naive] + ^- [nonce=@ _point] + =* own own.point + ?- proxy + %own + :- nonce.owner.own + point(nonce.owner.own +(nonce.owner.own)) + :: + %spawn + :- nonce.spawn-proxy.own + point(nonce.spawn-proxy.own +(nonce.spawn-proxy.own)) + :: + %manage + :- nonce.management-proxy.own + point(nonce.management-proxy.own +(nonce.management-proxy.own)) + :: + %vote + :- nonce.voting-proxy.own + point(nonce.voting-proxy.own +(nonce.voting-proxy.own)) + :: + %transfer + :- nonce.transfer-proxy.own + point(nonce.transfer-proxy.own +(nonce.transfer-proxy.own)) + == +:: +-- diff --git a/pkg/arvo/lib/hood/kiln.hoon b/pkg/arvo/lib/hood/kiln.hoon index 1c565423c..d87de9cd9 100644 --- a/pkg/arvo/lib/hood/kiln.hoon +++ b/pkg/arvo/lib/hood/kiln.hoon @@ -408,9 +408,6 @@ .^([rev=@ud @da] %cw /(scot %p our)/[d]/(scot %da now)) == take-commit:(abed:vats %base) - =? kiln ?=(^ wef) - =/ except=(set desk) (sy %base %kids ~) - (bump:vats u.wef except force=%.n) =. wef ~ abet:kiln :: @@ -605,7 +602,7 @@ vats ~> %slog.(fmt "{} pausing updates") =/ rel ral - =. rail.rak `rel(paused &, aeon 0) + =. rail.rak `rel(paused &, aeon 0, next ~) vats :: :: +gall-lyv: watch gall source for reloading @@ -683,11 +680,11 @@ |= [kel=weft except=(set desk) force=?] ^+ kiln =/ ded (find-blocked kel except) - ?: force - =. kiln (suspend-many ded) - (bump-many kel (all-desks-but (~(uni in except) ded))) - ?: =(~ ded) - (bump-many kel (all-desks-but except)) + =? kiln force (suspend-many ded) + ?: |(force =(~ ded)) + ?: !=(zuse+zuse kel) + (bump-one kel %base) + (bump-many (all-desks-but (~(uni in except) ded))) =- (^emit (pyre:pass leaf/- ~)) "kiln: desks blocked upgrade to {}: {}" :: @@ -707,7 +704,7 @@ $(ded t.ded, kiln abet:(suspend i.ded)) :: ++ bump-many - |= [kel=weft live=(set desk)] + |= live=(set desk) ^+ kiln :: ensure %base is always reloaded first :: @@ -721,7 +718,7 @@ :: |- ^+ kiln ?~ liv kiln - $(liv t.liv, kiln (bump-one kel i.liv)) + $(liv t.liv, kiln (bump-one zuse+zuse i.liv)) :: ++ bump-one |= [kel=weft =desk] @@ -736,7 +733,7 @@ ?: =(kel u.kul) ~> %slog.(fmt "{here} already at {<[lal num]:kel>}") update-running-dudes - =^ tem rail.rak (crank-next %| kel) + =^ tem rail.rak (crank-next kel) ?^ tem (emit merge-main:pass) =- (emit (pyre:pass leaf/- ~)) @@ -864,7 +861,8 @@ ++ kelvin-same ^+ vats ~> %slog.(fmt "merging into {here}") - =. rail.rak +:(crank-next %& (dec aeon:ral)) + ?> ?=(^ rail.rak) + =. next.u.rail.rak ~ (emil ~[merge-main sync-ud]:pass) :: ++ do-base @@ -881,7 +879,8 @@ =/ =diff [%block loc rak new-weft blockers] (emil sync-ud:pass (diff:give diff) ~) ~> %slog.(fmt "applying OTA to {here}, kelvin: {}") - =. rail.rak +:(crank-next %& (dec aeon:ral)) + ?> ?=(^ rail.rak) + =. next.u.rail.rak ~ =. wef ?: =(old-weft new-weft) ~ `new-weft @@ -915,11 +914,7 @@ update-running-dudes ?. =(%base loc) kiln - =/ kel=[@tas @ud] - ?~ rail.rak zuse/zuse - ?~ next.u.rail.rak zuse/zuse - weft.i.next.u.rail.rak - (bump-many kel (all-desks-but (sy %base ~))) + (bump-many (all-desks-but (get-unblockers ark))) :: ++ take-merge-main |= syn=sign-arvo @@ -994,7 +989,7 @@ :: +crank-next: pop stale items from .next until one matches :: ++ crank-next - |= new=(each aeon weft) + |= new=weft ^+ [match=*(unit rung) rail.rak] ?~ rail.rak ~| [%no-rail-for desk=loc] @@ -1003,10 +998,7 @@ =- [match `u.rail.rak(next next)] |- ^- [match=(unit rung) next=(list rung)] ?~ rog [~ next.u.rail.rak] - ?: ?- -.new - %& =(p.new aeon.i.rog) - %| =(p.new weft.i.rog) - == + ?: =(new weft.i.rog) [`i.rog t.rog] $(rog t.rog) :: @@ -1034,6 +1026,19 @@ ?: (lien next.u.rail.arak |=([* k=weft] =(k kel))) ~ `desk +:: +get-unblockers: find desks which shouldn't block a kernel upgrade +:: +++ get-unblockers + |= ark=(map desk arak) + =/ base=(set desk) (sy %base %kids ~) + %- ~(gas in base) + %+ murn ~(tap by ark) + |= [loc=desk ark=arak] + ^- (unit desk) + ?. liv.rein.ark `loc + ?~ rail.ark `loc + ?: paused.u.rail.ark `loc + ~ :: +get-germ: select merge strategy into local desk :: :: If destination desk doesn't exist, need a %init merge. If this is @@ -1202,9 +1207,9 @@ abet:abet:(install:vats +<) :: ++ poke-label - |= [syd=desk lab=@tas] + |= [syd=desk lab=@tas aey=(unit aeon)] =+ pax=/(scot %p our)/[syd]/[lab] - (poke-info "labeled {(spud pax)}" `[syd %| lab]) + (poke-info "labeled {(spud pax)}" `[syd %| lab aey]) :: ++ poke-merge |= kiln-merge diff --git a/pkg/arvo/lib/json/rpc.hoon b/pkg/arvo/lib/json/rpc.hoon index e44ad1d68..e2b3b3c06 100644 --- a/pkg/arvo/lib/json/rpc.hoon +++ b/pkg/arvo/lib/json/rpc.hoon @@ -17,15 +17,85 @@ |= request ^- json %- pairs:enjs:format - :~ jsonrpc+s+'0.2' + :~ jsonrpc+s+'2.0' id+s+id method+s+method :: :- %params ^- json ?- -.params - %list [%a +.params] - %object [%o (~(gas by *(map @t json)) +.params)] - == + %list [%a +.params] + :: FIXME: support either %map or %object (also in /sur/json/rpc) + :: + %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] !!) + %batch a+(turn bas.response response-to-json) + :: + %result + %- pairs:enjs:format + :: FIXME: return 'id' as string, number or NULL + :: + :~ ['jsonrpc' s+'2.0'] + ['id' s+id.response] + ['result' res.response] + == + :: + %error + =, enjs:format + %- pairs + :~ ['jsonrpc' s+'2.0'] + ['id' ?~(id.response ~ s+id.response)] + :: + :- 'error' + %- pairs + :~ ['code' n+code.response] + ['message' s+message.response] + == == == +:: +++ validate-request + |= body=(unit octs) + ^- (unit batch-request) + ?~ body ~ + ?~ jon=(de-json:html q.u.body) ~ + =, dejs-soft:format + =; reparser + ?: ?=([%a *] u.jon) + (bind ((ar reparser) u.jon) (lead %a)) + (bind (reparser u.jon) (lead %o)) + %- ot + :~ :: FIXME: parse 'id' as string, number or NULL + :: + ['id' so] + ['jsonrpc' (su (jest '2.0'))] + ['method' so] + :: + :- 'params' + |= =json + ^- (unit request-params) + ?+ -.json ~ + %a `[%list ((ar:dejs:format same) json)] + %o `[%map ((om:dejs:format same) json)] + == == +:: +++ error + |_ id=@t + :: https://www.jsonrpc.org/specification#error_object + :: + ++ parse [%error id '-32700' 'Failed to parse'] + ++ 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'] + ++ todo [%error id '-32001' 'Method not implemented'] + -- -- diff --git a/pkg/arvo/lib/naive-transactions.hoon b/pkg/arvo/lib/naive-transactions.hoon new file mode 100644 index 000000000..7e92947e9 --- /dev/null +++ b/pkg/arvo/lib/naive-transactions.hoon @@ -0,0 +1,218 @@ +/+ naive, ethereum +:: Types +|% ++$ address address:ethereum ++$ nonce @ud ++$ proxy ?(%own %spawn %manage %vote %transfer) +-- +:: +|% +:: +:: TODO: does this uniquely produce the pubkey? +++ verifier + ^- ^verifier:naive + |= [dat=octs v=@ r=@ s=@] + ?: (gth v 3) ~ :: TODO: move to jet + =/ result + %- mule + |. + =, secp256k1:secp:crypto + %- address-from-pub:key:ethereum + %- serialize-point + (ecdsa-raw-recover (hash-tx dat) v r s) + ?- -.result + %| ~ + %& `p.result + == +:: Verify signature and produce signer address +:: +++ verify-sig + |= [sig=@ txdata=octs] + ^- (unit address) + |^ + :: Reversed of the usual r-s-v order because Ethereum integers are + :: big-endian + :: + =^ v sig (take 3) + =^ s sig (take 3 32) + =^ r sig (take 3 32) + :: In Ethereum, v is generally 27 + recid, and verifier expects a + :: recid. Old versions of geth used 0 + recid, so most software + :: now supports either format. See: + :: + :: https://github.com/ethereum/go-ethereum/issues/2053 + :: + =? v (gte v 27) (sub v 27) + (verifier txdata v r s) + :: + ++ take + |= =bite + [(end bite sig) (rsh bite sig)] + -- +:: +++ unsigned-tx + |= [chain-id=@ud =nonce tx=octs] + ^- octs + =/ prepared-data (prepare-for-sig chain-id nonce tx) + =/ len (rsh [3 2] (scot %ui p.prepared-data)) + %: cad:naive 3 + 26^'\19Ethereum Signed Message:\0a' + (met 3 len)^len + prepared-data + ~ + == +:: +++ sign-tx + |= [pk=@ =nonce tx=octs] ^- octs + =/ sign-data + %- hash-tx + (unsigned-tx 1.337 nonce tx) + =+ (ecdsa-raw-sign:secp256k1:secp:crypto sign-data pk) + (cad:naive 3 1^v 32^s 32^r tx ~) +:: +++ prepare-for-sig + |= [chain-id=@ud =nonce tx=octs] + ^- octs + =/ chain-t (rsh [3 2] (scot %ui chain-id)) + %: cad:naive 3 + 14^'UrbitIDV1Chain' + (met 3 chain-t)^chain-t + 1^':' + 4^nonce + tx + ~ + == +:: +++ extract-address + |= [=raw-tx:naive nas=^state:naive chain-id=@] + ^- (unit @ux) + ?~ point=(get:orm:naive points.nas ship.from.tx.raw-tx) + ~ + =/ =nonce:naive + =< nonce + (proxy-from-point:naive proxy.from.tx.raw-tx u.point) + =/ message=octs + (unsigned-tx chain-id nonce raw.raw-tx) + (verify-sig sig.raw-tx message) +:: +++ gen-tx + |= [=nonce tx=tx:naive pk=@] ^- octs + :: takes in a nonce, tx:naive, and private key and returned a signed transactions as octs + %^ sign-tx pk nonce (gen-tx-octs tx) +:: +++ gen-tx-octs + :: generates octs for a transaction + |= tx=tx:naive + |^ + ^- octs + =/ raw=octs + ?- +<.tx + %spawn (get-spawn +>.tx) + %transfer-point (get-transfer +>.tx) + %configure-keys (get-keys +>.tx) + %escape (get-escape +.tx) + %cancel-escape (get-escape +.tx) + %adopt (get-escape +.tx) + %reject (get-escape +.tx) + %detach (get-escape +.tx) + %set-management-proxy (get-ship-address +.tx) + %set-spawn-proxy (get-ship-address +.tx) + %set-transfer-proxy (get-ship-address +.tx) + == + raw + :: + ++ get-spawn + |= [child=ship to=address] ^- octs + %: cad:naive 3 + (from-proxy proxy.from.tx) + 4^ship.from.tx + 1^%1 :: %spawn + 4^child + 20^to + ~ + == + :: + ++ get-transfer + |= [=address reset=?] ^- octs + %: cad:naive 3 + (from-proxy proxy.from.tx) + 4^ship.from.tx + 1^(can 0 7^%0 1^reset ~) :: %transfer-point + 20^address + ~ + == + :: + ++ get-keys + |= [crypt=@ auth=@ suite=@ breach=?] ^- octs + %: cad:naive 3 + (from-proxy proxy.from.tx) + 4^ship.from.tx + 1^(can 0 7^%2 1^breach ~) :: %configure-keys + 32^crypt + 32^auth + 4^suite + ~ + == + :: + ++ get-escape + |= [action=@tas other=ship] ^- octs + =/ op + ?+ action !! + %escape %3 + %cancel-escape %4 + %adopt %5 + %reject %6 + %detach %7 + == + %: cad:naive 3 + (from-proxy proxy.from.tx) + 4^ship.from.tx + 1^(can 0 7^op 1^0 ~) + 4^other + ~ + == + :: + ++ get-ship-address + |= [action=@tas =address] ^- octs + =/ op + ?+ action !! + %set-management-proxy %8 + %set-spawn-proxy %9 + %set-transfer-proxy %10 + == + %: cad:naive 3 + (from-proxy proxy.from.tx) + 4^ship.from.tx + 1^(can 0 7^op 1^0 ~) + 20^address + ~ + == + :: + ++ from-proxy + |= prx=@tas + ^- [@ @] + =/ proxy + ?+ prx !! + %own %0 + %spawn %1 + %manage %2 + %vote %3 + %transfer %4 + == + 1^(can 0 3^proxy 5^0 ~) + :: + -- +:: +++ hash-tx keccak-256:keccak:crypto +:: +++ hash-raw-tx + |= raw-tx:naive + ^- @ux + %- hash-tx + %: cad:naive 3 + 65^sig + raw + ~ + == +:: +-- diff --git a/pkg/arvo/lib/naive.hoon b/pkg/arvo/lib/naive.hoon new file mode 100644 index 000000000..7f46eaf01 --- /dev/null +++ b/pkg/arvo/lib/naive.hoon @@ -0,0 +1,926 @@ +/+ tiny +!. +=> => tiny +:: Laconic bit +:: +=| lac=? +:: Constants +:: +|% +:: Transfers on L1 to this address count as depositing to L2 +:: +++ deposit-address 0x1111.1111.1111.1111.1111.1111.1111.1111.1111.1111 +++ log-names + |% + :: Generated with (keccak-256:keccak:crypto (as-octs:mimes:html name)) + :: + :: OwnerChanged(uint32,address) + ++ owner-changed + 0x16d0.f539.d49c.6cad.822b.767a.9445.bfb1. + cf7e.a6f2.a6c2.b120.a7ea.4cc7.660d.8fda + :: + :: Activated(uint32) + ++ activated + 0xe74c.0380.9d07.69e1.b1f7.06cc.8414.258c. + d1f3.b6fe.020c.d15d.0165.c210.ba50.3a0f + :: + :: Spawned(uint32,uint32) + ++ spawned + 0xb2d3.a6e7.a339.f5c8.ff96.265e.2f03.a010. + a854.1070.f374.4a24.7090.9644.1508.1546 + :: + :: OwnershipTransferred(address,address) + ++ ownership-transferred + 0x8be0.079c.5316.5914.1344.cd1f.d0a4.f284. + 1949.7f97.22a3.daaf.e3b4.186f.6b64.57e0 + :: + :: EscapeRequested(uint32,uint32) + ++ escape-requested + 0xb4d4.850b.8f21.8218.141c.5665.cba3.79e5. + 3e9b.b015.b51e.8d93.4be7.0210.aead.874a + :: + :: EscapeCanceled(uint32,uint32) + ++ escape-canceled + 0xd653.bb0e.0bb7.ce83.93e6.24d9.8fbf.17cd. + a590.2c83.28ed.0cd0.9988.f368.90d9.932a + :: + :: EscapeAccepted(uint32,uint32) + ++ escape-accepted + 0x7e44.7c9b.1bda.4b17.4b07.96e1.00bf.7f34. + ebf3.6dbb.7fe6.6549.0b1b.fce6.246a.9da5 + :: + :: LostSponsor(uint32,uint32) + ++ lost-sponsor + 0xd770.4f9a.2519.3dbd.0b0c.b4a8.09fe.ffff. + a7f1.9d1a.ae88.17a7.1346.c194.4482.10d5 + :: + :: ChangedKeys(uint32,bytes32,bytes32,uint32,uint32) + ++ changed-keys + 0xaa10.e7a0.117d.4323.f1d9.9d63.0ec1.69be. + bb3a.988e.8957.70e3.5198.7e01.ff54.23d5 + :: + :: BrokeContinuity(uint32,uint32) + ++ broke-continuity + 0x2929.4799.f1c2.1a37.ef83.8e15.f79d.d91b. + cee2.df99.d63c.d1c1.8ac9.68b1.2951.4e6e + :: + :: ChangedSpawnProxy(uint32,address) + ++ changed-spawn-proxy + 0x9027.36af.7b3c.efe1.0d9e.840a.ed0d.687e. + 35c8.4095.122b.2505.1a20.ead8.866f.006d + :: + :: ChangedTransferProxy(uint32,address) + ++ changed-transfer-proxy + 0xcfe3.69b7.197e.7f0c.f067.93ae.2472.a9b1. + 3583.fecb.ed2f.78df.a14d.1f10.796b.847c + :: + :: ChangedManagementProxy(uint32,address) + ++ changed-management-proxy + 0xab9c.9327.cffd.2acc.168f.afed.be06.139f. + 5f55.cb84.c761.df05.e051.1c25.1e2e.e9bf + :: + :: ChangedVotingProxy(uint32,address) + ++ changed-voting-proxy + 0xcbd6.269e.c714.57f2.c7b1.a227.74f2.46f6. + c5a2.eae3.795e.d730.0db5.1768.0c61.c805 + :: + :: ChangedDns(string,string,string) + ++ changed-dns + 0xfafd.04ad.e1da.ae2e.1fdb.0fc1.cc6a.899f. + d424.063e.d5c9.2120.e67e.0730.53b9.4898 + :: + :: ApprovalForAll(address,address,bool) + ++ approval-for-all + 0x1730.7eab.39ab.6107.e889.9845.ad3d.59bd. + 9653.f200.f220.9204.89ca.2b59.3769.6c31 + -- +-- => +:: Types +|% +:: ethereum address, 20 bytes. +:: ++$ address @ux ++$ nonce @ud ++$ dominion ?(%l1 %l2 %spawn) ++$ keys [=life suite=@ud auth=@ crypt=@] +++ orm ((on ship point) por) +++ point + $: :: domain + :: + =dominion + :: + :: ownership + :: + $= own + $: owner=[=address =nonce] + spawn-proxy=[=address =nonce] + management-proxy=[=address =nonce] + voting-proxy=[=address =nonce] + transfer-proxy=[=address =nonce] + == + :: + :: networking + :: + $= net + $: rift=@ud + =keys + sponsor=[has=? who=@p] + escape=(unit @p) + == + == +:: +++ diff + $% [%nonce =ship =proxy =nonce] + [%tx =raw-tx err=(unit @tas)] + [%operator owner=address operator=address approved=?] + [%dns domains=(list @t)] + $: %point =ship + $% [%rift =rift] + [%keys =keys] + [%sponsor sponsor=(unit @p)] + [%escape to=(unit @p)] + [%owner =address] + [%spawn-proxy =address] + [%management-proxy =address] + [%voting-proxy =address] + [%transfer-proxy =address] + [%dominion =dominion] + == == == +:: ++$ state + $: %0 + =points + =operators + dns=(list @t) + == ++$ points (tree [ship point]) ++$ operators (jug address address) ++$ effects (list diff) ++$ proxy ?(%own %spawn %manage %vote %transfer) ++$ roll (list raw-tx) ++$ raw-tx [sig=@ raw=octs =tx] ++$ tx [from=[=ship =proxy] skim-tx] ++$ skim-tx + $% [%transfer-point =address reset=?] + [%spawn =ship =address] + [%configure-keys encrypt=@ auth=@ crypto-suite=@ breach=?] + [%escape parent=ship] + [%cancel-escape parent=ship] + [%adopt =ship] + [%reject =ship] + [%detach =ship] + [%set-management-proxy =address] + [%set-spawn-proxy =address] + [%set-transfer-proxy =address] + == +:: ++$ event-log + $: address=@ux + data=@ux + topics=(lest @ux) + == ++$ input + $: block=@ud + $% [%bat batch=@] + [%log =event-log] + == == +:: ECDSA verifier. +:: +:: Must keccak `dat` and recover the ethereum address which signed. +:: Must not crash. `v` will normally be between 0 and 3; if it is not, +:: should produce null. +:: ++$ verifier $-([dat=octs v=@ r=@ s=@] (unit address)) +-- => +:: +|% +++ debug + |* [meg=@t *] + ?: lac + +<+ + ~> %slog.[0 meg] + +<+ +:: +++ parse-roll + |= batch=@ + =| =roll + =| pos=@ud + =/ las (met 0 batch) + |- ^+ roll + ?: (gte pos las) + (flop roll) + =/ parse-result (parse-raw-tx pos batch) + :: Parsing failed, abort batch + :: + ?~ parse-result + (debug %parse-failed ~) + =^ =raw-tx pos u.parse-result + $(roll [raw-tx roll]) +:: +++ parse-raw-tx + |= [pos=@ud batch=@] + ^- (unit [raw-tx pos=@ud]) + |^ + =^ sig pos (take 3 65) + =/ res=(unit [=tx pos=@ud]) parse-tx + ?~ res ~ + =/ dif (sub pos.u.res pos) + =/ len =>((dvr dif 8) ?>(=(0 q) p)) + :- ~ :_ pos.u.res + [sig [len (cut 0 [pos dif] batch)] tx.u.res] + :: + ++ parse-tx + ^- (unit [tx pos=@ud]) + =^ from-proxy=@ pos (take 0 3) + ?. ?=(?(%0 %1 %2 %3 %4) from-proxy) (debug %bad-proxy ~) + =/ =proxy + ?- from-proxy + %0 %own + %1 %spawn + %2 %manage + %3 %vote + %4 %transfer + == + =^ pad pos (take 0 5) + =^ from-ship=ship pos (take 3 4) + =- ?~ res + ~ + `[[[from-ship proxy] skim-tx.u.res] pos.u.res] + ^- res=(unit [=skim-tx pos=@ud]) + =^ op pos (take 0 7) + ?+ op (debug %strange-opcode ~) + %0 + =^ reset=@ pos (take 0) + =^ =address pos (take 3 20) + `[[%transfer-point address =(0 reset)] pos] + :: + %1 + =^ pad=@ pos (take 0) + =^ =ship pos (take 3 4) + =^ =address pos (take 3 20) + `[[%spawn ship address] pos] + :: + %2 + =^ breach=@ pos (take 0) + =^ encrypt=@ pos (take 3 32) + =^ auth=@ pos (take 3 32) + =^ crypto-suite=@ pos (take 3 4) + `[[%configure-keys encrypt auth crypto-suite =(0 breach)] pos] + :: + %3 =^(res pos take-ship `[[%escape res] pos]) + %4 =^(res pos take-ship `[[%cancel-escape res] pos]) + %5 =^(res pos take-ship `[[%adopt res] pos]) + %6 =^(res pos take-ship `[[%reject res] pos]) + %7 =^(res pos take-ship `[[%detach res] pos]) + %8 =^(res pos take-address `[[%set-management-proxy res] pos]) + %9 =^(res pos take-address `[[%set-spawn-proxy res] pos]) + %10 =^(res pos take-address `[[%set-transfer-proxy res] pos]) + == + :: + :: Take a bite + :: + ++ take + |= =bite + ^- [@ @ud] + =/ =step + ?@ bite (bex bite) + (mul step.bite (bex bloq.bite)) + [(cut 0 [pos step] batch) (add pos step)] + :: Encode ship and address + :: + ++ take-address + ^- [address @ud] + =^ pad=@ pos (take 0) + =^ =address pos (take 3 20) + [address pos] + :: Encode escape-related txs + :: + ++ take-ship + ^- [ship @ud] + =^ pad=@ pos (take 0) + =^ other=ship pos (take 3 4) + [other pos] + -- +:: +++ 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] + ^- ? + |^ + =/ 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-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 + :: ID. + :: + :: We also include a nonce so that a transaction cannot be + :: rebroadcast. + :: + =/ prepared-data=octs + %: cad 3 + 14^'UrbitIDV1Chain' + (met 3 chain-t)^chain-t + 1^':' + 4^nonce.need + raw.raw-tx + ~ + == + :: Wallets which support personal_sign include this preamble to avoid + :: letting personal_sign be used to sign ethereum transactions + :: + =/ signed-data=octs + =/ len (ud-to-ascii p.prepared-data) + %: cad 3 + 26^'\19Ethereum Signed Message:\0a' + (met 3 len)^len + prepared-data + ~ + == + =/ dress (verify-sig sig.raw-tx signed-data) + ?~ dress + | + =(address.need u.dress) + :: Verify signature and produce signer address + :: + ++ verify-sig + |= [sig=@ txdata=octs] + ^- (unit address) + |^ + :: Reversed of the usual r-s-v order because Ethereum integers are + :: big-endian + :: + =^ v sig (take 3) + =^ s sig (take 3 32) + =^ r sig (take 3 32) + :: In Ethereum, v is generally 27 + recid, and verifier expects a + :: recid. Old versions of geth used 0 + recid, so most software + :: now supports either format. See: + :: + :: https://github.com/ethereum/go-ethereum/issues/2053 + :: + =? v (gte v 27) (sub v 27) + (verifier txdata v r s) + :: + ++ take + |= =bite + [(end bite sig) (rsh bite sig)] + -- + -- +:: ASCII-decimal encode +:: +++ ud-to-ascii + |= n=@ud + ?~ n '0' + =| l=(list @) + |- ^- @t + ?~ n (rep 3 l) + =+ (dvr n 10) + $(n p, l [(add '0' q) l]) +:: +++ ship-rank + |= =ship + ^- ?(%0 %1 %2 %3 %4) + ?: (lth ship 0x100) %0 + ?: (lth ship 0x1.0000) %1 + ?: (lth ship 0x1.0000.0000) %2 + ?: (lth ship 0x1.0000.0000.0000.0000) %3 + %4 +:: +++ sein :: autoboss + |= who=ship + ^- ship + =/ mir (ship-rank who) + ?- mir + %0 who + %1 (end 3 who) + %2 (end 4 who) + %3 (end 5 who) + %4 (end 4 who) + == +:: +:: Produces null only if ship is not a galaxy, star, or planet +:: +++ get-point + |= [=state =ship] + ^- (unit point) + =/ existing (get:orm points.state ship) + ?^ existing + `u.existing + =| =point + =. who.sponsor.net.point (sein ship) + ?+ (ship-rank ship) (debug %strange-point ~) + %0 `point(dominion %l1) + ?(%1 %2) + =/ existing-parent $(ship (sein ship)) + ?~ existing-parent ~ + :- ~ + %= point + dominion + ?- dominion.u.existing-parent + %l1 %l1 + %l2 %l2 + %spawn %l2 + == + == + == +-- => +|% +:: Receive log from L1 transaction +:: +++ receive-log + |= [=state log=event-log] + ^- [effects ^state] + =* log-name i.topics.log + ?: =(log-name activated:log-names) `state + ?: =(log-name spawned:log-names) `state + ?: =(log-name ownership-transferred:log-names) `state + ?: =(log-name changed-dns:log-names) + ?> ?=(~ t.topics.log) + =/ words (rip 8 data.log) + :: This is only true if each domain is <= 32 bytes + :: + ?. ?=([c=@ @ b=@ @ a=@ @ @ @ @ ~] words) `state + =* one &5.words + =* two &3.words + =* tri &1.words + =/ domains ~[(swp 3 one) (swp 3 two) (swp 3 tri)] + :- [%dns domains]~ + state(dns domains) + :: + ?: =(log-name approval-for-all:log-names) + ?> ?=([@ @ ~] t.topics.log) + =* owner i.t.topics.log + =* operator i.t.t.topics.log + =/ approved !=(0 data.log) + :- [%operator owner operator approved]~ + =- state(operators -) + ?: approved + (~(put ju operators.state) owner operator) + (~(del ju operators.state) owner operator) + :: + :: The rest of the logs modify a particular ship, specified in the + :: second topic. We fetch it, and insert the modification back into + :: our state. + :: + ?> ?=([@ *] t.topics.log) + =* ship=@ i.t.topics.log + =/ the-point (get-point state ship) + ?> ?=(^ the-point) + =* point u.the-point + :: + :: Important to fully no-op on failure so we don't insert an entry + :: into points.state + :: + =- ?~ res + `state + [effects.u.res state(points (put:orm points.state ship new-point.u.res))] + ^- res=(unit [=effects new-point=^point]) + :: + ?: =(log-name changed-spawn-proxy:log-names) + ?. ?=(%l1 -.point) ~ + ?> ?=([@ ~] t.t.topics.log) + =* to i.t.t.topics.log + :: Depositing to L2 is represented by a spawn proxy change on L1, + :: but it doesn't change the actual spawn proxy. + :: + ?: =(deposit-address to) + :+ ~ [%point ship %dominion %spawn]~ + point(dominion %spawn) + :+ ~ [%point ship %spawn-proxy to]~ + point(address.spawn-proxy.own to) + :: + ?: =(log-name escape-accepted:log-names) + ?> ?=([@ ~] t.t.topics.log) + =* parent=@ i.t.t.topics.log + =/ parent-point (get-point state parent) + ?> ?=(^ parent-point) + ?: ?=(%l2 -.u.parent-point) ~ + :+ ~ [%point ship %sponsor `parent]~ + point(escape.net ~, sponsor.net [%& parent]) + :: + ?: =(log-name lost-sponsor:log-names) + ?> ?=([@ ~] t.t.topics.log) + =* parent=@ i.t.t.topics.log + :: If the sponsor we lost was not our actual sponsor, we didn't + :: actually lose anything. + :: + ?. =(parent who.sponsor.net.point) ~ + :: + =/ parent-point (get-point state parent) + ?> ?=(^ parent-point) + :: + :: We can detach even if the child is on L2, as long as the parent + :: is on L1. + :: + ?: ?=(%l2 -.u.parent-point) ~ + :+ ~ [%point ship %sponsor ~]~ + point(has.sponsor.net %|) + :: + :: The rest can be done by any ship on L1, even if their spawn proxy + :: is set to L2 + :: + ?: ?=(%l2 -.point) ~ + :: + ?: =(log-name escape-requested:log-names) + ?> ?=([@ ~] t.t.topics.log) + =* parent=@ i.t.t.topics.log + =/ parent-point (get-point state parent) + ?> ?=(^ parent-point) + :+ ~ [%point ship %escape `parent]~ + point(escape.net `parent) + :: + ?: =(log-name escape-canceled:log-names) + ?> ?=([@ ~] t.t.topics.log) + =* parent=@ i.t.t.topics.log + =/ parent-point (get-point state parent) + ?> ?=(^ parent-point) + :+ ~ [%point ship %escape ~]~ + point(escape.net ~) + :: + ?: =(log-name broke-continuity:log-names) + ?> ?=(~ t.t.topics.log) + =* rift=@ data.log + :+ ~ [%point ship %rift rift]~ + point(rift.net rift) + :: + ?: =(log-name changed-keys:log-names) + ?> ?=(~ t.t.topics.log) + =/ =keys + :* life=(cut 8 [0 1] data.log) + suite=(cut 8 [1 1] data.log) + auth=(cut 8 [2 1] data.log) + crypt=(cut 8 [3 1] data.log) + == + :+ ~ [%point ship %keys keys]~ + point(keys.net keys) + :: + ?: =(log-name owner-changed:log-names) + ?> ?=([@ ~] t.t.topics.log) + =* to i.t.t.topics.log + :: Depositing to L2 is represented by an ownership change on L1, + :: but it doesn't change who actually owns the ship. + :: + ?: =(deposit-address to) + :+ ~ [%point ship %dominion %l2]~ + point(dominion %l2) + :+ ~ [%point ship %owner to]~ + point(address.owner.own to) + :: + ?: =(log-name changed-transfer-proxy:log-names) + ?> ?=([@ ~] t.t.topics.log) + =* to i.t.t.topics.log + :+ ~ [%point ship %transfer-proxy to]~ + point(address.transfer-proxy.own to) + :: + ?: =(log-name changed-management-proxy:log-names) + ?> ?=([@ ~] t.t.topics.log) + =* to i.t.t.topics.log + :+ ~ [%point ship %management-proxy to]~ + point(address.management-proxy.own to) + :: + ?: =(log-name changed-voting-proxy:log-names) + ?> ?=([@ ~] t.t.topics.log) + =* to i.t.t.topics.log + :+ ~ [%point ship %voting-proxy to]~ + point(address.voting-proxy.own to) + :: + (debug %unknown-log ~) +:: +:: Receive batch of L2 transactions +:: +++ receive-batch + |= [=verifier chain-id=@ud =state batch=@] + =/ chain-t (ud-to-ascii chain-id) + =/ =roll (parse-roll batch) + |- ^- [effects ^state] + ?~ roll + [~ state] + :: Verify signature, else skip tx + :: + ?. (verify-sig-and-nonce verifier chain-t state i.roll) + %+ debug %l2-sig-failed + =^ effects state $(roll t.roll) + :_ state + [[%tx i.roll `%sig-or-nonce-failed] effects] + :: Increment nonce, even if it later fails + :: + =^ effects-1 points.state (increment-nonce state from.tx.i.roll) + :: Process tx + :: + =^ effects-2 state + =/ tx-result=(unit [=effects =^state]) (receive-tx state tx.i.roll) + ?~ tx-result + %+ debug %l2-tx-failed + [[%tx i.roll `%tx-failed]~ state] + [[[%tx i.roll ~] effects.u.tx-result] state.u.tx-result] + =^ effects-3 state $(roll t.roll) + [:(welp effects-1 effects-2 effects-3) state] +:: +++ increment-nonce + |= [=state =ship =proxy] + =/ point (get-point state ship) + ?> ?=(^ point) :: we only parsed 4 bytes + =* own own.u.point + =^ nonce u.point + ?- proxy + %own + :- nonce.owner.own + u.point(nonce.owner.own +(nonce.owner.own)) + :: + %spawn + :- nonce.spawn-proxy.own + u.point(nonce.spawn-proxy.own +(nonce.spawn-proxy.own)) + :: + %manage + :- nonce.management-proxy.own + u.point(nonce.management-proxy.own +(nonce.management-proxy.own)) + :: + %vote + :- nonce.voting-proxy.own + u.point(nonce.voting-proxy.own +(nonce.voting-proxy.own)) + :: + %transfer + :- nonce.transfer-proxy.own + u.point(nonce.transfer-proxy.own +(nonce.transfer-proxy.own)) + == + :: + :- [%nonce ship proxy nonce]~ + (put:orm points.state ship u.point) +:: +:: Receive an individual L2 transaction +:: +++ receive-tx + |= [=state =tx] + |^ + ^- (unit [effects ^state]) + ?- +<.tx + %spawn (process-spawn +>.tx) + %transfer-point (w-point process-transfer-point ship.from.tx +>.tx) + %configure-keys (w-point process-configure-keys ship.from.tx +>.tx) + %escape (w-point-esc process-escape ship.from.tx +>.tx) + %cancel-escape (w-point-esc process-cancel-escape ship.from.tx +>.tx) + %adopt (w-point-esc process-adopt ship.tx +>.tx) + %reject (w-point-esc process-reject ship.tx +>.tx) + %detach (w-point-esc process-detach ship.tx +>.tx) + %set-spawn-proxy + (w-point-spawn process-set-spawn-proxy ship.from.tx +>.tx) + :: + %set-transfer-proxy + (w-point process-set-transfer-proxy ship.from.tx +>.tx) + :: + %set-management-proxy + (w-point process-set-management-proxy ship.from.tx +>.tx) + == + :: + ++ w-point + |* [fun=$-([ship point *] (unit [effects point])) =ship rest=*] + ^- (unit [effects ^state]) + =/ point (get-point state ship) + ?~ point (debug %strange-ship ~) + ?. ?=(%l2 -.u.point) (debug %ship-not-on-l2 ~) + :: Important to fully no-op on failure so we don't insert an entry + :: into points.state + :: + =/ res=(unit [=effects new-point=^point]) (fun u.point rest) + ?~ res + ~ + `[effects.u.res state(points (put:orm points.state ship new-point.u.res))] + :: + ++ w-point-esc + |* [fun=$-([ship point *] (unit [effects point])) =ship rest=*] + ^- (unit [effects ^state]) + =/ point (get-point state ship) + ?~ point (debug %strange-ship ~) + =/ res=(unit [=effects new-point=^point]) (fun u.point rest) + ?~ res + ~ + `[effects.u.res state(points (put:orm points.state ship new-point.u.res))] + :: + ++ w-point-spawn + |* [fun=$-([ship point *] (unit [effects point])) =ship rest=*] + ^- (unit [effects ^state]) + =/ point (get-point state ship) + ?~ point (debug %strange-ship ~) + ?: ?=(%l1 -.u.point) (debug %ship-on-l2 ~) + =/ res=(unit [=effects new-point=^point]) (fun u.point rest) + ?~ res + ~ + `[effects.u.res state(points (put:orm points.state ship new-point.u.res))] + :: + ++ process-transfer-point + |= [=point to=address reset=?] + =* ship ship.from.tx + :: Assert from owner or transfer prxoy + :: + ?. |(=(%own proxy.from.tx) =(%transfer proxy.from.tx)) + (debug %bad-permission ~) + :: Execute transfer + :: + =/ effects-1 + ~[[%point ship %owner to] [%point ship %transfer-proxy *address]] + =: address.owner.own.point to + address.transfer-proxy.own.point *address + == + :: Execute reset if requested + :: + ?. reset + `[effects-1 point] + :: + =^ effects-2 net.point + ?: =([0 0 0] +.keys.net.point) + `net.point + =/ =keys [+(life.keys.net.point) 0 0 0] + :- [%point ship %keys keys]~ + [rift.net.point keys sponsor.net.point escape.net.point] + =^ effects-3 rift.net.point + ?: =(0 life.keys.net.point) + `rift.net.point + :- [%point ship %rift +(rift.net.point)]~ + +(rift.net.point) + =/ effects-4 + :~ [%point ship %spawn-proxy *address] + [%point ship %management-proxy *address] + [%point ship %voting-proxy *address] + [%point ship %transfer-proxy *address] + == + =: address.spawn-proxy.own.point *address + address.management-proxy.own.point *address + address.voting-proxy.own.point *address + address.transfer-proxy.own.point *address + == + `[:(welp effects-1 effects-2 effects-3 effects-4) point] + :: + ++ process-spawn + |= [=ship to=address] + ^- (unit [effects ^state]) + =/ parent=^ship (sein ship) + :: Assert parent is on L2 + :: + =/ parent-point (get-point state parent) + ?~ parent-point ~ + ?. ?=(?(%l2 %spawn) -.u.parent-point) ~ + :: Assert from owner or spawn proxy + :: + ?. ?& =(parent ship.from.tx) + |(=(%own proxy.from.tx) =(%spawn proxy.from.tx)) + == + (debug %bad-permission ~) + :: Assert child not already spawned + :: + ?^ (get:orm points.state ship) (debug %spawn-exists ~) + :: Assert one-level-down + :: + ?. =(+((ship-rank parent)) (ship-rank ship)) (debug %bad-rank ~) + :: + =/ [=effects new-point=point] + =/ point=(unit point) (get-point state ship) + ?> ?=(^ point) :: only parsed 4 bytes + :: If spawning to self, just do it + :: + ?: ?| ?& =(%own proxy.from.tx) + =(to address.owner.own.u.parent-point) + == + ?& =(%spawn proxy.from.tx) + =(to address.spawn-proxy.own.u.parent-point) + == + == + :- ~[[%point ship %dominion %l2] [%point ship %owner to]] + u.point(address.owner.own to) + :: Else spawn to parent and set transfer proxy + :: + :- :~ [%point ship %dominion %l2] + [%point ship %owner address.owner.own.u.parent-point] + [%point ship %transfer-proxy to] + == + %= u.point + address.owner.own address.owner.own.u.parent-point + address.transfer-proxy.own to + == + `[effects state(points (put:orm points.state ship new-point))] + :: + ++ process-configure-keys + |= [=point crypt=@ auth=@ suite=@ breach=?] + =* ship ship.from.tx + :: + ?. |(=(%own proxy.from.tx) =(%manage proxy.from.tx)) + (debug %bad-permission ~) + :: + =^ rift-effects rift.net.point + ?. breach + `rift.net.point + [[%point ship %rift +(rift.net.point)]~ +(rift.net.point)] + :: + =^ keys-effects keys.net.point + ?: =(+.keys.net.point [suite auth crypt]) + `keys.net.point + =/ =keys + [+(life.keys.net.point) suite auth crypt] + [[%point ship %keys keys]~ keys] + :: + `[(welp rift-effects keys-effects) point] + :: + ++ process-escape + |= [=point parent=ship] + =* ship ship.from.tx + ?. |(=(%own proxy.from.tx) =(%manage proxy.from.tx)) + (debug %bad-permission ~) + :: + ?. =(+((ship-rank parent)) (ship-rank ship)) + (debug %bad-rank ~) + :: + :+ ~ [%point ship %escape `parent]~ + point(escape.net `parent) + :: + ++ process-cancel-escape + |= [=point parent=ship] + =* ship ship.from.tx + ?. |(=(%own proxy.from.tx) =(%manage proxy.from.tx)) + (debug %bad-permission ~) + :: + :+ ~ [%point ship %escape ~]~ + point(escape.net ~) + :: + ++ process-adopt + |= [=point =ship] + =* parent ship.from.tx + ?. |(=(%own proxy.from.tx) =(%manage proxy.from.tx)) + (debug %bad-permission ~) + :: + ?. =(escape.net.point `parent) (debug %no-adopt ~) + :+ ~ [%point ship %sponsor `parent]~ + point(escape.net ~, sponsor.net [%& parent]) + :: + ++ process-reject + |= [=point =ship] + =* parent ship.from.tx + ?. |(=(%own proxy.from.tx) =(%manage proxy.from.tx)) + (debug %bad-permission ~) + :: + ?. =(escape.net.point `parent) (debug %no-reject ~) + :+ ~ [%point ship %escape ~]~ + point(escape.net ~) + :: + ++ process-detach + |= [=point =ship] + =* parent ship.from.tx + ?. |(=(%own proxy.from.tx) =(%manage proxy.from.tx)) + (debug %bad-permission ~) + :: + ?. =(who.sponsor.net.point parent) (debug %no-detach ~) + :+ ~ [%point ship %sponsor ~]~ + point(has.sponsor.net %|) + :: + ++ process-set-management-proxy + |= [=point =address] + ?. |(=(%own proxy.from.tx) =(%manage proxy.from.tx)) + (debug %bad-permission ~) + :: + :+ ~ [%point ship.from.tx %management-proxy address]~ + point(address.management-proxy.own address) + :: + ++ process-set-spawn-proxy + |= [=point =address] + ?. |(=(%own proxy.from.tx) =(%spawn proxy.from.tx)) + (debug %bad-permission ~) + :: + ?: (gte (ship-rank ship.from.tx) 2) + (debug %spawn-proxy-planet ~) + :: + :+ ~ [%point ship.from.tx %spawn-proxy address]~ + point(address.spawn-proxy.own address) + :: + ++ process-set-transfer-proxy + |= [=point =address] + ?. |(=(%own proxy.from.tx) =(%transfer proxy.from.tx)) + (debug %bad-permission ~) + :: + :+ ~ [%point ship.from.tx %transfer-proxy address]~ + point(address.transfer-proxy.own address) + -- +-- +:: +:: State transition function +:: +|= [=verifier chain-id=@ud =state =input] +^- [effects ^state] +?: ?=(%log +<.input) + :: Received log from L1 transaction + :: + (receive-log state event-log.input) +:: Received L2 batch +:: +:: %+ debug %batch +(receive-batch verifier chain-id state batch.input) diff --git a/pkg/arvo/lib/tiny.hoon b/pkg/arvo/lib/tiny.hoon new file mode 100644 index 000000000..f4cbf064f --- /dev/null +++ b/pkg/arvo/lib/tiny.hoon @@ -0,0 +1,670 @@ +!. +=> %a50 +~% %a.50 ~ ~ +|% +:: Types +:: ++$ ship @p ++$ life @ud ++$ rift @ud ++$ pass @ ++$ bloq @ ++$ step _`@u`1 ++$ bite $@(bloq [=bloq =step]) ++$ octs [p=@ud q=@] ++$ mold $~(* $-(* *)) +++ unit |$ [item] $@(~ [~ u=item]) +++ list |$ [item] $@(~ [i=item t=(list item)]) +++ lest |$ [item] [i=item t=(list item)] +++ tree |$ [node] $@(~ [n=node l=(tree node) r=(tree node)]) +++ pair |$ [head tail] [p=head q=tail] +++ map + |$ [key value] + $| (tree (pair key value)) + |=(a=(tree (pair)) ?:(=(~ a) & ~(apt by a))) +:: +++ set + |$ [item] + $| (tree item) + |=(a=(tree) ?:(=(~ a) & ~(apt in a))) +:: +++ jug |$ [key value] (map key (set value)) +:: +:: Bits +:: +++ dec :: decrement + ~/ %dec + |= a=@ + ~_ leaf+"decrement-underflow" + ?< =(0 a) + =+ b=0 + |- ^- @ + ?: =(a +(b)) b + $(b +(b)) +:: +++ add :: plus + ~/ %add + |= [a=@ b=@] + ^- @ + ?: =(0 a) b + $(a (dec a), b +(b)) +:: +++ sub :: subtract + ~/ %sub + |= [a=@ b=@] + ~_ leaf+"subtract-underflow" + :: difference + ^- @ + ?: =(0 b) a + $(a (dec a), b (dec b)) +:: +++ mul :: multiply + ~/ %mul + |: [a=`@`1 b=`@`1] + ^- @ + =+ c=0 + |- + ?: =(0 a) c + $(a (dec a), c (add b c)) +:: +++ div :: divide + ~/ %div + |: [a=`@`1 b=`@`1] + ^- @ + ~_ leaf+"divide-by-zero" + ?< =(0 b) + =+ c=0 + |- + ?: (lth a b) c + $(a (sub a b), c +(c)) +:: +++ dvr :: divide w/remainder + ~/ %dvr + |: [a=`@`1 b=`@`1] + ^- [p=@ q=@] + [(div a b) (mod a b)] +:: +++ mod :: modulus + ~/ %mod + |: [a=`@`1 b=`@`1] + ^- @ + ?< =(0 b) + (sub a (mul b (div a b))) +:: +++ bex :: binary exponent + ~/ %bex + |= a=bloq + ^- @ + ?: =(0 a) 1 + (mul 2 $(a (dec a))) +:: +++ lsh :: left-shift + ~/ %lsh + |= [a=bite b=@] + =/ [=bloq =step] ?^(a a [a *step]) + (mul b (bex (mul (bex bloq) step))) +:: +++ rsh :: right-shift + ~/ %rsh + |= [a=bite b=@] + =/ [=bloq =step] ?^(a a [a *step]) + (div b (bex (mul (bex bloq) step))) +:: +++ con :: binary or + ~/ %con + |= [a=@ b=@] + =+ [c=0 d=0] + |- ^- @ + ?: ?&(=(0 a) =(0 b)) d + %= $ + a (rsh 0 a) + b (rsh 0 b) + c +(c) + d %+ add d + %+ lsh [0 c] + ?& =(0 (end 0 a)) + =(0 (end 0 b)) + == + == +:: +++ dis :: binary and + ~/ %dis + |= [a=@ b=@] + =| [c=@ d=@] + |- ^- @ + ?: ?|(=(0 a) =(0 b)) d + %= $ + a (rsh 0 a) + b (rsh 0 b) + c +(c) + d %+ add d + %+ lsh [0 c] + ?| =(0 (end 0 a)) + =(0 (end 0 b)) + == + == +:: +++ mix :: binary xor + ~/ %mix + |= [a=@ b=@] + ^- @ + =+ [c=0 d=0] + |- + ?: ?&(=(0 a) =(0 b)) d + %= $ + a (rsh 0 a) + b (rsh 0 b) + c +(c) + d (add d (lsh [0 c] =((end 0 a) (end 0 b)))) + == +:: +++ lth :: less + ~/ %lth + |= [a=@ b=@] + ^- ? + ?& !=(a b) + |- + ?| =(0 a) + ?& !=(0 b) + $(a (dec a), b (dec b)) + == == == +:: +++ lte :: less or equal + ~/ %lte + |= [a=@ b=@] + |(=(a b) (lth a b)) +:: +++ gte :: greater or equal + ~/ %gte + |= [a=@ b=@] + ^- ? + !(lth a b) +:: +++ gth :: greater + ~/ %gth + |= [a=@ b=@] + ^- ? + !(lte a b) +:: +++ swp :: naive rev bloq order + ~/ %swp + |= [a=bloq b=@] + (rep a (flop (rip a b))) +:: +++ met :: measure + ~/ %met + |= [a=bloq b=@] + ^- @ + =+ c=0 + |- + ?: =(0 b) c + $(b (rsh a b), c +(c)) +:: +++ end :: tail + ~/ %end + |= [a=bite b=@] + =/ [=bloq =step] ?^(a a [a *step]) + (mod b (bex (mul (bex bloq) step))) +:: +++ cat :: concatenate + ~/ %cat + |= [a=bloq b=@ c=@] + (add (lsh [a (met a b)] c) b) +:: +++ cut :: slice + ~/ %cut + |= [a=bloq [b=step c=step] d=@] + (end [a c] (rsh [a b] d)) +:: +++ can :: assemble + ~/ %can + |= [a=bloq b=(list [p=step q=@])] + ^- @ + ?~ b 0 + (add (end [a p.i.b] q.i.b) (lsh [a p.i.b] $(b t.b))) +:: +++ cad :: assemble specific + ~/ %cad + |= [a=bloq b=(list [p=step q=@])] + ^- [=step @] + :_ (can a b) + |- + ?~ b + 0 + (add p.i.b $(b t.b)) +:: +++ rep :: assemble fixed + ~/ %rep + |= [a=bite b=(list @)] + =/ [=bloq =step] ?^(a a [a *step]) + =| i=@ud + |- ^- @ + ?~ b 0 + %+ add $(i +(i), b t.b) + (lsh [bloq (mul step i)] (end [bloq step] i.b)) +:: +++ rip :: disassemble + ~/ %rip + |= [a=bite b=@] + ^- (list @) + ?: =(0 b) ~ + [(end a b) $(b (rsh a b))] +:: +:: +:: Lists +:: +++ lent :: length + ~/ %lent + |= a=(list) + ^- @ + =+ b=0 + |- + ?~ a b + $(a t.a, b +(b)) +:: +++ slag :: suffix + ~/ %slag + |* [a=@ b=(list)] + |- ^+ b + ?: =(0 a) b + ?~ b ~ + $(b t.b, a (dec a)) +:: +++ snag :: index + ~/ %snag + |* [a=@ b=(list)] + |- ^+ ?>(?=(^ b) i.b) + ?~ b + ~_ leaf+"snag-fail" + !! + ?: =(0 a) i.b + $(b t.b, a (dec a)) +:: +++ homo :: homogenize + |* a=(list) + ^+ =< $ + |@ ++ $ ?:(*? ~ [i=(snag 0 a) t=$]) + -- + a +:: +++ flop :: reverse + ~/ %flop + |* a=(list) + => .(a (homo a)) + ^+ a + =+ b=`_a`~ + |- + ?~ a b + $(a t.a, b [i.a b]) +:: +++ welp :: concatenate + ~/ %welp + =| [* *] + |@ + ++ $ + ?~ +<- + +<-(. +<+) + +<-(+ $(+<- +<->)) + -- +:: +++ reap :: replicate + ~/ %reap + |* [a=@ b=*] + |- ^- (list _b) + ?~ a ~ + [b $(a (dec a))] +:: +:: Modular arithmetic +:: +++ fe :: modulo bloq + |_ a=bloq + ++ rol |= [b=bloq c=@ d=@] ^- @ :: roll left + =+ e=(sit d) + =+ f=(bex (sub a b)) + =+ g=(mod c f) + (sit (con (lsh [b g] e) (rsh [b (sub f g)] e))) + ++ sum |=([b=@ c=@] (sit (add b c))) :: wrapping add + ++ sit |=(b=@ (end a b)) :: enforce modulo + -- +:: +:: Hashes +:: +++ muk :: standard murmur3 + ~% %muk ..muk ~ + =+ ~(. fe 5) + |= [syd=@ len=@ key=@] + =. syd (end 5 syd) + =/ pad (sub len (met 3 key)) + =/ data (welp (rip 3 key) (reap pad 0)) + =/ nblocks (div len 4) :: intentionally off-by-one + =/ h1 syd + =+ [c1=0xcc9e.2d51 c2=0x1b87.3593] + =/ blocks (rip 5 key) + =/ i nblocks + =. h1 =/ hi h1 |- + ?: =(0 i) hi + =/ k1 (snag (sub nblocks i) blocks) :: negative array index + =. k1 (sit (mul k1 c1)) + =. k1 (rol 0 15 k1) + =. k1 (sit (mul k1 c2)) + =. hi (mix hi k1) + =. hi (rol 0 13 hi) + =. hi (sum (sit (mul hi 5)) 0xe654.6b64) + $(i (dec i)) + =/ tail (slag (mul 4 nblocks) data) + =/ k1 0 + =/ tlen (dis len 3) + =. h1 + ?+ tlen h1 :: fallthrough switch + %3 =. k1 (mix k1 (lsh [0 16] (snag 2 tail))) + =. k1 (mix k1 (lsh [0 8] (snag 1 tail))) + =. k1 (mix k1 (snag 0 tail)) + =. k1 (sit (mul k1 c1)) + =. k1 (rol 0 15 k1) + =. k1 (sit (mul k1 c2)) + (mix h1 k1) + %2 =. k1 (mix k1 (lsh [0 8] (snag 1 tail))) + =. k1 (mix k1 (snag 0 tail)) + =. k1 (sit (mul k1 c1)) + =. k1 (rol 0 15 k1) + =. k1 (sit (mul k1 c2)) + (mix h1 k1) + %1 =. k1 (mix k1 (snag 0 tail)) + =. k1 (sit (mul k1 c1)) + =. k1 (rol 0 15 k1) + =. k1 (sit (mul k1 c2)) + (mix h1 k1) + == + =. h1 (mix h1 len) + |^ (fmix32 h1) + ++ fmix32 + |= h=@ + =. h (mix h (rsh [0 16] h)) + =. h (sit (mul h 0x85eb.ca6b)) + =. h (mix h (rsh [0 13] h)) + =. h (sit (mul h 0xc2b2.ae35)) + =. h (mix h (rsh [0 16] h)) + h + -- +:: +++ mug :: mug with murmur3 + ~/ %mug + |= a=* + |^ ?@ a (mum 0xcafe.babe 0x7fff a) + =/ b (cat 5 $(a -.a) $(a +.a)) + (mum 0xdead.beef 0xfffe b) + :: + ++ mum + |= [syd=@uxF fal=@F key=@] + =/ wyd (met 3 key) + =| i=@ud + |- ^- @F + ?: =(8 i) fal + =/ haz=@F (muk syd wyd key) + =/ ham=@F (mix (rsh [0 31] haz) (end [0 31] haz)) + ?.(=(0 ham) ham $(i +(i), syd +(syd))) + -- +:: +++ gor :: mug order + ~/ %gor + |= [a=* b=*] + ^- ? + =+ [c=(mug a) d=(mug b)] + ?: =(c d) + (dor a b) + (lth c d) +:: +++ mor :: more mug order + ~/ %mor + |= [a=* b=*] + ^- ? + =+ [c=(mug (mug a)) d=(mug (mug b))] + ?: =(c d) + (dor a b) + (lth c d) +:: +++ dor :: tree order + ~/ %dor + |= [a=* b=*] + ^- ? + ?: =(a b) & + ?. ?=(@ a) + ?: ?=(@ b) | + ?: =(-.a -.b) + $(a +.a, b +.b) + $(a -.a, b -.b) + ?. ?=(@ b) & + (lth a b) +:: +++ por :: parent order + ~/ %por + |= [a=@p b=@p] + ^- ? + ?: =(a b) & + =| i=@ + |- + ?: =(i 2) + :: second two bytes + (lte a b) + :: first two bytes + =+ [c=(end 3 a) d=(end 3 b)] + ?: =(c d) + $(a (rsh 3 a), b (rsh 3 b), i +(i)) + (lth c d) +:: +:: Maps +:: +++ by + ~/ %by + =| a=(tree (pair)) :: (map) + =* node ?>(?=(^ a) n.a) + |@ + ++ get + ~/ %get + |* b=* + => .(b `_?>(?=(^ a) p.n.a)`b) + |- ^- (unit _?>(?=(^ a) q.n.a)) + ?~ a + ~ + ?: =(b p.n.a) + `q.n.a + ?: (gor b p.n.a) + $(a l.a) + $(a r.a) + :: + ++ put + ~/ %put + |* [b=* c=*] + |- ^+ a + ?~ a + [[b c] ~ ~] + ?: =(b p.n.a) + ?: =(c q.n.a) + a + a(n [b c]) + ?: (gor b p.n.a) + =+ d=$(a l.a) + ?> ?=(^ d) + ?: (mor p.n.a p.n.d) + a(l d) + d(r a(l r.d)) + =+ d=$(a r.a) + ?> ?=(^ d) + ?: (mor p.n.a p.n.d) + a(r d) + d(l a(r l.d)) + :: + ++ del + ~/ %del + |* b=* + |- ^+ a + ?~ a + ~ + ?. =(b p.n.a) + ?: (gor b p.n.a) + a(l $(a l.a)) + a(r $(a r.a)) + |- ^- [$?(~ _a)] + ?~ l.a r.a + ?~ r.a l.a + ?: (mor p.n.l.a p.n.r.a) + l.a(r $(l.a r.l.a)) + r.a(l $(r.a l.r.a)) + :: + ++ apt + =< $ + ~/ %apt + =| [l=(unit) r=(unit)] + |. ^- ? + ?~ a & + ?& ?~(l & &((gor p.n.a u.l) !=(p.n.a u.l))) + ?~(r & &((gor u.r p.n.a) !=(u.r p.n.a))) + ?~ l.a & + &((mor p.n.a p.n.l.a) !=(p.n.a p.n.l.a) $(a l.a, l `p.n.a)) + ?~ r.a & + &((mor p.n.a p.n.r.a) !=(p.n.a p.n.r.a) $(a r.a, r `p.n.a)) + == + -- +:: +++ on :: ordered map + ~/ %on + |* [key=mold val=mold] + => |% + +$ item [key=key val=val] + -- + :: + ~% %comp +>+ ~ + |= compare=$-([key key] ?) + ~% %core + ~ + |% + :: + ++ apt + ~/ %apt + |= a=(tree item) + =| [l=(unit key) r=(unit key)] + |- ^- ? + ?~ a %.y + ?& ?~(l %.y (compare key.n.a u.l)) + ?~(r %.y (compare u.r key.n.a)) + ?~(l.a %.y &((mor key.n.a key.n.l.a) $(a l.a, l `key.n.a))) + ?~(r.a %.y &((mor key.n.a key.n.r.a) $(a r.a, r `key.n.a))) + == + :: + ++ get + ~/ %get + |= [a=(tree item) b=key] + ^- (unit val) + ?~ a ~ + ?: =(b key.n.a) + `val.n.a + ?: (compare b key.n.a) + $(a l.a) + $(a r.a) + :: + ++ has + ~/ %has + |= [a=(tree item) b=key] + ^- ? + !=(~ (get a b)) + :: + ++ put + ~/ %put + |= [a=(tree item) =key =val] + ^- (tree item) + ?~ a [n=[key val] l=~ r=~] + ?: =(key.n.a key) a(val.n val) + ?: (compare key key.n.a) + =/ l $(a l.a) + ?> ?=(^ l) + ?: (mor key.n.a key.n.l) + a(l l) + l(r a(l r.l)) + =/ r $(a r.a) + ?> ?=(^ r) + ?: (mor key.n.a key.n.r) + a(r r) + r(l a(r l.r)) + -- +:: +:: Sets +:: +++ in + ~/ %in + =| a=(tree) :: (set) + |@ + ++ put + ~/ %put + |* b=* + |- ^+ a + ?~ a + [b ~ ~] + ?: =(b n.a) + a + ?: (gor b n.a) + =+ c=$(a l.a) + ?> ?=(^ c) + ?: (mor n.a n.c) + a(l c) + c(r a(l r.c)) + =+ c=$(a r.a) + ?> ?=(^ c) + ?: (mor n.a n.c) + a(r c) + c(l a(r l.c)) + :: + ++ del + ~/ %del + |* b=* + |- ^+ a + ?~ a + ~ + ?. =(b n.a) + ?: (gor b n.a) + a(l $(a l.a)) + a(r $(a r.a)) + |- ^- [$?(~ _a)] + ?~ l.a r.a + ?~ r.a l.a + ?: (mor n.l.a n.r.a) + l.a(r $(l.a r.l.a)) + r.a(l $(r.a l.r.a)) + :: + ++ apt + =< $ + ~/ %apt + =| [l=(unit) r=(unit)] + |. ^- ? + ?~ a & + ?& ?~(l & (gor n.a u.l)) + ?~(r & (gor u.r n.a)) + ?~(l.a & ?&((mor n.a n.l.a) $(a l.a, l `n.a))) + ?~(r.a & ?&((mor n.a n.r.a) $(a r.a, r `n.a))) + == + -- +:: +:: Jugs +:: +++ ju + =| a=(tree (pair * (tree))) :: (jug) + |@ + ++ get + |* b=* + =+ c=(~(get by a) b) + ?~(c ~ u.c) + :: + ++ del + |* [b=* c=*] + ^+ a + =+ d=(get b) + =+ e=(~(del in d) c) + ?~ e + (~(del by a) b) + (~(put by a) b e) + :: + ++ put + |* [b=* c=*] + ^+ a + =+ d=(get b) + (~(put by a) b (~(put in d) c)) + -- +-- diff --git a/pkg/arvo/lib/vere.hoon b/pkg/arvo/lib/vere.hoon index 0a6d9b009..8ecbbe248 100644 --- a/pkg/arvo/lib/vere.hoon +++ b/pkg/arvo/lib/vere.hoon @@ -44,23 +44,10 @@ :: |give:dawn: produce requests for pre-boot validation :: ++ give - =, rpc:ethereum - =, abi:ethereum - =/ tract azimuth:contracts:azimuth |% - :: +bloq:give:dawn: Eth RPC for latest block number - :: - ++ bloq - ^- octs - %- as-octt:mimes:html - %- en-json:html - %+ request-to-json - `~.0 - [%eth-block-number ~] :: +czar:give:dawn: Eth RPC for galaxy table :: ++ czar - |= boq=@ud ^- octs %- as-octt:mimes:html %- en-json:html @@ -68,40 +55,43 @@ %+ turn (gulf 0 255) |= gal=@ %+ request-to-json - `(cat 3 'gal-' (scot %ud gal)) - :+ %eth-call - =- [from=~ to=tract gas=~ price=~ value=~ data=-] - (encode-call 'points(uint32)' [%uint gal]~) - [%number boq] + (cat 3 'gal-' (scot %ud gal)) + :- 'getPoint' + (~(put by *(map @t json)) 'ship' s+(scot %p gal)) :: +point:give:dawn: Eth RPC for ship's contract state :: ++ point - |= [boq=@ud who=ship] + |= who=ship ^- octs %- as-octt:mimes:html %- en-json:html %+ request-to-json - `~.0 - :+ %eth-call - =- [from=~ to=tract gas=~ price=~ value=~ data=-] - (encode-call 'points(uint32)' [%uint `@`who]~) - [%number boq] + ~. + :- 'getPoint' + (~(put by *(map @t json)) 'ship' s+(scot %p who)) :: +turf:give:dawn: Eth RPC for network domains :: ++ turf - |= boq=@ud ^- octs %- as-octt:mimes:html %- en-json:html - :- %a - %+ turn (gulf 0 2) - |= idx=@ %+ request-to-json - `(cat 3 'turf-' (scot %ud idx)) - :+ %eth-call - =- [from=~ to=tract gas=~ price=~ value=~ data=-] - (encode-call 'dnsDomains(uint256)' [%uint idx]~) - [%number boq] + 'turf' + ['getDns' ~] + :: +request-to-json:give:dawn: internally used for request generation + :: + ::NOTE we could import this from /lib/json/rpc, but adding that as a + :: dependency seems a bit unclean + :: + ++ request-to-json + |= [id=@t method=@t params=(map @t json)] + ^- json + %- pairs:enjs:format + :~ jsonrpc+s+'2.0' + id+s+id + method+s+method + params+o+params + == -- :: |take:dawn: parse responses for pre-boot validation :: @@ -111,23 +101,6 @@ =, azimuth =, dejs-soft:format |% - :: +bloq:take:dawn: parse block number - :: - ++ bloq - |= rep=octs - ^- (unit @ud) - =/ jon=(unit json) (de-json:html q.rep) - ?~ jon - ~&([%bloq-take-dawn %invalid-json] ~) - =/ res=(unit cord) ((ot result+so ~) u.jon) - ?~ res - ~&([%bloq-take-dawn %invalid-response rep] ~) - =/ out - %- mule |. - (hex-to-num:ethereum u.res) - ?: ?=(%& -.out) - (some p.out) - ~&([%bloq-take-dawn %invalid-block-number] ~) :: +czar:take:dawn: parse galaxy table :: ++ czar @@ -136,58 +109,94 @@ =/ jon=(unit json) (de-json:html q.rep) ?~ jon ~&([%czar-take-dawn %invalid-json] ~) - =/ res=(unit (list [@t @t])) - ((ar (ot id+so result+so ~)) u.jon) + =/ res=(unit (list [@t @ud @ud @])) + %. u.jon + =, dejs-soft:format + =- (ar (ot id+so result+(ot network+- ~) ~)) + %- ot + :~ :- 'rift' (su dim:ag) + :- 'keys' (ot 'life'^(su dim:ag) ~) + :- 'keys' %+ cu pass-from-eth:azimuth + %- ot + :~ 'crypt'^(cu (lead 32) (su ;~(pfix (jest '0x') hex))) + 'auth'^(cu (lead 32) (su ;~(pfix (jest '0x') hex))) + 'suite'^(su dim:ag) + == + == ?~ res - ~&([%czar-take-dawn %invalid-response rep] ~) - =/ dat=(unit (list [who=@p point:azimuth-types])) - =- ?:(?=(%| -.out) ~ (some p.out)) - ^= out %- mule |. - %+ turn u.res - |= [id=@t result=@t] - ^- [who=ship point:azimuth-types] - =/ who `@p`(slav %ud (rsh [3 4] id)) - :- who - %+ point-from-eth - who - :_ *deed:eth-noun - %+ decode-results - result - point:eth-type - ?~ dat - ~&([%bloq-take-dawn %invalid-galaxy-table] ~) + ~&([%czar-take-dawn %incomplete-json] ~) :- ~ - %+ roll u.dat - |= $: [who=ship =point:azimuth-types] + %+ roll u.res + |= $: [id=@t deet=[=rift =life =pass]] kyz=(map ship [=rift =life =pass]) == ^+ kyz - ?~ net.point + ?: =(0 life.deet) kyz - (~(put by kyz) who [continuity-number life pass]:u.net.point) + %+ ~(put by kyz) + (slav %ud (rsh [3 4] id)) + deet :: +point:take:dawn: parse ship's contract state :: ++ point |= [who=ship rep=octs] ^- (unit point:azimuth) + ~! *point:azimuth =/ jon=(unit json) (de-json:html q.rep) ?~ jon ~&([%point-take-dawn %invalid-json] ~) - =/ res=(unit cord) ((ot result+so ~) u.jon) - ?~ res - ~&([%point-take-dawn %invalid-response rep] ~) - ~? =(u.res '0x') - :- 'bad result from node; is azimuth address correct?' - azimuth:contracts - =/ out - %- mule |. - %+ point-from-eth - who - :_ *deed:eth-noun ::TODO call rights to fill - (decode-results u.res point:eth-type) - ?: ?=(%& -.out) - (some p.out) - ~&([%point-take-dawn %invalid-point] ~) + =- ?~ res + ~&([%point-take-dawn %incomplete-json] ~) + =, u.res + %- some + :+ own + ?: =(0 life) ~ + `[life pass rift sponsor ~] ::NOTE escape unknown ::TODO could be! + ?. (gth who 0xffff) ~ + `[spawn ~] ::NOTE spawned unknown + ^- $= res + %- unit + $: [spawn=@ own=[@ @ @ @]] + [=rift =life =pass sponsor=[? ship]] + == + %. u.jon + =, dejs-soft:format + =- (ot result+- ~) + %- ot + :~ :- 'ownership' + %- ot + |^ :~ 'spawnProxy'^address + 'owner'^address + 'managementProxy'^address + 'votingProxy'^address + 'transferProxy'^address + == + :: + ++ address + (ot 'address'^(cu hex-to-num:ethereum so) ~) + -- + :: + :- 'network' + %- ot + ::TODO dedupe with +czar + :~ 'rift'^(su dim:ag) + 'keys'^(ot 'life'^(su dim:ag) ~) + :: + :- 'keys' + %+ cu pass-from-eth:azimuth + %- ot + :~ 'crypt'^(cu (lead 32) (su ;~(pfix (jest '0x') hex))) + 'auth'^(cu (lead 32) (su ;~(pfix (jest '0x') hex))) + 'suite'^(su dim:ag) + == + :: + ::TODO inconsistent @p string + 'sponsor'^(ot 'has'^bo 'who'^ni ~) + :: + ::TODO escape + ::TODO what if escape or sponsor not present? possible? + == + == :: +turf:take:dawn: parse network domains :: ++ turf @@ -196,38 +205,21 @@ =/ jon=(unit json) (de-json:html q.rep) ?~ jon ~&([%turf-take-dawn %invalid-json] ~) - =/ res=(unit (list [@t @t])) - ((ar (ot id+so result+so ~)) u.jon) + =/ res=(unit (list @t)) + ((ot result+(ar so) ~) u.jon) ?~ res - ~&([%turf-take-dawn %invalid-response rep] ~) - =/ dat=(unit (list (pair @ud ^turf))) - =- ?:(?=(%| -.out) ~ (some p.out)) - ^= out %- mule |. - %+ turn u.res - |= [id=@t result=@t] - ^- (pair @ud ^turf) - :- (slav %ud (rsh [3 5] id)) - =/ dom=tape - (decode-results result [%string]~) - =/ hot=host:eyre - (scan dom thos:de-purl:html) - ?>(?=(%& -.hot) p.hot) - ?~ dat - ~&([%turf-take-dawn %invalid-domains] ~) - :- ~ - =* dom u.dat - :: sort by id, ascending, removing duplicates + ~&([%turf-take-dawn %invalid-response] ~) + :: remove duplicates, parse into turfs :: - =| tuf=(map ^turf @ud) - |- ^- (list ^turf) - ?~ dom - %+ turn - %+ sort ~(tap by tuf) - |=([a=(pair ^turf @ud) b=(pair ^turf @ud)] (lth q.a q.b)) - head - =? tuf !(~(has by tuf) q.i.dom) - (~(put by tuf) q.i.dom p.i.dom) - $(dom t.dom) + =- `doz + %+ roll u.res + |= [dom=@t doh=(set @t) doz=(list ^turf)] + ?: (~(has in doh) dom) [doh doz] + :- (~(put in doh) dom) + =/ hot=host:eyre + (rash dom thos:de-purl:html) + ?. ?=(%& -.hot) doz + (snoc doz p.hot) -- :: +veri:dawn: validate keys, life, discontinuity, &c :: diff --git a/pkg/arvo/mar/csv.hoon b/pkg/arvo/mar/csv.hoon deleted file mode 100644 index 15445aad9..000000000 --- a/pkg/arvo/mar/csv.hoon +++ /dev/null @@ -1,15 +0,0 @@ -=, format -=, mimes:html -|_ csv=wain -:: -++ grab :: convert from - |% - ++ mime |=((pair mite octs) (to-wain q.q)) - ++ noun wain :: clam from %noun - -- -++ grow - |% - ++ mime [/text/csv (as-octs (of-wain csv))] - -- -++ grad %mime --- diff --git a/pkg/arvo/mar/eth/logs.hoon b/pkg/arvo/mar/eth/logs.hoon new file mode 100644 index 000000000..241a61d5e --- /dev/null +++ b/pkg/arvo/mar/eth/logs.hoon @@ -0,0 +1,20 @@ +:: list of ethereum logs +:: +/+ ethereum +:: +|_ logs=(list event-log:rpc:ethereum) +++ grab + |% + ++ noun (list event-log:rpc:ethereum) + ++ mime + |= [mite =octs] + (noun (cue q.octs)) + -- +:: +++ grow + |% + ++ mime + [/application/x-ethereum-logs (as-octs:mimes:html (jam logs))] + -- +++ grad %mime +-- diff --git a/pkg/arvo/mar/kiln/bump.hoon b/pkg/arvo/mar/kiln/bump.hoon index 35896403b..766454277 100644 --- a/pkg/arvo/mar/kiln/bump.hoon +++ b/pkg/arvo/mar/kiln/bump.hoon @@ -1,5 +1,5 @@ |% -+$ bump [%kiln-bump except=(set desk) force=_|] ++$ bump [except=(set desk) force=_|] -- |_ b=bump ++ grad %noun @@ -9,7 +9,6 @@ ++ json ^- $-(^json bump) =, dejs:format - %+ pe %kiln-bump %- ot :~ except+(as so) force+bo diff --git a/pkg/arvo/sur/crunch.hoon b/pkg/arvo/sur/crunch.hoon deleted file mode 100644 index e2d5a5a73..000000000 --- a/pkg/arvo/sur/crunch.hoon +++ /dev/null @@ -1,9 +0,0 @@ -/- resource -:: -|% -+$ channel-info - $: group=resource:resource - channel=resource:resource - channel-type=term - == --- diff --git a/pkg/arvo/sur/dice.hoon b/pkg/arvo/sur/dice.hoon new file mode 100644 index 000000000..2ba9e310f --- /dev/null +++ b/pkg/arvo/sur/dice.hoon @@ -0,0 +1,96 @@ +:: dice: structures for L2 rollers +:: +/+ naive, ethereum +:: +|% ++$ owner [=proxy:naive =address:naive] ++$ owners (jug owner ship) ++$ sponsors (map ship [residents=(set ship) requests=(set ship)]) ++$ net ?(%mainnet %ropsten %local %default) +:: ++$ config + $% [%frequency frequency=@dr] + [%setkey pk=@] + [%endpoint endpoint=@t =net] + [%resend-time time=@dr] + [%update-rate rate=@dr] + [%slice slice=@dr] + [%quota quota=@ud] + == +:: ++$ indices + $: nas=^state:naive + own=owners + spo=sponsors + == +:: ++$ azimuth-config + $: refresh-rate=@dr + == +:: ++$ roller-config + $: next-batch=time + frequency=@dr + resend-time=@dr + update-rate=@dr + contract=@ux + chain-id=@ + slice=@dr + quota=@ud + == +:: ++$ keccak @ux +:: ++$ status + ?(%unknown %pending %sending %confirmed %failed %cancelled) +:: ++$ tx-status + $: =status + pointer=(unit l1-tx-pointer) + == +:: ++$ l1-tx-pointer + $: =address:ethereum + nonce=@ud + == +:: ++$ l2-tx + $? %transfer-point + %spawn + %configure-keys + %escape + %cancel-escape + %adopt + %reject + %detach + %set-management-proxy + %set-spawn-proxy + %set-transfer-proxy + == +:: ++$ update + $% [%point =ship =point:naive new=owner old=(unit owner)] + [%tx =address:ethereum =roll-tx] + == +:: ++$ hist-tx [p=time q=roll-tx] ++$ roll-tx [=ship =status hash=keccak type=l2-tx] ++$ pend-tx [force=? =address:naive =time =raw-tx:naive] ++$ send-tx [next-gas-price=@ud sent=? txs=(list raw-tx:naive)] ++$ part-tx + $% [%raw raw=octs] + [%don =tx:naive] + [%ful raw=octs =tx:naive] ::TODO redundant? + == +:: ++$ rpc-send-roll + $: endpoint=@t + contract=address:ethereum + chain-id=@ + pk=@ + :: + nonce=@ud + next-gas-price=@ud + txs=(list raw-tx:naive) + == +-- diff --git a/pkg/arvo/sur/eth-watcher.hoon b/pkg/arvo/sur/eth-watcher.hoon index eb6967d2a..71618721e 100644 --- a/pkg/arvo/sur/eth-watcher.hoon +++ b/pkg/arvo/sur/eth-watcher.hoon @@ -18,6 +18,7 @@ timeout-time=@dr from=number:block contracts=(list address:ethereum) + batchers=(list address:ethereum) =topics == :: diff --git a/pkg/arvo/sys.kelvin b/pkg/arvo/sys.kelvin index b7464903a..e68acb6a4 100644 --- a/pkg/arvo/sys.kelvin +++ b/pkg/arvo/sys.kelvin @@ -1 +1 @@ -[%zuse 420] +[%zuse 419] diff --git a/pkg/arvo/sys/hoon.hoon b/pkg/arvo/sys/hoon.hoon index 3ffd858c3..566010fbe 100644 --- a/pkg/arvo/sys/hoon.hoon +++ b/pkg/arvo/sys/hoon.hoon @@ -5962,7 +5962,14 @@ ++ spat |=(pax=path (crip (spud pax))) :: render path to cord ++ spud |=(pax=path ~(ram re (smyt pax))) :: render path to tape ++ stab |=(zep=@t `path`(rash zep stap)) :: parse cord to path -++ stap ;~(pfix fas (more fas urs:ab)) :: path parser +++ stap :: path parser + %+ sear + |= p=path + ^- (unit path) + ?: ?=([~ ~] p) `~ + ?. =(~ (rear p)) `p + ~ + ;~(pfix fas (most fas urs:ab)) :: :::: 4n: virtualization :: @@ -9247,144 +9254,6 @@ hag [q.p.dix q.q.dix] == :: - ++ ad - |% - ++ arc - |% - ++ deft :: generic - |% - ++ bath * :: leg match type - ++ claw * :: arm match type - ++ form |*([* *] p=+<-) :: attach build state - ++ skin |*(p=* p) :: reveal build state - ++ meat |*(p=* p) :: remove build state - -- - ++ make :: for mint - |% - ++ bath type :: leg match type - ++ claw onyx :: arm - ++ form |*([* *] [p=+<- q=+<+]) :: - ++ skin |*([p=* q=*] q) :: unwrap baggage - ++ meat |*([p=* q=*] p) :: unwrap filling - -- - -- - ++ def - =+ deft:arc - |@ ++ $ - => +< - |% - ++ pord |*(* (form +< *nock)) :: wrap mint formula - ++ rosh |*(* (form +< *(list pock))) :: wrap mint changes - ++ fleg _(pord $:bath) :: legmatch + code - ++ fram _(pord $:claw) :: armmatch + - ++ foat _(rosh $:bath) :: leg with changes - ++ fult _(rosh $:claw) :: arm with changes - -- -- - :: - ++ lib - |% - ++ deft - => (def deft:arc) - |% - ++ halp ^|(|:($:hoon $:fleg)) - ++ vant - |% ++ trep ^|(|:($:,[bath wing bath] $:,[axis bath])) - ++ tasp ^|(|:($:,[[axis bath] fleg foat] $:foat)) - ++ tyle ^|(|:($:foat $:foat)) - -- - ++ vunt - |% ++ trep ^|(|:($:,[claw wing bath] $:,[axis claw])) - ++ tasp ^|(|:($:,[[axis claw] fleg fult] $:fult)) - ++ tyle ^|(|:($:fult $:foat)) - -- -- - :: - ++ make - => (def make:arc) - |% - ++ halp |~ a=hoon - ^- fleg - (mint %noun a) - ++ vant - |% ++ trep |: $:,[a=type b=wing c=type] - ^- [axis type] - (tack(sut a) b c) - ++ tasp |: $:,[a=(pair axis type) b=fleg c=foat] - ^- foat - [q.a [[p.a (skin b)] (skin c)]] - ++ tyle |:($:foat +<) - -- - ++ vunt - |% ++ trep |: $:,[a=claw b=wing c=bath] - ^- (pair axis claw) - (toss b c a) - ++ tasp |: $:,[a=(pair axis claw) b=fleg c=fult] - ^- fult - [q.a [[p.a (skin b)] (skin c)]] - ++ tyle |: $:fult - ^- foat - [(fire +<-) +<+] - -- -- -- - :: - ++ bin - =+ deft:lib - |@ ++ $ - => +< - |% - ++ rame - => vant |% - ++ clom bath - ++ chog fleg - ++ ceut foat - -- - ++ gelp - => vunt |% - ++ clom claw - ++ chog fram - ++ ceut fult - -- - ++ ecbo (ecco rame) - ++ eclo (ecco gelp) - ++ ecco - =+ rame - |@ ++ $ - => +< - |: $:,[rum=clom rig=(list (pair wing hoon))] - ^- foat - %- tyle - |- ^- ceut - ?~ rig (rosh rum) - =+ mor=$(rig t.rig) - =+ zil=(halp q.i.rig) - =+ dar=(trep (meat mor) p.i.rig (meat zil)) - (tasp dar zil mor) - -- -- -- -- - :: - ++ oc - =+ inc=(bin:ad) - |@ ++ $ - => inc - |% - ++ echo - |: $:,[rum=bath rig=(list (pair wing hoon))] - (ecbo rum rig) - :: - ++ ecmo - |: $:,[hag=claw rig=(list (pair wing hoon))] - (eclo hag rig) - -- -- - :: - ++ etco - |= [lop=palo rig=(list (pair wing hoon))] - ^- (pair type nock) - =+ cin=(oc (bin:ad make:lib:ad)) - =. rig (flop rig) :: XX this unbreaks, void order in devulc - =+ axe=(tend p.lop) - ?: ?=(%& -.q.lop) - =- [p.- (hike axe q.-)] - (echo:cin p.q.lop rig) - =- [p.- [%9 p.q.lop (hike axe q.-)]] - (ecmo:cin ~(tap in q.q.lop) rig) - :: ++ et |_ [hyp=wing rig=(list (pair wing hoon))] :: @@ -9400,7 +9269,7 @@ =+ lug=(find %read hyp) ?: ?=(%| -.lug) ~>(%mean.'hoon' ?>(?=(~ rig) p.lug)) =- ?>(?|(!vet (nest(sut gol) & p.-)) -) - (etco p.lug rig) + (ergo p.lug rig) :: ++ mull |= [gol=type dox=type] @@ -10088,7 +9957,6 @@ [(nice %noun) [%2 q:$(gen p.gen, gol %noun) q:$(gen q.gen, gol %noun)]] :: [%dtts *] - =+ [one two]=[$(gen p.gen, gol %noun) $(gen q.gen, gol %noun)] [(nice bool) [%5 q:$(gen p.gen, gol %noun) q:$(gen q.gen, gol %noun)]] :: [%dtwt *] [(nice bool) [%3 q:$(gen p.gen, gol %noun)]] diff --git a/pkg/arvo/sys/lull.hoon b/pkg/arvo/sys/lull.hoon index 14d4b5b57..2e457aa4c 100644 --- a/pkg/arvo/sys/lull.hoon +++ b/pkg/arvo/sys/lull.hoon @@ -850,7 +850,7 @@ +$ mool [=case paths=(set (pair care path))] :: requests in desk +$ nori :: repository action $% [%& p=soba] :: delta - [%| p=@tas] :: label + [%| p=@tas q=(unit aeon)] :: label == :: +$ nuri :: repository action $% [%& p=suba] :: delta @@ -1906,6 +1906,7 @@ [%private-keys ~] :: sub to privates [%public-keys ships=(set ship)] :: sub to publics [%rekey =life =ring] :: update private keys + [%ruin ships=(set ship)] :: pretend breach $>(%trim vane-task) :: trim state [%turf ~] :: view domains $>(%vega vane-task) :: report upgrade diff --git a/pkg/arvo/sys/vane/clay.hoon b/pkg/arvo/sys/vane/clay.hoon index 379f39c0f..871bbe376 100644 --- a/pkg/arvo/sys/vane/clay.hoon +++ b/pkg/arvo/sys/vane/clay.hoon @@ -1445,6 +1445,32 @@ == == :: + :: Attach label to aeon + :: + ++ label + |= [bel=@tas aey=(unit aeon)] + ^+ ..park + =/ yon ?~(aey let.dom u.aey) + =/ yen (~(get by lab.dom) bel) :: existing aeon? + :: no existing aeon is bound to this label + :: + ?~ yen + =. lab.dom (~(put by lab.dom) bel yon) + ..park + :: an aeon is bound to this label, + :: but it is the same as the existing one, so we no-op + :: + ?: =(u.yen yon) + ~& "clay: tried to rebind existing label {} to equivalent aeon {}" + ..park + :: an existing aeon bound to the label + :: that is distinct from the requested one. + :: rewriting would violate referential transparency + :: + ~| %tried-to-rewrite-existing-label + ~| "requested aeon: {}, existing aeon: {}" + !! + :: :: Porcelain commit :: ++ info @@ -4374,8 +4400,12 @@ :: %info ?: ?=(%| -.dit.req) - ~| %labelling-not-implemented - !! + =/ bel=@tas p.dit.req + =/ aey=(unit aeon) q.dit.req + =^ mos ruf + =/ den ((de now rof hen ruf) our des.req) + abet:(label:den bel aey) + [mos ..^$] =/ [deletes=(set path) changes=(map path cage)] =/ =soba p.dit.req =| deletes=(set path) diff --git a/pkg/arvo/sys/vane/jael.hoon b/pkg/arvo/sys/vane/jael.hoon index 4274ecca8..46533ab34 100644 --- a/pkg/arvo/sys/vane/jael.hoon +++ b/pkg/arvo/sys/vane/jael.hoon @@ -34,18 +34,16 @@ :: manage subscriptions efficiently. :: => |% -+$ state-1 - $: %1 - pki=state-pki-1 :: ++$ state-2 + $: %2 + pki=state-pki-2 :: etn=state-eth-node :: eth connection state == :: -+$ state-pki-1 :: urbit metadata ++$ state-pki-2 :: urbit metadata $: $= own :: vault (vein) $: yen=(set duct) :: trackers sig=(unit oath) :: for a moon tuf=(list turf) :: domains - boq=@ud :: boot block - nod=purl:eyre :: eth gateway fak=_| :: fake keys lyf=life :: version step=@ud :: login code step @@ -181,7 +179,7 @@ == :: all vane state :: - state-1 + state-2 == :: lex: all durable state :: moz: pending actions @@ -207,8 +205,8 @@ [our our] app %poke - %azimuth-tracker-poke - !>([%watch (crip (en-purl:html purl))]) + %azimuth-poke + !>([%watch (crip (en-purl:html purl)) %default]) == :: ++ sein :: sponsor @@ -254,14 +252,6 @@ :: ~| [our who.seed.tac] ?> =(our who.seed.tac) - :: save our boot block - :: - =. boq.own.pki bloq.tac - :: save our ethereum gateway (required for galaxies) - :: - =. nod.own.pki - %+ fall node.tac - (need (de-purl:html 'http://eth-mainnet.urbit.org:8545')) :: save our parent signature (only for moons) :: =. sig.own.pki sig.seed.tac @@ -312,26 +302,29 @@ :: :: start subscriptions :: - =. +>.$ (poke-watch hen %azimuth-tracker nod.own.pki) =. +>.$ - :: get everything from azimuth-tracker because jael subscriptions + %^ poke-watch hen %azimuth + %+ fall node.tac + (need (de-purl:html 'http://eth-mainnet.urbit.org:8545')) + =. +>.$ + :: get everything from /app/azimuth because jael subscriptions :: seem to be flaky for now :: ?: & %- curd =< abet - (sources:~(feel su hen now pki etn) ~ [%| %azimuth-tracker]) + (sources:~(feel su hen now pki etn) ~ [%| %azimuth]) :: ?- (clan:title our) %czar %- curd =< abet - (sources:~(feel su hen now pki etn) ~ [%| %azimuth-tracker]) + (sources:~(feel su hen now pki etn) ~ [%| %azimuth]) :: * =. +>.$ %- curd =< abet %+ sources:~(feel su hen now pki etn) (silt (turn spon-points head)) - [%| %azimuth-tracker] + [%| %azimuth] %- curd =< abet (sources:~(feel su hen now pki etn) ~ [%& (need spon-ship)]) == @@ -489,6 +482,7 @@ :: [%trim p=@ud] :: %trim + ::TODO consider %ruin-ing long-offline comets +>.$ :: :: watch private keys @@ -521,6 +515,20 @@ =. moz [[hen %give %done ~] moz] $(tac message) == + :: + :: pretend ships breached + :: [%ruin ships=(set ship)] + :: + %ruin + ::NOTE we blast this out to _all_ known ducts, because the common + :: use case for this is comets, about who nobody cares. + =/ dus ~(key by yen.zim.pki) + =/ sus ~(. su hen now pki etn) + =/ sis ~(tap in ships.tac) + |- + ?~ sis (curd abet:sus) + =. sus (exec:sus dus %give %public-keys %breach i.sis) + $(sis t.sis) == :: ++ take @@ -548,7 +556,7 @@ [%behn %wake *] ?^ error.hin %- %+ slog - leaf+"jael unable to resubscribe, run :azimuth-tracker|listen" + leaf+"jael unable to resubscribe, run :azimuth|listen" u.error.hin +>.$ ?> ?=([%breach @ ~] tea) @@ -565,7 +573,14 @@ [%gall %unto *] ?- +>-.hin %raw-fact !! - %kick ~|([%jael-unexpected-quit tea hin] !!) + :: + %kick + ?> ?=([@ *] tea) + =* app i.tea + ::NOTE we expect azimuth-tracker to be kill + ?: =(%azimuth-tracker app) +>.$ + ~|([%jael-unexpected-quit tea hin] !!) + :: %poke-ack ?~ p.p.+>.hin +>.$ @@ -589,7 +604,7 @@ :: :: ++curd:of ++ curd :: relative moves |= $: moz=(list move) - pki=state-pki-1 + pki=state-pki-2 etn=state-eth-node == +>(pki pki, etn etn, moz (weld (flop moz) ^moz)) @@ -609,7 +624,7 @@ =| moz=(list move) =| $: hen=duct now=@da - state-pki-1 + state-pki-2 state-eth-node == :: moz: moves in reverse order @@ -990,7 +1005,7 @@ :: :: lex: all durable %jael state :: -=| lex=state-1 +=| lex=state-2 |= $: :: now: current time :: eny: unique entropy :: ski: namespace resolver @@ -1020,8 +1035,42 @@ [did ..^$] :: :: ++load ++ load :: upgrade - |= old=state-1 + => |% + :: + +$ any-state $%(state-1 state-2) + +$ state-1 + $: %1 + pki=state-pki-1 + etn=state-eth-node + == + +$ state-pki-1 + $: $= own + $: yen=(set duct) + sig=(unit oath) + tuf=(list turf) + boq=@ud + nod=purl:eyre + fak=_| + lyf=life + step=@ud + jaw=(map life ring) + == + $= zim + $: yen=(jug duct ship) + ney=(jug ship duct) + nel=(set duct) + dns=dnses + pos=(map ship point) + == == + -- + |= old=any-state ^+ ..^$ + =? old ?=(%1 -.old) + %= old + - %2 + own.pki own.pki.old(+>+ +>.+>+.own.pki.old) + == + ?> ?=(%2 -.old) ..^$(lex old) :: :: ++scry ++ scry :: inspect @@ -1064,6 +1113,12 @@ =/ sec (~(got by jaw.own.pki.lex) lyf.own.pki.lex) =/ sal (add %pass step.own.pki.lex) ``[%noun !>((end 6 (shaf sal (shax sec))))] + :: + %fake + ?. ?=(~ tyl) [~ ~] + ?. =([%& our] why) + [~ ~] + ``[%noun !>(fak.own.pki.lex)] :: %life ?. ?=([@ ~] tyl) [~ ~] diff --git a/pkg/arvo/sys/zuse.hoon b/pkg/arvo/sys/zuse.hoon index 238eab774..753b531a2 100644 --- a/pkg/arvo/sys/zuse.hoon +++ b/pkg/arvo/sys/zuse.hoon @@ -4,7 +4,7 @@ => ..lull ~% %zuse ..part ~ |% -++ zuse %420 +++ zuse %419 :: :: :: :::: :: :: (2) engines :: :: :: @@ -4910,13 +4910,20 @@ ++ cite :: render ship |= who=@p ^- tape - =+ kind=(clan who) - =+ name=(scow %p who) - ?: =(%earl kind) - :(weld "~" (swag [15 6] name) "^" (swag [22 6] name)) - ?: =(%pawn kind) - :(weld (swag [0 7] name) "_" (swag [51 6] name)) - name + =/ wid (met 4 who) + ?: (lte wid 2) (scow %p who) + ?: (lte wid 4) + =/ nom (scow %p (end 5 who)) + :(weld (scag 7 nom) "^" (slag 8 nom)) + %- trip + %+ rap 3 + :~ '~' + (tos:po (cut 3 [(dec (mul wid 2)) 1] who)) + (tod:po (cut 3 [(mul (dec wid) 2) 1] who)) + '_' + (tos:po (cut 3 [1 1] who)) + (tod:po (end 3 who)) + == :: :: ++saxo:title ++ saxo :: autocanon |= [our=ship now=@da who=ship] diff --git a/pkg/arvo/ted/eth-watcher.hoon b/pkg/arvo/ted/eth-watcher.hoon index 9cb742338..5e53e03e3 100644 --- a/pkg/arvo/ted/eth-watcher.hoon +++ b/pkg/arvo/ted/eth-watcher.hoon @@ -1,7 +1,7 @@ :: eth-watcher: ethereum event log collector :: /- spider, *eth-watcher -/+ strandio, ethio +/+ strandio, ethio, azimuth =, ethereum-types =, jael :: @@ -12,21 +12,22 @@ =+ !<([~ pup=watchpup] args) =/ m (strand:strandio ,vase) ^- form:m -;< =latest=block bind:m (get-latest-block:ethio url.pup) -;< pup=watchpup bind:m (zoom pup number.id.latest-block) +;< =latest=block bind:m (get-latest-block:ethio url.pup) +;< pup=watchpup bind:m (zoom pup number.id.latest-block) =| vows=disavows -?. eager.pup +;< pup=watchpup bind:m (fetch-batches pup) +::?. eager.pup (pure:m !>([vows pup])) -|- ^- form:m -=* loop $ -?: (gth number.pup number.id.latest-block) - (pure:m !>([vows pup])) -;< =block bind:m (get-block-by-number:ethio url.pup number.pup) -;< [=new=disavows pup=watchpup] bind:m (take-block pup block) -%= loop - pup pup - vows (weld vows new-disavows) -== +:: |- ^- form:m +:: =* loop $ +:: ?: (gth number.pup number.id.latest-block) +:: (pure:m !>([vows pup])) +:: ;< =block bind:m (get-block-by-number:ethio url.pup number.pup) +:: ;< [=new=disavows pup=watchpup] bind:m (take-block pup block) +:: %= loop +:: pup pup +:: vows (weld vows new-disavows) +:: == :: :: Process a block, detecting and handling reorgs :: @@ -37,8 +38,9 @@ :: if this next block isn't direct descendant of our logs, reorg happened ?: &(?=(^ blocks.pup) !=(parent-hash.block hash.id.i.blocks.pup)) (rewind pup block) + =/ contracts (weld contracts.pup batchers.pup) ;< =new=loglist bind:m :: oldest first - (get-logs-by-hash:ethio url.pup hash.id.block contracts.pup topics.pup) + (get-logs-by-hash:ethio url.pup hash.id.block contracts topics.pup) %- pure:m :- ~ %_ pup @@ -80,21 +82,38 @@ |= [pup=watchpup =latest=number:block] =/ m (strand:strandio ,watchpup) ^- form:m - =/ zoom-margin=number:block 30 + =/ zoom-margin=number:block 0 :: TODO: 30! =/ zoom-step=number:block 100.000 ?: (lth latest-number (add number.pup zoom-margin)) (pure:m pup) - =/ up-to-number=number:block (sub latest-number zoom-margin) + =/ up-to-number=number:block + (min (add 10.000.000 number.pup) (sub latest-number zoom-margin)) |- =* loop $ ?: (gth number.pup up-to-number) (pure:m pup(blocks ~)) =/ to-number=number:block - (min up-to-number (add number.pup zoom-step)) + =; step + (min up-to-number (add number.pup step)) + :: Between "launch" (6.784.800) and "public" (7.033.765) blocks, + :: there are a lot events belonging to all the pre-ethereum ships + :: being established on-chain. By reducing the step, we avoid crashing. + :: + ?. =(contracts:azimuth mainnet-contracts:azimuth) + zoom-step + ?: ?| &((gte number.pup 6.951.132) (lth number.pup 6.954.242)) + &((gte number.pup 7.011.857) (lth number.pup 7.021.881)) + == + 50 + ?: ?& (gte number.pup launch:mainnet-contracts:azimuth) + (lth number.pup public:mainnet-contracts:azimuth) + == + 500 + zoom-step ;< =loglist bind:m :: oldest first %: get-logs-by-range:ethio url.pup - contracts.pup + (weld contracts.pup batchers.pup) topics.pup number.pup to-number @@ -102,4 +121,53 @@ =? pending-logs.pup ?=(^ loglist) (~(put by pending-logs.pup) to-number loglist) loop(number.pup +(to-number)) +:: Fetch input for any logs in batchers.pup +:: +++ fetch-batches + |= pup=watchpup + =/ m (strand:strandio ,watchpup) + =| res=(list [number:block loglist]) + =/ pending=(list [=number:block =loglist]) ~(tap by pending-logs.pup) + |- ^- form:m + =* loop $ + ?~ pending + (pure:m pup(pending-logs (malt res))) + ;< logs=(list event-log:rpc:ethereum) bind:m + (fetch-inputs pup loglist.i.pending) + =. res [[number.i.pending logs] res] + loop(pending t.pending) +:: Fetch inputs for a list of logs +:: +++ fetch-inputs + |= [pup=watchpup logs=(list event-log:rpc:ethereum)] + =/ m (strand:strandio ,(list event-log:rpc:ethereum)) + =| res=(list event-log:rpc:ethereum) + |- ^- form:m + =* loop $ + ?~ logs + (pure:m (flop res)) + ;< log=event-log:rpc:ethereum bind:m (fetch-input pup i.logs) + =. res [log res] + loop(logs t.logs) +:: Fetch input for a log +:: +++ fetch-input + |= [pup=watchpup log=event-log:rpc:ethereum] + =/ m (strand:strandio ,event-log:rpc:ethereum) + ^- form:m + ?~ mined.log + (pure:m log) + ?^ input.u.mined.log + (pure:m log) + ?. (lien batchers.pup |=(=@ux =(ux address.log))) + (pure:m log) + ;< res=transaction-result:rpc:ethereum bind:m + (get-tx-by-hash:ethio url.pup transaction-hash.u.mined.log) + (pure:m log(input.u.mined `(data-to-hex input.res))) +:: +++ data-to-hex + |= data=@t + ?~ data *@ux + ?: =(data '0x') *@ux + (hex-to-num:ethereum data) -- diff --git a/pkg/arvo/ted/roller/nonce.hoon b/pkg/arvo/ted/roller/nonce.hoon new file mode 100644 index 000000000..311e1e9d5 --- /dev/null +++ b/pkg/arvo/ted/roller/nonce.hoon @@ -0,0 +1,15 @@ +:: aggregator/nonce: get next nonce +:: +/- rpc=json-rpc +/+ ethereum, ethio, strandio +:: +|= args=vase +=+ !<([endpoint=@t pk=@] args) +=/ m (strand:strandio ,vase) +^- form:m +:: +=/ =address:ethereum + (address-from-prv:key:ethereum pk) +;< expected-nonce=@ud bind:m + (get-next-nonce:ethio endpoint address) +(pure:m !>(expected-nonce)) diff --git a/pkg/arvo/ted/roller/send.hoon b/pkg/arvo/ted/roller/send.hoon new file mode 100644 index 000000000..443f0cb5f --- /dev/null +++ b/pkg/arvo/ted/roller/send.hoon @@ -0,0 +1,134 @@ +:: roller/send: send rollup tx +:: +/- rpc=json-rpc, *dice +/+ naive, ethereum, ethio, strandio +:: +:: +|= args=vase +=+ !<(rpc-send-roll args) +=/ m (strand:strandio ,vase) +|^ +^- form:m +:: =* not-sent (pure:m !>(%.n^next-gas-price)) +:: +=/ =address:ethereum (address-from-prv: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) + ~& [%unexpected-nonce nonce expected+expected-nonce] + (pure:m !>(%.n^[%not-sent %unexpected-nonce])) +:: 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) +:: +=/ batch-data=octs + %+ cad:naive 3 + %- flop + %+ roll txs + |= [=raw-tx:naive out=(list octs)] + [raw.raw-tx 65^sig.raw-tx out] +:: TODO: keep this to avoid sending bad batches or disregard? +:: +?~ (parse-roll:naive q.batch-data) + (pure:m !>(%.n^[%not-sent %batch-parse-error])) +:: +:: each l2 signature is 65 bytes + XX bytes for the raw data +:: from the ethereum yellow paper: +:: gasLimit = G_transaction + G_txdatanonzero × dataByteLength +:: where +:: G_transaction = 21000 gas (base fee) +:: + G_txdatanonzero = 68 gas +:: * dataByteLength = (65 + raw) * (lent txs) bytes +:: +:: TODO: enforce max number of tx in batch? +:: +=/ gas-limit=@ud (add 21.000 (mul 68 p.batch-data)) +:: 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 + (get-balance:ethio endpoint address) +?: (gth max-cost balance) + (pure:m !>(%.n^[%not-sent %insufficient-roller-balance])) +:: +::NOTE this fails the thread if sending fails, which in the app gives us +:: the "retry with same gas price" behavior we want +;< =response:rpc bind:m + %+ send-batch endpoint + =; tx=transaction:rpc:ethereum + (sign-transaction:key:ethereum tx pk) + :* nonce + use-gas-price + gas-limit + contract + 0 + q.batch-data + chain-id + == +:: log batch tx-hash to getTransactionReceipt(tx-hash) +:: +~? &(?=(%result -.response) ?=(%s -.res.response)) + ^-([nonce=@ud batch-hash=@t] nonce^(so:dejs:format res.response)) +%- pure:m +!> ^- (each @ud [term @t]) +:: TODO: capture if the tx fails (e.g. Runtime Error: revert) +:: check that tx-hash in +.response is non-zero? +:: enforce max here, or in app? +:: +?+ -.response %.n^[%error 'unexpected rpc response'] + %error %.n^[%error message.response] + :: add five gwei to gas price of next attempt + :: + %result %.y^(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 10.000.000.000) + ?. ?& ?=([~ %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 ~) ~) +:: +++ send-batch + |= [endpoint=@ta batch=@ux] + =/ m (strand:strandio ,response:rpc) + ^- form:m + =/ req=[(unit @t) request:rpc:ethereum] + [`'sendRawTransaction' %eth-send-raw-transaction batch] + ;< res=(list response:rpc) bind:m + (request-batch-rpc-loose:ethio endpoint [req]~) + ?: ?=([* ~] res) + (pure:m i.res) + %+ strand-fail:strandio + %unexpected-multiple-results + [>(lent res)< ~] +:: +-- diff --git a/pkg/arvo/ted/test.hoon b/pkg/arvo/ted/test.hoon index a25496fc2..43a81700c 100644 --- a/pkg/arvo/ted/test.hoon +++ b/pkg/arvo/ted/test.hoon @@ -66,7 +66,7 @@ =/ fire-arm=nock ~| [%failed-to-compile-test-arm name] q:(~(mint ut typ) p:!>(*tang) [%limb name]) - [name |.(;;(tang .*(cor fire-arm)))] + [name |.(;;(tang ~>(%bout.[1 name] .*(cor fire-arm))))] :: +has-test-prefix: does the arm define a test we should run? :: ++ has-test-prefix diff --git a/pkg/arvo/tests/lib/naive.hoon b/pkg/arvo/tests/lib/naive.hoon new file mode 100644 index 000000000..aa107df84 --- /dev/null +++ b/pkg/arvo/tests/lib/naive.hoon @@ -0,0 +1,3730 @@ +/+ *test, naive, ethereum, azimuth, *naive-transactions +:: +|% +:: This gate passes a state and input to naive.hoon for both L1 and L2 +:: transactions. Every transaction implemented in this test suite utilizes it. +:: +++ n + |= [=^state:naive input=_+:*^input:naive] + (%*(. naive lac &) verifier 1.337 state 0 input) +:: +++ orm ((on ship point:naive) por:naive) +++ addr address-from-prv:key:ethereum +:: +:: The next section of this core generates "universes" of Azimuth points, each +:: of which is intended for particular test(s). There are more of these +:: than strictly necessary - we utilize different galaxies/etc to perform +:: different kinds of tests, and using different @p's helps to remember +:: what the galaxy was set up to test when reading the tests. +:: +:: ~zod is for testing potential padding issues caused by leading or trailing +:: zeroes. +:: +++ init-zod + |= =^state:naive + ^- [effects:naive ^state:naive] + =^ f1 state (n state (owner-changed:l1 ~zod (addr %zod-key-0))) + =^ f2 state (n state (owner-changed:l1 ~dopzod (addr %dopzod-key-0))) + =^ f3 state (n state (changed-spawn-proxy:l1 ~zod (addr %zod-skey-0))) + =^ f4 state (n state (changed-spawn-proxy:l1 ~zod deposit-address:naive)) + =^ f5 state (n state (owner-changed:l1 ~dopzod deposit-address:naive)) + [:(welp f1 f2 f3 f4 f5) state] +:: +:: ~bud is so that we aren't testing something impossible in Azimuth, like a +:: star spawned before its sponsor galaxy +:: +++ init-bud + |= =^state:naive + ^- [effects:naive ^state:naive] + (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))) +:: +:: ~rut and the accompanying points beneath is for testing nearly every +:: sort of properly-formed L2 transactions unrelated to sponsorship +:: actions, each submitted as a single-transaction batch. In particular +:: it tests %transfer-point, %configure-keys, %spawn, %set-management-proxy +:: %set-spawn-proxy, and %set-transfer-proxy. See +test-rut for more +:: information. +:: +:: ~rut is %l1 galaxy +:: ~tyl is %spawn galxy +:: +:: ~rigrut is %l1 star +:: ~larsyx-mapmeg is %l1 planet under ~rigrut +:: ~holrut is %spawn star +:: ~rabsum-ravtyd is %l1 planet under ~holrut +:: ~dovmul-mogryt is %l2 planet under ~holrut made w/ %own proxy +:: ~pidted-dacnum is %l2 planet under ~holrut made w/ %spawn proxy predeposited +:: +:: ~losrut is %l2 star +:: ~radres-tinnyl is %l1 planet under ~losrut +:: ~pinpun-pilsun is %l2 planet under ~losrut made w/ %own proxy +:: ~habtyc-nibpyx is %l2 planet under ~losrut made w/ %spawn proxy predeposited +:: ~disryt-nolpet is %l2 planet under ~losrut made w/ %spawn proxy postdeposited +:: +++ init-rut-full + |= =^state:naive + ^- [effects:naive ^state:naive] + :: + =/ dm-spawn + [[~holrut %own] %spawn ~dovmul-mogryt (addr %holrut-dm-key-0)] + =/ pd-spawn + [[~holrut %spawn] %spawn ~pidted-dacnum (addr %holrut-pd-key-0)] + :: + =/ pp-spawn + [[~losrut %own] %spawn ~pinpun-pilsun (addr %losrut-pp-key-0)] + =/ hn-spawn + [[~losrut %spawn] %spawn ~habtyc-nibpyx (addr %losrut-hn-key-0)] + =/ dn-spawn + [[~losrut %spawn] %spawn ~disryt-nolpet (addr %losrut-dn-key-0)] + =/ losrut-sproxy + [[~losrut %spawn] %set-spawn-proxy (addr %losrut-skey-1)] + =/ losrut-mproxy + [[~losrut %own] %set-management-proxy (addr %losrut-mkey-0)] + =/ losrut-tproxy + [[~losrut %own] %set-transfer-proxy (addr %losrut-tkey-0)] + :: + =/ dm-xfer + [[~dovmul-mogryt %transfer] %transfer-point (addr %holrut-dm-key-0) &] + =/ dm-tproxy + [[~dovmul-mogryt %own] %set-transfer-proxy (addr %dm-tkey-0)] + =/ dm-mproxy + [[~dovmul-mogryt %own] %set-management-proxy (addr %holrut-dm-mkey-0)] + :: + =/ pd-xfer + [[~pidted-dacnum %transfer] %transfer-point (addr %holrut-pd-key-0) &] + =/ pd-tproxy + [[~pidted-dacnum %own] %set-transfer-proxy (addr %pd-tkey-0)] + =/ pd-mproxy + [[~pidted-dacnum %own] %set-management-proxy (addr %holrut-pd-mkey-0)] + :: + :: + =/ pp-xfer + [[~pinpun-pilsun %transfer] %transfer-point (addr %losrut-pp-key-0) &] + =/ pp-tproxy + [[~pinpun-pilsun %own] %set-transfer-proxy (addr %pp-tkey-0)] + =/ pp-mproxy + [[~pinpun-pilsun %own] %set-management-proxy (addr %losrut-pp-mkey-0)] + :: + =/ hn-xfer + [[~habtyc-nibpyx %transfer] %transfer-point (addr %losrut-hn-key-0) &] + =/ hn-tproxy + [[~habtyc-nibpyx %own] %set-transfer-proxy (addr %hn-tkey-0)] + =/ hn-mproxy + [[~habtyc-nibpyx %own] %set-management-proxy (addr %losrut-hn-mkey-0)] + :: + =/ dn-xfer + [[~disryt-nolpet %transfer] %transfer-point (addr %losrut-dn-key-0) &] + =/ dn-tproxy + [[~disryt-nolpet %own] %set-transfer-proxy (addr %dn-tkey-0)] + =/ dn-mproxy + [[~disryt-nolpet %own] %set-management-proxy (addr %losrut-dn-mkey-0)] + :: + =^ f1 state + (n state (owner-changed:l1 ~rut (addr %rut-key-0))) + =^ f2 state + (n state (owner-changed:l1 ~rigrut (addr %rigrut-key-0))) + =^ f3 state + (n state (owner-changed:l1 ~holrut (addr %holrut-key-0))) + =^ f4 state + (n state (owner-changed:l1 ~losrut (addr %losrut-key-0))) + =^ f5 state + (n state (owner-changed:l1 ~larsyx-mapmeg (addr %rigrut-lm-key-0))) + =^ f6 state + (n state (owner-changed:l1 ~rabsum-ravtyd (addr %holrut-rr-key-0))) + =^ f7 state + (n state (owner-changed:l1 ~radres-tinnyl (addr %losrut-rt-key-0))) + =^ f8 state + (n state (changed-spawn-proxy:l1 ~rut (addr %rut-skey-0))) + =^ f9 state + (n state (changed-spawn-proxy:l1 ~holrut (addr %holrut-skey-0))) + =^ f10 state + (n state (changed-spawn-proxy:l1 ~losrut (addr %losrut-skey-0))) + =^ f11 state + (n state (changed-spawn-proxy:l1 ~holrut deposit-address:naive)) + :: + =^ f12 state + (n state %bat q:(gen-tx 0 dm-spawn %holrut-key-0)) + =^ f13 state + (n state %bat q:(gen-tx 0 pd-spawn %holrut-skey-0)) + =^ f14 state + (n state (owner-changed:l1 ~losrut deposit-address:naive)) + =^ f15 state + (n state %bat q:(gen-tx 0 pp-spawn %losrut-key-0)) + =^ f16 state + (n state %bat q:(gen-tx 0 hn-spawn %losrut-skey-0)) + =^ f17 state + (n state %bat q:(gen-tx 1 losrut-sproxy %losrut-skey-0)) + =^ f18 state + (n state %bat q:(gen-tx 2 dn-spawn %losrut-skey-1)) + =^ f19 state + (n state %bat q:(gen-tx 0 dm-xfer %holrut-dm-key-0)) + =^ f20 state + (n state %bat q:(gen-tx 0 pd-xfer %holrut-pd-key-0)) + =^ f21 state + (n state %bat q:(gen-tx 0 pp-xfer %losrut-pp-key-0)) + =^ f22 state + (n state %bat q:(gen-tx 0 hn-xfer %losrut-hn-key-0)) + =^ f23 state + (n state %bat q:(gen-tx 0 dn-xfer %losrut-dn-key-0)) + :: + =^ p1 state + (n state (changed-management-proxy:l1 ~rut (addr %rut-mkey-0))) + =^ p2 state + (n state (changed-management-proxy:l1 ~rigrut (addr %rigrut-mkey-0))) + =^ p3 state + (n state (changed-management-proxy:l1 ~larsyx-mapmeg (addr %rigrut-lm-mkey-0))) + =^ p4 state + (n state (changed-management-proxy:l1 ~holrut (addr %holrut-mkey-0))) + =^ p5 state + (n state (changed-management-proxy:l1 ~rabsum-ravtyd (addr %holrut-rr-mkey-0))) + =^ p6 state + (n state (changed-management-proxy:l1 ~radres-tinnyl (addr %losrut-rt-mkey-0))) + =^ p7 state + (n state %bat q:(gen-tx 0 dm-mproxy %holrut-dm-key-0)) + =^ p8 state + (n state %bat q:(gen-tx 0 pd-mproxy %holrut-pd-key-0)) + =^ p9 state + (n state %bat q:(gen-tx 0 pp-mproxy %losrut-pp-key-0)) + =^ p10 state + (n state %bat q:(gen-tx 0 hn-mproxy %losrut-hn-key-0)) + =^ p11 state + (n state %bat q:(gen-tx 0 dn-mproxy %losrut-dn-key-0)) + =^ p12 state + (n state %bat q:(gen-tx 1 losrut-mproxy %losrut-key-0)) + =^ p13 state + (n state (changed-transfer-proxy:l1 ~rut (addr %rut-tkey-0))) + =^ p14 state + (n state (changed-transfer-proxy:l1 ~rigrut (addr %rigrut-tkey-0))) + =^ p15 state + (n state (changed-transfer-proxy:l1 ~larsyx-mapmeg (addr %lm-tkey-0))) + =^ p16 state + (n state (changed-transfer-proxy:l1 ~holrut (addr %holrut-tkey-0))) + =^ p17 state + (n state (changed-transfer-proxy:l1 ~rabsum-ravtyd (addr %rr-tkey-0))) + =^ p18 state + (n state (changed-transfer-proxy:l1 ~radres-tinnyl (addr %rt-tkey-0))) + =^ p19 state + (n state %bat q:(gen-tx 2 losrut-tproxy %losrut-key-0)) + =^ p20 state + (n state %bat q:(gen-tx 1 dm-tproxy %holrut-dm-key-0)) + =^ p21 state + (n state %bat q:(gen-tx 1 pd-tproxy %holrut-pd-key-0)) + =^ p22 state + (n state %bat q:(gen-tx 1 pp-tproxy %losrut-pp-key-0)) + =^ p23 state + (n state %bat q:(gen-tx 1 hn-tproxy %losrut-hn-key-0)) + =^ p24 state + (n state %bat q:(gen-tx 1 dn-tproxy %losrut-dn-key-0)) + =^ t1 state + (n state (owner-changed:l1 ~tyl (addr %tyl-key-0))) + =^ t2 state + (n state (changed-spawn-proxy:l1 ~tyl (addr %tyl-skey-0))) + =^ t3 state + (n state (changed-spawn-proxy:l1 ~tyl deposit-address:naive)) + =^ t4 state + (n state (changed-management-proxy:l1 ~tyl (addr %tyl-mkey-0))) + =^ t5 state + (n state (changed-transfer-proxy:l1 ~tyl (addr %tyl-tkey-0))) + :: + :- ;: welp + f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 + f11 f12 f13 f14 f15 f16 f17 f18 + f19 f20 f21 f22 f23 + p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 + p11 p12 p13 p14 p15 p16 p17 p18 + p19 p20 p21 p22 p23 p24 + t1 t2 t3 t4 t5 + == + state +:: +:: +init-red-full adds another galaxy to the ~rut universe, ~red, and additional +:: points used for testing sponsorship actions. +:: +++ init-red-full + |= =^state:naive + ^- [effects:naive ^state:naive] + =/ pp-escape [[~pinpun-pilsun %own] %escape ~losred] + =/ dm-escape [[~dovmul-mogryt %own] %escape ~rigred] + =/ lm-escape [[~larsyx-mapmeg %own] %escape ~losred] + =/ rr-escape [[~rabsum-ravtyd %own] %escape ~rigred] + =^ f1 state (init-rut-full state) + =^ f2 state (n state (owner-changed:l1 ~red (addr %red-key-0))) + =^ f3 state (n state (owner-changed:l1 ~rigred (addr %rigred-key-0))) + =^ f4 state (n state (owner-changed:l1 ~losred (addr %losred-key-0))) + =^ f5 state + (n state (changed-management-proxy:l1 ~rigred (addr %rigred-mkey-0))) + =^ f6 state + (n state (changed-management-proxy:l1 ~losred (addr %losred-mkey-0))) + =^ f7 state (n state (owner-changed:l1 ~losred deposit-address:naive)) + :: each pending escape will be followed by a %adopt, %reject, or + :: %cancel-escape + :: L1->L1 + :: + =^ f8 state (n state %bat q:(gen-tx 0 rr-escape %holrut-rr-key-0)) + :: L2->L2 + :: + =^ f9 state (n state %bat q:(gen-tx 2 pp-escape %losrut-pp-key-0)) + :: L2->L1 + :: + =^ f10 state (n state %bat q:(gen-tx 2 dm-escape %holrut-dm-key-0)) + :: L1->L2 + :: + =^ f11 state (n state %bat q:(gen-tx 0 lm-escape %rigrut-lm-key-0)) + [:(welp f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11) state] +:: +:: ~dopbud is for testing L1 ownership with L2 spawn proxy +:: +++ init-dopbud + |= =^state:naive + ^- [effects:naive ^state:naive] + =^ f1 state (init-bud state) + =^ f2 state (n state (owner-changed:l1 ~dopbud (addr %dopbud-key-0))) + =^ f3 state + (n state (changed-spawn-proxy:l1 ~dopbud deposit-address:naive)) + [:(welp f1 f2 f3) state] +:: +:: ~marbud is for testing L2 ownership +:: +++ init-marbud + |= =^state:naive + ^- [effects:naive ^state:naive] + =^ f1 state (init-bud state) + =^ f2 state (n state (owner-changed:l1 ~marbud (addr %marbud-key-0))) + =^ f3 state (n state (owner-changed:l1 ~marbud deposit-address:naive)) + [:(welp f1 f2 f3) state] +:: +:: ~litbud is for testing L2 sponsorship +:: +++ init-litbud + |= =^state:naive + ^- [effects:naive ^state:naive] + =^ f1 state (n state (owner-changed:l1 ~litbud (addr %litbud-key-0))) + =^ f2 state (n state (owner-changed:l1 ~litbud deposit-address:naive)) + [:(welp f1 f2) state] +:: +:: ~sambud is for testing L1 stars +:: +++ init-sambud + |= =^state:naive + ^- [effects:naive ^state:naive] + =^ f1 state (init-bud state) + =^ f2 state (n state (owner-changed:l1 ~sambud (addr %sambud-key-0))) + [:(welp f1 f2) state] +:: +:: +l2-event-gen is a core used to generate all permutations of +:: [=rank owner=? nonce=? =dominion:naive =proxy:naive =tx-type] +:: as well as whether such an event ought to succeed as a L2 transaction, +:: assuming that arguments are appropriate. The gates in this core are +:: only utilized by +test-rut, but the types are used elsewhere in addition. +:: +:: We note that while +test-rut only tests actions unrelated to sponsorship, +:: +l2-event-gen deals with all L2 transaction types for the sake of potential +:: future needs. +:: +++ l2-event-gen + |% + +$ rank ?(%galaxy %star %planet) + +$ tx-type $? %transfer-point + %spawn + %configure-keys + %escape + %cancel-escape + %adopt + %reject + %detach + %set-management-proxy + %set-spawn-proxy + %set-transfer-proxy + == + +$ event [=rank owner=? nonce=? =dominion:naive =proxy:naive =tx-type] + +$ event-list (list event) + +$ success-map (map event ?) + +$ event-jar (jar @p event) + +$ full-tx [nonce=@ =tx:naive pk=@] + +$ tx-list (list full-tx) + :: + ++ make-success-map + :: +make-success-map maps each $event to a flag denoting whether or not such + :: a L2 transaction ought to succeed or fail, assuming that the arguments for + :: the transaction are appropriate for the transaction (e.g. ~marzod + :: attempting to spawn ~wicdev-wisryt). + :: + :: This is done in a more verbose style than strictly necessary to make it + :: easier to read through and determine why a particular $event maps to %.y + :: or %.n + :: + |= =event-list ^- success-map + =| =success-map + |^ + ?~ event-list success-map + =/ cur-event i.event-list + ?: ?| =(owner.cur-event %.n) :: if owner or nonce are wrong then the + =(nonce.cur-event %.n) :: event fails + == + (add-event-check cur-event %.n) + :: :: we first switch on dominion since + ?- dominion.cur-event :: it cleaves the largest differences + %l1 :: in what is permitted + (add-event-check cur-event (l1-check cur-event)) + :: + %spawn + (add-event-check cur-event (spawnd-check cur-event)) + :: + %l2 + (add-event-check cur-event (l2-check cur-event)) + == + :: + ++ add-event-check + |= [=event suc=?] + %= ^$ + event-list +.event-list + success-map (~(put by success-map) event suc) + == + :: + ++ l1-check :: checks for %l1 dominion + |^ + |= cur-event=event ^- ? + :: Switch on which proxy is attempting the transaction. + :: L1 points are allowed to perform L2 sponsorship actions, which can be + :: performed with either %own or %manage proxies. + :: + ?- proxy.cur-event + %own (manage-own-check cur-event) :: sponsorship tx allowed + %spawn %.n :: cannot do sponsorship tx + %manage (manage-own-check cur-event) :: sponsorship tx allowed + %vote %.n :: cannot do any L2 tx + %transfer %.n :: cannot do sponsorship tx + == + :: + ++ manage-own-check :: %own and %manage are + |^ :: identical in %l1 + |= cur-event=event ^- ? + ?- rank.cur-event :: switch on rank + %galaxy (galaxy-check cur-event) :: each rank has different + %star (star-check cur-event) :: allowed actions + %planet (planet-check cur-event) + == + ++ galaxy-check + |= cur-event=event ^- ? + ?+ tx-type.cur-event %.n :: galaxies do not have sponsors + %adopt %.y :: can adopt on L2 + %reject %.y :: can reject on L2 + %detach %.y :: can detach on L2 + == + ++ star-check + |= cur-event=event ^- ? + ?+ tx-type.cur-event %.n :: may only do L2 sponsorship tx + %adopt %.y :: can %adopt on L2 + %reject %.y :: can %reject on L2 + %detach %.y :: can %detach on L2 + %escape %.y :: can %escape on L2 + %cancel-escape %.y :: can %cancel-escape on L2 + == + ++ planet-check + |= cur-event=event ^- ? + ?+ tx-type.cur-event %.n :: planets do not have sponsees + %escape %.y :: can %escape on L2 + %cancel-escape %.y :: can %cancel-escape on L2 + == + :: + -- :: end +manage-own-check in %l1 + :: + -- :: end +l1-check + :: + ++ spawnd-check :: checks for %spawn dominion + |^ + |= cur-event=event ^- ? + ?- rank.cur-event :: switch on rank + %galaxy (galaxy-check cur-event) :: galaxies can be on %spawn + %star (star-check cur-event) :: stars can be on %spawn + %planet %.n :: planets cannot be on %spawn + == + ++ star-check :: %spawn dominion star check + |^ + |= cur-event=event ^- ? + ?- proxy.cur-event :: switch on proxy + %own (ownp-check cur-event) :: can do sponsorship and spawn + %manage (managep-check cur-event) :: can do sponsorship tx + %spawn (spawnp-check cur-event) :: can do spawn tx + %vote %.n :: stars have no %vote proxy + %transfer %.n :: cannot sponsor/spawn + == + ++ ownp-check + |= cur-event=event ^- ? + ?+ tx-type.cur-event %.n :: only sponsorship/spawn tx + %spawn %.y :: can %spawn on L2 + %adopt %.y :: can %adopt on L2 + %reject %.y :: can %reject on L2 + %detach %.y :: can %detach on L2 + %escape %.y :: can %escape on L2 + %cancel-escape %.y :: can %cancel-escape on L2 + %set-spawn-proxy %.y :: can %set-spawn-proxy on L2 + == + ++ managep-check :: %configure-keys disallowed + |= cur-event=event ^- ? :: for %spawn dominion + ?+ tx-type.cur-event %.n :: only sponsorship actions + %adopt %.y :: can %adopt on L2 + %reject %.y :: can %reject on L2 + %detach %.y :: can %detach on L2 + %escape %.y :: can %escape on L2 + %cancel-escape %.y :: can %cancel-escape on L2 + == + ++ spawnp-check + |= cur-event=event ^- ? + ?+ tx-type.cur-event %.n :: only spawn tx allowed + %spawn %.y :: can %spawn on L2 + %set-spawn-proxy %.y :: can %set-spawn-proxy on L2 + == + -- :: end +star-check in %spawn + :: + ++ galaxy-check :: %spawn dominion galaxy check + |^ + |= cur-event=event ^- ? + ?- proxy.cur-event :: switch on proxy + %own (ownp-check cur-event) :: can do sponsorship and spawn + %manage (managep-check cur-event) :: can do sponsorship tx + %spawn (spawnp-check cur-event) :: can do spawn tx + %vote %.n :: no L2 %vote proxy allowed + %transfer %.n :: cannot sponsor/spawn + == + ++ ownp-check + |= cur-event=event ^- ? + ?+ tx-type.cur-event %.n :: only sponsorship/spawn tx + %spawn %.y :: can %spawn on L2 + %adopt %.y :: can %adopt on L2 + %reject %.y :: can %reject on L2 + %detach %.y :: can %detach on L2 + %set-spawn-proxy %.y :: can %set-spawn-proxy on L2 + == + ++ managep-check :: %configure-keys disallowed + |= cur-event=event ^- ? :: for %spawn dominion + ?+ tx-type.cur-event %.n :: only sponsorship actions + %adopt %.y :: can %adopt on L2 + %reject %.y :: can %reject on L2 + %detach %.y :: can %detach on L2 + == + ++ spawnp-check + |= cur-event=event ^- ? + ?+ tx-type.cur-event %.n :: only spawn tx allowed + %spawn %.y :: can %spawn on L2 + %set-spawn-proxy %.y :: can %set-spawn-proxy on L2 + == + -- :: end +galaxy-check in %spawn + :: + -- :: end +spawnd-check + :: + ++ l2-check :: checks for %l2 dominion + |^ + |= cur-event=event ^- ? + ?- rank.cur-event :: switch on rank + %galaxy %.n :: no %l2 dominion galaxies + %star (star-check cur-event) :: stars can be on %l2 + %planet (planet-check cur-event) :: planets can be on %l2 + == + ++ star-check + |^ + |= cur-event=event ^- ? + ?- proxy.cur-event :: switch on proxy + %own %.y :: all L2 tx allowed + %manage (managep-check cur-event) :: %manage proxy tx allowed + %spawn (spawnp-check cur-event) :: %spawn tx allowed + %vote %.n :: stars have no %vote proxy + %transfer (xferp-check cur-event) :: %transfer proxy tx allowed + == + ++ managep-check + |= cur-event=event ^- ? + ?- tx-type.cur-event :: switch on tx-type + %configure-keys %.y :: permitted tx identical to L1 + %escape %.y :: management proxy permissions + %cancel-escape %.y + %adopt %.y + %reject %.y + %detach %.y + %set-management-proxy %.y + %set-spawn-proxy %.n :: disallowed events given + %set-transfer-proxy %.n :: explicit cases to make it + %transfer-point %.n :: more clear that this is the + %spawn %.n :: same as L1 + == + ++ spawnp-check + |= cur-event=event ^- ? + ?+ tx-type.cur-event %.n :: permitted tx identical to L1 + %spawn %.y :: spawn proxy permissions + %set-spawn-proxy %.y + == + ++ xferp-check + |= cur-event=event ^- ? :: permitted tx identical to L1 + ?+ tx-type.cur-event %.n :: transfer proxy permissions + %transfer-point %.y + %set-transfer-proxy %.y + == + -- :: end +star-check in %l2 + ++ planet-check :: checks for %l2 planets + |^ + |= cur-event=event ^- ? + ?- proxy.cur-event :: switch on proxy + %own (ownp-check cur-event) :: permitted tx identical to L1 + %manage (managep-check cur-event) :: permitted tx identical to L1 + %spawn %.n :: planets have no %spawn proxy + %vote %.n :: planets have no %vote proxy + %transfer (xferp-check cur-event) :: permitted tx identical to L1 + == + ++ ownp-check + |= cur-event=event ^- ? + ?- tx-type.cur-event :: permitted tx identical to L1 + %transfer-point %.y :: ownership proxy permissions + %configure-keys %.y + %set-management-proxy %.y + %set-transfer-proxy %.y + %escape %.y + %cancel-escape %.y + %spawn %.n + %adopt %.n + %reject %.n + %detach %.n + %set-spawn-proxy %.n + == + ++ managep-check + |= cur-event=event ^- ? + ?+ tx-type.cur-event %.n :: permitted tx identical to L1 + %configure-keys %.y :: management proxy permissions + %escape %.y + %cancel-escape %.y + %set-management-proxy %.y + == + ++ xferp-check + |= cur-event=event ^- ? :: permitted tx identica to L1 + ?+ tx-type.cur-event %.n :: transfer proxy permissions + %transfer-point %.y + %set-transfer-proxy %.y + == + :: + -- :: end %l2 +planet-check + :: + -- :: end +l2-check + :: + -- :: end +make-success-map + :: + :: creates a list of all values of $event for use by +test-rut + :: + ++ make-event-list ^- event-list + =| =event-list + =+ rank-i=1 + |^ + ?: (gth rank-i 3) + (remove-wrong-dominion event-list) + =+ owner-i=0 + |- + ?. (lte owner-i 1) + ^$(rank-i +(rank-i)) + =+ nonce-i=0 + |- + ?. (lte nonce-i 1) + ^$(owner-i +(owner-i)) + =+ dominion-i=1 + |- + ?. (lte dominion-i 3) + ^$(nonce-i +(nonce-i)) + =+ proxy-i=1 + |- + ?. (lte proxy-i 5) + ^$(dominion-i +(dominion-i)) + =+ tx-type-i=1 + |- + ?. (lte tx-type-i 11) + ^$(proxy-i +(proxy-i)) + %= $ + tx-type-i +(tx-type-i) + event-list :- :* (num-to-rank rank-i) + (num-to-flag owner-i) + (num-to-flag nonce-i) + (num-to-dominion dominion-i) + (num-to-proxy proxy-i) + (num-to-tx-type tx-type-i) + == + event-list + == + :: + ++ num-to-flag + |= val=@ud ^- ? + ?+ val !! + %0 %.y + %1 %.n + == + :: + ++ num-to-rank + |= val=@ud ^- rank + ?+ val !! + %1 %galaxy + %2 %star + %3 %planet + == + :: + ++ num-to-dominion + |= val=@ud ^- dominion:naive + ?+ val !! + %1 %l1 + %2 %l2 + %3 %spawn + == + :: + ++ num-to-proxy + |= val=@ud ^- proxy:naive + ?+ val !! + %1 %own + %2 %spawn + %3 %manage + %4 %vote + %5 %transfer + == + :: + ++ num-to-tx-type + |= val=@ud ^- tx-type + ?+ val !! + %1 %transfer-point + %2 %spawn + %3 %configure-keys + %4 %escape + %5 %cancel-escape + %6 %adopt + %7 %reject + %8 %detach + %9 %set-management-proxy + %10 %set-spawn-proxy + %11 %set-transfer-proxy + == + :: + -- :: end +make-event-list + :: + :: used to remove values of +make-event-list that have planets in the %spawn + :: dominion or galaxies in the %l2 dominion + :: + :: TODO: Why does this not work when I put it inside the above trap? + :: + ++ remove-wrong-dominion + |= in=event-list ^- event-list + =| out=event-list + |- + ?~ in out + ?: ?& =(rank.i.in %galaxy) + =(dominion.i.in %l2) + == + $(in t.in) + ?: ?& =(rank.i.in %planet) + =(dominion.i.in %spawn) + == + $(in t.in) + %= $ + in t.in + out i.in^out + == + :: + :: jar of events for +test-rut. each @p is mapped to a list of events + :: it ought to attempt. This is done according to rank. + :: + :: This gate may be modified to filter out a subset of events you wish to + :: test by commenting out or modifying parts of the filter gate. Remember that + :: +test-rut is only designed to test %spawn, %transfer-point, + :: %configure-keys, %set-management-proxy, %set-spawn-proxy, and + :: %set-transfer-proxy. Adding in other transaction types will result in a + :: crash. + :: + ++ gen-rut-jar + ^~ ^- (jar @p event) + =/ filter ;: cork + (cury filter-owner %.y) + ::(cury filter-proxy %spawn) + (cury filter-nonce %.y) + ::(cury filter-rank %galaxy) + ::(cury filter-dominion %l1) + %- cury + :- filter-tx-type + :* ::%spawn + ::%transfer-point + %configure-keys + ::%set-management-proxy + ::%set-spawn-proxy + ::%set-transfer-proxy + ~ + == + == + =/ filtered-events (filter make-event-list) + =| rut-jar=(jar @p event) + |^ + ?~ filtered-events rut-jar + =/ current-event i.filtered-events + ?: =(rank.current-event %galaxy) + ?+ dominion.current-event !! + %l1 (list-in-jar (ly ~[~rut]) current-event) + %spawn (list-in-jar (ly ~[~tyl]) current-event) + == + ?: =(rank.current-event %star) + ?- dominion.current-event + %l1 (list-in-jar (ly ~[~rigrut]) current-event) + %spawn (list-in-jar (ly ~[~holrut]) current-event) + %l2 (list-in-jar (ly ~[~losrut]) current-event) + == + ?: =(rank.current-event %planet) + ?+ dominion.current-event !! + %l1 %- list-in-jar + :- %- ly + :* ~larsyx-mapmeg + ~rabsum-ravtyd + ~radres-tinnyl + ~ + == + current-event + %l2 %- list-in-jar + :- %- ly + :* ~dovmul-mogryt + ~pidted-dacnum + ~pinpun-pilsun + ~habtyc-nibpyx + ~disryt-nolpet + ~ + == + current-event + == + $(filtered-events t.filtered-events) + :: adds event to the list associated to each value of ships in rut-jar + :: + ++ list-in-jar + |= [ships=(list ship) =event] + ^+ rut-jar + |- + ?~ ships + ^^$(filtered-events +.filtered-events) + =. rut-jar (~(add ja rut-jar) i.ships event) + $(ships t.ships) + -- :: end +gen-rut-jar + :: + ++ filter-tx-type + |= [typs=(list =tx-type) =event-list] + %+ skim + event-list + |=(=event (lien typs |=(=tx-type =(tx-type tx-type.event)))) + :: + ++ filter-proxy + |= [=proxy:naive =event-list] + (skim event-list |=(=event =(proxy.event proxy))) + :: + ++ filter-rank + |= [=rank =event-list] + (skim event-list |=(=event =(rank.event rank))) + :: + ++ filter-owner + |= [owner=? =event-list] + (skim event-list |=(=event =(owner.event owner))) + :: + ++ filter-nonce + |= [nonce=? =event-list] + (skim event-list |=(=event =(nonce.event nonce))) + :: + ++ filter-dominion + |= [=dominion:naive =event-list] + (skim event-list |=(=event =(dominion.event dominion))) + :: + :: Takes in a list of full-tx and turns them into a batch=@ to be submitted to + :: +n. The ordering on the list is the order in which the transactions are + :: processed. + :: + ++ tx-list-to-batch + |= =tx-list ^- @ + (can 3 (turn tx-list gen-tx)) + :: + -- :: end +l2-event-gen +:: +:: This core generates L1 transaction logs. It is important to keep in mind +:: that Azimuth already handles the logic on what is or is not allowed on L1, +:: so if you tell naive.hoon that ~zod adopted ~hodler without ~hodler having +:: escaped to ~zod first, ~zod will be the new sponsor of ~hodler anyways. In +:: the real world, such an action would have been blocked by the smart contract +:: and never made its way to naive.hoon. +:: +++ l1 + |% + :: This gate takes in raw information for L1 transactions and formats them + :: appropriately for use with +n. + :: + ++ log + |= [log-name=@ux data=@ux topics=(list @)] + [%log *@ux data log-name topics] + :: + ++ owner-changed + |= [=ship =address] + (log owner-changed:log-names:naive *@ux ship address ~) + :: + ++ escape-requested + |= [escapee=ship parent=ship] + (log escape-requested:log-names:naive *@ux escapee parent ~) + :: + ++ escape-canceled + :: The parent is pinned but not used in lib/naive.hoon for some reason + |= [escapee=ship parent=ship] + (log escape-canceled:log-names:naive *@ux escapee parent ~) + :: + ++ escape-accepted + |= [escapee=ship parent=ship] + (log escape-accepted:log-names:naive *@ux escapee parent ~) + :: + ++ lost-sponsor + |= [lost=ship parent=ship] + (log lost-sponsor:log-names:naive *@ux lost parent ~) + :: + ++ changed-keys + |= [=ship suite=@ encr=@ auth=@ life=@] + =/ keys=@ux + %: can 8 + 1^life + 1^suite + 1^auth + 1^encr + ~ + == + (log changed-keys:log-names:naive keys ship ~) + :: + ++ broke-continuity + |= [=ship rift=@] + (log broke-continuity:log-names:naive rift ship ~) + :: + ++ changed-spawn-proxy + |= [=ship =address] + (log changed-spawn-proxy:log-names:naive *@ux ship address ~) + :: + ++ changed-transfer-proxy + |= [=ship =address] + (log changed-transfer-proxy:log-names:naive *@ux ship address ~) + :: + ++ changed-management-proxy + |= [=ship =address] + (log changed-management-proxy:log-names:naive *@ux ship address ~) + :: + ++ changed-voting-proxy + |= [=ship =address] + (log changed-voting-proxy:log-names:naive *@ux ship address ~) + :: + ++ changed-dns + |= [data=@] + (log changed-dns:log-names:naive data ~) + :: + ++ approval-for-all + |= [owner=address operator=address approved=@] + (log approval-for-all:log-names:naive approved owner operator ~) + :: + -- :: end +l1 +:: +-- +:: +:: 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 %own] ::key %marbud-key-0 +++ marbud-spn [~marbud %spawn] :: key %marbud-skey +++ marbud-mgt [~marbud %manage] :: key %marbud-mkey +++ marbud-xfr [~marbud %transfer] :: key %marbud-key-1 +:: +++ dopbud-own [~dopbud %own] :: key %dopbud-key-0 +:: +++ litbud-own [~litbud %own] :: key %litbud-key-0 +:: +++ lt-own [~linnup-torsyx %own] :: key %lt-key-0 +++ lt-xfr [~linnup-torsyx %transfer] :: key %lt-key-0 +:: +:: rut tests +:: +++ common-mgmt %mgmt-key-0 +++ common-spwn %spwn-key-0 +++ common-vote %vote-key-0 +++ common-ownr %ownr-key-0 +++ common-tran %tran-key-0 +++ rut-ship-list %- ly + :* ~rut + ~tyl + ~holrut + ~rigrut + ~losrut + ~larsyx-mapmeg + ~rabsum-ravtyd + ~disryt-nolpet + ~pinpun-pilsun + ~dovmul-mogryt + ~habtyc-nibpyx + ~pidted-dacnum + ~radres-tinnyl + ~ + == +:: +:: initial keys for each point under ~rut +:: +++ default-own-keys %- my:nl + :* [~rut %rut-key-0] + [~tyl %tyl-key-0] + [~holrut %holrut-key-0] + [~rigrut %rigrut-key-0] + [~losrut %losrut-key-0] + [~larsyx-mapmeg %rigrut-lm-key-0] + [~rabsum-ravtyd %holrut-rr-key-0] + [~disryt-nolpet %losrut-dn-key-0] + [~pinpun-pilsun %losrut-pp-key-0] + [~dovmul-mogryt %holrut-dm-key-0] + [~habtyc-nibpyx %losrut-hn-key-0] + [~pidted-dacnum %holrut-pd-key-0] + [~radres-tinnyl %losrut-rt-key-0] + ~ + == +:: +++ default-manage-keys %- my:nl + :* [~rut %rut-mkey-0] + [~tyl %tyl-mkey-0] + [~holrut %holrut-mkey-0] + [~rigrut %rigrut-mkey-0] + [~losrut %losrut-mkey-0] + [~larsyx-mapmeg %rigrut-lm-mkey-0] + [~rabsum-ravtyd %holrut-rr-mkey-0] + [~disryt-nolpet %losrut-dn-mkey-0] + [~pinpun-pilsun %losrut-pp-mkey-0] + [~dovmul-mogryt %holrut-dm-mkey-0] + [~habtyc-nibpyx %losrut-hn-mkey-0] + [~pidted-dacnum %holrut-pd-mkey-0] + [~radres-tinnyl %losrut-rt-mkey-0] + ~ + == +++ default-spawn-keys %- my:nl + :* [~rut %rut-skey-0] + [~tyl %tyl-skey-0] + [~holrut %holrut-skey-0] + [~losrut %losrut-skey-1] + [~rigrut %rigrut-skey-0] + ~ + == +:: +++ default-xfer-keys %- my:nl + :* [~rut %rut-tkey-0] + [~tyl %tyl-tkey-0] + [~rigrut %rigrut-tkey-0] + [~larsyx-mapmeg %lm-tkey-0] + [~holrut %holrut-tkey-0] + [~rabsum-ravtyd %rr-tkey-0] + [~radres-tinnyl %rt-tkey-0] + [~losrut %losrut-tkey-0] + [~dovmul-mogryt %dm-tkey-0] + [~pinpun-pilsun %pp-tkey-0] + [~pidted-dacnum %pd-tkey-0] + [~habtyc-nibpyx %hn-tkey-0] + [~disryt-nolpet %dn-tkey-0] + ~ + == +:: +:: sponsorship tests +++ losrut-own [~losrut %own] +++ losrut-mgmt [~losrut %manage] +++ holrut-own [~holrut %own] +++ holrut-mgmt [~holrut %manage] +++ rigrut-own [~rigrut %own] +++ rigrut-mgmt [~rigrut %manage] +++ losred-own [~losred %own] +++ losred-mgmt [~losred %manage] +++ rigred-own [~rigred %own] +++ rigred-mgmt [~rigred %manage] +:: +-- +=/ init-rut-simple (init-rut-full *^state:naive) +=/ init-red-simple (init-red-full *^state:naive) +:: +:: Tests +:: +|% +:: This test spawns a "full galaxy" containing all varieties of points. It then +:: saves this initial state, and runs single transaction batches for all +:: possible L2 "event types". It compares the entire new state to the entire +:: initial state and checks for the expected state change. It then resets the +:: state to the initial state and tries the next event on the list. +:: +:: More specifically, there is a $jar called event-jar that maps ships to +:: lists of events it should try. It then picks off a ship, tries all the events +:: in the list associated to it as described above, and then moves on to the +:: next ship, until it has exhausted all values in the lists in the jar. +:: +:: This arm does not test any L1 transactions beyond the ones needed to spawn +:: the galaxy (+init-rut). +:: +++ test-rut ^- tang + =, l2-event-gen + :: Initialize the PKI state, the list of ships to iterate through, and the + :: map from $event to ? + :: + =| initial-state=^state:naive + =^ f initial-state init-rut-simple + =/ ship-list rut-ship-list + =/ suc-map (make-success-map make-event-list) + :: Iterate through ships and get the list of events to try with that ship. + :: + |- ^- tang + ?~ ship-list ~ + %+ weld $(ship-list t.ship-list) + =* cur-ship i.ship-list + %+ category (scow %p cur-ship) + =/ cur-events (~(get ja gen-rut-jar) cur-ship) + :: Iterate through events and try to perform each one with cur-ship using + :: supplied default arguments. + :: + |^ ^- tang + ?~ cur-events ~ + %+ weld $(cur-events t.cur-events) + :: + =* cur-event i.cur-events + %+ category (weld "dominion " (scow %tas dominion.cur-event)) + %+ category (weld "proxy " (scow %tas proxy.cur-event)) + %+ category (weld "tx-type " (scow %tas tx-type.cur-event)) + %+ category (weld "owner? " (scow %f owner.cur-event)) + %+ category (weld "correct nonce? " (scow %f nonce.cur-event)) + %+ category (weld "success map " (scow %f (~(got by suc-map) cur-event))) + :: + =/ cur-point (got:orm points.initial-state cur-ship) + =* own own.cur-point + =/ cur-nonce + ?- proxy.cur-event + %own nonce.owner.own + %spawn nonce.spawn-proxy.own + %manage nonce.management-proxy.own + %vote nonce.voting-proxy.own + %transfer nonce.transfer-proxy.own + == + =/ new-nonce %^ calculate-nonce + cur-event + cur-nonce + address.transfer-proxy.own + =/ expect-state initial-state + :: + |^ :: begin expected state trap + %+ expect-eq + :: expected state + :: + !> + |^ ^- ^state:naive + ?. (~(got by suc-map) cur-event) + %- alter-state + ?- proxy.cur-event + %own cur-point(nonce.owner.own new-nonce) + %spawn cur-point(nonce.spawn-proxy.own new-nonce) + %manage cur-point(nonce.management-proxy.own new-nonce) + %vote cur-point(nonce.voting-proxy.own new-nonce) + %transfer cur-point(nonce.transfer-proxy.own new-nonce) + == + ?+ tx-type.cur-event !! + %transfer-point set-xfer + %configure-keys set-keys + %set-management-proxy set-mgmt-proxy + %set-spawn-proxy set-spwn-proxy + %set-transfer-proxy set-xfer-proxy + %spawn (new-point which-spawn) + == + :: + ++ set-keys ^- ^state:naive + =/ new-keys + %= cur-point + suite.keys.net + suit + :: + auth.keys.net + auth + :: + crypt.keys.net + encr + :: + life.keys.net + +(life.keys.net:(got:orm points.initial-state cur-ship)) + == + (alter-state new-keys) + :: + ++ set-xfer ^- ^state:naive + =/ new-xfer + %= cur-point + address.owner.own (addr %transfer-test) + address.transfer-proxy.own 0x0 + == + (alter-state new-xfer) + :: + ++ set-mgmt-proxy ^- ^state:naive + =/ new-mgmt + %= cur-point + address.management-proxy.own (addr %proxy-test) + == + (alter-state new-mgmt) + :: + ++ set-spwn-proxy ^- ^state:naive + =/ new-spwn + %= cur-point + address.spawn-proxy.own (addr %proxy-test) + == + (alter-state new-spwn) + :: + ++ set-xfer-proxy ^- ^state:naive + =/ new-xfer + %= cur-point + address.transfer-proxy.own (addr %proxy-test) + == + (alter-state new-xfer) + :: + ++ new-point + |= =ship ^- ^state:naive + =| new-point=point:naive + =/ spawned + %= new-point + dominion + %l2 + :: + sponsor.net + [has=%.y who=cur-ship] + :: + address.transfer-proxy.own + (addr %spawn-test) + :: + address.owner.own + (addr (~(got by default-own-keys) cur-ship)) + == + :: The following updates the nonce of the spawner + :: + =/ expect-state (alter-state cur-point) + %= expect-state + points (put:orm points.expect-state ship spawned) + == + :: + ++ alter-state + :: this updates the expect-state with the new point, and takes + :: care of incrementing the nonce as well. + :: + |= alt-point=point:naive ^- ^state:naive + =/ updated-point=point:naive + ?- proxy.cur-event + %own alt-point(nonce.owner.own new-nonce) + %spawn alt-point(nonce.spawn-proxy.own new-nonce) + %manage alt-point(nonce.management-proxy.own new-nonce) + %vote alt-point(nonce.voting-proxy.own new-nonce) + %transfer alt-point(nonce.transfer-proxy.own new-nonce) + == + %= expect-state + points (put:orm points.expect-state cur-ship updated-point) + == + :: + -- :: end of expected state trap + :: + :: actual state + :: + !> + |^ ^- ^state:naive :: begin actual state trap + =| state=^state:naive + :: The following is basically just tall form exploded view of a + :: parameterization of the same =^ call used to modify the PKI state + :: used everywhere else in the test suite. + :: + =^ f + state + %- n + :+ initial-state + %bat + =< q + %- gen-tx + :+ ?: nonce.cur-event + cur-nonce + 999 :: wrong nonce + :- :- cur-ship + proxy.cur-event + def-args + ?: owner.cur-event + ?+ proxy.cur-event + %wrong-key + :: + %own + (~(got by default-own-keys) cur-ship) + :: + %manage + (~(got by default-manage-keys) cur-ship) + :: + %transfer + (~(got by default-xfer-keys) cur-ship) + :: + %spawn + ?: ?| =(rank.cur-event %galaxy) + =(rank.cur-event %star) + == + (~(got by default-spawn-keys) cur-ship) + %wrong-key + == + %wrong-key :: if not owner then use wrong key + state + :: + ++ def-args + ^- skim-tx:naive + |^ + ?+ tx-type.cur-event !! + %spawn [%spawn which-spawn (addr %spawn-test)] + %transfer-point [%transfer-point (addr %transfer-test) |] + %configure-keys [%configure-keys encr auth suit |] + %set-management-proxy [%set-management-proxy (addr %proxy-test)] + %set-spawn-proxy [%set-spawn-proxy (addr %proxy-test)] + %set-transfer-proxy [%set-transfer-proxy (addr %proxy-test)] + == + :: + -- :: +def-args + :: + -- :: end of actual state trap + :: + ++ which-spawn ^- ship + ?+ cur-ship !! + %~rut ~hasrut + %~tyl ~hastyl + %~rigrut ~batbec-tapmep + %~larsyx-mapmeg ~nocryl-tobned + %~holrut ~namtuc-ritnux + %~rabsum-ravtyd ~docsec-wanlug + %~dovmul-mogryt ~docsec-wanlug + %~pidted-dacnum ~docsec-wanlug + %~losrut ~mishus-loplus + %~radres-tinnyl ~tapfur-fitsep + %~pinpun-pilsun ~tapfur-fitsep + %~habtyc-nibpyx ~tapfur-fitsep + %~disryt-nolpet ~tapfur-fitsep + == + :: + -- :: end of +expect-eq trap + :: + ++ calculate-nonce + |= [cur-event=event cur-nonce=@ xfer-address=@ux] + ?: &(nonce.cur-event owner.cur-event) + ?- proxy.cur-event + ?(%own %manage) + +(cur-nonce) + :: + %spawn + ?- rank.cur-event + %galaxy ?- dominion.cur-event + ?(%l1 %spawn) +(cur-nonce) + %l2 cur-nonce + == + %star ?- dominion.cur-event + %l1 cur-nonce + ?(%spawn %l2) +(cur-nonce) + == + %planet cur-nonce + == + :: end %spawn case + %transfer + ?~ xfer-address + cur-nonce + +(cur-nonce) + :: + %vote + cur-nonce + == + cur-nonce + :: + -- :: end of test trap +:: +:: The following are sponsorship tests. They probably ought to be consolidated +:: into one large test. +:: +:: Each arm is named according to the scheme is test-galaxy-X-Y-action-L-N. +:: X is the layer of the sponsee, Y is the layer of the sponsor, L is the +:: layer of the action, and N (which does not appear for all tests) is an +:: index denoting which test of the (X,Y,L) tuple it is (according to which +:: order it appears in the table), as some of these have multiple setups +:: necessary to test the action. +:: +:: Each row of the following table has one or more tests that cover it. +:: Above each test is a comment with the row that that test is testing. +:: Thus you can grep for the line and find the appropriate test. A few of +:: the tests cannot be performed here - there are the ones marked by !! +:: but we include what the tests would look like anyways as a comment. +:: These are ones involving L1 actions where Azimuth would prevent the +:: situation from ever occurring. naive.hoon does not make these checks, +:: and so the corresponding tests would fail. For example, you could submit +:: a layer 1 adopt action of a star on any planet regardless of whether it +:: has escaped to that star, and naive.hoon will allow the adoption to work. +:: Such an action would be prevented by Azimuth before it ever got to +:: naive.hoon, so if naive.hoon does receive such a log then it presumes +:: it to be correct. This is also why there are no tests where L2 ships +:: attempt to perform L1 actions. naive.hoon ignores these actions so +:: they're no-ops, but Azimuth also wouldn't allow them in the first place +:: since as far as Azimuth is concerned, all L2 ships belong to the deposit +:: address, so the L1 action would be signed with the wrong key anyways. +:: +:: * on the left means all possible states, on the right it means no change. +:: !! means that case can never happen per L1 contract. +:: L1-cancel can be triggered by "cancel escape" by the child or "reject +:: by the sponsor. +:: A1 and A2 are arbitrary but distinct ships one class above the main ship +:: Event | E_1 | E_2 | S_1 | S_2 | -> | E_1 | E_2 | S_1 | S_2 +:: L1-escape A1 | * | * | * | * | -> | A1 | A1 | * | * +:: L1-cancel A1 | ~ | * | * | * | -> !! :: no cancel if not escaping +:: L1-cancel A1 | A1 | * | * | * | -> | ~ | ~ | * | * +:: L1-adopt A1 | A1 | * | * | * | -> | ~ | ~ | A1 | A2 +:: L1-adopt A1 | ~ | * | * | * | -> !! :: no adopt if not escaping +:: L1-adopt A1 | A2 | * | * | * | -> !! :: no adopt if not escaping +:: L1-detach A1 | * | * | A1 | A1 | -> | * | * | ~ | ~ +:: L1-detach A1 | * | * | A1 | A2 | -> | * | * | ~ | A2 +:: L1-detach A1 | * | * | A1 | ~ | -> | * | * | ~ | ~ +:: L2-escape A1 | * | * | * | * | -> | * | A1 | * | * +:: L2-cancel A1 | * | * | * | * | -> | * | ~ | * | * +:: L2-adopt A1 | * | A1 | * | * | -> | * | ~ | * | A1 +:: L2-adopt A1 | * | A2 | * | * | -> | * | A2 | * | * +:: L2-adopt A1 | * | ~ | * | * | -> | * | ~ | * | * +:: L2-reject A1 | * | A1 | * | * | -> | * | ~ | * | * +:: L2-reject A1 | * | A2 | * | * | -> | * | A2 | * | * +:: L2-reject A1 | * | ~ | * | * | -> | * | ~ | * | * +:: L2-detach A1 | * | * | * | A1 | -> | * | * | * | ~ +:: L2-detach A1 | * | * | * | A2 | -> | * | * | * | A2 +:: L2-detach A1 | * | * | * | ~ | -> | * | * | * | ~ +:: +++ test-rut-l1-l1-escape-l1 ^- tang +:: L1-escape A1 | * | * | * | * | -> | A1 | A1 | * | * + %+ expect-eq + !> [[~ ~rigred] %.y ~holrut] + :: + !> + =| =^state:naive + =^ f state init-rut-simple + =^ f state (n state (escape-requested:l1 ~rabsum-ravtyd ~rigred)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) +:: +++ test-rut-l1-l2-escape-l1 ^- tang + :: L1-escape A1 | * | * | * | * | -> | A1 | A1 | * | * + %+ expect-eq + !> [[~ ~losred] %.y ~rigrut] + :: + !> + =| =^state:naive + =^ f state init-rut-simple + =^ f state (n state (escape-requested:l1 ~larsyx-mapmeg ~losred)) + [escape.net sponsor.net]:(got:orm points.state ~larsyx-mapmeg) +:: +++ test-red-l2-l2-adopt-l2-1 ^- tang + :: L2-adopt A1 | * | A1 | * | * | -> | * | ~ | * | A1 + =/ pp-adopt [losred-own %adopt ~pinpun-pilsun] + =/ pp-m-adopt [losred-mgmt %adopt ~pinpun-pilsun] + :: + ;: weld + %+ expect-eq + !> [~ %.y ~losred] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 0 pp-adopt %losred-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~pinpun-pilsun) + :: + %+ expect-eq + !> [~ %.y ~losred] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 0 pp-m-adopt %losred-mkey-0)) + [escape.net sponsor.net]:(got:orm points.state ~pinpun-pilsun) + == +:: +++ test-red-l1-l2-adopt-l2-1 + :: L2-adopt A1 | * | A1 | * | * | -> | * | ~ | * | A1 + =/ lm-adopt [losred-own %adopt ~larsyx-mapmeg] + =/ lm-m-adopt [losred-mgmt %adopt ~larsyx-mapmeg] + :: + ;: weld + %+ expect-eq + !> [~ %.y ~losred] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 0 lm-adopt %losred-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~larsyx-mapmeg) + :: + %+ expect-eq + !> [~ %.y ~losred] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 0 lm-m-adopt %losred-mkey-0)) + [escape.net sponsor.net]:(got:orm points.state ~larsyx-mapmeg) + == +:: +++ test-red-l2-l1-adopt-l2-1 + :: L2-adopt A1 | * | A1 | * | * | -> | * | ~ | * | A1 + =/ dm-adopt [rigred-own %adopt ~dovmul-mogryt] + =/ dm-m-adopt [rigred-mgmt %adopt ~dovmul-mogryt] + :: + ;: weld + %+ expect-eq + !> [~ %.y ~rigred] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 0 dm-adopt %rigred-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~dovmul-mogryt) + :: + %+ expect-eq + !> [~ %.y ~rigred] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 0 dm-m-adopt %rigred-mkey-0)) + [escape.net sponsor.net]:(got:orm points.state ~dovmul-mogryt) + == +:: +++ test-red-l1-l1-adopt-l2-1 + :: L2-adopt A1 | * | A1 | * | * | -> | * | ~ | * | A1 + =/ rr-adopt [rigred-own %adopt ~rabsum-ravtyd] + =/ rr-m-adopt [rigred-mgmt %adopt ~rabsum-ravtyd] + :: + ;: weld + %+ expect-eq + !> [~ %.y ~rigred] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 0 rr-adopt %rigred-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) + :: + %+ expect-eq + !> [~ %.y ~rigred] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 0 rr-m-adopt %rigred-mkey-0)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) + == +:: +++ test-red-l1-l1-adopt-l2-2 + :: L2-adopt A1 | * | A2 | * | * | -> | * | A2 | * | * + =/ rr-adopt [losred-own %adopt ~rabsum-ravtyd] + =/ rr-m-adopt [losred-mgmt %adopt ~rabsum-ravtyd] + :: + ;: weld + %+ expect-eq + !> [[~ ~rigred] %.y ~holrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 0 rr-adopt %losred-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) + :: + %+ expect-eq + !> [[~ ~rigred] %.y ~holrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 0 rr-m-adopt %losred-mkey-0)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) + == +:: +++ test-rut-l1-l1-adopt-l2-3 ^- tang + :: L2-adopt A1 | * | ~ | * | * | -> | * | ~ | * | * + :: + =/ rr-h-detach [1 [holrut-own %detach ~rabsum-ravtyd] %holrut-key-0] + =/ rr-h-m-detach [0 [holrut-mgmt %detach ~rabsum-ravtyd] %holrut-mkey-0] + =/ rr-adopt [0 [losred-own %adopt ~rabsum-ravtyd] %losred-key-0] + =/ rr-m-adopt [0 [losred-mgmt %adopt ~rabsum-ravtyd] %losred-mkey-0] + :: + =, l2-event-gen + =/ rr-batch-1=tx-list (limo ~[rr-h-detach rr-adopt]) + =/ rr-batch-2=tx-list (limo ~[rr-h-m-detach rr-m-adopt]) + :: + =/ init-state=^state:naive +:init-rut-simple + ;: weld + %+ expect-eq + !> [~ %.n ~holrut] + :: + !> + =| =^state:naive + =^ f state (n init-state %bat q:(gen-tx rr-h-detach)) + =^ f state (n state %bat q:(gen-tx rr-adopt)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) + :: + %+ expect-eq + !> [~ %.n ~holrut] + + !> + =| =^state:naive + =^ f state (n init-state %bat (tx-list-to-batch rr-batch-1)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) + :: + %+ expect-eq + !> [~ %.n ~holrut] + :: + !> + =| =^state:naive + =^ f state (n init-state %bat q:(gen-tx rr-h-m-detach)) + =^ f state (n state %bat q:(gen-tx rr-m-adopt)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) + :: + %+ expect-eq + !> [~ %.n ~holrut] + :: + !> + =| =^state:naive + =^ f state (n init-state %bat (tx-list-to-batch rr-batch-2)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) + == +:: +:: the following tests L2 %rejects +++ test-red-l2-l2-reject-l2-1 ^- tang + :: L2-reject A1 | * | A1 | * | * | -> | * | ~ | * | * + =/ pp-reject [losred-own %reject ~pinpun-pilsun] + =/ pp-m-reject [losred-mgmt %reject ~pinpun-pilsun] + :: + ;: weld + %+ expect-eq + !> [~ %.y ~losrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 0 pp-reject %losred-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~pinpun-pilsun) + :: + %+ expect-eq + !> [~ %.y ~losrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 0 pp-m-reject %losred-mkey-0)) + [escape.net sponsor.net]:(got:orm points.state ~pinpun-pilsun) + == +:: +++ test-red-l2-l1-reject-l2-1 ^- tang + :: L2-reject A1 | * | A1 | * | * | -> | * | ~ | * | * + =/ dm-reject [rigred-own %reject ~dovmul-mogryt] + =/ dm-m-reject [rigred-mgmt %reject ~dovmul-mogryt] + :: + ;: weld + %+ expect-eq + !> [~ %.y ~holrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 0 dm-reject %rigred-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~dovmul-mogryt) + :: + %+ expect-eq + !> [~ %.y ~holrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 0 dm-m-reject %rigred-mkey-0)) + [escape.net sponsor.net]:(got:orm points.state ~dovmul-mogryt) + == +:: +++ test-red-l1-l2-reject-l2-1 ^- tang + :: L2-reject A1 | * | A1 | * | * | -> | * | ~ | * | * + =/ lm-reject [losred-own %reject ~larsyx-mapmeg] + =/ lm-m-reject [losred-mgmt %reject ~larsyx-mapmeg] + :: + ;: weld + %+ expect-eq + !> [~ %.y ~rigrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 0 lm-reject %losred-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~larsyx-mapmeg) + :: + %+ expect-eq + !> [~ %.y ~rigrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 0 lm-m-reject %losred-mkey-0)) + [escape.net sponsor.net]:(got:orm points.state ~larsyx-mapmeg) + == +:: +++ test-red-l1-l1-reject-l2-1 ^- tang + :: L2-reject A1 | * | A1 | * | * | -> | * | ~ | * | * + =/ rr-reject [rigred-own %reject ~rabsum-ravtyd] + =/ rr-m-reject [rigred-mgmt %reject ~rabsum-ravtyd] + :: + ;: weld + %+ expect-eq + !> [~ %.y ~holrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 0 rr-reject %rigred-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) + :: + %+ expect-eq + !> [~ %.y ~holrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 0 rr-m-reject %rigred-mkey-0)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) + == +++ test-red-l2-l2-reject-l2-2 ^- tang + :: L2-reject A1 | * | A2 | * | * | -> | * | A2 | * | * + =/ pp-reject [losrut-own %reject ~pinpun-pilsun] + =/ pp-m-reject [losrut-mgmt %reject ~pinpun-pilsun] + :: + ;: weld + %+ expect-eq + !> [[~ ~losred] %.y ~losrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 2 pp-reject %losrut-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~pinpun-pilsun) + :: + %+ expect-eq + !> [[~ ~losred] %.y ~losrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 0 pp-m-reject %losrut-mkey-0)) + [escape.net sponsor.net]:(got:orm points.state ~pinpun-pilsun) + == +:: +++ test-red-l2-l1-reject-l2-2 ^- tang + :: L2-reject A1 | * | A2 | * | * | -> | * | A2 | * | * + =/ dm-reject [holrut-own %reject ~dovmul-mogryt] + =/ dm-m-reject [holrut-mgmt %reject ~dovmul-mogryt] + :: + ;: weld + %+ expect-eq + !> [[~ ~rigred] %.y ~holrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 1 dm-reject %holrut-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~dovmul-mogryt) + :: + %+ expect-eq + !> [[~ ~rigred] %.y ~holrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 0 dm-m-reject %holrut-mkey-0)) + [escape.net sponsor.net]:(got:orm points.state ~dovmul-mogryt) + == +:: +++ test-red-l1-l2-reject-l2-2 ^- tang + :: L2-reject A1 | * | A2 | * | * | -> | * | A2 | * | * + =/ lm-reject [rigrut-own %reject ~larsyx-mapmeg] + =/ lm-m-reject [rigrut-mgmt %reject ~larsyx-mapmeg] + :: + ;: weld + %+ expect-eq + !> [[~ ~losred] %.y ~rigrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 0 lm-reject %rigrut-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~larsyx-mapmeg) + :: + %+ expect-eq + !> [[~ ~losred] %.y ~rigrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 0 lm-m-reject %rigrut-mkey-0)) + [escape.net sponsor.net]:(got:orm points.state ~larsyx-mapmeg) + == +:: +++ test-red-l1-l1-reject-l2-2 ^- tang + :: L2-reject A1 | * | A2 | * | * | -> | * | A2 | * | * + =/ rr-reject [holrut-own %reject ~rabsum-ravtyd] + =/ rr-m-reject [holrut-mgmt %reject ~rabsum-ravtyd] + :: + ;: weld + %+ expect-eq + !> [[~ ~rigred] %.y ~holrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 1 rr-reject %holrut-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) + :: + %+ expect-eq + !> [[~ ~rigred] %.y ~holrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 0 rr-m-reject %holrut-mkey-0)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) + == +:: +++ test-red-l1-l1-reject-l2-3 ^- tang + :: L2-reject A1 | * | ~ | * | * | -> | * | ~ | * | * + =/ rt-reject [holrut-own %reject ~radres-tinnyl] + =/ rt-m-reject [holrut-mgmt %reject ~radres-tinnyl] + :: + ;: weld + %+ expect-eq + !> [~ %.y ~losrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 1 rt-reject %holrut-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~radres-tinnyl) + :: + %+ expect-eq + !> [~ %.y ~losrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 0 rt-m-reject %holrut-mkey-0)) + [escape.net sponsor.net]:(got:orm points.state ~radres-tinnyl) + == +:: +:: the following tests L2 %cancel-escape +:: +++ test-red-l2-l2-cancel-escape-l2 ^- tang + :: L2-cancel A1 | * | * | * | * | -> | * | ~ | * | * + =/ pp-cancel-escape [[~pinpun-pilsun %own] %cancel-escape ~losred] + =/ pp-m-cancel-escape [[~pinpun-pilsun %manage] %cancel-escape ~losred] + :: + ;: weld + %+ expect-eq + !> [~ %.y ~losrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f + state + (n state %bat q:(gen-tx 3 pp-cancel-escape %losrut-pp-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~pinpun-pilsun) + :: + %+ expect-eq + !> [~ %.y ~losrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f + state + (n state %bat q:(gen-tx 0 pp-m-cancel-escape %losrut-pp-mkey-0)) + [escape.net sponsor.net]:(got:orm points.state ~pinpun-pilsun) + == +:: +++ test-red-l2-l1-cancel-escape-l2 ^- tang + :: L2-cancel A1 | * | * | * | * | -> | * | ~ | * | * + =/ dm-cancel-escape [[~dovmul-mogryt %own] %cancel-escape ~rigred] + =/ dm-m-cancel-escape [[~dovmul-mogryt %manage] %cancel-escape ~rigred] + :: + ;: weld + %+ expect-eq + !> [~ %.y ~holrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f + state + (n state %bat q:(gen-tx 3 dm-cancel-escape %holrut-dm-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~dovmul-mogryt) + :: + %+ expect-eq + !> [~ %.y ~holrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f + state + (n state %bat q:(gen-tx 0 dm-m-cancel-escape %holrut-dm-mkey-0)) + [escape.net sponsor.net]:(got:orm points.state ~dovmul-mogryt) + == +:: +++ test-red-l1-l2-cancel-escape-l2 ^- tang + :: L2-cancel A1 | * | * | * | * | -> | * | ~ | * | * + =/ lm-cancel-escape [[~larsyx-mapmeg %own] %cancel-escape ~losred] + =/ lm-m-cancel-escape [[~larsyx-mapmeg %manage] %cancel-escape ~losred] + :: + ;: weld + %+ expect-eq + !> [~ %.y ~rigrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f + state + (n state %bat q:(gen-tx 1 lm-cancel-escape %rigrut-lm-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~larsyx-mapmeg) + :: + %+ expect-eq + !> [~ %.y ~rigrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f + state + (n state %bat q:(gen-tx 0 lm-m-cancel-escape %rigrut-lm-mkey-0)) + [escape.net sponsor.net]:(got:orm points.state ~larsyx-mapmeg) + == +:: +++ test-red-l1-l1-cancel-escape-l2 ^- tang + :: L2-cancel A1 | * | * | * | * | -> | * | ~ | * | * + =/ rr-cancel-escape [[~rabsum-ravtyd %own] %cancel-escape ~rigred] + =/ rr-m-cancel-escape [[~rabsum-ravtyd %manage] %cancel-escape ~rigred] + :: + ;: weld + %+ expect-eq + !> [~ %.y ~holrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f + state + (n state %bat q:(gen-tx 1 rr-cancel-escape %holrut-rr-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) + :: + %+ expect-eq + !> [~ %.y ~holrut] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f + state + (n state %bat q:(gen-tx 0 rr-m-cancel-escape %holrut-rr-mkey-0)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) + == +:: +++ test-rut-l2-l2-detach-l2-1 ^- tang + :: L2-detach A1 | * | * | * | A1 | -> | * | * | * | ~ + =/ pp-detach [losrut-own %detach ~pinpun-pilsun] + =/ pp-m-detach [losrut-mgmt %detach ~pinpun-pilsun] + :: + ;: weld + %+ expect-eq + !> [~ %.n ~losrut] + :: + !> + =| =^state:naive + =^ f state init-rut-simple + =^ f state (n state %bat q:(gen-tx 3 pp-detach %losrut-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~pinpun-pilsun) + :: + %+ expect-eq + !> [~ %.n ~losrut] + :: + !> + =| =^state:naive + =^ f state init-rut-simple + =^ f state (n state %bat q:(gen-tx 0 pp-m-detach %losrut-mkey-0)) + [escape.net sponsor.net]:(got:orm points.state ~pinpun-pilsun) + == +:: +++ test-rut-l2-l1-detach-l2-1 ^- tang + :: L2-detach A1 | * | * | * | A1 | -> | * | * | * | ~ + =/ rt-detach [losrut-own %detach ~radres-tinnyl] + =/ rt-m-detach [losrut-mgmt %detach ~radres-tinnyl] + :: + ;: weld + %+ expect-eq + !> [~ %.n ~losrut] + :: + !> + =| =^state:naive + =^ f state init-rut-simple + =^ f state (n state %bat q:(gen-tx 3 rt-detach %losrut-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~radres-tinnyl) + :: + %+ expect-eq + !> [~ %.n ~losrut] + :: + !> + =| =^state:naive + =^ f state init-rut-simple + =^ f state (n state %bat q:(gen-tx 0 rt-m-detach %losrut-mkey-0)) + [escape.net sponsor.net]:(got:orm points.state ~radres-tinnyl) + == +:: +++ test-rut-l1-l2-detach-l2-1 ^- tang + :: L2-detach A1 | * | * | * | A1 | -> | * | * | * | ~ + =/ dm-detach [holrut-own %detach ~dovmul-mogryt] + =/ dm-m-detach [holrut-mgmt %detach ~dovmul-mogryt] + :: + ;: weld + %+ expect-eq + !> [~ %.n ~holrut] + :: + !> + =| =^state:naive + =^ f state init-rut-simple + =^ f state (n state %bat q:(gen-tx 1 dm-detach %holrut-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~dovmul-mogryt) + :: + %+ expect-eq + !> [~ %.n ~holrut] + :: + !> + =| =^state:naive + =^ f state init-rut-simple + =^ f state (n state %bat q:(gen-tx 0 dm-m-detach %holrut-mkey-0)) + [escape.net sponsor.net]:(got:orm points.state ~dovmul-mogryt) + == +:: +++ test-rut-l1-l1-detach-l2-1 ^- tang + :: L2-detach A1 | * | * | * | A1 | -> | * | * | * | ~ + =/ lm-detach [rigrut-own %detach ~larsyx-mapmeg] + =/ lm-m-detach [rigrut-mgmt %detach ~larsyx-mapmeg] + :: + ;: weld + %+ expect-eq + !> [~ %.n ~rigrut] + :: + !> + =| =^state:naive + =^ f state init-rut-simple + =^ f state (n state %bat q:(gen-tx 0 lm-detach %rigrut-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~larsyx-mapmeg) + :: + %+ expect-eq + !> [~ %.n ~rigrut] + :: + !> + =| =^state:naive + =^ f state init-rut-simple + =^ f state (n state %bat q:(gen-tx 0 lm-m-detach %rigrut-mkey-0)) + [escape.net sponsor.net]:(got:orm points.state ~larsyx-mapmeg) + == +:: +++ test-rut-l1-l1-detach-l2-2 ^- tang + :: L2-detach A1 | * | * | * | A2 | -> | * | * | * | A2 + :: + =/ rr-detach [rigrut-own %detach ~rabsum-ravtyd] + =/ rr-m-detach [rigrut-mgmt %detach ~rabsum-ravtyd] + :: + ;: weld + %+ expect-eq + !> [~ %.y ~holrut] + :: + !> + =| =^state:naive + =^ f state init-rut-simple + =^ f state (n state %bat q:(gen-tx 0 rr-detach %rigrut-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) + :: + %+ expect-eq + !> [~ %.y ~holrut] + :: + !> + =| =^state:naive + =^ f state init-rut-simple + =^ f state (n state %bat q:(gen-tx 0 rr-m-detach %rigrut-mkey-0)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) + == +:: +++ test-rut-l1-l1-detach-l2-3 ^- tang + :: L2-detach A1 | * | * | * | ~ | -> | * | * | * | ~ + :: + =/ rr-h-detach [1 [holrut-own %detach ~rabsum-ravtyd] %holrut-key-0] + =/ rr-h-m-detach [0 [holrut-mgmt %detach ~rabsum-ravtyd] %holrut-mkey-0] + =/ rr-detach [0 [rigrut-own %detach ~rabsum-ravtyd] %rigrut-key-0] + =/ rr-m-detach [0 [rigrut-mgmt %detach ~rabsum-ravtyd] %rigrut-mkey-0] + :: + =, l2-event-gen + =/ rr-detach-batch-1=tx-list (limo rr-h-detach rr-detach ~) + =/ rr-detach-batch-2=tx-list (limo rr-h-m-detach rr-m-detach ~) + :: + =/ init-state=^state:naive +:init-rut-simple + ;: weld + %+ expect-eq + !> [~ %.n ~holrut] + :: + !> + =| =^state:naive + =^ f state (n init-state %bat q:(gen-tx rr-h-detach)) + =^ f state (n state %bat q:(gen-tx rr-detach)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) + :: + %+ expect-eq + !> [~ %.n ~holrut] + :: + !> + =| =^state:naive + =^ f state (n init-state %bat (tx-list-to-batch rr-detach-batch-1)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) + :: + %+ expect-eq + !> [~ %.n ~holrut] + :: + !> + =| =^state:naive + =^ f state (n init-state %bat q:(gen-tx rr-h-m-detach)) + =^ f state (n state %bat q:(gen-tx rr-m-detach)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) + :: + %+ expect-eq + !> [~ %.n ~holrut] + :: + !> + =| =^state:naive + =^ f state (n init-state %bat (tx-list-to-batch rr-detach-batch-2)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) + + == +:: +:: The following tests are miscellaneous sponsorship tests between +:: two L1 points that test a few of the edge cases, like a L1 escape +:: followed by a L2 adopt. +:: +++ test-red-l1-escape-l2-adopt ^- tang + =/ rr-adopt [rigred-own %adopt ~rabsum-ravtyd] + %+ expect-eq + !> [~ %.y ~rigred] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state (escape-requested:l1 ~rabsum-ravtyd ~rigred)) + =^ f state (n state %bat q:(gen-tx 0 rr-adopt %rigred-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) +:: +:: The following test fails because the action would be prevented +:: by Azimuth but is not by naive.hoon. +:: +:: ++ test-red-l2-escape-l1-adopt ^- tang +:: :: shouldn't be possible to accept a L2 escape with a L1 adopt +:: %+ expect-eq +:: !> [[~ ~rigred] %.y ~holrut] +:: :: +:: !> +:: =| =^state:naive +:: =^ f state init-red-simple +:: =^ f state (n state (escape-accepted:l1 ~rabsum-ravtyd ~rigred)) +:: [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) +:: +++ test-rut-l1-adoption-on-l2-wrong-key-or-nonce + =/ rr-escape [[~rabsum-ravtyd %own] %escape ~rigred] + =/ rr-adopt [rigred-own %adopt ~rabsum-ravtyd] + :: + =/ init-state +:init-rut-simple + :: + ;: weld + %+ expect-eq + !> [~ %.y ~holrut] + :: + !> + =| =^state:naive + =^ f state (n init-state %bat q:(gen-tx 1 rr-escape %wrong-key)) + =^ f state (n state %bat q:(gen-tx 0 rr-adopt %rigred-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) + :: + %+ expect-eq + !> [~ %.y ~holrut] + :: + !> + =| =^state:naive + =^ f + state + (n init-state %bat q:(gen-tx 999 rr-escape %holrut-rr-key-0)) + =^ f state (n state %bat q:(gen-tx 0 rr-adopt %rigred-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) + == +:: +++ test-own-sponsor-l2-escape + =/ rr-escape [[~rabsum-ravtyd %own] %escape ~holrut] + :: + %+ expect-eq + !> [[~ ~holrut] %.y ~holrut] + :: + !> + =| =^state:naive + =^ f state init-rut-simple + =^ f state (n state %bat q:(gen-tx 0 rr-escape %holrut-rr-key-0)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) +:: +++ test-rut-l1-detach-1 + :: L1-detach A1 | * | * | A1 | A1 | -> | * | * | ~ | ~ + :: this checks that if you have the same sponsor on L1 and L2, then + :: a L1 detach makes you lose both + :: + :: ~rabsum-ravtyd is a L1 planet under a L1 star so would theortically + :: already be sponsored by ~holrut on L1. this already appears in + :: the L2 state as being sponsored by ~holrut, but we will go through + :: with adopting ~rabsum-ravtyd on L2 anyways before the L1 detach + :: + =/ rr-escape [[~rabsum-ravtyd %own] %escape ~holrut] + =/ rr-adopt [holrut-own %adopt ~rabsum-ravtyd] + %+ expect-eq + !> [~ %.n ~holrut] + :: + !> + =| =^state:naive + =^ f state init-rut-simple + =^ f state (n state %bat q:(gen-tx 0 rr-escape %holrut-rr-key-0)) + =^ f state (n state %bat q:(gen-tx 1 rr-adopt %holrut-key-0)) + =^ f state (n state (lost-sponsor:l1 ~rabsum-ravtyd ~holrut)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) +:: +++ test-red-l1-detach-2 + :: this takes a L1 planet with L1 sponsor that acquires a L2 sponsor + :: and is then detached by their L1 sponsor + :: + :: L1-detach A1 | * | * | A1 | A2 | -> | * | * | ~ | A2 + :: + =/ lm-adopt [losred-own %adopt ~larsyx-mapmeg] + :: + %+ expect-eq + !> [~ %.y ~losred] + :: + !> + =| =^state:naive + =^ f state init-red-simple + =^ f state (n state %bat q:(gen-tx 0 lm-adopt %losred-key-0)) + =^ f state (n state (lost-sponsor:l1 ~larsyx-mapmeg ~rigrut)) + [escape.net sponsor.net]:(got:orm points.state ~larsyx-mapmeg) +:: +++ test-rut-l1-detach-3 + :: L1-detach A1 | * | * | A1 | ~ | -> | * | * | ~ | ~ + :: Since we don't see L1 state explicitly, we can't really test + :: this transition here. But I've included it for completeness sake + =/ rr-detach [holrut-own %detach ~rabsum-ravtyd] + :: + %+ expect-eq + !> [~ %.n ~holrut] + :: + !> + =| =^state:naive + =^ f state init-rut-simple + =^ f state (n state %bat q:(gen-tx 1 rr-detach %holrut-key-0)) + =^ f state (n state (escape-requested:l1 ~rabsum-ravtyd ~holrut)) + =^ f state (n state (escape-accepted:l1 ~rabsum-ravtyd ~holrut)) + =^ f state (n state (lost-sponsor:l1 ~rabsum-ravtyd ~holrut)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) +:: +:: The L1 action in the following test would be prevented by Azimuth +:: but is not by naive.hoon, so this test would fail. +:: +:: ++ test-rut-l1-l1-cancel-l1-1 +:: :: L1-cancel A1 | ~ | * | * | * | -> !! +:: :: no cancel if not escaping +:: :: Note we're using ~rut so there are no initial escapes +:: :: +:: %+ expect-eq +:: !> ~ +:: :: +:: !> +:: =| =^state:naive +:: =^ f state init-rut-simple +:: =^ f state (n state (escape-canceled:l1 ~rabsum-ravtyd ~rigred)) +:: escape.net:(got:orm points.state ~rabsum-ravtyd) +:: +++ test-rut-l1-l1-cancel-l1-2 + :: L1-cancel A1 | A1 | * | * | * | -> | ~ | ~ | * | * + %+ expect-eq + !> ~ + :: + !> + =| =^state:naive + =^ f state init-rut-simple + =^ f state (n state (escape-requested:l1 ~rabsum-ravtyd ~rigred)) + =^ f state (n state (escape-canceled:l1 ~rabsum-ravtyd ~rigred)) + escape.net:(got:orm points.state ~rabsum-ravtyd) +:: +++ test-rut-l1-l1-adopt-l1-1 + :: L1-adopt A1 | A1 | * | * | * | -> | ~ | ~ | A1 | A2 + %+ expect-eq + !> [~ %.y ~rigred] + :: + !> + =| =^state:naive + =^ f state init-rut-simple + =^ f state (n state (escape-requested:l1 ~rabsum-ravtyd ~rigred)) + =^ f state (n state (escape-accepted:l1 ~rabsum-ravtyd ~rigred)) + [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) +:: +:: These commented out tests fail, but it is because L1 adopt is only +:: accepted if Azimuth allows it. So these rows of the table +:: cannot be tested here. +:: +:: ++ test-rut-l1-l1-adopt-l1-2 +:: :: L1-adopt A1 | ~ | * | * | * | -> !! +:: :: no adopt if not escaping +:: %+ expect-eq +:: !> [~ %.y ~holrut] +:: :: +:: !> +:: =| =^state:naive +:: =^ f state init-rut-simple +:: =^ f state (n state (escape-accepted:l1 ~rabsum-ravtyd ~rigred)) +:: [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) +:: :: +:: ++ test-rut-l1-l1-adopt-l1-3 +:: :: L1-adopt A1 | A2 | * | * | * | -> !! +:: :: no adopt if not escaping +:: %+ expect-eq +:: !> [[~ ~rigrut] %.y ~holrut] +:: :: +:: !> +:: =| =^state:naive +:: =^ f state init-rut-simple +:: =^ f state (n state (escape-requested:l1 ~rabsum-ravtyd ~rigrut)) +:: =^ f state (n state (escape-accepted:l1 ~rabsum-ravtyd ~rigred)) +:: [escape.net sponsor.net]:(got:orm points.state ~rabsum-ravtyd) +:: +:: The remaining tests are not categorized in any particular way. Some of them +:: are already covered by +test-rut but have been left in since they can't +:: hurt. +:: +++ test-marbud-l2-change-keys-whole-state ^- tang + =/ new-keys [%configure-keys encr auth suit |] + =| =^state:naive + =^ f state (init-marbud state) + =/ marbud-point (got:orm points.state ~marbud) + =/ new-marbud marbud-point(keys.net [1 suit auth encr], nonce.owner.own 1) + :: + %+ expect-eq + !> state(points (put:orm points.state ~marbud new-marbud)) + :: + !> + =^ f + state + (n state %bat q:(gen-tx 0 [marbud-own new-keys] %marbud-key-0)) + state +:: +++ test-log ^- tang + %+ expect-eq + !> + :- [%point ~bud %owner (addr %bud-key-0)]~ + :- %0 + :_ [~ ~] :_ [~ ~] + :- ~bud + %* . *point:naive + dominion %l1 + owner.own (addr %bud-key-0)^0 + who.sponsor.net ~bud + == + :: + !> + %^ naive verifier 1.337 :+ *^state:naive 0 + :* %log *@ux *@ux + owner-changed:log-names:naive (@ux ~bud) (addr %bud-key-0) ~ + == +:: +++ test-deposit ^- tang + %+ expect-eq + !> %l2 + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + dominion:(got:orm points.state ~marbud) +:: +++ test-transfer-batch ^- tang + =/ marbud-transfer + [0 [marbud-own %transfer-point (addr %marbud-key-0) |] %marbud-key-0] + =/ marbud-transfer-2 + [1 [marbud-own %transfer-point (addr %marbud-key-1) |] %marbud-key-0] + :: + =, l2-event-gen + =/ marbud-batch=tx-list (limo marbud-transfer marbud-transfer-2 ~) + :: + ;: weld + %+ expect-eq + !> [(addr %marbud-key-1) 2] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (n state %bat q:(gen-tx marbud-transfer)) + =^ f state (n state %bat q:(gen-tx marbud-transfer-2)) + owner.own:(got:orm points.state ~marbud) + :: + %+ expect-eq + !> [(addr %marbud-key-1) 2] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (n state %bat (tx-list-to-batch marbud-batch)) + owner.own:(got:orm points.state ~marbud) + == +:: +++ test-l1-changed-spawn-proxy ^- tang + %+ expect-eq + !> [(addr %bud-skey) 0] + :: + !> + =| =^state:naive + =^ f state (init-bud state) + =^ f state (n state (changed-spawn-proxy:l1 ~bud (addr %bud-skey))) + spawn-proxy.own:(got:orm points.state ~bud) +:: +++ test-l1-changed-transfer-proxy ^- tang + %+ expect-eq + !> [(addr %bud-key-1) 0] + :: + !> + =| =^state:naive + =^ f state (init-bud state) + =^ f state (n state (changed-transfer-proxy:l1 ~bud (addr %bud-key-1))) + transfer-proxy.own:(got:orm points.state ~bud) +:: +++ test-l1-changed-management-proxy ^- tang + %+ expect-eq + !> [(addr %bud-mkey) 0] + :: + !> + =| =^state:naive + =^ f state (init-bud state) + =^ f state (n state (changed-management-proxy:l1 ~bud (addr %bud-mkey))) + management-proxy.own:(got:orm points.state ~bud) +:: +++ test-l1-changed-voting-proxy ^- tang + %+ expect-eq + !> [(addr %bud-vkey) 0] + :: + !> + =| =^state:naive + =^ f state (init-bud state) + =^ f state (n state (changed-voting-proxy:l1 ~bud (addr %bud-vkey))) + voting-proxy.own:(got:orm points.state ~bud) +:: +++ test-l1-changed-keys ^- tang + =/ life 1 + =/ new-keys [~bud suit encr auth life] + :: + %+ expect-eq + !> [suit auth encr] + :: + !> + =| =^state:naive + =^ f state (init-bud state) + =^ f state (n state (changed-keys:l1 new-keys)) + |1:keys.net:(got:orm 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:orm 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:orm 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:orm 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:orm points.state ~sambud) +:: +++ test-l2-set-spawn-proxy ^- tang + =/ marbud-sproxy [marbud-own %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:(gen-tx 0 marbud-sproxy %marbud-key-0)) + spawn-proxy.own:(got:orm points.state ~marbud) +:: +++ test-l2-set-transfer-proxy ^- tang + =/ marbud-tproxy [marbud-own %set-transfer-proxy (addr %marbud-tkey)] + :: + %+ expect-eq + !> [(addr %marbud-tkey) 0] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (n state %bat q:(gen-tx 0 marbud-tproxy %marbud-key-0)) + transfer-proxy.own:(got:orm points.state ~marbud) +:: +++ test-l2-set-management-proxy ^- tang + =/ marbud-mproxy [marbud-own %set-management-proxy (addr %marbud-mkey)] + :: + %+ expect-eq + !> [(addr %marbud-mkey) 0] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (n state %bat q:(gen-tx 0 marbud-mproxy %marbud-key-0)) + management-proxy.own:(got:orm points.state ~marbud) +:: +++ test-l2-dopbud-spawn-proxy-deposit ^- tang + %+ expect-eq + !> %spawn + :: + !> + =| =^state:naive + =^ f state (init-dopbud state) + dominion:(got:orm points.state ~dopbud) +:: +++ test-l2-sambud-spawn-proxy-predeposit ^- tang + %+ expect-eq + !> [(addr %sambud-skey) 0] + :: + !> + =| =^state:naive + =^ f state (init-sambud state) + =^ f + state + (n state (changed-spawn-proxy:l1 ~sambud (addr %sambud-skey))) + =^ f + state + (n state (changed-spawn-proxy:l1 ~sambud deposit-address:naive)) + spawn-proxy.own:(got:orm points.state ~sambud) +:: +++ test-l2-sambud-own-spawn-proxy-postdeposit ^- tang + =/ sambud-sproxy [[~sambud %own] %set-spawn-proxy (addr %sambud-skey-0)] + %+ expect-eq + !> [(addr %sambud-skey-0) 0] + :: + !> + =| =^state:naive + =^ f state (init-sambud state) + =^ f state + (n state (changed-spawn-proxy:l1 ~sambud deposit-address:naive)) + =^ f state (n state %bat q:(gen-tx 0 sambud-sproxy %sambud-key-0)) + spawn-proxy.own:(got:orm points.state ~sambud) +:: +++ test-l2-sambud-spawn-spawn-proxy-postdeposit ^- tang + =/ sambud-sproxy [[~sambud %spawn] %set-spawn-proxy (addr %sambud-skey-1)] + %+ expect-eq + !> [(addr %sambud-skey-1) 1] + :: + !> + =| =^state:naive + =^ f state (init-sambud state) + =^ f state + (n state (changed-spawn-proxy:l1 ~sambud (addr %sambud-skey-0))) + =^ f state + (n state (changed-spawn-proxy:l1 ~sambud deposit-address:naive)) + =^ f state (n state %bat q:(gen-tx 0 sambud-sproxy %sambud-skey-0)) + spawn-proxy.own:(got:orm points.state ~sambud) +:: +++ test-l2-sambud-spawn-proxy-predeposit-spawn ^- tang + =/ l2-sproxy [[~sambud %spawn] %set-spawn-proxy (addr %sambud-skey-1)] + =/ lf-spawn [[~sambud %spawn] %spawn ~lisdur-fodrys (addr %lf-key-0)] + ;: weld + %+ expect-eq + !> [`@ux`(addr %lf-key-0) 0] + :: + !> + =| =^state:naive + =^ f state (init-sambud state) + =^ f state + (n state (changed-spawn-proxy:l1 ~sambud (addr %sambud-skey-0))) + =^ f state + (n state (changed-spawn-proxy:l1 ~sambud deposit-address:naive)) + =^ f state + (n state %bat q:(gen-tx 0 lf-spawn %sambud-skey-0)) + transfer-proxy.own:(got:orm points.state ~lisdur-fodrys) + :: + %+ expect-eq + !> [`@ux`(addr %lf-key-0) 0] + :: + !> + =| =^state:naive + =^ f state (init-sambud state) + =^ f state + (n state (changed-spawn-proxy:l1 ~sambud (addr %sambud-skey-0))) + =^ f state + (n state (changed-spawn-proxy:l1 ~sambud deposit-address:naive)) + =^ f state + (n state %bat q:(gen-tx 0 l2-sproxy %sambud-skey-0)) + =^ f state + (n state %bat q:(gen-tx 1 lf-spawn %sambud-skey-1)) + transfer-proxy.own:(got:orm points.state ~lisdur-fodrys) + == +++ test-linnup-torsyx-spawn ^- tang + :: try to spawn a L2 planet with a L2 planet + =/ rt-spawn + [lt-own %spawn ~radres-tinnyl (addr %rt-key-0)] + =/ lt-spawn + [marbud-own %spawn ~linnup-torsyx (addr %lt-key-0)] + =/ lt-transfer-yes-breach + [lt-xfr %transfer-point (addr %lt-key-0) &] + :: + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (init-litbud state) + =^ f state (n state %bat q:(gen-tx 0 lt-spawn %marbud-key-0)) + =^ f state (n state %bat q:(gen-tx 0 lt-transfer-yes-breach %lt-key-0)) + =/ lt-point (got:orm points.state ~linnup-torsyx) + =/ new-lt lt-point(nonce.owner.own 1) + =/ no-op-state state(points (put:orm points.state ~linnup-torsyx new-lt)) + :: + %+ expect-eq + !> no-op-state + :: + !> + =^ f state (n state %bat q:(gen-tx 0 rt-spawn %lt-key-0)) + state +:: +++ test-marbud-l2-spawn ^- tang + =/ lt-spawn + [%spawn ~linnup-torsyx (addr %lt-key-0)] + =/ marbud-sproxy + [0 [marbud-own %set-spawn-proxy (addr %marbud-skey)] %marbud-key-0] + =, l2-event-gen + =/ spawn-batch=tx-list + (limo marbud-sproxy [0 [marbud-spn lt-spawn] %marbud-skey] ~) + :: + ;: 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] %marbud-key-0)) + transfer-proxy.own:(got:orm 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 marbud-sproxy)) + =^ f state + (n state %bat q:(gen-tx 0 [marbud-spn lt-spawn] %marbud-skey)) + transfer-proxy.own:(got:orm points.state ~linnup-torsyx) + :: + %+ expect-eq + :: Tests l2 spawning with spawn proxy as a batch + !> [`@ux`(addr %lt-key-0) 0] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (n state %bat (tx-list-to-batch spawn-batch)) + transfer-proxy.own:(got:orm points.state ~linnup-torsyx) + == +:: +++ test-marbud-l2-double-spawn ^- tang + :: Attempts to spawn the same planet twice, once with ownership and once + :: with spawn proxy + =/ marbud-sproxy [marbud-own %set-spawn-proxy (addr %marbud-skey)] + =/ lt-spawn-0 [marbud-own %spawn ~linnup-torsyx (addr %lt-key-0)] + =/ lt-spawn-1 [marbud-spn %spawn ~linnup-torsyx (addr %lt-key-1)] + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (n state %bat q:(gen-tx 0 marbud-sproxy %marbud-key-0)) + =^ f state (n state %bat q:(gen-tx 1 lt-spawn-0 %marbud-key-0)) + =/ marbud-point (got:orm points.state ~marbud) + =/ new-marbud marbud-point(nonce.spawn-proxy.own 1) + =/ no-op-state state(points (put:orm points.state ~marbud new-marbud)) + :: + %+ expect-eq + !> no-op-state + :: + !> + =^ f state (n state %bat q:(gen-tx 0 lt-spawn-1 %marbud-skey)) + state +:: +++ test-marbud-l2-change-keys ^- tang + =/ new-keys [%configure-keys encr auth suit |] + =/ marbud-mproxy [marbud-own %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] %marbud-key-0)) + |1:keys.net:(got:orm 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-mproxy %marbud-key-0)) + =^ f state + (n state %bat q:(gen-tx 0 [marbud-mgt new-keys] %marbud-mkey)) + |1:keys.net:(got:orm points.state ~marbud) + :: + == +:: +++ test-marbud-l2-proxies-transfer ^- tang + =/ marbud-new-keys + [0 [marbud-own %configure-keys encr auth suit |] %marbud-key-0] + =/ marbud-sproxy + [0 [marbud-own %set-spawn-proxy (addr %marbud-skey)] %marbud-key-0] + =/ marbud-mproxy + [1 [marbud-own %set-management-proxy (addr %marbud-mkey)] %marbud-key-0] + =/ marbud-tproxy + [2 [marbud-own %set-transfer-proxy (addr %marbud-key-1)] %marbud-key-0] + =/ marbud-transfer-breach + [1 [marbud-own %transfer-point (addr %marbud-key-1) &] %marbud-key-0] + =/ marbud-transfer-no-breach + [1 [marbud-own %transfer-point (addr %marbud-key-1) |] %marbud-key-0] + =/ marbud-xfr-breach + [0 [marbud-xfr %transfer-point (addr %marbud-key-1) &] %marbud-key-1] + =/ marbud-xfr-no-breach + [0 [marbud-xfr %transfer-point (addr %marbud-key-1) |] %marbud-key-1] + :: + =, l2-event-gen + =/ test1=tx-list + (ly marbud-sproxy marbud-mproxy marbud-tproxy marbud-xfr-breach ~) + =/ test2=tx-list + (ly marbud-new-keys marbud-transfer-breach ~) + =/ test3=tx-list + (ly marbud-sproxy marbud-mproxy marbud-tproxy marbud-xfr-no-breach ~) + =/ test4=tx-list + (ly marbud-new-keys marbud-transfer-no-breach ~) + :: + ;: 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 marbud-sproxy)) + =^ f state (n state %bat q:(gen-tx marbud-mproxy)) + =^ f state (n state %bat q:(gen-tx marbud-tproxy)) + =^ f state (n state %bat q:(gen-tx marbud-xfr-breach)) + ^- [[@ @] [@ @] [@ @] [@ @] [@ @]] + own:(got:orm points.state ~marbud) + :: + %+ expect-eq + :: batch version + :: + !> + :* [(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 (tx-list-to-batch test1)) + ^- [[@ @] [@ @] [@ @] [@ @] [@ @]] + own:(got:orm 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 marbud-new-keys)) + =^ f state (n state %bat q:(gen-tx marbud-transfer-breach)) + |1:keys.net:(got:orm points.state ~marbud) + :: + %+ expect-eq + :: batch version + !> + [0 0 0] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (n state %bat (tx-list-to-batch test2)) + |1:keys.net:(got:orm 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 marbud-sproxy)) + =^ f state (n state %bat q:(gen-tx marbud-mproxy)) + =^ f state (n state %bat q:(gen-tx marbud-tproxy)) + =^ f state (n state %bat q:(gen-tx marbud-xfr-no-breach)) + ^- [[@ @] [@ @] [@ @] [@ @] [@ @]] + own:(got:orm points.state ~marbud) + :: + %+ expect-eq + :: batch version + !> + :* [(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 (tx-list-to-batch test3)) + ^- [[@ @] [@ @] [@ @] [@ @] [@ @]] + own:(got:orm 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 marbud-new-keys)) + =^ f state (n state %bat q:(gen-tx marbud-transfer-no-breach)) + |1:keys.net:(got:orm points.state ~marbud) + :: + %+ expect-eq + :: batch version + !> + [suit auth encr] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (n state %bat (tx-list-to-batch test4)) + |1:keys.net:(got:orm points.state ~marbud) + == +:: +:: TODO: life+rift changes via transfer proxy +:: +++ test-marbud-life-rift ^- tang + =/ new-keys-no-reset + [marbud-own %configure-keys encr auth suit |] + =/ new-keys-yes-reset + [marbud-own %configure-keys encr auth suit &] + =/ zero-keys-no-reset + [marbud-own %configure-keys 0 0 0 |] + =/ zero-keys-yes-reset + [marbud-own %configure-keys 0 0 0 &] + =/ marbud-transfer-no-breach + [marbud-own %transfer-point (addr %marbud-key-1) |] + =/ marbud-transfer-yes-breach + [marbud-own %transfer-point (addr %marbud-key-1) &] + =/ marbud-own-1 + [~marbud %marbud-key-1 %own] + :: + ;: 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 new-keys-no-reset %marbud-key-0)) + =^ f state (n state %bat q:(gen-tx 1 new-keys-no-reset %marbud-key-0)) + [rift.net life.keys.net]:(got:orm 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 new-keys-yes-reset %marbud-key-0)) + [rift.net life.keys.net]:(got:orm 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) + :: inc life and rift + =^ f state + (n state %bat q:(gen-tx 0 new-keys-yes-reset %marbud-key-0)) + :: inc life + =^ f state + (n state %bat q:(gen-tx 1 zero-keys-no-reset %marbud-key-0)) + :: inc rift + =^ f state + (n state %bat q:(gen-tx 2 zero-keys-yes-reset %marbud-key-0)) + [rift.net life.keys.net]:(got:orm points.state ~marbud) + :: + %+ expect-eq + :: Keep the same keys while breaching via %configure-keys + :: + !> [2 1] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + :: inc life and rift + =^ f state + (n state %bat q:(gen-tx 0 new-keys-yes-reset %marbud-key-0)) + :: inc life and rift + =^ f state + (n state %bat q:(gen-tx 1 new-keys-yes-reset %marbud-key-0)) + [rift.net life.keys.net]:(got:orm points.state ~marbud) + :: + %+ expect-eq + :: + !> [1 2] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state + (n state %bat q:(gen-tx 0 new-keys-no-reset %marbud-key-0)) + =^ f state + (n state %bat q:(gen-tx 1 marbud-transfer-no-breach %marbud-key-0)) + =^ f state + (n state %bat q:(gen-tx 2 zero-keys-yes-reset %marbud-key-1)) + [rift.net life.keys.net]:(got:orm points.state ~marbud) + :: + %+ expect-eq + :: set networking keys, then transfer and set networking keys with breach + :: + !> [1 3] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + :: inc life + =^ f state + (n state %bat q:(gen-tx 0 new-keys-no-reset %marbud-key-0)) + :: inc life and rift + =^ f state + (n state %bat q:(gen-tx 1 marbud-transfer-yes-breach %marbud-key-0)) + :: inc life + =^ f state + (n state %bat q:(gen-tx 2 new-keys-no-reset %marbud-key-1)) + [rift.net life.keys.net]:(got:orm 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) + :: inc life and rift + =^ f state + (n state %bat q:(gen-tx 0 new-keys-yes-reset %marbud-key-0)) + :: inc life + =^ f state + (n state %bat q:(gen-tx 1 zero-keys-no-reset %marbud-key-0)) + :: inc rift + =^ f state + (n state %bat q:(gen-tx 2 marbud-transfer-yes-breach %marbud-key-0)) + [rift.net life.keys.net]:(got:orm points.state ~marbud) + :: + == +:: +++ test-dopbud-l2-spawn ^- tang + =/ pp-spawn [dopbud-own %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:(gen-tx 0 pp-spawn %dopbud-key-0)) + transfer-proxy.own:(got:orm points.state ~palsep-picdun) +:: +++ test-dopbud-l2-spawn-after-transfer ^- tang + =/ pp-spawn [dopbud-own %spawn ~palsep-picdun (addr %pp-key-0)] + =/ lr-spawn [dopbud-own %spawn ~laclur-rachul (addr %lr-key-0)] + :: + %+ expect-eq + !> [`@ux`(addr %lr-key-0) 0] + :: + !> + =| =^state:naive + =^ f state (init-dopbud state) + =^ f state (n state %bat q:(gen-tx 0 pp-spawn %dopbud-key-0)) + =^ f state (n state (owner-changed:l1 ~dopbud (addr %dopbud-key-1))) + =^ f state (n state %bat q:(gen-tx 1 lr-spawn %dopbud-key-1)) + transfer-proxy.own:(got:orm points.state ~laclur-rachul) +:: +++ test-linnup-torsyx-l2-transfer-ownership ^- tang + =/ lt-spawn + [marbud-own %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:(gen-tx 0 lt-spawn %marbud-key-0)) + =^ f state + (n state %bat q:(gen-tx 0 [lt-xfr lt-transfer-yes-breach] %lt-key-0)) + owner.own:(got:orm points.state ~linnup-torsyx) +:: +++ test-palsep-picdun-l2-transfer-ownership ^- tang + =/ pp-xfr + [~palsep-picdun %transfer] + =/ pp-spawn + [dopbud-own %spawn ~palsep-picdun (addr %pp-key-0)] + =/ pp-transfer-yes-breach + [pp-xfr %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:(gen-tx 0 pp-spawn %dopbud-key-0)) + =^ f state (n state %bat q:(gen-tx 0 pp-transfer-yes-breach %pp-key-0)) + owner.own:(got:orm points.state ~palsep-picdun) +:: +++ test-linnup-torsyx-l2-escape-request ^- tang + =/ lt-spawn + [marbud-own %spawn ~linnup-torsyx (addr %lt-key-0)] + =/ lt-transfer-yes-breach + [lt-xfr %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 lt-spawn %marbud-key-0)) + =^ f state + (n state %bat q:(gen-tx 0 lt-transfer-yes-breach %lt-key-0)) + =^ f state + (n state %bat q:(gen-tx 0 [lt-own [%escape ~litbud]] %lt-key-0)) + escape.net:(got:orm points.state ~linnup-torsyx) +:: +++ test-linnup-torsyx-l2-cancel-escape-request ^- tang + =/ lt-spawn + [marbud-own %spawn ~linnup-torsyx (addr %lt-key-0)] + =/ lt-transfer-yes-breach + [lt-xfr %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 lt-spawn %marbud-key-0)) + =^ f state + (n state %bat q:(gen-tx 0 lt-transfer-yes-breach %lt-key-0)) + =^ f state + (n state %bat q:(gen-tx 0 [lt-own [%escape ~litbud]] %lt-key-0)) + =^ f state + (n state %bat q:(gen-tx 1 [lt-own [%cancel-escape ~litbud]] %lt-key-0)) + escape.net:(got:orm points.state ~linnup-torsyx) +:: +++ test-linnup-torsyx-l2-adopt-accept ^- tang + =/ lt-spawn + [marbud-own %spawn ~linnup-torsyx (addr %lt-key-0)] + =/ lt-transfer-yes-breach + [lt-xfr %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 lt-spawn %marbud-key-0)) + =^ f state + (n state %bat q:(gen-tx 0 lt-transfer-yes-breach %lt-key-0)) + =^ f state + (n state %bat q:(gen-tx 0 [lt-own [%escape ~litbud]] %lt-key-0)) + =^ f state + %- n :+ state %bat =< q + (gen-tx 0 [litbud-own [%adopt ~linnup-torsyx]] %litbud-key-0) + [escape.net sponsor.net]:(got:orm points.state ~linnup-torsyx) +:: +++ test-linnup-torsyx-l2-adopt-reject ^- tang + =/ lt-spawn + [marbud-own %spawn ~linnup-torsyx (addr %lt-key-0)] + =/ lt-transfer-yes-breach + [lt-xfr %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 lt-spawn %marbud-key-0)) + =^ f state + (n state %bat q:(gen-tx 0 lt-transfer-yes-breach %lt-key-0)) + =^ f state + (n state %bat q:(gen-tx 0 [lt-own [%escape ~litbud]] %lt-key-0)) + =^ f state + %- n :+ state %bat =< q + (gen-tx 0 [litbud-own [%reject ~linnup-torsyx]] %litbud-key-0) + escape.net:(got:orm points.state ~linnup-torsyx) +:: +++ test-linnup-torsyx-l2-detach ^- tang + =/ lt-spawn + [marbud-own %spawn ~linnup-torsyx (addr %lt-key-0)] + =/ lt-transfer-yes-breach + [lt-xfr %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 lt-spawn %marbud-key-0)) + =^ f state + (n state %bat q:(gen-tx 0 lt-transfer-yes-breach %lt-key-0)) + =^ f state + %- n :+ state %bat =< q + (gen-tx 1 [marbud-own [%detach ~linnup-torsyx]] %marbud-key-0) + [escape.net sponsor.net]:(got:orm points.state ~linnup-torsyx) +:: +:: Fuzz tests. These just feed the L2 contract various forms of garbage. +:: They should all be no-ops. +:: +++ test-fuzz-octs +:: this test just throws completely random octs at naive.hoon +:: + =+ [seed=`@`%test-fuzz-octs i=0] + =| =^state:naive + =^ f state init-red-simple + =/ init-state state + |- ^- tang + ?: =(i 10) ~ + %+ weld $(seed (shas `@`%versace seed), i +(i)) + =/ state init-state + =/ rng ~(. og seed) + =^ proxy rng (raws:rng 8) + =^ ship rng (raws:rng 32) + =^ action rng (raws:rng 8) + =^ junk-length rng (rads:rng 200) + :: increment junk-length to prevent 0 case + =^ junk rng (raws:rng +(junk-length)) + =^ nonce rng (rads:rng 999) + =^ key rng (raws:rng 256) + =/ fuzz=octs + %: cad:naive 3 + 1^proxy + 4^ship + 1^action + (met 3 junk)^junk + ~ + == + =/ random-tx + %^ sign-tx key nonce fuzz + :: + %+ expect-eq + !> init-state + :: :: + !> + =^ f state (n state %bat q:random-tx) + state +:: +++ test-fuzz-valid-ship-key +:: this test uses a valid ship and key but otherwise +:: hands the contract garbage +:: + =+ [seed=`@`%test-fuzz-valid-ship-key i=0] + =| =^state:naive + =^ f state init-red-simple + =/ init-state state + |- ^- tang + ?: =(i 100) ~ + %+ weld $(seed (shas `@`%iceberg-simpson seed), i +(i)) + =/ state init-state + =/ rng ~(. og seed) + =/ ship ~pinpun-pilsun + =^ proxy rng (raws:rng 8) + =^ action rng (raws:rng 8) + =^ junk-length rng (rads:rng 200) + :: increment junk-length to prevent 0 case + =^ junk rng (raws:rng +(junk-length)) + =^ nonce rng (rads:rng 999) + =/ fuzz=octs + %: cad:naive 3 + 1^proxy + 4^ship + 1^action + (met 3 junk)^junk + ~ + == + =/ random-tx + %^ sign-tx %losrut-pp-key-0 nonce fuzz + :: + %+ expect-eq + !> init-state + :: :: + !> + =^ f state (n state %bat q:random-tx) + state +:: +++ test-fuzz-valid-ship-key-proxy-nonce +:: this test uses a valid ship, key, proxy, nonce but otherwise +:: hands the contract garbage +:: + =+ [seed=`@`%test-fuzz-valid-ship-key-proxy-nonce i=0] + =| =^state:naive + =^ f state init-red-simple + =/ init-state state + |- ^- tang + ?: =(i 100) ~ + %+ weld $(seed (shas `@`%tiptoe seed), i +(i)) + =/ state init-state + =/ rng ~(. og seed) + =/ ship=@p ~pinpun-pilsun + =^ action rng (raws:rng 8) + =^ junk-length rng (rads:rng 200) + :: increment junk-length to prevent case of 0 + =^ junk rng (raws:rng +(junk-length)) + =/ fuzz=octs + %: cad:naive 3 + 1^(can 0 3^%0 5^0 ~) :: %own proxy + 4^ship + 1^action + (met 3 junk)^junk + ~ + == + =/ random-tx + %^ sign-tx %losrut-pp-key-0 1 fuzz + :: + %+ expect-eq + !> init-state + :: + !> + =^ f state (n state %bat q:random-tx) + state +:: +:: I think the following test ought to be trying something else: +:: checking to see if valid transactions followed by garbage still +:: process the valid tx +:: ++ test-fuzz-after-tx +:: :: this creates a valid transaction of each type but then adds +:: :: random bits to the end of it +:: :: +:: =+ [seed=`@`%test-fuzz-after-tx1 i=0] +:: =| =^state:naive +:: =^ f state init-red-simple +:: =/ init-state state +:: |- ^- tang +:: ?: =(i 11) ~ :: 10 attempts for each transaction type +:: %+ weld $(seed (shas `@`%howmuchisfour seed), i +(i)) +:: =+ j=0 +:: |^ ^- tang +:: ?: =(j 11) ~ :: there are 10 transaction types +:: %+ weld $(seed (shas `@`%eris seed), j +(j)) +:: =/ rng ~(. og seed) +:: =^ junk-length rng (rads:rng 200) +:: ::increment to prevent zero-length junk +:: =^ junk rng (raws:rng +(junk-length)) +:: =/ tx-octs=octs +:: ?+ j !! +:: %0 do-spawn +:: %1 do-transfer-point +:: %2 do-configure-keys +:: %3 do-escape +:: %4 do-cancel-escape +:: %5 do-adopt +:: %6 do-reject +:: %7 do-detach +:: %8 do-set-management-proxy +:: %9 do-set-spawn-proxy +:: %10 do-set-transfer-proxy +:: == +:: =/ fuzz (mix (lsh [3 (met 3 q:tx-octs)] junk) q:tx-octs) +:: =/ fuzz-octs=octs [(met 3 fuzz) fuzz] +:: :: the conditionals that follow are to ensure the correct key and +:: :: nonce are used. +:: =/ random-tx +:: ?: =(j 4) +:: %^ sign-tx %holrut-rr-key-0 1 fuzz-octs +:: ?: |(=(j 5) =(j 6)) +:: %^ sign-tx %rigred-key-0 0 fuzz-octs +:: %^ sign-tx %losrut-key-0 2 fuzz-octs +:: :: +:: =/ state init-state +:: %+ category (weld "fuzz tx type " (scow %ud j)) +:: %+ expect-eq +:: !> init-state +:: :: +:: !> +:: =^ f state (n state %bat q:random-tx) +:: ~& ['tx-type' j] +:: state +:: :: +:: ++ do-spawn ^- octs +:: =/ from [ship=~losrut proxy=%own] +:: =/ sptx=skim-tx:naive [%spawn ~mishus-loplus (addr %nowhere)] +:: =/ tx=tx:naive [from sptx] +:: (gen-tx-octs tx) +:: ++ do-transfer-point ^- octs +:: =/ from [ship=~losrut proxy=%own] +:: =/ xrtx=skim-tx:naive [%transfer-point (addr %somewhere) &] +:: =/ tx=tx:naive [from xrtx] +:: (gen-tx-octs tx) +:: ++ do-configure-keys ^- octs +:: =/ from [ship=~losrut proxy=%own] +:: =/ cftx=skim-tx:naive +:: [%configure-keys (shax 'uno') (shax 'dos') (shax 'tres') |] +:: =/ tx=tx:naive [from cftx] +:: (gen-tx-octs tx) +:: ++ do-escape ^- octs +:: =/ from [ship=~losrut proxy=%own] +:: =/ estx=skim-tx:naive [%escape ~red] +:: =/ tx=tx:naive [from estx] +:: (gen-tx-octs tx) +:: ++ do-cancel-escape ^- octs +:: =/ from [ship=~rabsum-ravtyd proxy=%own] +:: =/ cetx=skim-tx:naive [%cancel-escape ~rigred] +:: =/ tx=tx:naive [from cetx] +:: (gen-tx-octs tx) +:: ++ do-adopt ^- octs +:: =/ from [ship=~rigred proxy=%own] +:: =/ adtx=skim-tx:naive [%adopt ~rabsum-ravtyd] +:: =/ tx=tx:naive [from adtx] +:: (gen-tx-octs tx) +:: ++ do-reject ^- octs +:: =/ from [ship=~rigred proxy=%own] +:: =/ rjtx=skim-tx:naive [%adopt ~rabsum-ravtyd] +:: =/ tx=tx:naive [from rjtx] +:: (gen-tx-octs tx) +:: ++ do-detach +:: =/ from [ship=~losrut proxy=%own] +:: =/ dttx=skim-tx:naive [%detach ~rabsum-ravtyd] +:: =/ tx=tx:naive [from dttx] +:: (gen-tx-octs tx) +:: ++ do-set-management-proxy +:: =/ from [ship=~losrut proxy=%own] +:: =/ mgtx=skim-tx:naive [%set-management-proxy (addr %new-mgmt)] +:: =/ tx=tx:naive [from mgtx] +:: (gen-tx-octs tx) +:: ++ do-set-spawn-proxy +:: =/ from [ship=~losrut proxy=%own] +:: =/ sptx=skim-tx:naive [%set-spawn-proxy (addr %new-spawn)] +:: =/ tx=tx:naive [from sptx] +:: (gen-tx-octs tx) +:: ++ do-set-transfer-proxy +:: =/ from [ship=~losrut proxy=%own] +:: =/ tftx=skim-tx:naive [%set-transfer-proxy (addr %new-xfer)] +:: =/ tx=tx:naive [from tftx] +:: (gen-tx-octs tx) +:: -- +:: +:: the following tests are to ensure that padding of zeroes creates +:: no issues +:: +++ test-zod-spawn-to-zero + =/ bz-spawn [[~zod %spawn] %spawn ~binzod 0x0] + :: + %+ expect-eq + !> [0x0 0] + :: + !> + =| =^state:naive + =^ f state (init-zod state) + =^ f state (n state %bat q:(gen-tx 0 bz-spawn %zod-skey-0)) + transfer-proxy.own:(got:orm points.state ~binzod) +:: +++ test-zod-spawn-proxy + =/ bz-spawn [[~zod %spawn] %spawn ~binzod (addr %binzod-key-0)] + :: + %+ expect-eq + !> [`@ux`(addr %binzod-key-0) 0] + :: + !> + =| =^state:naive + =^ f state (init-zod state) + =^ f state (n state %bat q:(gen-tx 0 bz-spawn %zod-skey-0)) + transfer-proxy.own:(got:orm points.state ~binzod) +:: +++ test-dopzod-spawn + =/ tm-spawn [[~dopzod %own] %spawn ~tasben-monbur (addr %tm)] + :: + %+ expect-eq + !> [`@ux`(addr %tm) 0] + :: + !> + =| =^state:naive + =^ f state (init-zod state) + =^ f state (n state %bat q:(gen-tx 0 tm-spawn %dopzod-key-0)) + transfer-proxy.own:(got:orm points.state ~tasben-monbur) +:: +++ test-address-padding + :: tells ~dopzod to spawn ~tasben-monbur at 0x00000000001111111111 + =/ spawn-octs=octs + %: cad:naive 3 + 1^(can 0 3^%0 5^0 ~) :: %own proxy + 4^~dopzod + 1^%1 :: %spawn + 4^~tasben-monbur + 20^(can 3 10^0 1^1 9^0 ~) + ~ + == + =/ signed-tx=octs + %^ sign-tx %dopzod-key-0 0 spawn-octs + :: + %+ expect-eq + !> [`@ux`(can 3 10^0 1^1 9^0 ~) 0] + :: + !> + =| =^state:naive + =^ f state (init-zod state) + =^ f state (n state %bat q:signed-tx) + transfer-proxy.own:(got:orm points.state ~tasben-monbur) +:: +:: TODO: L1 tests with leading zeroes. in particular, changing +:: keys uses data.log, so keys with leading zeroes might run into +:: issues +:: +++ test-batch-generation + =, l2-event-gen + =/ marbud-transfer [marbud-own %transfer-point (addr %marbud-key-0) |] + =/ marbud-transfer-2 [marbud-own %transfer-point (addr %marbud-key-1) |] + :: + =/ tx-1=full-tx [0 marbud-transfer %marbud-key-0] + =/ tx-2=full-tx [1 marbud-transfer-2 %marbud-key-0] + =/ txs=tx-list (limo ~[tx-1 tx-2]) + %+ expect-eq + !> [(addr %marbud-key-1) 2] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (n state %bat (tx-list-to-batch txs)) + owner.own:(got:orm points.state ~marbud) +:: +++ test-changed-dns + :: uses actual data from ETH transaction + :: 0x51a26c3b100ad1c7aa8d593068df60465046d437edc3e939fadee4056791fd13 + :: + =/ data %- crip + ;: weld + "0x000000000000000000000000000000" + "00000000000000000000000000000000" + "60000000000000000000000000000000" + "00000000000000000000000000000000" + "a0000000000000000000000000000000" + "00000000000000000000000000000000" + "e0000000000000000000000000000000" + "00000000000000000000000000000000" + "0975726269742e6f7267000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "0975726269742e6f7267000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "0975726269742e6f7267000000000000" + "00000000000000000000000000000000" + "00" + == + :: + %+ expect-eq + !> `(list @t)`['urbit.org' 'urbit.org' 'urbit.org' ~] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (n state (changed-dns:l1 (hex-to-num:ethereum data))) + dns.state +:: +++ test-approval-for-all + =| operators=(jug address address) + =/ op1 (~(put ju operators) (addr %test1) (addr %test2)) + =/ del1 (~(del ju op1) (addr %test1) (addr %test2)) + =/ op2 (~(put ju op1) (addr %test1) (addr %test3)) + =/ del2 (~(del ju op2) (addr %test1) (addr %test2)) + :: + ;: weld + %+ expect-eq + !> op1 + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state + (n state (approval-for-all:l1 (addr %test1) (addr %test2) 1)) + operators.state + :: + %+ expect-eq + !> del1 + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state + (n state (approval-for-all:l1 (addr %test1) (addr %test2) 1)) + =^ f state + (n state (approval-for-all:l1 (addr %test1) (addr %test2) 0)) + operators.state + :: + %+ expect-eq + !> op2 + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state + (n state (approval-for-all:l1 (addr %test1) (addr %test2) 1)) + =^ f state + (n state (approval-for-all:l1 (addr %test1) (addr %test3) 1)) + operators.state + :: + %+ expect-eq + !> del2 + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state + (n state (approval-for-all:l1 (addr %test1) (addr %test2) 1)) + =^ f state + (n state (approval-for-all:l1 (addr %test1) (addr %test3) 1)) + =^ f state + (n state (approval-for-all:l1 (addr %test1) (addr %test2) 0)) + operators.state + == +:: +++ test-metamask-signature ^- tang + =/ meta-owner=address + (hex-to-num:ethereum '0x57694bb21054b54d55e6c03387D082B3AFf902f6') + =/ tx-octs (gen-tx-octs [from=[~marbud %own] [%transfer-point 0x1234 &]]) + :: Must reverse endianness as below for Metamask signature + :: =/ signabletx (prepare-for-sig 1.337 1 tx-octs) + :: =/ signabletx-rev (rev 3 p.signabletx q.signabletx) + :: Generated with myetherwallet w/ metamask. + =/ sig + %- hex-to-num:ethereum + %^ cat 3 '0x2c331a47caeb758c617624882d99737eea96a492bf0af7a44c42fc5fd2' + 'c535c15c36704ab91688f4ef3735ab3fbd17a15f012dfd22ce5c5de62e03657113619a1c' + :: + %+ expect-eq + !> [0x1234 2] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state + %^ n state %bat + q:(gen-tx 0 [marbud-own %transfer-point meta-owner &] %marbud-key-0) + =^ f state (n state %bat (cat 3 sig q:tx-octs)) + owner.own:(got:orm points.state ~marbud) +:: +++ test-trezor-signature ^- tang + =/ trezor-owner=address + (hex-to-num:ethereum '0x9e00bb696bb406e14706ad47535bd1a449f3611e') + =/ tx-octs (gen-tx-octs [from=[~marbud %own] [%transfer-point 0x1234 &]]) + :: Must reverse endianness as below for Trezor signature + :: =/ signabletx (prepare-for-sig 1.337 1 tx-octs) + :: =/ signabletx-rev (rev 3 p.signabletx q.signabletx) + :: Generated with myetherwallet w/ Trezor Model T. + =/ sig + %- hex-to-num:ethereum + %^ cat 3 '0xb064428c293494dbee2967c1068807a8e241185c471cd547256708fe8d' + '2860ad7e8668aac3b61115c13aad325da87ed6c9526b495b2d996d6d43c060d00b12c21b' + :: + %+ expect-eq + !> [0x1234 2] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state + %^ n state %bat + q:(gen-tx 0 [marbud-own %transfer-point trezor-owner &] %marbud-key-0) + =^ f state (n state %bat (cat 3 sig q:tx-octs)) + owner.own:(got:orm points.state ~marbud) +:: +++ test-ledger-signatures ^- tang + :: We have two tests here to account for the different format of the v byte + :: in the signature as compared to MM and Trezor - it is 00 or 01 as opposed + :: to 1b or 1c. + =/ ledger-owner-1=address + (hex-to-num:ethereum '0xd6442b0668b478f407e08ff7215262e4118ccc12') + =/ ledger-owner-2=address + (hex-to-num:ethereum '0x8c611e9061a1e7bd77acb4c9869cdbca1346f70d') + =/ tx-octs (gen-tx-octs [from=[~marbud %own] [%transfer-point 0x1234 &]]) + :: Must reverse endianness as below for Trezor signature + :: =/ signabletx (prepare-for-sig 1.337 1 tx-octs) + :: =/ signabletx-rev (rev 3 p.signabletx q.signabletx) + :: Generated with myetherwallet w/ Ledger Nano S. + =/ sig-1 + %- hex-to-num:ethereum + %^ cat 3 '0x0f95347681767f9381dc82b1f26f2dbd4ccb56a98102f548b48d919b69' + '76749b70c71e3134d309b5974532af87ceaed7161cb1cdf3147f91a86d77371547a21101' + =/ sig-2 + %- hex-to-num:ethereum + %^ cat 3 '0xecb2ccff0167b5103484cea072e398426a7bce9fffa1b98ddfecd58a2f' + '80d99804737eeda2dc67147366f510af8e8cde4a97a007cc216439002498b368e2613e00' + :: + =| init-state=^state:naive + =^ f init-state (init-marbud init-state) + ;: weld + %+ expect-eq + !> [0x1234 2] + :: + !> + =| =^state:naive + =^ f state + %^ n init-state %bat + q:(gen-tx 0 [marbud-own %transfer-point ledger-owner-1 &] %marbud-key-0) + =^ f state (n state %bat (cat 3 sig-1 q:tx-octs)) + owner.own:(got:orm points.state ~marbud) + :: + %+ expect-eq + !> [0x1234 2] + :: + !> + =| =^state:naive + =^ f state + %^ n init-state %bat + q:(gen-tx 0 [marbud-own %transfer-point ledger-owner-2 &] %marbud-key-0) + =^ f state (n state %bat (cat 3 sig-2 q:tx-octs)) + owner.own:(got:orm points.state ~marbud) + == +:: +++ test-large-batch-parse ^- tang + =/ batch-size 5.000 :: should be an even number + =/ tx-1=tx:naive [marbud-own %transfer-point (addr %marbud-key-1) |] + =/ tx-2=tx:naive [marbud-own %transfer-point (addr %marbud-key-0) |] + :: + =/ bat=octs + %+ cad:naive 3 + %+ join + (gen-tx 1 tx-2 %marbud-key-1) + (reap +((div batch-size 2)) (gen-tx 0 tx-1 %marbud-key-0)) + :: + =| =^state:naive + =^ f state (init-marbud state) + %+ expect-eq + !> +(batch-size) + :: + !> + ~& > %starting-large-parse + =/ r (parse-roll:naive q.bat) + ~& > %ending-large-parse + (lent r) +:: +++ test-large-batch-full ^- tang + :: XX bump up to 5k + :: + =/ batch-size 50 :: should be an even number + :: + =/ tx-1=tx:naive [marbud-own %transfer-point (addr %marbud-key-1) |] + =/ tx-2=tx:naive [marbud-own %transfer-point (addr %marbud-key-0) |] + =/ batch=tx-list:l2-event-gen + %+ spun (join tx-2 (reap +((div batch-size 2)) tx-1)) + |= [b=tx:naive c=@] + ?: =((mod c 2) 0) + [[c b %marbud-key-0] +(c)] + [[c b %marbud-key-1] +(c)] + :: + %+ expect-eq + !> [`@ux`(addr %marbud-key-1) +(batch-size)] + :: + !> + =| =^state:naive + =^ f state (init-marbud state) + =^ f state (n state %bat (tx-list-to-batch:l2-event-gen batch)) + owner.own:(got:orm points.state ~marbud) +:: +-- diff --git a/pkg/arvo/tests/lib/vere/dawn.hoon b/pkg/arvo/tests/lib/vere/dawn.hoon index 80e3f37e0..b33f75cb9 100644 --- a/pkg/arvo/tests/lib/vere/dawn.hoon +++ b/pkg/arvo/tests/lib/vere/dawn.hoon @@ -29,15 +29,6 @@ %+ weld "0x" (render-hex-bytes:ethereum 20 `@`azimuth:contracts:^azimuth) :: -++ test-give-bloq - =/ oct - %- as-octs:mimes:html - '{"params":[],"id":"0","jsonrpc":"2.0","method":"eth_blockNumber"}' - %+ expect-eq - !> oct - !> bloq:give:dawn -:: this produces a 1000+ line payload, so we just check that it doesn't crash -:: ++ test-give-czar =/ zar czar:give:dawn ~! zar @@ -45,146 +36,6 @@ !> & !> ?=(^ zar) :: -++ test-give-point - =/ oct - %- as-octs:mimes:html - %+ rap 3 - :~ '{"params":[{"to":"' azimuth '","data":"' - '0x63fa9a87' - '0000000000000000000000000000000000000000000000000000000000000000' - '"},"0x0"],"id":"0","jsonrpc":"2.0","method":"eth_call"}' - == - %+ expect-eq - !> oct - !> (point:give:dawn 0 ~zod) -:: -++ test-give-turf - =/ oct - %- as-octs:mimes:html - %+ rap 3 - :~ '[{"params":[{"to":"' azimuth '","data":"' - '0xeccc8ff1' - '0000000000000000000000000000000000000000000000000000000000000000' - '"},"0x0"],"id":"turf-0","jsonrpc":"2.0","method":"eth_call"},' - '{"params":[{"to":"' azimuth '","data":"' - '0xeccc8ff1' - '0000000000000000000000000000000000000000000000000000000000000001' - '"},"0x0"],"id":"turf-1","jsonrpc":"2.0","method":"eth_call"},' - '{"params":[{"to":"' azimuth '","data":"' - '0xeccc8ff1' - '0000000000000000000000000000000000000000000000000000000000000002' - '"},"0x0"],"id":"turf-2","jsonrpc":"2.0","method":"eth_call"}]' - == - %+ expect-eq - !> oct - !> (turf:give:dawn 0) -:: -++ test-take-bloq - =/ oct - %- as-octs:mimes:html - '{"id":"0","jsonrpc":"2.0","result":"0x20"}' - =/ boq 32 - %+ expect-eq - !> [~ boq] - !> (bloq:take:dawn oct) -:: -++ test-take-czar - =/ oct - %- as-octs:mimes:html - %+ rap 3 - :~ '[{"id":"gal-0","jsonrpc":"2.0","result":"' - '0xb69b6818b17b7cc22f8e0a2291f58e4aa840cbf44cb2f1c94dc3d71e3cda0d94' - '3defb87516f42ce4327820b588002aa53e52527af8d23bee4aa215fa296bdf5f' - '0000000000000000000000000000000000000000000000000000000000000001' - '0000000000000000000000000000000000000000000000000000000000000001' - '0000000000000000000000000000000000000000000000000000000000000000' - '0000000000000000000000000000000000000000000000000000000000000000' - '0000000000000000000000000000000000000000000000000000000000000000' - '0000000000000000000000000000000000000000000000000000000000000001' - '0000000000000000000000000000000000000000000000000000000000000001' - '0000000000000000000000000000000000000000000000000000000000000002' - '"},{"id":"gal-1","jsonrpc":"2.0","result":"' - '0xb727e38d031162e50913b2e37a2e29d4ba457eff4f7fd4ac47dc68fcb54260d3' - 'b8bfe4789483c171f7fa359438cdcc8d268d40fe08d6c1d8b36267748d2139f8' - '0000000000000000000000000000000000000000000000000000000000000001' - '0000000000000000000000000000000000000000000000000000000000000001' - '0000000000000000000000000000000000000000000000000000000000000000' - '0000000000000000000000000000000000000000000000000000000000000000' - '0000000000000000000000000000000000000000000000000000000000000000' - '0000000000000000000000000000000000000000000000000000000000000001' - '0000000000000000000000000000000000000000000000000000000000000001' - '0000000000000000000000000000000000000000000000000000000000000003' - '"},{"id":"gal-2","jsonrpc":"2.0","result":"' - '0x0000000000000000000000000000000000000000000000000000000000000000' - '0000000000000000000000000000000000000000000000000000000000000000' - '0000000000000000000000000000000000000000000000000000000000000001' - '0000000000000000000000000000000000000000000000000000000000000001' - '0000000000000000000000000000000000000000000000000000000000000000' - '0000000000000000000000000000000000000000000000000000000000000000' - '0000000000000000000000000000000000000000000000000000000000000000' - '0000000000000000000000000000000000000000000000000000000000000001' - '0000000000000000000000000000000000000000000000000000000000000001' - '0000000000000000000000000000000000000000000000000000000000000004' - '"}]' - == - =/ kyz - ^- [zod=pass nec=pass] - :- 2.448.360.348.730.164.860.814.441.775.703.143.856.915.192.920.639.124. - 529.297.987.279.849.833.790.775.864.413.949.853.880.667.744.188.597.545. - 066.664.466.963.044.328.182.155.965.137.512.758.548.384.637.214.562 - :: - 2.455.718.000.840.284.920.492.237.722.671.938.413.341.955.411.945.312. - 638.361.167.187.097.711.481.986.932.531.569.955.478.938.087.263.286.158. - 823.313.739.767.009.446.819.531.923.255.637.798.148.055.143.938.146 - %+ expect-eq - !> :- ~ - %- ~(gas by *(map ship [=rift =life =pass])) - [[~zod 2 1 zod.kyz] [~nec 3 1 nec.kyz] [~bud 4 1 'b'] ~] - !> (czar:take:dawn oct) -:: -++ test-take-point - =/ oct - %- as-octs:mimes:html - %+ rap 3 - :~ '{"jsonrpc":"2.0","result":"' - '0xb69b6818b17b7cc22f8e0a2291f58e4aa840cbf44cb2f1c94dc3d71e3cda0d94' - '3defb87516f42ce4327820b588002aa53e52527af8d23bee4aa215fa296bdf5f' - '0000000000000000000000000000000000000000000000000000000000000001' - '0000000000000000000000000000000000000000000000000000000000000001' - '0000000000000000000000000000000000000000000000000000000000000000' - '0000000000000000000000000000000000000000000000000000000000000000' - '0000000000000000000000000000000000000000000000000000000000000000' - '0000000000000000000000000000000000000000000000000000000000000001' - '0000000000000000000000000000000000000000000000000000000000000001' - '0000000000000000000000000000000000000000000000000000000000000000' - '"}' - == - %+ expect-eq - !> [~ pot] - !> (point:take:dawn ~zod oct) -:: -++ test-take-turf - =/ oct - %- as-octs:mimes:html - %+ rap 3 - :~ '[{"id":"turf-0","jsonrpc":"2.0","result":"' - '0x0000000000000000000000000000000000000000000000000000000000000020' - '0000000000000000000000000000000000000000000000000000000000000009' - '75726269742e6f72670000000000000000000000000000000000000000000000' - '"},{"id":"turf-1","jsonrpc":"2.0","result":"' - '0x0000000000000000000000000000000000000000000000000000000000000020' - '0000000000000000000000000000000000000000000000000000000000000009' - '75726269742e6f72670000000000000000000000000000000000000000000000' - '"},{"id":"turf-2","jsonrpc":"2.0","result":"' - '0x0000000000000000000000000000000000000000000000000000000000000020' - '0000000000000000000000000000000000000000000000000000000000000009' - '75726269742e6f72670000000000000000000000000000000000000000000000' - '"}]' - == - %+ expect-eq - !> [~ [/org/urbit ~]] - !> (turf:take:dawn oct) -:: ++ test-veri-good =/ sed [~zod 1 sec ~] %+ expect-eq diff --git a/pkg/arvo/tests/sys/zuse/title.hoon b/pkg/arvo/tests/sys/zuse/title.hoon new file mode 100644 index 000000000..086715035 --- /dev/null +++ b/pkg/arvo/tests/sys/zuse/title.hoon @@ -0,0 +1,28 @@ +:: tests for |title +:: +/+ *test +=, title +|% +++ test-cite + ;: weld + %+ expect-eq + !> "~zod^" + !> (cite ~dister-dozzod-dozzod) + :: + %+ expect-eq + !> "~marzod^" + !> (cite ~dister-dozzod-marzod) + :: + %+ expect-eq + !> "~palfun^foslup" + !> (cite ~littel-palfun-foslup) + :: + %+ expect-eq + !> "~palfun^foslup" + !> (cite ~littel-bittel-palfun-foslup) + :: + %+ expect-eq + !> "~sampel_sampel" + !> (cite ~sampel--dozzod-dozzod-dozzod-sampel) + == +-- diff --git a/pkg/arvo/tmp/base.jam b/pkg/arvo/tmp/base.jam deleted file mode 100644 index 435ca593f..000000000 --- a/pkg/arvo/tmp/base.jam +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1d227633641c8abb68d16633e110467fd4a4330c921496312d75b471677e2a02 -size 3057639 diff --git a/pkg/arvo/tmp/bitcoin.jam b/pkg/arvo/tmp/bitcoin.jam deleted file mode 100644 index 87e36bb36..000000000 --- a/pkg/arvo/tmp/bitcoin.jam +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:66e64f702b542347f1d8e267dc87c542e3f8f537278f6a221aa6d7d793b21d55 -size 461160 diff --git a/pkg/arvo/tmp/garden.jam b/pkg/arvo/tmp/garden.jam deleted file mode 100644 index bc3a6971f..000000000 --- a/pkg/arvo/tmp/garden.jam +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fb475f30c6d6c68b3c31ce46155a1e3d98b18359b6750b7bb6b00e429187e1ef -size 376635 diff --git a/pkg/arvo/tmp/landscape.jam b/pkg/arvo/tmp/landscape.jam deleted file mode 100644 index f31d727ea..000000000 --- a/pkg/arvo/tmp/landscape.jam +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:45a54c6e05e3db80b3cc9746a65f185da29d8644d7a0bf953fade9f15a78dad4 -size 1812725 diff --git a/pkg/arvo/tmp/webterm.jam b/pkg/arvo/tmp/webterm.jam deleted file mode 100644 index 726d88c1a..000000000 --- a/pkg/arvo/tmp/webterm.jam +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8fe9b7b9b38fa7f16f8ec234984c44c616856937eff50353e11eb62c173f6b09 -size 306377 diff --git a/pkg/base-dev/desk.bill b/pkg/base-dev/desk.bill deleted file mode 100644 index 7f45256db..000000000 --- a/pkg/base-dev/desk.bill +++ /dev/null @@ -1,5 +0,0 @@ -:~ :- %apes - ~ - :- %fish - ~ -== diff --git a/pkg/base-dev/lib/ethereum.hoon b/pkg/base-dev/lib/ethereum.hoon index a7ba9fd84..c292eec3d 100644 --- a/pkg/base-dev/lib/ethereum.hoon +++ b/pkg/base-dev/lib/ethereum.hoon @@ -553,7 +553,9 @@ top=(list ?(@ux (list @ux))) == [%eth-get-filter-changes fid=@ud] + [%eth-get-transaction-by-hash txh=@ux] [%eth-get-transaction-count adr=address =block] + [%eth-get-balance adr=address =block] [%eth-get-transaction-receipt txh=@ux] [%eth-send-raw-transaction dat=@ux] == @@ -569,10 +571,20 @@ [%eth-transaction-hash haz=@ux] == :: + ++ transaction-result + $: block-hash=(unit @ux) + block-number=(unit @ud) + transaction-index=(unit @ud) + from=@ux + to=(unit @ux) + input=@t + == + :: ++ event-log $: :: null for pending logs $= mined %- unit - $: log-index=@ud + $: input=(unit @ux) + log-index=@ud transaction-index=@ud transaction-hash=@ux block-number=@ud @@ -778,6 +790,15 @@ :~ (tape (address-to-hex adr.req)) (block-to-json block.req) == + :: + %eth-get-balance + :- 'eth_getBalance' + :~ (tape (address-to-hex adr.req)) + (block-to-json block.req) + == + :: + %eth-get-transaction-by-hash + ['eth_getTransactionByHash' (tape (transaction-to-hex txh.req)) ~] :: %eth-get-transaction-receipt ['eth_getTransactionReceipt' (tape (transaction-to-hex txh.req)) ~] @@ -854,6 +875,8 @@ :: ++ parse-eth-get-transaction-count parse-hex-result :: + ++ parse-eth-get-balance parse-hex-result + :: ++ parse-event-logs (ar:dejs:format parse-event-log) :: @@ -865,7 +888,7 @@ :~ =- ['logIndex'^(cu - (mu so))] |= li=(unit @t) ?~ li ~ - =- `((ou -) log) ::TODO not sure if elegant or hacky. + =- ``((ou -) log) ::TODO not sure if elegant or hacky. :~ 'logIndex'^(un (cu hex-to-num so)) 'transactionIndex'^(un (cu hex-to-num so)) 'transactionHash'^(un (cu hex-to-num so)) @@ -884,6 +907,27 @@ :- (hex-to-num i.r) (turn t.r hex-to-num) == + :: + ++ parse-transaction-result + =, dejs:format + |= jon=json + ~| jon=jon + ^- transaction-result + =- ((ot -) jon) + :~ 'blockHash'^_~ :: TODO: fails if maybe-num? + 'blockNumber'^maybe-num + 'transactionIndex'^maybe-num + from+(cu hex-to-num so) + to+maybe-num + input+so + == + :: + ++ maybe-num + =, dejs:format + =- (cu - (mu so)) + |= r=(unit @t) + ?~ r ~ + `(hex-to-num u.r) -- :: :: utilities diff --git a/pkg/base-dev/lib/ethio.hoon b/pkg/base-dev/lib/ethio.hoon index a377290e3..0e4c7793e 100644 --- a/pkg/base-dev/lib/ethio.hoon +++ b/pkg/base-dev/lib/ethio.hoon @@ -108,16 +108,25 @@ ++ parse-one-response |= =json ^- (unit response:rpc) - =/ res=(unit [@t ^json]) + ?. &(?=([%o *] json) (~(has by p.json) 'error')) + =/ res=(unit [@t ^json]) + %. json + =, dejs-soft:format + (ot id+so result+some ~) + ?~ res ~ + `[%result u.res] + ~| parse-one-response=json + =/ error=(unit [id=@t ^json code=@ta mssg=@t]) %. json =, dejs-soft:format - (ot id+so result+some ~) - ?^ res `[%result u.res] - ~| parse-one-response=json - :+ ~ %error %- need - %. json - =, dejs-soft:format - (ot id+so error+(ot code+no message+so ~) ~) + :: A 'result' member is present in the error + :: response when using ganache, even though + :: that goes against the JSON-RPC spec + :: + (ot id+so result+some error+(ot code+no message+so ~) ~) + ?~ error ~ + =* err u.error + `[%error id.err code.err mssg.err] -- :: :: +read-contract: calls a read function on a contract, produces result hex @@ -209,6 +218,19 @@ ++ parse-hex |=(=json `(unit @)`(some (parse-hex-result:rpc:ethereum json))) -- :: +++ get-tx-by-hash + |= [url=@ta tx-hash=@ux] + =/ m (strand:strandio transaction-result:rpc:ethereum) + ^- form:m + ;< =json bind:m + %+ request-rpc url + :* `'tx by hash' + %eth-get-transaction-by-hash + tx-hash + == + %- pure:m + (parse-transaction-result:rpc:ethereum json) +:: ++ get-logs-by-hash |= [url=@ta =hash:block contracts=(list address) =topics] =/ m (strand:strandio (list event-log:rpc:ethereum)) @@ -254,4 +276,14 @@ [%eth-get-transaction-count address [%label %latest]] %- pure:m (parse-eth-get-transaction-count:rpc:ethereum json) +:: +++ get-balance + |= [url=@ta =address] + =/ m (strand:strandio ,@ud) + ^- form:m + ;< =json bind:m + %^ request-rpc url `'balance' + [%eth-get-balance address [%label %latest]] + %- pure:m + (parse-eth-get-balance:rpc:ethereum json) -- diff --git a/pkg/base-dev/sur/hood.hoon b/pkg/base-dev/sur/hood.hoon index 420276243..7ef167bf1 100644 --- a/pkg/base-dev/sur/hood.hoon +++ b/pkg/base-dev/sur/hood.hoon @@ -191,7 +191,7 @@ == ^- [jolt=(list dude) idle=(list dude)] =/ all=(list dude) (read-bill local) - =/ want (get-apps-want all rein) + =/ want (get-apps-want local all rein) =/ have (get-apps-live local) [want (skip have ~(has in (sy want)))] :: @@ -223,8 +223,10 @@ :: +get-apps-want: find which apps should be running on a desk :: ++ get-apps-want - |= [duz=(list dude) =rein] + |= [local=[our=ship =desk now=@da] duz=(list dude) =rein] ^- (list dude) + ?. liv.rein ~ + ?. |(=(`zuse+zuse (read-kelvin-local local)) =(%base desk.local)) ~ =. duz (skip duz ~(has in sub.rein)) =. duz (weld duz (skip ~(tap in add.rein) ~(has in (sy duz)))) duz diff --git a/pkg/base-dev/sur/json/rpc.hoon b/pkg/base-dev/sur/json/rpc.hoon index 350f2cae1..1c99b0f0a 100644 --- a/pkg/base-dev/sur/json/rpc.hoon +++ b/pkg/base-dev/sur/json/rpc.hoon @@ -1,14 +1,21 @@ :: json-rpc: protocol types :: |% ++$ batch-request + $% [%a p=(list request)] + [%o p=request] + == +:: +$ 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/bitcoin/sys.kelvin b/pkg/bitcoin/sys.kelvin index b7464903a..e68acb6a4 100644 --- a/pkg/bitcoin/sys.kelvin +++ b/pkg/bitcoin/sys.kelvin @@ -1 +1 @@ -[%zuse 420] +[%zuse 419] diff --git a/pkg/garden/app/settings-store.hoon b/pkg/garden/app/settings-store.hoon index b6c8808c4..33f9acf6b 100644 --- a/pkg/garden/app/settings-store.hoon +++ b/pkg/garden/app/settings-store.hoon @@ -24,11 +24,7 @@ def ~(. (default-agent this %|) bol) io ~(. agentio bol) :: - ++ on-init - ^- (quip card _this) - =^ cards state - (put-entry:do q.byk.bol %tutorial %seen b+|) - [cards this] + ++ on-init on-init:def :: ++ on-save !>(state) :: diff --git a/pkg/garden/desk.docket-0 b/pkg/garden/desk.docket-0 index be2d8630d..8c07fb65c 100644 --- a/pkg/garden/desk.docket-0 +++ b/pkg/garden/desk.docket-0 @@ -1,10 +1,10 @@ :~ title+'System' info+'An app launcher for Urbit.' color+0xee.5432 - glob-http+['https://bootstrap.urbit.org/glob-0v5.fdf99.nph65.qecq3.ncpjn.q13mb.glob' 0v5.fdf99.nph65.qecq3.ncpjn.q13mb] + glob-http+['https://bootstrap.urbit.org/glob-0v4.64ana.19ug9.ik7l6.og080.68ce4.glob' 0v4.64ana.19ug9.ik7l6.og080.68ce4] ::glob-ames+~zod^0v0 base+'grid' - version+[1 0 0] + version+[1 0 2] website+'https://tlon.io' license+'MIT' == diff --git a/pkg/garden/sys.kelvin b/pkg/garden/sys.kelvin index b7464903a..e68acb6a4 100644 --- a/pkg/garden/sys.kelvin +++ b/pkg/garden/sys.kelvin @@ -1 +1 @@ -[%zuse 420] +[%zuse 419] diff --git a/pkg/grid/src/app.tsx b/pkg/grid/src/app.tsx index 65371fd88..c18188296 100644 --- a/pkg/grid/src/app.tsx +++ b/pkg/grid/src/app.tsx @@ -49,8 +49,6 @@ const AppRoutes = () => { } }, [isDarkMode, theme]); - useEffect(() => {}, []); - useEffect( handleError(() => { window.name = 'grid'; diff --git a/pkg/grid/src/nav/Leap.tsx b/pkg/grid/src/nav/Leap.tsx index 526cbd3a0..6475e09e2 100644 --- a/pkg/grid/src/nav/Leap.tsx +++ b/pkg/grid/src/nav/Leap.tsx @@ -227,6 +227,7 @@ export const Leap = React.forwardRef( [selection, rawInput, match, matches, selectedMatch] ); + return (
- {selection || 'Search'} + {menu === 'upgrading' + ? 'Your Urbit is being updated, this page will update when ready' + : selection || 'Search'} - + {menu !== 'upgrading' ? ( + + ) : null}
{menu === 'search' && ( = ({ menu }) => { const select = useLeapStore((state) => state.select); const menuState = menu || 'closed'; - const isOpen = menuState !== 'closed'; + const isOpen = menuState !== 'upgrading' && menuState !== 'closed'; const eitherOpen = isOpen || systemMenuOpen; useEffect(() => { diff --git a/pkg/grid/src/nav/notifications/Inbox.tsx b/pkg/grid/src/nav/notifications/Inbox.tsx index 66299772c..4661f884e 100644 --- a/pkg/grid/src/nav/notifications/Inbox.tsx +++ b/pkg/grid/src/nav/notifications/Inbox.tsx @@ -12,7 +12,7 @@ function renderNotification(notification: Notification, key: string, lid: HarkLi if (notification.bin.place.path === '/lag') { return ; } - if (notification.bin.place.path === '/blocked') { + if (notification.bin.path === '/blocked' && notification.bin.place.path === '/desk/base') { return ; } if (notification.bin.place.path === '/onboard') { diff --git a/pkg/grid/src/nav/notifications/SystemNotification.tsx b/pkg/grid/src/nav/notifications/SystemNotification.tsx index 5bc951849..c92822ae8 100644 --- a/pkg/grid/src/nav/notifications/SystemNotification.tsx +++ b/pkg/grid/src/nav/notifications/SystemNotification.tsx @@ -1,4 +1,4 @@ -import { pick } from 'lodash'; +import { pick, pickBy, partition } from 'lodash'; import React, { useCallback } from 'react'; import { kilnBump } from '@urbit/api'; import { AppList } from '../../components/AppList'; @@ -7,9 +7,12 @@ import { Dialog, DialogClose, DialogContent, DialogTrigger } from '../../compone import { Elbow } from '../../components/icons/Elbow'; import api from '../../state/api'; import { useCharges } from '../../state/docket'; +import useKilnState, { useVat } from '../../state/kiln'; import { NotificationButton } from './NotificationButton'; import { disableDefault } from '../../state/util'; +import { Vat } from '@urbit/api'; +import {useHistory} from 'react-router-dom'; export const RuntimeLagNotification = () => (
(
); +function vatIsBlocked(newKelvin: number, vat: Vat) { + return !(vat.arak?.rail?.next || []).find(({ aeon, weft }) => weft.kelvin === newKelvin); +} + export const BaseBlockedNotification = () => { - const desks: string[] = []; + const base = useVat('base'); + const { push } = useHistory(); + // TODO: assert weft.name === 'zuse'?? + const newKelvin = base?.arak?.rail?.next?.[0]?.weft?.kelvin || 420; const charges = useCharges(); - const blockedCharges = Object.values(pick(charges, desks)); + const [blocked, unblocked] = useKilnState((s) => { + const [b, u] = partition(Object.entries(s.vats), ([desk, vat]) => vatIsBlocked(newKelvin, vat)); + return [b.map(([d]) => d), u.map(([d]) => d)] as const; + }); + + const blockedCharges = Object.values(pick(charges, blocked)); const count = blockedCharges.length; const handlePauseOTAs = useCallback(() => {}, []); const handleArchiveApps = useCallback(async () => { api.poke(kilnBump(true)); + push('/leap/upgrading'); }, []); return ( diff --git a/pkg/grid/src/pages/Grid.tsx b/pkg/grid/src/pages/Grid.tsx index 1ad02a9cc..9c3c6c756 100644 --- a/pkg/grid/src/pages/Grid.tsx +++ b/pkg/grid/src/pages/Grid.tsx @@ -1,27 +1,51 @@ import { map, omit } from 'lodash'; -import React, { FunctionComponent } from 'react'; +import React, { FunctionComponent, useEffect } from 'react'; import { ErrorBoundary } from 'react-error-boundary'; -import { Route, RouteComponentProps } from 'react-router-dom'; +import { Route, RouteComponentProps, useHistory, useParams } from 'react-router-dom'; import { ErrorAlert } from '../components/ErrorAlert'; import { MenuState, Nav } from '../nav/Nav'; import { useCharges } from '../state/docket'; +import useKilnState from '../state/kiln'; import { RemoveApp } from '../tiles/RemoveApp'; import { SuspendApp } from '../tiles/SuspendApp'; import { Tile } from '../tiles/Tile'; import { TileInfo } from '../tiles/TileInfo'; -type GridProps = RouteComponentProps<{ +interface RouteProps { menu?: MenuState; -}>; +} -export const Grid: FunctionComponent = ({ match, history }) => { +export const Grid: FunctionComponent<{}> = () => { const charges = useCharges(); + const { push } = useHistory(); + const { menu } = useParams(); const chargesLoaded = Object.keys(charges).length > 0; + useEffect(() => { + // TOOD: rework + // Heuristically detect reload completion and redirect + async function attempt(count = 0) { + if(count > 5) { + window.location.reload(); + } + const start = performance.now(); + await useKilnState.getState().fetchVats(); + await useKilnState.getState().fetchVats(); + if((performance.now() - start) > 5000) { + attempt(count+1); + } else { + push('/'); + } + } + if(menu === 'upgrading') { + attempt(); + } + }, [menu]) + return (
-
@@ -30,11 +54,11 @@ export const Grid: FunctionComponent = ({ match, history }) => {
{charges && map(omit(charges, window.desk), (charge, desk) => ( - + ))}
)} - history.push('/')}> + push('/')}> diff --git a/pkg/grid/src/state/mock-data.ts b/pkg/grid/src/state/mock-data.ts index 44240b3f3..f21d638d8 100644 --- a/pkg/grid/src/state/mock-data.ts +++ b/pkg/grid/src/state/mock-data.ts @@ -241,7 +241,17 @@ function createMockSysNotification(path: string, body: HarkBody[] = []) { } const lag = createMockSysNotification('/lag'); -const blocked = createMockSysNotification('/blocked'); +const blocked = { + bin: { + place: { + desk: window.desk, + path: '/desk/base' + }, + path: '/blocked' + }, + time: Date.now() - 3_600, + body: [] +}; const onboard = createMockSysNotification('/onboard'); const updateNotification = createMockSysNotification('/desk/bitcoin', [ diff --git a/pkg/grid/src/tiles/RemoveApp.tsx b/pkg/grid/src/tiles/RemoveApp.tsx index 4f0783091..a2357d03d 100644 --- a/pkg/grid/src/tiles/RemoveApp.tsx +++ b/pkg/grid/src/tiles/RemoveApp.tsx @@ -22,16 +22,19 @@ export const RemoveApp = () => { return ( !open && history.push('/')}> -

Remove “{getAppName(docket)}”?

+

Uninstall “{getAppName(docket)}”?

- This will remove the software's tile from your home screen. + The app tile will be removed from Landscape, all processes will be stopped and their data archived, and the app will stop receiving updates. +

+

+ If the app is reinstalled, the archived data will be restored and you'll be able to pick up where you left off.

Cancel - Remove “{getAppName(docket)}” + Uninstall
diff --git a/pkg/grid/src/tiles/SuspendApp.tsx b/pkg/grid/src/tiles/SuspendApp.tsx index c8c3e4732..a31c65cfd 100644 --- a/pkg/grid/src/tiles/SuspendApp.tsx +++ b/pkg/grid/src/tiles/SuspendApp.tsx @@ -27,15 +27,17 @@ export const SuspendApp = () => {

Suspend “{getAppName(charge)}”

- Suspending an app will turn off automatic updates. You cannot use an app when it is - suspended, but you can resume it at any time. + All processes will be stopped and data archived. The app will continue to receive updates from its publisher. +

+

+ When unsuspended, archived data will be loaded and all processes will resume running, so you can pick up where you left off.

Cancel - Suspend “{getAppName(charge)}” + Suspend
diff --git a/pkg/grid/src/tiles/Tile.tsx b/pkg/grid/src/tiles/Tile.tsx index 45280d70f..ce172926f 100644 --- a/pkg/grid/src/tiles/Tile.tsx +++ b/pkg/grid/src/tiles/Tile.tsx @@ -13,19 +13,20 @@ import { Bullet } from '../components/icons/Bullet'; type TileProps = { charge: ChargeWithDesk; desk: string; + disabled?: boolean; }; -export const Tile: FunctionComponent = ({ charge, desk }) => { +export const Tile: FunctionComponent = ({ charge, desk, disabled = false }) => { const addRecentApp = useRecentsStore((state) => state.addRecentApp); const { title, image, color, chad, href } = charge; const vat = useVat(desk); const { lightText, tileColor, menuColor, suspendColor, suspendMenuColor } = useTileColor(color); - const loading = 'install' in chad; - const suspended = 'suspend' in chad; + const loading = !disabled && 'install' in chad; + const suspended = disabled || 'suspend' in chad; const hung = 'hung' in chad; - const active = chadIsRunning(chad); + const active = !disabled && chadIsRunning(chad); const link = getAppHref(href); - const backgroundColor = active ? tileColor || 'purple' : suspendColor; + const backgroundColor = suspended ? suspendColor : active ? tileColor || 'purple' : suspendColor; return ( = ({ charge, desk }) => { <> {loading && } - {suspended && 'Suspended'} - {loading && 'Installing'} - {hung && 'Errored'} + {suspended ? 'Suspended' : loading ? 'Installing' : hung ? 'Errored' : null } )}
- {vat?.arak.rail?.paused && ( + {vat?.arak.rail?.paused && !disabled && ( )} toggleDocket(desk)}>Resume App} - Remove App + Uninstall App diff --git a/pkg/hs/urbit-king/lib/Urbit/Vere/Pier.hs b/pkg/hs/urbit-king/lib/Urbit/Vere/Pier.hs index 24e7bb7ff..3cad0b976 100644 --- a/pkg/hs/urbit-king/lib/Urbit/Vere/Pier.hs +++ b/pkg/hs/urbit-king/lib/Urbit/Vere/Pier.hs @@ -439,7 +439,7 @@ data PierVersionNegotiationFailed = PierVersionNegotiationFailed deriving (Show, Exception) zuseVersion :: Word -zuseVersion = 420 +zuseVersion = 419 wyrd :: HasKingEnv e => RIO e Ev wyrd = do diff --git a/pkg/hs/urbit-king/package.yaml b/pkg/hs/urbit-king/package.yaml index caabc0000..65b932f7d 100644 --- a/pkg/hs/urbit-king/package.yaml +++ b/pkg/hs/urbit-king/package.yaml @@ -1,5 +1,5 @@ name: urbit-king -version: 1.6 +version: 1.8 license: MIT license-file: LICENSE data-files: diff --git a/pkg/interface/config/webpack.dev.js b/pkg/interface/config/webpack.dev.js index 41d412e1a..eb024c458 100644 --- a/pkg/interface/config/webpack.dev.js +++ b/pkg/interface/config/webpack.dev.js @@ -111,11 +111,6 @@ module.exports = { 'process.env.LANDSCAPE_SHORTHASH': JSON.stringify(GIT_DESC), 'process.env.LANDSCAPE_STORAGE_VERSION': JSON.stringify(Date.now()), 'process.env.LANDSCAPE_LAST_WIPE': JSON.stringify('2021-10-20'), - 'process.env.TUTORIAL_HOST': JSON.stringify('~difmex-passed'), - 'process.env.TUTORIAL_GROUP': JSON.stringify('beginner-island'), - 'process.env.TUTORIAL_CHAT': JSON.stringify('introduce-yourself-7010'), - 'process.env.TUTORIAL_BOOK': JSON.stringify('guides-9684'), - 'process.env.TUTORIAL_LINKS': JSON.stringify('community-articles-2143') }), // new CleanWebpackPlugin(), diff --git a/pkg/interface/config/webpack.prod.js b/pkg/interface/config/webpack.prod.js index 812e9bef6..e19f35744 100644 --- a/pkg/interface/config/webpack.prod.js +++ b/pkg/interface/config/webpack.prod.js @@ -75,11 +75,6 @@ module.exports = { 'process.env.LANDSCAPE_SHORTHASH': JSON.stringify(GIT_DESC), 'process.env.LANDSCAPE_STORAGE_VERSION': Date.now().toString(), 'process.env.LANDSCAPE_LAST_WIPE': '2021-10-20', - 'process.env.TUTORIAL_HOST': JSON.stringify('~difmex-passed'), - 'process.env.TUTORIAL_GROUP': JSON.stringify('beginner-island'), - 'process.env.TUTORIAL_CHAT': JSON.stringify('introduce-yourself-7010'), - 'process.env.TUTORIAL_BOOK': JSON.stringify('guides-9684'), - 'process.env.TUTORIAL_LINKS': JSON.stringify('community-articles-2143') }), new HtmlWebpackPlugin({ title: 'Groups', diff --git a/pkg/interface/src/logic/lib/omnibox.ts b/pkg/interface/src/logic/lib/omnibox.ts index c7ad00812..9febb443f 100644 --- a/pkg/interface/src/logic/lib/omnibox.ts +++ b/pkg/interface/src/logic/lib/omnibox.ts @@ -93,7 +93,6 @@ const otherIndex = function(config) { messages: result('Messages', '/~landscape/messages', 'messages', null), logout: result('Log Out', '/~/logout', 'logout', null) }; - other.push(result('Tutorial', '/?tutorial=true', 'tutorial', null)); for(const cat of config.categories) { if(idx[cat]) { other.push(idx[cat]); diff --git a/pkg/interface/src/logic/lib/tutorialModal.ts b/pkg/interface/src/logic/lib/tutorialModal.ts deleted file mode 100644 index 81908f4ee..000000000 --- a/pkg/interface/src/logic/lib/tutorialModal.ts +++ /dev/null @@ -1,173 +0,0 @@ -import { Associations } from '@urbit/api'; -import { AlignX, AlignY } from '~/logic/lib/relativePosition'; -import { TutorialProgress } from '~/types'; -import { Direction } from '~/views/components/Triangle'; - -export const MODAL_WIDTH = 256; -export const MODAL_HEIGHT = 256; -export const MODAL_WIDTH_PX = `${MODAL_WIDTH}px`; -export const MODAL_HEIGHT_PX = `${MODAL_HEIGHT}px`; - -export const TUTORIAL_HOST = process.env.TUTORIAL_HOST!; -export const TUTORIAL_GROUP = process.env.TUTORIAL_GROUP!; -export const TUTORIAL_CHAT = process.env.TUTORIAL_CHAT!; -export const TUTORIAL_BOOK = process.env.TUTORIAL_BOOK!; -export const TUTORIAL_LINKS = process.env.TUTORIAL_LINKS!; -export const TUTORIAL_GROUP_RESOURCE = `/ship/${TUTORIAL_HOST}/${TUTORIAL_GROUP}` ; - -interface StepDetail { - title: string; - description: string; - url: string; - alignX: AlignX | AlignX[]; - alignY: AlignY | AlignY[]; - offsetX: number; - offsetY: number; - arrow?: Direction; -} - -export function hasTutorialGroup(props: { associations: Associations }) { - return ( - TUTORIAL_GROUP_RESOURCE in props.associations.groups - ); -} - -export const getTrianglePosition = (dir: Direction) => { - const midY = `${MODAL_HEIGHT / 2 - 8}px`; - const midX = `${MODAL_WIDTH / 2 - 8}px`; - switch(dir) { - case 'East': - return { - top: midY, - right: '-32px' - }; - case 'West': - return { - top: midY, - left: '-32px' - }; - case 'North': - return { - top: '-32px', - left: midX - }; - case 'South': - return { - bottom: '-32px', - left: midX - }; - } -}; - -export const progressDetails: Record = { - hidden: {} as any, - exit: {} as any, - done: { - title: 'End', - description: - 'This tutorial is finished. Would you like to leave Beginner Island?', - url: '/', - alignX: 'right', - alignY: 'top', - offsetX: MODAL_WIDTH + 8, - offsetY: 0 - }, - start: { - title: 'New Group added', - description: - 'We just added you to the Beginner island group to show you around. This group is public, but other groups can be private', - url: '/', - alignX: 'right', - alignY: 'top', - arrow: 'West', - offsetX: MODAL_WIDTH + 24, - offsetY: 64 - }, - 'group-desc': { - title: 'What\'s a group', - description: - 'A group contains members and tends to be centered around a topic or multiple topics.', - url: `/~landscape/ship/${TUTORIAL_HOST}/${TUTORIAL_GROUP}`, - alignX: 'left', - alignY: 'top', - arrow: 'East', - offsetX: MODAL_WIDTH + 24, - offsetY: 80 - }, - channels: { - title: 'Channels', - description: - 'Inside a group you have three types of Channels: Chat, Collection, or Notebook. Mix and match these depending on your group context!', - url: `/~landscape/ship/${TUTORIAL_HOST}/${TUTORIAL_GROUP}`, - alignY: 'top', - alignX: 'right', - arrow: 'West', - offsetX: MODAL_WIDTH + 24, - offsetY: -8 - }, - chat: { - title: 'Chat', - description: - 'Chat channels are for messaging within your group. Direct Messages can be accessed from Messages in the top right', - url: `/~landscape/ship/${TUTORIAL_HOST}/${TUTORIAL_GROUP}/resource/chat/ship/${TUTORIAL_HOST}/${TUTORIAL_CHAT}`, - alignY: 'top', - arrow: 'North', - alignX: 'right', - offsetY: -56, - offsetX: -8 - }, - link: { - title: 'Collection', - description: - 'A collection is where you can share and view links, images, and other media within your group. Every item in a Collection can have it’s own comment thread.', - url: `/~landscape/ship/${TUTORIAL_HOST}/${TUTORIAL_GROUP}/resource/link/ship/${TUTORIAL_HOST}/${TUTORIAL_LINKS}`, - alignY: 'top', - alignX: 'right', - arrow: 'North', - offsetX: -8, - offsetY: -56 - }, - publish: { - title: 'Notebook', - description: - 'Notebooks are for creating long-form content within your group. Use markdown to create rich posts with headers, lists and images.', - url: `/~landscape/ship/${TUTORIAL_HOST}/${TUTORIAL_GROUP}/resource/publish/ship/${TUTORIAL_HOST}/${TUTORIAL_BOOK}`, - alignY: 'top', - alignX: 'right', - arrow: 'North', - offsetX: -8, - offsetY: -56 - }, - notifications: { - title: 'Notifications', - description: 'You will get updates from subscribed channels and mentions here. You can access Notifications through Leap.', - url: '/~notifications', - alignY: 'top', - alignX: 'left', - arrow: 'North', - offsetX: 0, - offsetY: -48 - }, - profile: { - title: 'Profile', - description: - 'Your profile is customizable and can be shared with other ships. Enter as much or as little information as you’d like.', - url: `/~profile/~${window.ship}`, - alignY: 'top', - alignX: 'right', - arrow: 'South', - offsetX: -300 + MODAL_WIDTH / 2, - offsetY: -4 - }, - leap: { - title: 'Leap', - description: - 'Leap allows you to go to a specific channel, message, collection, profile or group simply by typing in a command or selecting a shortcut from the dropdown menu.', - url: `/~profile/~${window.ship}`, - alignY: 'top', - alignX: 'left', - arrow: 'North', - offsetX: 76, - offsetY: -48 - } -}; diff --git a/pkg/interface/src/logic/lib/useResize.ts b/pkg/interface/src/logic/lib/useResize.ts index 4f159883c..4daf40b1d 100644 --- a/pkg/interface/src/logic/lib/useResize.ts +++ b/pkg/interface/src/logic/lib/useResize.ts @@ -15,11 +15,12 @@ export function useResize( callback(entry, observer); } } + let el = ref.current; const resizeObs = new ResizeObserver(observer); - resizeObs.observe(ref.current, { box: 'border-box' }); + resizeObs.observe(el, { box: 'border-box' }); return () => { - resizeObs.unobserve(ref.current); + resizeObs.unobserve(el); }; }, [callback]); diff --git a/pkg/interface/src/logic/lib/util.tsx b/pkg/interface/src/logic/lib/util.tsx index 2b0381587..70dec9192 100644 --- a/pkg/interface/src/logic/lib/util.tsx +++ b/pkg/interface/src/logic/lib/util.tsx @@ -4,14 +4,11 @@ import { patp2dec } from 'urbit-ob'; import f from 'lodash/fp'; import { Association, Contact, Patp } from '@urbit/api'; import { enableMapSet } from 'immer'; -import useSettingsState from '../state/settings'; /* eslint-disable max-lines */ import anyAscii from 'any-ascii'; import { sigil as sigiljs, stringRenderer } from '@tlon/sigil-js'; import bigInt, { BigInteger } from 'big-integer'; -import { foregroundFromBackground } from '~/logic/lib/sigil'; import { IconRef, Workspace } from '~/types'; -import useContactState from '../state/contact'; enableMapSet(); @@ -462,13 +459,6 @@ export function pluralize(text: string, isPlural = false, vowel = false) { return isPlural ? `${text}s` : `${vowel ? 'an' : 'a'} ${text}`; } -// Hide is an optional second parameter for when this function is used in class components -export function useShowNickname(contact: Contact | null, hide?: boolean): boolean { - const hideState = useSettingsState(state => state.calm.hideNicknames); - const hideNicknames = typeof hide !== 'undefined' ? hide : hideState; - return Boolean(contact && contact.nickname && !hideNicknames); -} - interface useHoveringInterface { hovering: boolean; bind: { @@ -513,21 +503,6 @@ export const svgDataURL = svg => 'data:image/svg+xml;base64,' + btoa(svg); export const svgBlobURL = svg => URL.createObjectURL(new Blob([svg], { type: 'image/svg+xml' })); -export const favicon = () => { - let background = '#ffffff'; - const contacts = useContactState.getState().contacts; - if (Object.prototype.hasOwnProperty.call(contacts, `~${window.ship}`)) { - background = `#${uxToHex(contacts[`~${window.ship}`].color)}`; - } - const foreground = foregroundFromBackground(background); - const svg = sigiljs({ - patp: window.ship, - renderer: stringRenderer, - size: 16, - colors: [background, foreground] - }); - return svg; -}; export function binaryIndexOf(arr: BigInteger[], target: BigInteger): number | undefined { let leftBound = 0; diff --git a/pkg/interface/src/logic/state/contact.ts b/pkg/interface/src/logic/state/contact.ts index 4646edab5..bf234ef32 100644 --- a/pkg/interface/src/logic/state/contact.ts +++ b/pkg/interface/src/logic/state/contact.ts @@ -1,4 +1,4 @@ -import { Contact, deSig, Patp, Rolodex } from '@urbit/api'; +import { Contact, deSig, Patp, Rolodex, uxToHex } from '@urbit/api'; import { useCallback } from 'react'; import _ from 'lodash'; import { reduce, reduceNacks } from '../reducers/contact-update'; @@ -7,6 +7,8 @@ import { createSubscription, reduceStateN } from './base'; +import { sigil as sigiljs, stringRenderer } from '@tlon/sigil-js'; +import { foregroundFromBackground } from '~/logic/lib/sigil'; export interface ContactState { contacts: Rolodex; @@ -51,4 +53,21 @@ export function useOurContact() { return useContact(`~${window.ship}`); } +export const favicon = () => { + let background = '#ffffff'; + const contacts = useContactState.getState().contacts; + if (Object.prototype.hasOwnProperty.call(contacts, `~${window.ship}`)) { + background = `#${uxToHex(contacts[`~${window.ship}`].color)}`; + } + const foreground = foregroundFromBackground(background); + const svg = sigiljs({ + patp: window.ship, + renderer: stringRenderer, + size: 16, + colors: [background, foreground] + }); + return svg; +}; + + export default useContactState; diff --git a/pkg/interface/src/logic/state/hark.ts b/pkg/interface/src/logic/state/hark.ts index 5b7a39c00..325972eeb 100644 --- a/pkg/interface/src/logic/state/hark.ts +++ b/pkg/interface/src/logic/state/hark.ts @@ -10,7 +10,8 @@ import { harkBinToId, decToUd, unixToDa, - opened + opened, + markEachAsRead } from '@urbit/api'; import { Poke } from '@urbit/http-api'; import { patp2dec } from 'urbit-ob'; @@ -25,6 +26,7 @@ import { reduceStateN } from './base'; import { reduce, reduceGraph, reduceGroup } from '../reducers/hark-update'; +import useMetadataState from './metadata'; export const HARK_FETCH_MORE_COUNT = 3; @@ -43,6 +45,8 @@ export interface HarkState { unreads: Unreads; archiveNote: (bin: HarkBin, lid: HarkLid) => Promise; readCount: (path: string) => Promise; + readGraph: (graph: string) => Promise; + readGroup: (group: string) => Promise; } const useHarkState = createState( @@ -54,6 +58,38 @@ const useHarkState = createState( poke: async (poke: Poke) => { await pokeOptimisticallyN(useHarkState, poke, [reduce]); }, + readGraph: async (graph: string) => { + const prefix = `/graph/${graph.slice(6)}`; + let counts = [] as string[]; + let eaches = [] as [string, string][]; + Object.entries(get().unreads).forEach(([path, unreads]) => { + if (path.startsWith(prefix)) { + if(unreads.count > 0) { + counts.push(path); + } + unreads.each.forEach(unread => { + eaches.push([path, unread]); + }); + } + }); + get().set(draft => { + counts.forEach(path => { + draft.unreads[path].count = 0; + }); + eaches.forEach(([path, each]) => { + draft.unreads[path].each = []; + }); + }); + await Promise.all([ + ...counts.map(path => markCountAsRead({ desk: window.desk, path })), + ...eaches.map(([path, each]) => markEachAsRead({ desk: window.desk, path }, each)) + ].map(pok => api.poke(pok))); + }, + readGroup: async (group: string) => { + const graphs = + _.pickBy(useMetadataState.getState().associations.graph, a => a.group === group); + await Promise.all(Object.keys(graphs).map(get().readGraph)); + }, readCount: async (path) => { const poke = markCountAsRead({ desk: (window as any).desk, path }); await pokeOptimisticallyN(useHarkState, poke, [reduce]); diff --git a/pkg/interface/src/logic/state/local.tsx b/pkg/interface/src/logic/state/local.tsx index 3bd6016fa..b1947bbb2 100644 --- a/pkg/interface/src/logic/state/local.tsx +++ b/pkg/interface/src/logic/state/local.tsx @@ -3,7 +3,7 @@ import f from 'lodash/fp'; import React from 'react'; import create, { State } from 'zustand'; import { persist } from 'zustand/middleware'; -import { BackgroundConfig, LeapCategories, RemoteContentPolicy, TutorialProgress, tutorialProgress } from '~/types/local-update'; +import { BackgroundConfig, LeapCategories, RemoteContentPolicy } from '~/types/local-update'; import airlock from '~/logic/api'; import { bootstrapApi } from '../api/bootstrap'; import { clearStorageMigration, createStorageKey, storageVersion, wait } from '~/logic/lib/util'; @@ -15,15 +15,9 @@ export interface LocalState { hideAvatars: boolean; hideNicknames: boolean; remoteContentPolicy: RemoteContentPolicy; - tutorialProgress: TutorialProgress; hideGroups: boolean; hideUtilities: boolean; - tutorialRef: HTMLElement | null, - hideTutorial: () => void; - nextTutStep: () => void; - prevTutStep: () => void; hideLeapCats: LeapCategories[]; - setTutorialRef: (el: HTMLElement | null) => void; dark: boolean; mobile: boolean; breaks: { @@ -62,27 +56,6 @@ const useLocalState = create(persist((set, get) => ({ hideLeapCats: [], hideGroups: false, hideUtilities: false, - tutorialProgress: 'hidden', - tutorialRef: null, - setTutorialRef: (el: HTMLElement | null) => set(produce((state) => { - state.tutorialRef = el; - })), - hideTutorial: () => set(produce((state) => { - state.tutorialProgress = 'hidden'; - state.tutorialRef = null; - })), - nextTutStep: () => set(produce((state) => { - const currIdx = tutorialProgress.findIndex(p => p === state.tutorialProgress); - if(currIdx < tutorialProgress.length) { - state.tutorialProgress = tutorialProgress[currIdx + 1]; - } - })), - prevTutStep: () => set(produce((state) => { - const currIdx = tutorialProgress.findIndex(p => p === state.tutorialProgress); - if(currIdx > 0) { - state.tutorialProgress = tutorialProgress[currIdx - 1]; - } - })), remoteContentPolicy: { imageShown: true, audioShown: true, @@ -132,8 +105,8 @@ const useLocalState = create(persist((set, get) => ({ set: fn => set(produce(fn)) }), { blacklist: [ - 'suspendedFocus', 'toggleOmnibox', 'omniboxShown', 'tutorialProgress', - 'prevTutStep', 'nextTutStep', 'tutorialRef', 'setTutorialRef', 'subscription', + 'suspendedFocus', 'toggleOmnibox', 'omniboxShown', + 'subscription', 'errorCount', 'breaks' ], name: createStorageKey('local'), diff --git a/pkg/interface/src/logic/state/settings.ts b/pkg/interface/src/logic/state/settings.ts index 4901b466a..bcbbccc55 100644 --- a/pkg/interface/src/logic/state/settings.ts +++ b/pkg/interface/src/logic/state/settings.ts @@ -16,7 +16,7 @@ import { import { useCallback } from 'react'; import { reduceUpdate } from '../reducers/settings-update'; import airlock from '~/logic/api'; -import { getDeskSettings, putEntry, Value } from '@urbit/api'; +import { Contact, getDeskSettings, putEntry, Value } from '@urbit/api'; export interface ShortcutMapping { cycleForward: string; @@ -48,10 +48,6 @@ export interface SettingsState { leap: { categories: LeapCategories[]; }; - tutorial: { - seen: boolean; - joined?: number; - }; } export const selectSettingsState = )>(keys: K[]) => @@ -87,10 +83,6 @@ const useSettingsState = createState( leap: { categories: leapCategories }, - tutorial: { - seen: true, - joined: undefined - }, keyboard: { cycleForward: 'ctrl+\'', cycleBack: 'ctrl+;', @@ -138,4 +130,11 @@ export function useTheme() { return useSettingsState(selTheme); } +// Hide is an optional second parameter for when this function is used in class components +export function useShowNickname(contact: Contact | null, hide?: boolean): boolean { + const hideState = useSettingsState(state => state.calm.hideNicknames); + const hideNicknames = typeof hide !== 'undefined' ? hide : hideState; + return Boolean(contact && contact.nickname && !hideNicknames); +} + export default useSettingsState; diff --git a/pkg/interface/src/types/local-update.ts b/pkg/interface/src/types/local-update.ts index 31e99560d..9d9dd8220 100644 --- a/pkg/interface/src/types/local-update.ts +++ b/pkg/interface/src/types/local-update.ts @@ -1,10 +1,7 @@ -export const tutorialProgress = ['hidden', 'start', 'group-desc', 'channels', 'chat', 'link', 'publish', 'profile', 'leap', 'notifications', 'done', 'exit'] as const; - export const leapCategories = ['mychannel', 'messages', 'updates', 'profile', 'logout']; export type LeapCategories = typeof leapCategories[number]; -export type TutorialProgress = typeof tutorialProgress[number]; interface LocalUpdateSetDark { setDark: boolean; } diff --git a/pkg/interface/src/views/App.js b/pkg/interface/src/views/App.js index 1490e7397..41fc6c346 100644 --- a/pkg/interface/src/views/App.js +++ b/pkg/interface/src/views/App.js @@ -10,16 +10,15 @@ import { hot } from 'react-hot-loader/root'; import { BrowserRouter as Router, withRouter } from 'react-router-dom'; import styled, { ThemeProvider } from 'styled-components'; import gcpManager from '~/logic/lib/gcpManager'; -import { favicon, svgDataURL } from '~/logic/lib/util'; +import { svgDataURL } from '~/logic/lib/util'; import withState from '~/logic/lib/withState'; -import useContactState from '~/logic/state/contact'; +import useContactState, { favicon } from '~/logic/state/contact'; import useLocalState from '~/logic/state/local'; import useSettingsState from '~/logic/state/settings'; import useGraphState from '~/logic/state/graph'; import { ShortcutContextProvider } from '~/logic/lib/shortcutContext'; import ErrorBoundary from '~/views/components/ErrorBoundary'; -import { TutorialModal } from '~/views/landscape/components/TutorialModal'; import './apps/chat/css/custom.css'; import Omnibox from './components/leap/Omnibox'; import StatusBar from './components/StatusBar'; @@ -171,7 +170,6 @@ class App extends React.Component { - { - const { connection } = props; - const [exitingTut, setExitingTut] = useState(false); - const seen = useSettingsState(s => s?.tutorial?.seen) ?? true; - const associations = useMetadataState(s => s.associations); - const hasLoaded = useMemo(() => Boolean(connection === 'connected'), [connection]); const notificationsCount = useHarkState(state => state.notificationsCount); const calmState = useSettingsState(selectCalmState); - const { hideUtilities } = calmState; - const { tutorialProgress, nextTutStep } = useLocalState(tutSelector); - let { hideGroups } = useLocalState(tutSelector); - !hideGroups ? { hideGroups } = calmState : null; - - const waiter = useWaitForProps({ ...props, associations }); - - const { query } = useQuery(); - - const { modal, showModal } = useModal({ - position: 'relative', - maxWidth: '350px', - modal: function modal(dismiss) { - const onDismiss = (e) => { - const { putEntry } = useSettingsState.getState(); - e.stopPropagation(); - putEntry('tutorial', 'seen', true); - dismiss(); - }; - const onContinue = async (e) => { - const { putEntry } = useSettingsState.getState(); - e.stopPropagation(); - if (!hasTutorialGroup({ associations })) { - await airlock.poke(join(TUTORIAL_HOST, TUTORIAL_GROUP)); - await putEntry('tutorial', 'joined', Date.now()); - await waiter(hasTutorialGroup); - await Promise.all( - [TUTORIAL_BOOK, TUTORIAL_CHAT, TUTORIAL_LINKS].map(graph => airlock.thread(joinGraph(TUTORIAL_HOST, graph)))); - - await waiter((p) => { - return `/ship/${TUTORIAL_HOST}/${TUTORIAL_CHAT}` in p.associations.graph && - `/ship/${TUTORIAL_HOST}/${TUTORIAL_BOOK}` in p.associations.graph && - `/ship/${TUTORIAL_HOST}/${TUTORIAL_LINKS}` in p.associations.graph; - }); - } - nextTutStep(); - dismiss(); - }; - return exitingTut ? ( - - - - You can always restart the tutorial by typing “tutorial” in Leap - - - - - - ) : ( - - - - - Welcome - - You have been invited to use Groups, an interface to chat - and interact with communities -
- Would you like a tour of Groups? -
- - - - Yes - - - - ); - } - }); - - useEffect(() => { - if(query.get('tutorial')) { - if (hasTutorialGroup({ associations })) { - if (nextTutStep) { - nextTutStep(); - } - } else { - showModal(); - } - } - }, [query, showModal]); - - useEffect(() => { - if(hasLoaded && !seen && tutorialProgress === 'hidden') { - showModal(); - } - }, [seen, hasLoaded]); + const { hideUtilities, hideGroups } = calmState; return ( <> @@ -156,7 +41,6 @@ export const LaunchApp = (props: LaunchAppProps): ReactElement | null => { - {modal} - a.group === TUTORIAL_GROUP_RESOURCE - ? -1 - : b.group === TUTORIAL_GROUP_RESOURCE - ? 1 - : alphabeticalOrder(a.metadata.title, b.metadata.title); + alphabeticalOrder(a.metadata.title, b.metadata.title); const getGraphUnreads = (associations: Associations) => { const state = useHarkState.getState(); const selUnread = (graph: string) => { const { count, each } = selHarkGraph(graph)(state); - const result = count + each.length; + const result = count + each.length; return result; }; return (path: string) => @@ -36,7 +31,10 @@ const getGraphUnreads = (associations: Associations) => { )(associations.graph); }; -const getGraphNotifications = (associations: Associations, unreads: Unreads) => (path: string) => +const getGraphNotifications = ( + associations: Associations, + unreads: Unreads +) => (path: string) => f.flow( f.pickBy((a: Association) => a.group === path), f.map('resource'), @@ -52,8 +50,11 @@ export default function Groups(props: Parameters[0]) { const groups = Object.values(associations?.groups || {}) .filter(e => e?.group in groupState) .sort(sortGroupsAlph); - const graphUnreads = getGraphUnreads(associations || {} as Associations); - const graphNotifications = getGraphNotifications(associations || {} as Associations, unreads); + const graphUnreads = getGraphUnreads(associations || ({} as Associations)); + const graphNotifications = getGraphNotifications( + associations || ({} as Associations), + unreads + ); return ( <> @@ -83,37 +84,26 @@ interface GroupProps { unreads: number; first: boolean; } -const selectJoined = (s: SettingsState) => s.tutorial.joined; function Group(props: GroupProps) { const { path, title, unreads, updates, first = false } = props; - const anchorRef = useRef(null); - const isTutorialGroup = path === `/ship/${TUTORIAL_HOST}/${TUTORIAL_GROUP}`; - useTutorialModal( - 'start', - isTutorialGroup, - anchorRef - ); const { hideUnreads } = useSettingsState(selectCalmState); - const joined = useSettingsState(selectJoined); - const days = Math.max(0, Math.floor(moment.duration(moment(joined) - .add(14, 'days') - .diff(moment())) - .as('days'))) || 0; return ( - + {title} - {!hideUnreads && ( - {isTutorialGroup && joined && - ({days} day{days !== 1 && 's'} remaining) - } - {updates > 0 && - ({updates} update{updates !== 1 && 's'} ) - } - {unreads > 0 && - ({unreads}) - } - + {!hideUnreads && ( + + {updates > 0 && ( + + {updates} update{updates !== 1 && 's'}{' '} + + )} + {unreads > 0 && {unreads}} + )} diff --git a/pkg/interface/src/views/apps/notifications/notifications.tsx b/pkg/interface/src/views/apps/notifications/notifications.tsx index cc75e996a..9b35836fb 100644 --- a/pkg/interface/src/views/apps/notifications/notifications.tsx +++ b/pkg/interface/src/views/apps/notifications/notifications.tsx @@ -1,11 +1,10 @@ import { Action, Box, Col, Icon, Row, Text } from '@tlon/indigo-react'; -import React, { ReactElement, ReactNode, useEffect, useRef } from 'react'; +import React, { ReactElement, ReactNode, useEffect } from 'react'; import Helmet from 'react-helmet'; import { Link, Route, Switch, useHistory, useLocation } from 'react-router-dom'; import useHarkState from '~/logic/state/hark'; import { Body } from '~/views/components/Body'; import { StatelessAsyncAction } from '~/views/components/StatelessAsyncAction'; -import { useTutorialModal } from '~/views/components/useTutorialModal'; import { Archive } from './Archive'; import { NewBox } from './NewBox'; @@ -41,8 +40,6 @@ export function NavLink({ export default function NotificationsScreen(props: any): ReactElement { const relativePath = (p: string) => baseUrl + p; - const anchorRef = useRef(null); - useTutorialModal('notifications', true, anchorRef); const notificationsCount = useHarkState(state => state.notificationsCount); const onReadAll = async () => {}; @@ -89,7 +86,6 @@ export default function NotificationsScreen(props: any): ReactElement { fontWeight="bold" fontSize={2} lineHeight={1} - ref={anchorRef} > Notifications diff --git a/pkg/interface/src/views/apps/profile/components/Profile.tsx b/pkg/interface/src/views/apps/profile/components/Profile.tsx index a4fad437f..ae2ce5c44 100644 --- a/pkg/interface/src/views/apps/profile/components/Profile.tsx +++ b/pkg/interface/src/views/apps/profile/components/Profile.tsx @@ -1,6 +1,6 @@ import { BaseImage, Box, Center, Row, Text } from '@tlon/indigo-react'; import { retrieve } from '@urbit/api'; -import React, { ReactElement, useEffect, useRef } from 'react'; +import React, { ReactElement, useEffect } from 'react'; import { useHistory } from 'react-router-dom'; import { Sigil } from '~/logic/lib/sigil'; import { uxToHex } from '~/logic/lib/util'; @@ -8,7 +8,6 @@ import useContactState from '~/logic/state/contact'; import useSettingsState, { selectCalmState } from '~/logic/state/settings'; import RichText from '~/views/components/RichText'; import { SetStatusBarModal } from '~/views/components/SetStatusBarModal'; -import { useTutorialModal } from '~/views/components/useTutorialModal'; import { EditProfile } from './EditProfile'; import { ViewProfile } from './ViewProfile'; import airlock from '~/logic/api'; @@ -32,10 +31,6 @@ export function ProfileImages(props: any): ReactElement { const { contact, hideCover, ship } = props; const hexColor = contact?.color ? `#${uxToHex(contact.color)}` : '#000000'; - const anchorRef = useRef(null); - - useTutorialModal('profile', ship === `~${window.ship}`, anchorRef); - const cover = contact?.cover && !hideCover ? ( - + {cover}
{props.children} diff --git a/pkg/interface/src/views/apps/publish/components/Note.tsx b/pkg/interface/src/views/apps/publish/components/Note.tsx index f6d21066b..af074dde5 100644 --- a/pkg/interface/src/views/apps/publish/components/Note.tsx +++ b/pkg/interface/src/views/apps/publish/components/Note.tsx @@ -61,6 +61,9 @@ export function Note(props: NoteProps & RouteComponentProps) { const noteId = bigInt(index[1]); useEffect(() => { airlock.poke(markEachAsRead(toHarkPlace(association.resource), `/${index[1]}`)); + // Unread may be malformed, dismiss anyway + // TODO: remove when %read-graph is implemented + airlock.poke(markEachAsRead(toHarkPlace(association.resource), `/1`)); }, [association, props.note]); const adminLinks: JSX.Element[] = []; diff --git a/pkg/interface/src/views/apps/publish/components/Notebook.tsx b/pkg/interface/src/views/apps/publish/components/Notebook.tsx index 66e04178d..8a4cbb458 100644 --- a/pkg/interface/src/views/apps/publish/components/Notebook.tsx +++ b/pkg/interface/src/views/apps/publish/components/Notebook.tsx @@ -2,11 +2,12 @@ import { Box, Button, Col, Row, Text } from '@tlon/indigo-react'; import { Association, Graph, readGraph } from '@urbit/api'; import React, { ReactElement, useCallback } from 'react'; import { RouteComponentProps } from 'react-router-dom'; -import { useShowNickname } from '~/logic/lib/util'; import useContactState from '~/logic/state/contact'; import useGroupState from '~/logic/state/group'; +import { useShowNickname } from '~/logic/state/settings'; import airlock from '~/logic/api'; import { NotebookPosts } from './NotebookPosts'; +import useHarkState from '~/logic/state/hark'; interface NotebookProps { ship: string; @@ -35,7 +36,7 @@ export function Notebook(props: NotebookProps & RouteComponentProps): ReactEleme const showNickname = useShowNickname(contact); const readBook = useCallback(() => { - airlock.poke(readGraph(association.resource)); + useHarkState.getState().readGraph(association.resource); }, [association.resource]); if (!group) { diff --git a/pkg/interface/src/views/components/Author.tsx b/pkg/interface/src/views/components/Author.tsx index b9007c3ca..c0f723131 100644 --- a/pkg/interface/src/views/components/Author.tsx +++ b/pkg/interface/src/views/components/Author.tsx @@ -3,10 +3,10 @@ import moment from 'moment'; import React, { ReactElement, ReactNode } from 'react'; import { Sigil } from '~/logic/lib/sigil'; import { useCopy } from '~/logic/lib/useCopy'; -import { cite, useShowNickname, uxToHex } from '~/logic/lib/util'; +import { cite, uxToHex } from '~/logic/lib/util'; import { useContact } from '~/logic/state/contact'; import { useDark } from '~/logic/state/join'; -import useSettingsState, { selectCalmState } from '~/logic/state/settings'; +import useSettingsState, { selectCalmState, useShowNickname } from '~/logic/state/settings'; import { PropFunc } from '~/types'; import ProfileOverlay from './ProfileOverlay'; import Timestamp from './Timestamp'; diff --git a/pkg/interface/src/views/components/MentionText.tsx b/pkg/interface/src/views/components/MentionText.tsx index ed8d2b249..ea431485a 100644 --- a/pkg/interface/src/views/components/MentionText.tsx +++ b/pkg/interface/src/views/components/MentionText.tsx @@ -2,8 +2,9 @@ import { Text } from '@tlon/indigo-react'; import { Contact, Content, Group } from '@urbit/api'; import React from 'react'; import { referenceToPermalink } from '~/logic/lib/permalinks'; -import { cite, deSig, useShowNickname } from '~/logic/lib/util'; +import { cite, deSig } from '~/logic/lib/util'; import { useContact } from '~/logic/state/contact'; +import { useShowNickname } from '~/logic/state/settings'; import { PropFunc } from '~/types'; import ProfileOverlay from '~/views/components/ProfileOverlay'; import RichText from '~/views/components/RichText'; diff --git a/pkg/interface/src/views/components/ProfileOverlay.tsx b/pkg/interface/src/views/components/ProfileOverlay.tsx index 803b124f9..7e858ae32 100644 --- a/pkg/interface/src/views/components/ProfileOverlay.tsx +++ b/pkg/interface/src/views/components/ProfileOverlay.tsx @@ -19,9 +19,8 @@ import { getRelativePosition } from '~/logic/lib/relativePosition'; import { Sigil } from '~/logic/lib/sigil'; import { useCopy } from '~/logic/lib/useCopy'; import { useOutsideClick } from '~/logic/lib/useOutsideClick'; -import { useShowNickname } from '~/logic/lib/util'; import { useContact } from '~/logic/state/contact'; -import useSettingsState, { SettingsState } from '~/logic/state/settings'; +import useSettingsState, { SettingsState, useShowNickname } from '~/logic/state/settings'; import { Portal } from './Portal'; import { ProfileStatus } from './ProfileStatus'; import RichText from './RichText'; diff --git a/pkg/interface/src/views/components/StatusBar.tsx b/pkg/interface/src/views/components/StatusBar.tsx index 35a600676..fc014f4d2 100644 --- a/pkg/interface/src/views/components/StatusBar.tsx +++ b/pkg/interface/src/views/components/StatusBar.tsx @@ -7,7 +7,7 @@ import { Row, Text } from '@tlon/indigo-react'; -import React, { useRef } from 'react'; +import React from 'react'; import { Link } from 'react-router-dom'; import { Sigil } from '~/logic/lib/sigil'; import { uxToHex } from '~/logic/lib/util'; @@ -18,7 +18,6 @@ import { Dropdown } from './Dropdown'; import { ProfileStatus } from './ProfileStatus'; import ReconnectButton from './ReconnectButton'; import { StatusBarItem } from './StatusBarItem'; -import { useTutorialModal } from './useTutorialModal'; import { StatusBarJoins } from './StatusBarJoins'; import useHarkState from '~/logic/state/hark'; @@ -48,13 +47,6 @@ const StatusBar = (props) => { ); - const anchorRef = useRef(null); - - const leapHighlight = useTutorialModal('leap', true, anchorRef); - - const floatLeap = - leapHighlight && window.matchMedia('(max-width: 550px)').matches; - return ( { > - toggleOmnibox()}> + toggleOmnibox()}> - + Leap diff --git a/pkg/interface/src/views/components/leap/Omnibox.tsx b/pkg/interface/src/views/components/leap/Omnibox.tsx index 84a38bc71..1b8db8778 100644 --- a/pkg/interface/src/views/components/leap/Omnibox.tsx +++ b/pkg/interface/src/views/components/leap/Omnibox.tsx @@ -119,7 +119,7 @@ export function Omnibox(props: OmniboxProps): ReactElement { if (category === 'other') { return [ 'other', - index.get('other').filter(({ app }) => app !== 'tutorial') + index.get('other') ]; } return [category, []]; @@ -159,7 +159,6 @@ export function Omnibox(props: OmniboxProps): ReactElement { defaultApps.includes(app.toLowerCase()) || app === 'profile' || app === 'messages' || - app === 'tutorial' || app === 'Links' || app === 'Terminal' || app === 'home' || diff --git a/pkg/interface/src/views/components/leap/OmniboxResult.tsx b/pkg/interface/src/views/components/leap/OmniboxResult.tsx index fedb0f7ea..e85c3ae69 100644 --- a/pkg/interface/src/views/components/leap/OmniboxResult.tsx +++ b/pkg/interface/src/views/components/leap/OmniboxResult.tsx @@ -169,17 +169,6 @@ export class OmniboxResult extends Component ); - } else if (icon === 'tutorial') { - graphic = ( - - ); } else { graphic = ( -) { - const { tutorialProgress, setTutorialRef } = useLocalState(localSelector); - - useEffect(() => { - if (show && (onProgress === tutorialProgress) && anchorRef?.current) { - setTutorialRef(anchorRef.current); - } - - return () => {}; - }, [tutorialProgress, show, anchorRef]); - - return show && onProgress === tutorialProgress; -} diff --git a/pkg/interface/src/views/landscape/components/GroupSummary.tsx b/pkg/interface/src/views/landscape/components/GroupSummary.tsx index d7c57c3e8..731ceb1ec 100644 --- a/pkg/interface/src/views/landscape/components/GroupSummary.tsx +++ b/pkg/interface/src/views/landscape/components/GroupSummary.tsx @@ -1,9 +1,7 @@ import { Col, Row, Text, Icon } from '@tlon/indigo-react'; import { Metadata } from '@urbit/api'; -import React, { ReactElement, ReactNode, useRef } from 'react'; -import { TUTORIAL_GROUP, TUTORIAL_HOST } from '~/logic/lib/tutorialModal'; +import React, { ReactElement, ReactNode } from 'react'; import { PropFunc, IconRef } from '~/types'; -import { useTutorialModal } from '~/views/components/useTutorialModal'; import { MetadataIcon } from './MetadataIcon'; import { useCopy } from '~/logic/lib/useCopy'; interface GroupSummaryProps { @@ -17,17 +15,24 @@ interface GroupSummaryProps { locked?: boolean; } -export function GroupSummary(props: GroupSummaryProps & PropFunc): ReactElement { - const { channelCount, memberCount, metadata, resource, children, ...rest } = props; - const anchorRef = useRef(null); - useTutorialModal( - 'group-desc', - resource === `/ship/${TUTORIAL_HOST}/${TUTORIAL_GROUP}`, - anchorRef +export function GroupSummary( + props: GroupSummaryProps & PropFunc +): ReactElement { + const { + channelCount, + memberCount, + metadata, + resource, + children, + ...rest + } = props; + const { doCopy, copyDisplay } = useCopy( + `web+urbitgraph://group${resource?.slice(5)}`, + 'Copy', + 'Checkmark' ); - const { doCopy, copyDisplay } = useCopy(`web+urbitgraph://group${resource?.slice(5)}`, "Copy", "Checkmark"); return ( - + ): R /> - {metadata.title} - - {props?.AllowCopy && - - } + + {metadata.title} + + {props?.AllowCopy && ( + + )} @@ -64,17 +70,17 @@ export function GroupSummary(props: GroupSummaryProps & PropFunc): R - {metadata.description && - + > {metadata.description} - } + )} {children} diff --git a/pkg/interface/src/views/landscape/components/GroupsPane.tsx b/pkg/interface/src/views/landscape/components/GroupsPane.tsx index 741a4e50a..3465aa65c 100644 --- a/pkg/interface/src/views/landscape/components/GroupsPane.tsx +++ b/pkg/interface/src/views/landscape/components/GroupsPane.tsx @@ -43,7 +43,7 @@ export function GroupsPane(props: GroupsPaneProps) { useShortcut('readGroup', useCallback(() => { if(groupPath) { - airlock.poke(readGroup(groupPath)); + useHarkState.getState().readGroup(groupPath); } }, [groupPath])); diff --git a/pkg/interface/src/views/landscape/components/JoinGroup.tsx b/pkg/interface/src/views/landscape/components/JoinGroup.tsx index db309c75c..bbdaddc6a 100644 --- a/pkg/interface/src/views/landscape/components/JoinGroup.tsx +++ b/pkg/interface/src/views/landscape/components/JoinGroup.tsx @@ -12,7 +12,6 @@ import React, { ReactElement, useCallback, useEffect, useState } from 'react'; import { useHistory } from 'react-router-dom'; import urbitOb from 'urbit-ob'; import * as Yup from 'yup'; -import { TUTORIAL_GROUP_RESOURCE } from '~/logic/lib/tutorialModal'; import { useQuery } from '~/logic/lib/useQuery'; import { useWaitForProps } from '~/logic/lib/useWaitForProps'; import { getModuleIcon } from '~/logic/lib/util'; @@ -23,7 +22,6 @@ import { FormError } from '~/views/components/FormError'; import { StatelessAsyncButton } from '~/views/components/StatelessAsyncButton'; import { GroupSummary } from './GroupSummary'; import airlock from '~/logic/api'; -import useSettingsState from '~/logic/state/settings'; const formSchema = Yup.object({ group: Yup.string() @@ -77,10 +75,6 @@ export function JoinGroup(props: JoinGroupProps): ReactElement { const onConfirm = useCallback(async (group: string) => { const [,,ship,name] = group.split('/'); - const { putEntry } = useSettingsState.getState(); - if(group === TUTORIAL_GROUP_RESOURCE) { - await putEntry('tutorial', 'joined', Date.now()); - } if (group in groups) { return history.push(`/~landscape${group}`); } diff --git a/pkg/interface/src/views/landscape/components/Sidebar/Sidebar.tsx b/pkg/interface/src/views/landscape/components/Sidebar/Sidebar.tsx index 54ae250c5..ee9fbc269 100644 --- a/pkg/interface/src/views/landscape/components/Sidebar/Sidebar.tsx +++ b/pkg/interface/src/views/landscape/components/Sidebar/Sidebar.tsx @@ -1,14 +1,13 @@ import { Col } from '@tlon/indigo-react'; -import React, { ReactElement, useRef } from 'react'; +import React, { ReactElement } from 'react'; import styled from 'styled-components'; import { roleForShip } from '~/logic/lib/group'; import { useLocalStorageState } from '~/logic/lib/useLocalStorageState'; import { getGroupFromWorkspace } from '~/logic/lib/workspace'; import useGroupState from '~/logic/state/group'; import { Workspace } from '~/types'; -import { useTutorialModal } from '~/views/components/useTutorialModal'; import { GroupSwitcher } from '../GroupSwitcher'; import { SidebarList } from './SidebarList'; import { SidebarListHeader } from './SidebarListHeader'; @@ -48,12 +47,8 @@ export function Sidebar(props: SidebarProps): ReactElement | null { const role = groups?.[groupPath] ? roleForShip(groups[groupPath], window.ship) : undefined; const isAdmin = (role === 'admin') || (workspace?.type === 'home'); - const anchorRef = useRef(null); - useTutorialModal('channels', true, anchorRef); - return ( 0 || each.length > 0; - return hasNotifications - ? 'notification' - : hasUnread - ? 'unread' - : isSubscribed - ? undefined - : 'unsubscribed'; + if(!isSubscribed) { + return 'unsubscribed'; + } else if (hasNotifications) { + return 'notification'; + } else if (hasUnread) { + return 'unread'; + } else { + return undefined; + } } function SidebarItemBase(props: { @@ -186,12 +186,6 @@ export const SidebarAssociationItem = React.memo((props: { const group = useGroupState(state => state.groups[groupPath]); const { hideNicknames } = useSettingsState(s => s.calm); const contacts = useContactState(s => s.contacts); - const anchorRef = useRef(null); - useTutorialModal( - mod as any, - groupPath === `/ship/${TUTORIAL_HOST}/${TUTORIAL_GROUP}`, - anchorRef - ); const isUnmanaged = group?.hidden || false; const DM = isUnmanaged && props.workspace?.type === 'messages'; const itemStatus = useAssociationStatus(rid); diff --git a/pkg/interface/src/views/landscape/components/TutorialModal.tsx b/pkg/interface/src/views/landscape/components/TutorialModal.tsx deleted file mode 100644 index c8f3802f3..000000000 --- a/pkg/interface/src/views/landscape/components/TutorialModal.tsx +++ /dev/null @@ -1,264 +0,0 @@ -import { Box, Button, Col, Icon, Row, Text } from '@tlon/indigo-react'; -import { leaveGroup } from '@urbit/api'; -import _ from 'lodash'; -import React, { useCallback, useEffect, useState } from 'react'; -import { useHistory } from 'react-router-dom'; -import { getRelativePosition } from '~/logic/lib/relativePosition'; -import { - getTrianglePosition, MODAL_WIDTH_PX, progressDetails, - - TUTORIAL_GROUP, TUTORIAL_HOST -} from '~/logic/lib/tutorialModal'; -import useLocalState, { selectLocalState } from '~/logic/state/local'; -import { tutorialProgress as progress } from '~/types'; -import { ModalOverlay } from '~/views/components/ModalOverlay'; -import { Portal } from '~/views/components/Portal'; -import { StatelessAsyncButton } from '~/views/components/StatelessAsyncButton'; -import { Triangle } from '~/views/components/Triangle'; -import airlock from '~/logic/api'; -import useSettingsState from '~/logic/state/settings'; - -const localSelector = selectLocalState([ - 'tutorialProgress', - 'nextTutStep', - 'prevTutStep', - 'tutorialRef', - 'hideTutorial', - 'set' -]); - -export function TutorialModal() { - const { - tutorialProgress, - tutorialRef, - nextTutStep, - prevTutStep, - hideTutorial - } = useLocalState(localSelector); - const { - title, - description, - arrow = 'North', - alignX, - alignY, - offsetX, - offsetY - } = progressDetails[tutorialProgress]; - - const [coords, setCoords] = useState({}); - const [paused, setPaused] = useState(false); - - const history = useHistory(); - - const next = useCallback( () => { - const idx = progress.findIndex(p => p === tutorialProgress); - const { url } = progressDetails[progress[idx + 1]]; - nextTutStep(); - history.push(url); - }, - [nextTutStep, history, tutorialProgress, setCoords] - ); - const prev = useCallback(() => { - const idx = progress.findIndex(p => p === tutorialProgress); - prevTutStep(); - history.push(progressDetails[progress[idx - 1]].url); - }, [prevTutStep, history, tutorialProgress]); - - const updatePos = useCallback(() => { - const newCoords = getRelativePosition( - tutorialRef, - alignX, - alignY, - offsetX, - offsetY - ); - const withMobile: any = _.mapValues(newCoords, (value: string[], key: string) => { - if(key === 'bottom' || key === 'left') { - return ['0px', ...value]; - } - return ['unset', ...value]; - }); - if(!('bottom' in withMobile)) { - withMobile.bottom = ['0px', 'unset']; - } - if(!('left' in withMobile)) { - withMobile.left = ['0px', 'unset']; - } - - if (newCoords) { - setCoords(withMobile); - } else { - setCoords({}); - } - }, [tutorialRef]); - - const dismiss = useCallback(async () => { - setPaused(false); - hideTutorial(); - const { putEntry } = useSettingsState.getState(); - await putEntry('tutorial', 'seen', true); - }, [hideTutorial]); - - const bailExit = useCallback(() => { - setPaused(false); - }, []); - - const tryExit = useCallback(() => { - setPaused(true); - }, []); - - const doLeaveGroup = useCallback(async () => { - await airlock.thread(leaveGroup(TUTORIAL_HOST, TUTORIAL_GROUP)); - await dismiss(); - }, [dismiss]); - - const progressIdx = progress.findIndex(p => p === tutorialProgress); - - useEffect(() => { - if ( - tutorialProgress !== 'hidden' && - tutorialProgress !== 'done' && - tutorialRef - ) { - const interval = setInterval(updatePos, 100); - return () => { - setCoords({}); - clearInterval(interval); - }; - } - return () => {}; - }, [tutorialRef, tutorialProgress, updatePos]); - - const triPos = getTrianglePosition(arrow); - - if (tutorialProgress === 'done') { - return ( - - - - - - Tutorial Finished - - - {progressIdx} of {progress.length - 2} - - - - This tutorial is finished. Would you like to leave Beginner Island? - - - - - Leave Group - - - - - - ); - } - - if (tutorialProgress === 'hidden') { - return null; - } - - if(paused) { - return ( - - - - - End Tutorial Now? - - - - You can always restart the tutorial by typing "tutorial" in Leap. - - - - - End Tutorial - - - - - - ); - } - - if(Object.keys(coords).length === 0) { - return null; - } - - return ( - - - - - - - - - - - {title} - - - {progressIdx} of {progress.length - 2} - - - - {description} - - { progressIdx > 1 && ( - - )} - - - - - - ); -} diff --git a/pkg/landscape/app/hark-graph-hook.hoon b/pkg/landscape/app/hark-graph-hook.hoon index 5e7a628dd..210f88dba 100644 --- a/pkg/landscape/app/hark-graph-hook.hoon +++ b/pkg/landscape/app/hark-graph-hook.hoon @@ -486,7 +486,7 @@ update-core ?- mode.kind %count (hark %unread-count place %.y 1) - %each (hark %unread-each place /(rsh 4 (scot %ui (rear index.post)))) + %each (hark %unread-each place /(rsh 4 (scot %ui (rear self-idx)))) %none update-core == == @@ -497,7 +497,7 @@ update-core ?- mode.kind %count (hark %unread-count place %.n 1) - %each (hark %read-each place /(rsh 4 (scot %ui (rear index.post)))) + %each (hark %read-each place /(rsh 4 (scot %ui (rear self-idx)))) %none update-core == == diff --git a/pkg/landscape/desk.docket-0 b/pkg/landscape/desk.docket-0 index 15e3d9879..fa8f2a3e0 100644 --- a/pkg/landscape/desk.docket-0 +++ b/pkg/landscape/desk.docket-0 @@ -1,9 +1,9 @@ :~ title+'Groups' info+'A suite of applications to communicate on Urbit' color+0xee.5432 - glob-http+['https://bootstrap.urbit.org/glob-0v4.10b75.pd4h0.n481d.ln7c6.cf174.glob' 0v4.10b75.pd4h0.n481d.ln7c6.cf174] + glob-http+['https://bootstrap.urbit.org/glob-0v2.fn2uu.2iu5q.ddmsu.01br7.8uaft.glob' 0v2.fn2uu.2iu5q.ddmsu.01br7.8uaft] base+'landscape' - version+[1 3 5] + version+[1 0 2] website+'https://tlon.io' license+'MIT' == diff --git a/pkg/landscape/sys.kelvin b/pkg/landscape/sys.kelvin index b7464903a..e68acb6a4 100644 --- a/pkg/landscape/sys.kelvin +++ b/pkg/landscape/sys.kelvin @@ -1 +1 @@ -[%zuse 420] +[%zuse 419] diff --git a/pkg/urbit/daemon/main.c b/pkg/urbit/daemon/main.c index cfb82e4d8..6e3bbcd1d 100644 --- a/pkg/urbit/daemon/main.c +++ b/pkg/urbit/daemon/main.c @@ -444,13 +444,14 @@ u3_ve_usage(c3_i argc, c3_c** argv) "-c pier Create a new urbit in pier/\n", "-D Recompute from events\n", "-d Daemon mode; implies -t\n", - "-e url Ethereum gateway\n", + "-e url Urbit ID (L2) gateway\n", "-F ship Fake keys; also disables networking\n", + "-G string Private key string (see also -k)\n", "-g Set GC flag\n", "-i jam_file import pier state\n", "-j Create json trace file in .urb/put/trace\n", "-K stage Start at Hoon kernel version stage\n", - "-k keys Private key file\n", + "-k file-path Private key file (see also -G)\n", "-L local networking only\n", "-P Profiling\n", "-p ames_port Set the ames port to bind to\n", diff --git a/pkg/urbit/include/c/motes.h b/pkg/urbit/include/c/motes.h index cbb4850b2..789fd209f 100644 --- a/pkg/urbit/include/c/motes.h +++ b/pkg/urbit/include/c/motes.h @@ -6,6 +6,7 @@ **/ # define c3__a c3_s1('a') +# define c3__a50 c3_s3('a','5','0') # define c3__abel c3_s4('a','b','e','l') # define c3__abo c3_s3('a','b','o') # define c3__actd c3_s4('a','c','t','d') @@ -112,6 +113,7 @@ # define c3__boot c3_s4('b','o','o','t') # define c3__born c3_s4('b','o','r','n') # define c3__both c3_s4('b','o','t','h') +# define c3__bout c3_s4('b','o','u','t') # define c3__box c3_s3('b','o','x') # define c3__br c3_s2('b','r') # define c3__bran c3_s4('b','r','a','n') diff --git a/pkg/urbit/include/noun/jets.h b/pkg/urbit/include/noun/jets.h index bc9b1e3b9..6a9d27756 100644 --- a/pkg/urbit/include/noun/jets.h +++ b/pkg/urbit/include/noun/jets.h @@ -72,9 +72,9 @@ c3_l jax_l; // index in global dashboard } u3j_core; - /* u3e_dash, u3_Dash, u3D: jet dashboard singleton + /* u3j_dash, u3_Dash, u3D: jet dashboard singleton */ - typedef struct _u3e_dash { + typedef struct _u3j_dash { u3j_core* dev_u; // null-terminated static list c3_l len_l; // dynamic array length c3_l all_l; // allocated length diff --git a/pkg/urbit/include/noun/trace.h b/pkg/urbit/include/noun/trace.h index 80b7bc1e5..28b42151d 100644 --- a/pkg/urbit/include/noun/trace.h +++ b/pkg/urbit/include/noun/trace.h @@ -93,6 +93,12 @@ void u3t_trace_close(); + /* u3t_trace_time(): returns current time since system epoc, + * whatever it is per system, in microseconds. + */ + c3_d + u3t_trace_time(); + /* u3t_nock_trace_push(): pushes a frame onto the trace stack; * return yes if active push. */ diff --git a/pkg/urbit/jets/tree.c b/pkg/urbit/jets/tree.c index 4100c54db..d1d33adde 100644 --- a/pkg/urbit/jets/tree.c +++ b/pkg/urbit/jets/tree.c @@ -2114,8 +2114,75 @@ static c3_c* _k140_ha[] = { 0 }; + +// TODO: probably need different ha hashes + +static u3j_core _a50_two__by_d[] = + { { "apt", 7, _140_two__by_apt_a, 0, _140_two__by_apt_ha }, + { "del", 7, _140_two__by_del_a, 0, _140_two__by_del_ha }, + { "get", 7, _140_two__by_get_a, 0, _140_two__by_get_ha }, + { "has", 7, _140_two__by_has_a, 0, _140_two__by_has_ha }, + { "put", 7, _140_two__by_put_a, 0, _140_two__by_put_ha }, + {} + }; + +static u3j_core _a50_two__in_d[] = + { { "apt", 7, _140_two__in_apt_a, 0, _140_two__in_apt_ha }, + { "del", 7, _140_two__in_del_a, 0, _140_two__in_del_ha }, + { "put", 7, _140_two__in_put_a, 0, _140_two__in_put_ha }, + {} + }; + +u3j_core _a50_d[] = +{ { "add", 7, _140_one_add_a, 0, _140_one_add_ha }, + { "dec", 7, _140_one_dec_a, 0, _140_one_dec_ha }, + { "div", 7, _140_one_div_a, 0, _140_one_div_ha }, + { "dvr", 7, _140_one_dvr_a, 0, _140_one_dvr_ha }, + { "gte", 7, _140_one_gte_a, 0, _140_one_gte_ha }, + { "gth", 7, _140_one_gth_a, 0, _140_one_gth_ha }, + { "lte", 7, _140_one_lte_a, 0, _140_one_lte_ha }, + { "lth", 7, _140_one_lth_a, 0, _140_one_lth_ha }, + { "mod", 7, _140_one_mod_a, 0, _140_one_mod_ha }, + { "mul", 7, _140_one_mul_a, 0, _140_one_mul_ha }, + { "sub", 7, _140_one_sub_a, 0, _140_one_sub_ha }, + + { "bex", 7, _140_two_bex_a, 0, _140_two_bex_ha }, + { "cat", 7, _140_two_cat_a, 0, _140_two_cat_ha }, + { "can", 7, _140_two_can_a, 0, _140_two_can_ha }, + { "con", 7, _140_two_con_a, 0, _140_two_con_ha }, + { "cut", 7, _140_two_cut_a, 0, _140_two_cut_ha }, + { "dis", 7, _140_two_dis_a, 0, _140_two_dis_ha }, + { "dor", 7, _140_two_dor_a, 0, _140_two_dor_ha }, + { "end", 7, _140_two_end_a, 0, _140_two_end_ha }, + { "gor", 7, _140_two_gor_a, 0, _140_two_gor_ha }, + { "lsh", 7, _140_two_lsh_a, 0, _140_two_lsh_ha }, + { "met", 7, _140_two_met_a, 0, _140_two_met_ha }, + { "mix", 7, _140_two_mix_a, 0, _140_two_mix_ha }, + { "mor", 7, _140_two_mor_a, 0, _140_two_mor_ha }, + { "mug", 7, _140_two_mug_a, 0, _140_two_mug_ha }, + { "muk", 59, _140_two_muk_a, 0, _140_two_muk_ha }, // TODO: why 59? + { "rep", 7, _140_two_rep_a, 0, _140_two_rep_ha }, + { "rip", 7, _140_two_rip_a, 0, _140_two_rip_ha }, + { "rsh", 7, _140_two_rsh_a, 0, _140_two_rsh_ha }, + { "swp", 7, _140_two_swp_a, 0, _140_two_swp_ha }, + + { "flop", 7, _140_two_flop_a, 0, _140_two_flop_ha }, + { "lent", 7, _140_two_lent_a, 0, _140_two_lent_ha }, + { "levy", 7, _140_two_levy_a, 0, _140_two_levy_ha }, + { "reap", 7, _140_two_reap_a, 0, _140_two_reap_ha }, + { "slag", 7, _140_two_slag_a, 0, _140_two_slag_ha }, + { "snag", 7, _140_two_snag_a, 0, _140_two_snag_ha }, + { "turn", 7, _140_two_turn_a, 0, _140_two_turn_ha }, + { "welp", 7, _140_two_welp_a, 0, _140_two_welp_ha }, + + { "by", 7, 0, _a50_two__by_d, _140_two__by_ha }, + { "in", 7, 0, _a50_two__in_d, _140_two__in_ha }, + {} +}; + static u3j_core _d[] = { { "k140", 0, 0, _k140_d, _k140_ha, 0, (u3j_core*) 140, 0 }, + { "a50", 0, 0, _a50_d, _k140_ha, 0, (u3j_core*) c3__a50, 0 }, {} }; diff --git a/pkg/urbit/noun/events.c b/pkg/urbit/noun/events.c index 224eb86d9..1be8a5b21 100644 --- a/pkg/urbit/noun/events.c +++ b/pkg/urbit/noun/events.c @@ -311,7 +311,6 @@ _ce_patch_verify(u3_ce_patch* pat_u) fprintf(stderr, "loom: patch version mismatch: have %u, need %u\r\n", pat_u->con_u->ver_y, u3e_version); - c3_assert(0); return c3n; } @@ -322,12 +321,10 @@ _ce_patch_verify(u3_ce_patch* pat_u) if ( -1 == lseek(pat_u->mem_i, (i_w << (u3a_page + 2)), SEEK_SET) ) { fprintf(stderr, "loom: patch seek: %s\r\n", strerror(errno)); - c3_assert(0); return c3n; } if ( -1 == read(pat_u->mem_i, mem_w, (1 << (u3a_page + 2))) ) { fprintf(stderr, "loom: patch read: %s\r\n", strerror(errno)); - c3_assert(0); return c3n; } { @@ -336,7 +333,6 @@ _ce_patch_verify(u3_ce_patch* pat_u) if ( mug_w != nug_w ) { fprintf(stderr, "loom: patch mug mismatch %d/%d; (%x, %x)\r\n", pag_w, i_w, mug_w, nug_w); - c3_assert(0); return c3n; } #if 0 @@ -605,8 +601,17 @@ _ce_patch_compose(void) static void _ce_patch_sync(u3_ce_patch* pat_u) { - c3_sync(pat_u->ctl_i); - c3_sync(pat_u->mem_i); + if ( -1 == c3_sync(pat_u->ctl_i) ) { + fprintf(stderr, "loom: control file sync failed: %s\r\n", + strerror(errno)); + c3_assert(!"loom: control sync"); + } + + if ( -1 == c3_sync(pat_u->mem_i) ) { + fprintf(stderr, "loom: patch file sync failed: %s\r\n", + strerror(errno)); + c3_assert(!"loom: patch sync"); + } } /* _ce_image_sync(): make sure image is synced to disk. @@ -614,7 +619,12 @@ _ce_patch_sync(u3_ce_patch* pat_u) static void _ce_image_sync(u3e_image* img_u) { - c3_sync(img_u->fid_i); + if ( -1 == c3_sync(img_u->fid_i) ) { + fprintf(stderr, "loom: image (%s) sync failed: %s\r\n", + img_u->nam_c, + strerror(errno)); + c3_assert(!"loom: image sync"); + } } /* _ce_image_resize(): resize image, truncating if it shrunk. @@ -758,6 +768,99 @@ _ce_image_fine(u3e_image* img_u, } #endif +/* _ce_image_copy(): +*/ +static c3_o +_ce_image_copy(u3e_image* fom_u, u3e_image* tou_u) +{ + c3_w i_w; + + // resize images + // + _ce_image_resize(tou_u, fom_u->pgs_w); + + // seek to begining of patch and images + // + if ( (-1 == lseek(fom_u->fid_i, 0, SEEK_SET)) + || (-1 == lseek(tou_u->fid_i, 0, SEEK_SET)) ) + { + fprintf(stderr, "loom: image copy seek 0: %s\r\n", strerror(errno)); + return c3n; + } + + // copy pages into destination image + // + for ( i_w = 0; i_w < fom_u->pgs_w; i_w++ ) { + c3_w mem_w[1 << u3a_page]; + c3_w off_w = i_w; + + if ( -1 == read(fom_u->fid_i, mem_w, (1 << (u3a_page + 2))) ) { + fprintf(stderr, "loom: image copy read: %s\r\n", strerror(errno)); + return c3n; + } + else { + if ( -1 == lseek(tou_u->fid_i, (off_w << (u3a_page + 2)), SEEK_SET) ) { + fprintf(stderr, "loom: image copy seek: %s\r\n", strerror(errno)); + return c3n; + } + if ( -1 == write(tou_u->fid_i, mem_w, (1 << (u3a_page + 2))) ) { + fprintf(stderr, "loom: image copy write: %s\r\n", strerror(errno)); + return c3n; + } + } + } + + return c3y; +} + +/* _ce_backup(); +*/ +static void +_ce_backup(void) +{ + u3e_image nop_u = { .nam_c = "north", .pgs_w = 0 }; + u3e_image sop_u = { .nam_c = "south", .pgs_w = 0 }; + c3_i mod_i = O_RDWR | O_CREAT; + c3_c ful_c[8193]; + + snprintf(ful_c, 8192, "%s/.urb/bhk", u3P.dir_c); + + if ( mkdir(ful_c, 0700) ) { + if ( EEXIST != errno ) { + fprintf(stderr, "loom: image backup: %s\r\n", strerror(errno)); + } + return; + } + + snprintf(ful_c, 8192, "%s/.urb/bhk/%s.bin", u3P.dir_c, nop_u.nam_c); + + if ( -1 == (nop_u.fid_i = open(ful_c, mod_i, 0666)) ) { + fprintf(stderr, "loom: open %s: %s\r\n", ful_c, strerror(errno)); + return; + } + + snprintf(ful_c, 8192, "%s/.urb/bhk/%s.bin", u3P.dir_c, sop_u.nam_c); + + if ( -1 == (sop_u.fid_i = open(ful_c, mod_i, 0666)) ) { + fprintf(stderr, "loom: open %s: %s\r\n", ful_c, strerror(errno)); + return; + } + + if ( (c3n == _ce_image_copy(&u3P.nor_u, &nop_u)) + || (c3n == _ce_image_copy(&u3P.sou_u, &sop_u)) ) + { + + unlink(ful_c); + snprintf(ful_c, 8192, "%s/.urb/bhk/%s.bin", u3P.dir_c, nop_u.nam_c); + unlink(ful_c); + snprintf(ful_c, 8192, "%s/.urb/bhk", u3P.dir_c); + rmdir(ful_c); + } + + close(nop_u.fid_i); + close(sop_u.fid_i); +} + /* u3e_save(): save current changes. @@ -794,7 +897,11 @@ u3e_save(void) // u3a_print_memory(stderr, "sync: save", 4096 * pat_u->con_u->pgs_w); _ce_patch_sync(pat_u); - _ce_patch_verify(pat_u); + + if ( c3n == _ce_patch_verify(pat_u) ) { + c3_assert(!"loom: save failed"); + } + _ce_patch_apply(pat_u); #ifdef U3_SNAPSHOT_VALIDATION @@ -816,6 +923,8 @@ u3e_save(void) _ce_image_sync(&u3P.sou_u); _ce_patch_free(pat_u); _ce_patch_delete(); + + _ce_backup(); } /* u3e_live(): start the checkpointing system. diff --git a/pkg/urbit/noun/nock.c b/pkg/urbit/noun/nock.c index bc41e5ddd..f2ec04e64 100644 --- a/pkg/urbit/noun/nock.c +++ b/pkg/urbit/noun/nock.c @@ -1004,8 +1004,8 @@ _n_emit(u3_noun *ops, u3_noun op) static c3_w _n_comp(u3_noun*, u3_noun, c3_o, c3_o); /* _n_bint(): hint-processing helper for _n_comp. - * hif: hint-formula (first part of 10). RETAIN. - * nef: next-formula (second part of 10). RETAIN. + * hif: hint-formula (first part of 11). RETAIN. + * nef: next-formula (second part of 11). RETAIN. */ static c3_w _n_bint(u3_noun* ops, u3_noun hif, u3_noun nef, c3_o los_o, c3_o tel_o) @@ -1021,18 +1021,22 @@ _n_bint(u3_noun* ops, u3_noun hif, u3_noun nef, c3_o los_o, c3_o tel_o) return _n_comp(ops, nef, los_o, tel_o); } - // no currently recognized static hints - // - case u3_none: { + case c3__bout: { u3_noun fen = u3_nul; c3_w nef_w = _n_comp(&fen, nef, los_o, tel_o); + // add appropriate hind opcode + ++nef_w; _n_emit(&fen, ( c3y == los_o ) ? HILL : HILK); + // skip over the cleanup opcode + ++nef_w; _n_emit(&fen, u3nc(SBIP, 1)); + // call hilt_fore // HILB overflows to HILS - // ++tot_w; _n_emit(ops, u3nc(HILB, u3nc(u3k(hif), u3k(nef)))); - ++tot_w; _n_emit(ops, u3nc(SBIN, nef_w + 1)); + // if fore return c3n, skip fen + ++tot_w; _n_emit(ops, u3nc(SBIN, nef_w)); tot_w += nef_w; _n_apen(ops, fen); - ++tot_w; _n_emit(ops, ( c3y == los_o ) ? HILL : HILK); + // post-skip cleanup opcode + ++tot_w; _n_emit(ops, ( c3y == los_o ) ? TOSS : SWAP); } break; } } @@ -1052,19 +1056,24 @@ _n_bint(u3_noun* ops, u3_noun hif, u3_noun nef, c3_o los_o, c3_o tel_o) tot_w += _n_comp(ops, nef, los_o, tel_o); } break; - // no currently recognized dynamic hints - // - case u3_none: { + case c3__bout: { u3_noun fen = u3_nul; c3_w nef_w = _n_comp(&fen, nef, los_o, tel_o); + // add appropriate hind opcode + ++nef_w; _n_emit(&fen, ( c3y == los_o ) ? HINL : HINK); + // skip over the cleanup opcode + ++nef_w; _n_emit(&fen, u3nc(SBIP, 1)); + // push clue tot_w += _n_comp(ops, hod, c3n, c3n); + // call hint_fore // HINB overflows to HINS - // ++tot_w; _n_emit(ops, u3nc(HINB, u3nc(u3k(zep), u3k(nef)))); - ++tot_w; _n_emit(ops, u3nc(SBIN, nef_w + 1)); + // if fore return c3n, skip fen + ++tot_w; _n_emit(ops, u3nc(SBIN, nef_w)); tot_w += nef_w; _n_apen(ops, fen); - ++tot_w; _n_emit(ops, ( c3y == los_o ) ? HINL : HINK); + // post-skip cleanup opcode + ++tot_w; _n_emit(ops, ( c3y == los_o ) ? TOSS : SWAP); } break; } } break; @@ -1677,18 +1686,25 @@ u3n_find(u3_noun key, u3_noun fol) } /* _n_hilt_fore(): literal (atomic) dynamic hint, before formula evaluation. -** lit: hint atom. TRANSFER +** hin: [hint-atom, formula]. TRANSFER ** bus: subject. RETAIN -** out: token for _n_hilt_hind(); -** conventionally, [lit] or [lit data]. ~ if unused. +** out: token for _n_hilt_hind(); convention: +** [hint-atom] or [hint-atom data], ~ if unused. ** ** any hints herein must be whitelisted in _n_burn(). */ static c3_o -_n_hilt_fore(u3_atom lit, u3_noun bus, u3_noun* out) // transfer, retain, n/a +_n_hilt_fore(u3_noun hin, u3_noun bus, u3_noun* out) { - u3z(lit); - *out = u3_nul; + if ( c3__bout == u3h(hin) ) { + u3_atom now = u3i_chub(u3t_trace_time()); + *out = u3i_cell(u3h(hin), now); + } + else { + *out = u3_nul; + } + + u3z(hin); return c3y; } @@ -1697,9 +1713,20 @@ _n_hilt_fore(u3_atom lit, u3_noun bus, u3_noun* out) // transfer, retain, n/a ** pro: product of formula evaluation. RETAIN */ static void -_n_hilt_hind(u3_noun tok, u3_noun pro) // transfer, retain +_n_hilt_hind(u3_noun tok, u3_noun pro) { - c3_assert( u3_nul == tok ); + u3_noun p_tok, q_tok; + if ( (c3y == u3r_cell(tok, &p_tok, &q_tok)) && (c3__bout == p_tok) ) { + u3_atom delta = u3ka_sub(u3i_chub(u3t_trace_time()), u3k(q_tok)); + c3_c str_c[64]; + snprintf(str_c, 63, "took %" PRIu64 "\xc2\xb5s", u3r_chub(0, delta) ); + u3t_slog(u3nc(0, u3i_string(str_c))); + u3z(delta); + } + else { + c3_assert( u3_nul == tok ); + } + u3z(tok); } @@ -1707,16 +1734,24 @@ _n_hilt_hind(u3_noun tok, u3_noun pro) // transfer, retain ** hin: [hint-atom, formula]. TRANSFER ** bus: subject. RETAIN ** clu: product of the hint-formula. TRANSFER -** also, token for _n_hint_hind(); -** conventionally, [hint-atom] or [hint-atom data]. ~ if unused. +** also, token for _n_hilt_hind(); convention: +** [hint-atom] or [hint-atom data], ~ if unused. ** ** any hints herein must be whitelisted in _n_burn(). */ static c3_o _n_hint_fore(u3_cell hin, u3_noun bus, u3_noun* clu) { - u3z(hin); u3z(*clu); - *clu = u3_nul; + if ( c3__bout == u3h(hin) ) { + u3_atom now = u3i_chub(u3t_trace_time()); + *clu = u3i_trel(u3h(hin), *clu, now); + } + else { + u3z(*clu); + *clu = u3_nul; + } + + u3z(hin); return c3y; } @@ -1727,7 +1762,43 @@ _n_hint_fore(u3_cell hin, u3_noun bus, u3_noun* clu) static void _n_hint_hind(u3_noun tok, u3_noun pro) { - c3_assert( u3_nul == tok ); + u3_noun p_tok, q_tok, r_tok; + if ( (c3y == u3r_trel(tok, &p_tok, &q_tok, &r_tok)) + && (c3__bout == p_tok) ) + { + // get the microseconds elapsed + u3_atom delta = u3ka_sub(u3i_chub(u3t_trace_time()), u3k(r_tok)); + + // unpack q_tok to get the priority integer and the tank + // p_q_tok is the priority, q_q_tok is the tank we will work with + u3_noun p_q_tok, q_q_tok; + c3_assert(c3y == u3r_cell(q_tok, &p_q_tok, &q_q_tok)); + + // format the timing report + c3_c str_c[64]; + snprintf(str_c, 63, "took %" PRIu64 "\xc2\xb5s", u3r_chub(0, delta) ); + + // join the timing report with the original tank from q_q_tok like so: + // "q_q_tok: report" + // prepend the priority to form a cell of the same shape q_tok + // send this to ut3_slog so that it can be logged out + u3t_slog( + u3nc( + u3k(p_q_tok), + u3nt( + c3__rose, + u3nt(u3nt(':', ' ', u3_nul), u3_nul, u3_nul), + u3nt(u3k(q_q_tok), u3i_string(str_c), u3_nul) + ) + ) + ); + + u3z(delta); + } + else { + c3_assert( u3_nul == tok ); + } + u3z(tok); } diff --git a/pkg/urbit/ur/hashcons.c b/pkg/urbit/ur/hashcons.c index 4863ef6b7..a2dd691d7 100644 --- a/pkg/urbit/ur/hashcons.c +++ b/pkg/urbit/ur/hashcons.c @@ -937,7 +937,6 @@ struct ur_walk_fore_s { ur_root_t *r; uint32_t prev; uint32_t size; - uint32_t fill; ur_nref *top; }; @@ -950,7 +949,6 @@ ur_walk_fore_init_with(ur_root_t *r, w->top = _oom("walk_fore", malloc(s_size * sizeof(*w->top))); w->prev = s_prev; w->size = s_size; - w->fill = 0; w->r = r; return w; @@ -969,45 +967,42 @@ ur_walk_fore_with(ur_walk_fore_t *w, void (*atom)(ur_root_t*, ur_nref, void*), ur_bool_t (*cell)(ur_root_t*, ur_nref, void*)) { - ur_root_t *r = w->r; - ur_nref *don = w->top; + ur_root_t *r = w->r; + uint32_t fill = 1; - w->top += ++w->fill; *w->top = ref; - while ( w->top != don ) { + do { // visit atom, pop stack // if ( !ur_deep(ref) ) { atom(r, ref, v); - w->top--; w->fill--; + fill--; } // visit cell, pop stack if false // else if ( !cell(r, ref, v) ) { - w->top--; w->fill--; + fill--; } // push the tail, continue into the head // else { - *w->top = ur_tail(r, ref); + w->top[fill++] = ur_tail(r, ref); // reallocate "stack" if full // - if ( w->size == w->fill ) { + if ( w->size == fill ) { uint32_t next = w->prev + w->size; - don = _oom("walk_fore", realloc(don, next * sizeof(*don))); - w->top = don + w->fill; + w->top = _oom("walk_fore", realloc(w->top, next * sizeof(*w->top))); w->prev = w->size; w->size = next; } - w->top++; w->fill++; - *w->top = ur_head(r, ref); + w->top[fill] = ur_head(r, ref); } - ref = *w->top; - } + ref = w->top[fill]; + } while ( fill ); } void diff --git a/pkg/urbit/ur/serial.c b/pkg/urbit/ur/serial.c index 61eeca39c..2bdfa2f4b 100644 --- a/pkg/urbit/ur/serial.c +++ b/pkg/urbit/ur/serial.c @@ -134,7 +134,7 @@ void ur_jam_done(ur_jam_t *j) { ur_dict_free((ur_dict_t*)&j->dict); - free(j->w); + ur_walk_fore_done(j->w); free(j); } diff --git a/pkg/urbit/vere/dawn.c b/pkg/urbit/vere/dawn.c index 9c4cd9959..6ad296341 100644 --- a/pkg/urbit/vere/dawn.c +++ b/pkg/urbit/vere/dawn.c @@ -236,50 +236,6 @@ _dawn_need_unit(u3_noun nit, c3_c* msg_c) } } -/* _dawn_purl(): ethereum gateway url as (unit purl) -*/ -static u3_noun -_dawn_purl(u3_noun rac) -{ - u3_noun url; - - if ( 0 == u3_Host.ops_u.eth_c ) { - if ( c3__czar == rac ) { - u3l_log("boot: galaxy requires ethereum gateway via -e\r\n"); - exit(1); - } - - url = u3_nul; - } - else { - // XX call de-purl directly - // - u3_noun par = u3v_wish("auru:de-purl:html"); - u3_noun lur = u3i_string(u3_Host.ops_u.eth_c); - u3_noun rul = u3dc("rush", u3k(lur), u3k(par)); - - if ( u3_nul == rul ) { - if ( c3__czar == rac ) { - u3l_log("boot: galaxy requires ethereum gateway via -e\r\n"); - exit(1); - } - - url = u3_nul; - } - else { - // XX revise for de-purl - // auru:de-purl:html parses to (pair user purl) - // we need (unit purl) - // - url = u3nc(u3_nul, u3k(u3t(u3t(rul)))); - } - - u3z(par); u3z(lur); u3z(rul); - } - - return url; -} - /* _dawn_turf(): override contract domains with -H */ static u3_noun @@ -330,30 +286,13 @@ _dawn_sponsor(u3_noun who, u3_noun rac, u3_noun pot) u3_noun u3_dawn_vent(u3_noun ship, u3_noun feed) { - u3_noun url, bok, sed, pos, pon, zar, tuf; + u3_noun sed, pos, pon, zar, tuf; u3_noun rank = u3do("clan:title", u3k(ship)); - url = _dawn_purl(rank); - - // XX require https? - // c3_c* url_c = ( 0 != u3_Host.ops_u.eth_c ) ? u3_Host.ops_u.eth_c : - "http://eth-mainnet.urbit.org:8545"; - - // pin block number - // - { - u3l_log("boot: retrieving latest block\r\n"); - - u3_noun oct = u3v_wish("bloq:give:dawn"); - u3_noun kob = _dawn_eth_rpc(url_c, u3k(oct)); - - bok = _dawn_need_unit(u3do("bloq:take:dawn", u3k(kob)), - "boot: block retrieval failed"); - u3z(oct); u3z(kob); - } + "https://roller.urbit.org/v1/azimuth"; { // +point:azimuth: on-chain state @@ -373,7 +312,7 @@ u3_dawn_vent(u3_noun ship, u3_noun feed) u3_Host.ops_u.who_c); { - u3_noun oct = u3dc("point:give:dawn", u3k(bok), u3k(ship)); + u3_noun oct = u3do("point:give:dawn", u3k(ship)); u3_noun luh = _dawn_eth_rpc(url_c, u3k(oct)); pot = _dawn_need_unit(u3dc("point:take:dawn", u3k(ship), u3k(luh)), @@ -411,7 +350,7 @@ u3_dawn_vent(u3_noun ship, u3_noun feed) { u3l_log("boot: retrieving galaxy table\r\n"); - u3_noun oct = u3do("czar:give:dawn", u3k(bok)); + u3_noun oct = u3v_wish("czar:give:dawn"); u3_noun raz = _dawn_eth_rpc(url_c, u3k(oct)); zar = _dawn_need_unit(u3do("czar:take:dawn", u3k(raz)), @@ -427,7 +366,7 @@ u3_dawn_vent(u3_noun ship, u3_noun feed) else { u3l_log("boot: retrieving network domains\r\n"); - u3_noun oct = u3do("turf:give:dawn", u3k(bok)); + u3_noun oct = u3v_wish("turf:give:dawn"); u3_noun fut = _dawn_eth_rpc(url_c, u3k(oct)); tuf = _dawn_need_unit(u3do("turf:take:dawn", u3k(fut)), @@ -451,7 +390,7 @@ u3_dawn_vent(u3_noun ship, u3_noun feed) // retrieve +point:azimuth of pos (sponsor of ship) // { - u3_noun oct = u3dc("point:give:dawn", u3k(bok), u3k(pos)); + u3_noun oct = u3do("point:give:dawn", u3k(pos)); u3_noun luh = _dawn_eth_rpc(url_c, u3k(oct)); son = _dawn_need_unit(u3dc("point:take:dawn", u3k(pos), u3k(luh)), @@ -474,8 +413,10 @@ u3_dawn_vent(u3_noun ship, u3_noun feed) // [%dawn seed sponsors galaxies domains block eth-url snap] // + //NOTE blocknum of 0 is fine because jael ignores it. + // should probably be removed from dawn event. u3_noun ven = u3nc(c3__dawn, - u3nq(u3k(u3t(sed)), pon, zar, u3nt(tuf, bok, url))); + u3nq(u3k(u3t(sed)), pon, zar, u3nt(tuf, 0, u3_nul))); u3z(sed); u3z(rank); u3z(pos); u3z(ship); u3z(feed); diff --git a/pkg/urbit/vere/disk.c b/pkg/urbit/vere/disk.c index 6f8240daa..4ef09546d 100644 --- a/pkg/urbit/vere/disk.c +++ b/pkg/urbit/vere/disk.c @@ -751,7 +751,7 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u) // "[..] on 64-bit there is no penalty for making this huge (say 1TB)." // { - #if defined(U3_CPU_aarch64) && defined(U3_OS_linux) + #if (defined(U3_CPU_aarch64) && defined(U3_OS_linux)) || defined(U3_OS_mingw) const size_t siz_i = 64424509440; #else const size_t siz_i = 1099511627776; diff --git a/pkg/urbit/vere/pier.c b/pkg/urbit/vere/pier.c index db072f641..9aad54105 100644 --- a/pkg/urbit/vere/pier.c +++ b/pkg/urbit/vere/pier.c @@ -687,7 +687,7 @@ _pier_wyrd_fail(u3_pier* pir_u, u3_ovum* egg_u, u3_noun lud) // XX organizing version constants // #define VERE_NAME "vere" -#define VERE_ZUSE 420 +#define VERE_ZUSE 419 /* _pier_wyrd_aver(): check for %wend effect and version downgrade. RETAIN */ @@ -1114,7 +1114,7 @@ _pier_on_lord_play_bail(void* ptr_v, u3_info fon_u, // dispose successful // - while ( tac_u->eve_d < eve_d ) { + while ( tac_u->eve_d <= eve_d ) { nex_u = tac_u->nex_u; las_l = tac_u->mug_l; u3_fact_free(tac_u); diff --git a/pkg/urbit/version b/pkg/urbit/version index dc39e58d9..468437494 100644 --- a/pkg/urbit/version +++ b/pkg/urbit/version @@ -1 +1 @@ -1.6 \ No newline at end of file +1.8 \ No newline at end of file diff --git a/pkg/urbit/worker/serf.c b/pkg/urbit/worker/serf.c index 3e005a750..55cb3ad7d 100644 --- a/pkg/urbit/worker/serf.c +++ b/pkg/urbit/worker/serf.c @@ -751,16 +751,12 @@ _serf_play_list(u3_serf* sef_u, u3_noun eve) eve = u3t(eve); } - // event succeeded, save and continue + // event failed, stop and send trace // else { - u3_noun dud = u3k(u3t(gon)); - // reset sent event counter // - sef_u->sen_d = sef_u->dun_d; - - u3z(gon); + sef_u->sen_d = sef_u->dun_d; // XX reclaim on meme ? // @@ -770,7 +766,7 @@ _serf_play_list(u3_serf* sef_u, u3_noun eve) u3z(vev); return u3nc(c3__bail, u3nt(u3i_chubs(1, &sef_u->dun_d), sef_u->mug_l, - dud)); + gon)); } } diff --git a/pkg/webterm/sys.kelvin b/pkg/webterm/sys.kelvin index b7464903a..e68acb6a4 100644 --- a/pkg/webterm/sys.kelvin +++ b/pkg/webterm/sys.kelvin @@ -1 +1 @@ -[%zuse 420] +[%zuse 419]