Merge branch 'master' into next/landscape

This commit is contained in:
Hunter Miller 2021-12-03 16:44:51 -06:00
commit 9e3ed16c76
150 changed files with 10465 additions and 2044 deletions

2
.gitattributes vendored
View File

@ -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

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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"

View File

@ -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.

View File

@ -1 +0,0 @@
{"orgId":"EDiU8DZExvM9N4unZGYQbG3d","projectId":"prj_fbAU5smemBgtr5t8lsk5ZoT9zNtI"}

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f50aee74e4f3dd6685d36520bbc924ab94d3d47a7bc86e649882e58ab069e7dd
size 991930
oid sha256:f59ec4eaf907227a1fd64e1d54810b769b5d39f6811c6bb254b2e89de528ca04
size 1209494

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:049801d388b4cb7203854b4668826688c21089f90430bd547d276e7b59386e8d
size 5588170
oid sha256:6f48518fe49584a6532a20018f4ac4eae3817b25d85d60536a99643eb5d65b2b
size 22872573

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d8d387759fe4830fcc09a1fc7b80d52e61327d518f7eb0713697aec1819eacf7
size 5608210
oid sha256:c29577dc949ac0689ba3c97ad13b812ea6c3c6cc9d255b770d2da95fd9af84b9
size 23121802

View File

@ -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
'';
}

View File

@ -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])

View File

@ -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 {<bind>}"
:_ 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)
==
--
--

View File

@ -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]

419
pkg/arvo/app/azimuth.hoon Normal file
View File

@ -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 &eth-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]~
--

Binary file not shown.

View File

@ -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

View File

@ -212,6 +212,7 @@
public:mainnet-contracts
~[azimuth delegated-sending]:mainnet-contracts
~
~
==
::
:: see also comment in +setup-cards

View File

@ -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 {<bind>}"
:_ 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)
==
--
--

1338
pkg/arvo/app/roller.hoon Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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]

View File

@ -1,5 +1,5 @@
:~ %acme
%azimuth-tracker
%azimuth
%dbug
%dojo
%eth-watcher

View File

@ -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
==

View File

@ -0,0 +1,4 @@
::
:- %say
|= [* [=binding:eyre ~] ~]
[%azimuth-action %disconnect binding]

View File

@ -1,4 +0,0 @@
:: Kick azimuth-tracker
:- %say
|= *
[%azimuth-tracker-poke %listen ~ %| %azimuth-tracker]

View File

@ -1,4 +0,0 @@
:: Change node url for azimuth-tracker
:- %say
|= [* [url=@ta ~] ~]
[%azimuth-tracker-poke %watch url]

View File

@ -0,0 +1,4 @@
:: Kick azimuth
:- %say
|= *
[%azimuth-poke %listen ~ %| %azimuth]

View File

@ -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]

View File

@ -0,0 +1,4 @@
:: Change node url and network for azimuth
:- %say
|= [* [url=@ta net=?(%mainnet %ropsten %local %default) ~] ~]
[%azimuth-poke %watch url net]

View File

@ -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)]

View File

@ -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]

View File

@ -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))

View File

@ -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 ~ ~] ~]

View File

@ -0,0 +1,5 @@
:: Submits a new L2 batch with all pending transactions
::
:- %say
|= *
[%roller-action %commit ~]

View File

@ -0,0 +1,7 @@
:: Updates a configuration option for /app/roller
::
/- *dice
::
:- %say
|= [* [=config ~] ~]
[%roller-action %config config]

View File

@ -0,0 +1,4 @@
::
:- %say
|= [* [url=@t net=?(%mainnet %ropsten %local) ~] ~]
[%roller-action %config %endpoint url net]

View File

@ -0,0 +1,4 @@
::
:- %say
|= [* [freq=@dr ~] ~]
[%roller-action %config %frequency freq]

View File

@ -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]

View File

@ -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]

View File

@ -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
==

View File

@ -0,0 +1,5 @@
:: Loads a private key into the roller and retrieves its L1 nonce
::
:- %say
|= [* [pk=@t ~] ~]
[%roller-action %config %setkey pk]

View File

@ -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]

View File

@ -1,4 +1,3 @@
/- *bill
:- %say
|= $: [now=@da eny=@uvJ bec=beak]
[=desk ~]
@ -11,5 +10,5 @@
:~ 'sys.kelvin:'
leaf/"[%{<lal>} %{<num>}]"
'desk.bill:'
(sell !>(.^(bill cx+(weld pax /desk/bill))))
(sell !>(.^((list dude:gall) cx+(weld pax /desk/bill))))
==

56
pkg/arvo/gen/tx.hoon Normal file
View File

@ -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)

View File

@ -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)]
--

View File

@ -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

View File

@ -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)]~]]
::
--

207
pkg/arvo/lib/dice.hoon Normal file
View File

@ -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))
==
::
--

View File

@ -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 "{<lac>} 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 {<zuse/zuse>}: {<ded>}"
::
@ -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: {<new-weft>}")
=. 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

View File

@ -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']
--
--

View File

@ -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
~
==
::
--

926
pkg/arvo/lib/naive.hoon Normal file
View File

@ -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)

670
pkg/arvo/lib/tiny.hoon Normal file
View File

@ -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))
--
--

View File

@ -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
::

View File

@ -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
--

View File

@ -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
--

View File

@ -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

View File

@ -1,9 +0,0 @@
/- resource
::
|%
+$ channel-info
$: group=resource:resource
channel=resource:resource
channel-type=term
==
--

96
pkg/arvo/sur/dice.hoon Normal file
View File

@ -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)
==
--

View File

@ -18,6 +18,7 @@
timeout-time=@dr
from=number:block
contracts=(list address:ethereum)
batchers=(list address:ethereum)
=topics
==
::

View File

@ -1 +1 @@
[%zuse 420]
[%zuse 419]

View File

@ -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)]]

View File

@ -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

View File

@ -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 {<bel>} to equivalent aeon {<yon>}"
..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: {<yon>}, existing aeon: {<u.yen>}"
!!
::
:: 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)

View File

@ -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) [~ ~]

View File

@ -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]

View File

@ -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)
--

View File

@ -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))

View File

@ -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)< ~]
::
--

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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)
==
--

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1d227633641c8abb68d16633e110467fd4a4330c921496312d75b471677e2a02
size 3057639

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:66e64f702b542347f1d8e267dc87c542e3f8f537278f6a221aa6d7d793b21d55
size 461160

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fb475f30c6d6c68b3c31ce46155a1e3d98b18359b6750b7bb6b00e429187e1ef
size 376635

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:45a54c6e05e3db80b3cc9746a65f185da29d8644d7a0bf953fade9f15a78dad4
size 1812725

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8fe9b7b9b38fa7f16f8ec234984c44c616856937eff50353e11eb62c173f6b09
size 306377

View File

@ -1,5 +0,0 @@
:~ :- %apes
~
:- %fish
~
==

View File

@ -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

View File

@ -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)
--

View File

@ -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

View File

@ -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

View File

@ -1 +1 @@
[%zuse 420]
[%zuse 419]

View File

@ -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)
::

View File

@ -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'
==

View File

@ -1 +1 @@
[%zuse 420]
[%zuse 419]

View File

@ -49,8 +49,6 @@ const AppRoutes = () => {
}
}, [isDarkMode, theme]);
useEffect(() => {}, []);
useEffect(
handleError(() => {
window.name = 'grid';

View File

@ -227,6 +227,7 @@ export const Leap = React.forwardRef(
[selection, rawInput, match, matches, selectedMatch]
);
return (
<div className="relative z-50 w-full">
<form
@ -234,6 +235,7 @@ export const Leap = React.forwardRef(
'flex items-center h-full w-full px-2 rounded-full bg-white default-ring focus-within:ring-2',
shouldDim && 'opacity-60',
!navOpen ? 'bg-gray-50' : '',
menu === 'upgrading' ? 'bg-orange-500' : '',
className
)}
onSubmit={onSubmit}
@ -241,28 +243,32 @@ export const Leap = React.forwardRef(
<label
htmlFor="leap"
className={classNames(
'inline-block flex-none p-2 h4 text-blue-400',
!selection && 'sr-only'
'inline-block flex-none p-2 h4 ',
menu === 'upgrading' ? 'text-white' : !selection ? 'sr-only' : 'text-blue-400'
)}
>
{selection || 'Search'}
{menu === 'upgrading'
? 'Your Urbit is being updated, this page will update when ready'
: selection || 'Search'}
</label>
<input
id="leap"
type="text"
ref={inputRef}
placeholder={selection ? '' : 'Search'}
className="flex-1 w-full h-full px-2 h4 text-base rounded-full bg-transparent outline-none"
value={rawInput}
onClick={toggleSearch}
onFocus={onFocus}
onChange={onChange}
onKeyDown={onKeyDown}
autoComplete="off"
aria-autocomplete="both"
aria-controls={dropdown}
aria-activedescendant={selectedMatch?.display || selectedMatch?.value}
/>
{menu !== 'upgrading' ? (
<input
id="leap"
type="text"
ref={inputRef}
placeholder={selection ? '' : 'Search'}
className="flex-1 w-full h-full px-2 h4 text-base rounded-full bg-transparent outline-none"
value={rawInput}
onClick={toggleSearch}
onFocus={onFocus}
onChange={onChange}
onKeyDown={onKeyDown}
autoComplete="off"
aria-autocomplete="both"
aria-controls={dropdown}
aria-activedescendant={selectedMatch?.display || selectedMatch?.value}
/>
) : null}
</form>
{menu === 'search' && (
<Link

View File

@ -52,7 +52,8 @@ export type MenuState =
| 'search'
| 'notifications'
| 'help-and-support'
| 'system-preferences';
| 'system-preferences'
| 'upgrading';
interface NavProps {
menu?: MenuState;
@ -68,7 +69,7 @@ export const Nav: FunctionComponent<NavProps> = ({ 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(() => {

View File

@ -12,7 +12,7 @@ function renderNotification(notification: Notification, key: string, lid: HarkLi
if (notification.bin.place.path === '/lag') {
return <RuntimeLagNotification key={key} />;
}
if (notification.bin.place.path === '/blocked') {
if (notification.bin.path === '/blocked' && notification.bin.place.path === '/desk/base') {
return <BaseBlockedNotification key={key} />;
}
if (notification.bin.place.path === '/onboard') {

View File

@ -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 = () => (
<section
@ -35,16 +38,29 @@ export const RuntimeLagNotification = () => (
</section>
);
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 (

View File

@ -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<GridProps> = ({ match, history }) => {
export const Grid: FunctionComponent<{}> = () => {
const charges = useCharges();
const { push } = useHistory();
const { menu } = useParams<RouteProps>();
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 (
<div className="flex flex-col">
<header className="fixed sm:sticky bottom-0 sm:bottom-auto sm:top-0 left-0 z-30 flex justify-center w-full px-4">
<Nav menu={match.params.menu} />
<Nav menu={menu} />
</header>
<main className="h-full w-full flex justify-center pt-4 md:pt-16 pb-32 relative z-0">
@ -30,11 +54,11 @@ export const Grid: FunctionComponent<GridProps> = ({ match, history }) => {
<div className="grid justify-center grid-cols-2 sm:grid-cols-[repeat(auto-fit,minmax(auto,250px))] gap-4 px-4 md:px-8 w-full max-w-6xl">
{charges &&
map(omit(charges, window.desk), (charge, desk) => (
<Tile key={desk} charge={charge} desk={desk} />
<Tile key={desk} charge={charge} desk={desk} disabled={menu === 'upgrading'} />
))}
</div>
)}
<ErrorBoundary FallbackComponent={ErrorAlert} onReset={() => history.push('/')}>
<ErrorBoundary FallbackComponent={ErrorAlert} onReset={() => push('/')}>
<Route exact path="/app/:desk">
<TileInfo />
</Route>

View File

@ -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', [

View File

@ -22,16 +22,19 @@ export const RemoveApp = () => {
return (
<Dialog open onOpenChange={(open) => !open && history.push('/')}>
<DialogContent showClose={false} className="space-y-6" containerClass="w-full max-w-md">
<h1 className="h4">Remove &ldquo;{getAppName(docket)}&rdquo;?</h1>
<h1 className="h4">Uninstall &ldquo;{getAppName(docket)}&rdquo;?</h1>
<p className="text-base tracking-tight pr-6">
This will remove the software&apos;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.
</p>
<p className="text-base tracking-tight pr-6">
If the app is reinstalled, the archived data will be restored and you'll be able to pick up where you left off.
</p>
<div className="flex space-x-6">
<DialogClose as={Button} variant="secondary">
Cancel
</DialogClose>
<DialogClose as={Button} onClick={handleRemoveApp}>
Remove &ldquo;{getAppName(docket)}&rdquo;
Uninstall
</DialogClose>
</div>
</DialogContent>

View File

@ -27,15 +27,17 @@ export const SuspendApp = () => {
<DialogContent showClose={false} className="space-y-6" containerClass="w-full max-w-md">
<h1 className="h4">Suspend &ldquo;{getAppName(charge)}&rdquo;</h1>
<p className="text-base tracking-tight pr-6">
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.
</p>
<p className="text-base tracking-tight pr-6">
When unsuspended, archived data will be loaded and all processes will resume running, so you can pick up where you left off.
</p>
<div className="flex space-x-6">
<DialogClose as={Button} variant="secondary">
Cancel
</DialogClose>
<DialogClose as={Button} onClick={handleSuspendApp}>
Suspend &ldquo;{getAppName(charge)}&rdquo;
Suspend
</DialogClose>
</div>
</DialogContent>

View File

@ -13,19 +13,20 @@ import { Bullet } from '../components/icons/Bullet';
type TileProps = {
charge: ChargeWithDesk;
desk: string;
disabled?: boolean;
};
export const Tile: FunctionComponent<TileProps> = ({ charge, desk }) => {
export const Tile: FunctionComponent<TileProps> = ({ 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 (
<a
@ -47,14 +48,12 @@ export const Tile: FunctionComponent<TileProps> = ({ charge, desk }) => {
<>
{loading && <Spinner className="h-6 w-6 mr-2" />}
<span className="text-gray-500">
{suspended && 'Suspended'}
{loading && 'Installing'}
{hung && 'Errored'}
{suspended ? 'Suspended' : loading ? 'Installing' : hung ? 'Errored' : null }
</span>
</>
)}
</div>
{vat?.arak.rail?.paused && (
{vat?.arak.rail?.paused && !disabled && (
<Bullet className="absolute z-10 top-5 left-5 sm:top-7 sm:left-7 w-4 h-4 text-orange-500 dark:text-black" />
)}
<TileMenu

View File

@ -85,7 +85,7 @@ export const TileMenu = ({ desk, chad, menuColor, lightText, className }: TileMe
)}
{suspended && <Item onSelect={() => toggleDocket(desk)}>Resume App</Item>}
<Item as={Link} to={`/app/${desk}/remove`} onSelect={linkOnSelect}>
Remove App
Uninstall App
</Item>
</DropdownMenu.Group>
<DropdownMenu.Arrow className="w-4 h-[10px] fill-current" style={{ color: menuColor }} />

View File

@ -439,7 +439,7 @@ data PierVersionNegotiationFailed = PierVersionNegotiationFailed
deriving (Show, Exception)
zuseVersion :: Word
zuseVersion = 420
zuseVersion = 419
wyrd :: HasKingEnv e => RIO e Ev
wyrd = do

View File

@ -1,5 +1,5 @@
name: urbit-king
version: 1.6
version: 1.8
license: MIT
license-file: LICENSE
data-files:

Some files were not shown because too many files have changed in this diff Show More