2019-08-07 01:42:37 +03:00
|
|
|
!: :: /vane/jael
|
2016-11-24 07:25:07 +03:00
|
|
|
:: :: %reference/0
|
|
|
|
!? 150
|
|
|
|
::
|
|
|
|
::
|
|
|
|
:: %jael: secrets and promises.
|
|
|
|
::
|
2016-12-16 09:34:01 +03:00
|
|
|
:: todo:
|
|
|
|
::
|
2016-11-24 07:25:07 +03:00
|
|
|
:: - communication with other vanes:
|
|
|
|
:: - actually use %behn for expiring secrets
|
|
|
|
:: - report %ames propagation errors to user
|
|
|
|
::
|
|
|
|
:: - nice features:
|
|
|
|
:: - scry namespace
|
|
|
|
:: - task for converting invites to tickets
|
|
|
|
::
|
|
|
|
|= pit/vase
|
2016-12-07 06:13:33 +03:00
|
|
|
=, pki:jael
|
2016-12-10 03:47:21 +03:00
|
|
|
=, able:jael
|
2016-12-02 22:34:07 +03:00
|
|
|
=, crypto
|
2016-11-24 07:25:07 +03:00
|
|
|
=, jael
|
2018-05-16 00:16:29 +03:00
|
|
|
=, ethereum
|
2018-12-18 01:38:24 +03:00
|
|
|
=, rpc
|
|
|
|
=, azimuth
|
2019-08-07 01:42:37 +03:00
|
|
|
=, point=point:able:jael
|
2016-11-24 07:25:07 +03:00
|
|
|
:: ::::
|
|
|
|
:::: # models :: data structures
|
|
|
|
:: ::::
|
|
|
|
:: the %jael state comes in two parts: absolute
|
|
|
|
:: and relative.
|
|
|
|
::
|
|
|
|
:: ++state-relative is subjective, denormalized and
|
|
|
|
:: derived. it consists of all the state we need to
|
|
|
|
:: manage subscriptions efficiently.
|
|
|
|
::
|
|
|
|
=> |%
|
2019-08-07 01:42:37 +03:00
|
|
|
+$ state :: all vane state
|
2019-06-21 21:03:53 +03:00
|
|
|
$: ver=$0 :: vane version
|
2019-08-07 01:42:37 +03:00
|
|
|
pki=state-pki ::
|
2018-05-29 00:04:33 +03:00
|
|
|
etn=state-eth-node :: eth connection state
|
2016-11-24 07:25:07 +03:00
|
|
|
== ::
|
2019-08-07 01:42:37 +03:00
|
|
|
+$ state-pki :: urbit metadata
|
|
|
|
$: $= own :: vault (vein)
|
2019-06-21 21:03:53 +03:00
|
|
|
$: yen=(set duct) :: trackers
|
2018-10-16 03:39:55 +03:00
|
|
|
sig=(unit oath) :: for a moon
|
2018-10-15 22:51:53 +03:00
|
|
|
tuf=(list turf) :: domains
|
2018-10-29 22:38:14 +03:00
|
|
|
boq=@ud :: boot block
|
2019-08-07 01:42:37 +03:00
|
|
|
nod=purl:eyre :: eth gateway
|
2019-06-21 21:03:53 +03:00
|
|
|
fak=_| :: fake keys
|
|
|
|
lyf=life :: version
|
|
|
|
jaw=(map life ring) :: private keys
|
2016-11-24 07:25:07 +03:00
|
|
|
== ::
|
2019-08-07 01:42:37 +03:00
|
|
|
$= zim :: public
|
|
|
|
$: yen=(jug duct ship) :: trackers
|
|
|
|
ney=(jug ship duct) :: reverse trackers
|
2019-08-20 20:22:52 +03:00
|
|
|
nel=(set duct) :: trackers of all
|
2018-05-29 00:04:33 +03:00
|
|
|
dns=dnses :: on-chain dns state
|
2018-12-14 00:23:17 +03:00
|
|
|
pos=(map ship point) :: on-chain ship state
|
2018-05-29 00:04:33 +03:00
|
|
|
== ::
|
2016-12-16 09:34:01 +03:00
|
|
|
== ::
|
2019-08-07 01:42:37 +03:00
|
|
|
+$ message :: message to her jael
|
|
|
|
$% [%nuke whos=(set ship)] :: cancel trackers
|
|
|
|
[%public-keys whos=(set ship)] :: view ethereum events
|
jael: provide edge-triggered breach notification
Until now, clients of Jael have had to store the first-seen rift if they
want to reliably detect breaches. Otherwise, they would get a false
positive if they heard an old message about a breach (eg if you kick
azimuth-tracker). Clay and Gall did this correctly, but Ames did not.
Jael already maintains this state, so I added a notification to the
existing subscription that happens whenever it notices a breach (a diff
or full where the new rift is greater than the old one).
Because this is an issue on the live network, I wrote state adapters
for Gall and Clay. The Gall one just removes the rift from our state,
but the Clay one is much more involved because we have to upgrade
instances of the clad monad that are possibly in progress.
Specifically, since more input is possible than before, we must wrap any
in-progress instances of the monad in a function that handles the
potential new input from Jael. This temporarily preservers a copy of
the old kernel, but only until the current commit/merge/update has
completed.
The real solution for Clay is to factor out those IO-heavy instances to
userspace tapp/async/imp/threads, and if an upgrade happens in the
middle, you should simply restart them.
Fixes #1852
2019-10-24 07:26:38 +03:00
|
|
|
[%public-keys-result =public-keys-result] ::
|
2016-11-24 07:25:07 +03:00
|
|
|
== ::
|
2019-08-07 01:42:37 +03:00
|
|
|
+$ card :: i/o action
|
2019-05-25 11:43:13 +03:00
|
|
|
(wind note gift) ::
|
2016-11-24 07:25:07 +03:00
|
|
|
:: ::
|
2019-06-22 00:45:00 +03:00
|
|
|
+$ move :: output
|
2019-06-21 21:03:53 +03:00
|
|
|
[p=duct q=card] ::
|
2019-05-25 11:43:13 +03:00
|
|
|
:: ::
|
|
|
|
+$ note :: out request $->
|
2019-08-07 01:42:37 +03:00
|
|
|
$~ [%a %want *ship *path **] ::
|
|
|
|
$% $: %a :: to %ames
|
2019-05-25 11:43:13 +03:00
|
|
|
$>(%want task:able:ames) :: send message
|
|
|
|
== ::
|
2019-08-07 01:42:37 +03:00
|
|
|
$: %g :: to self
|
jael: provide edge-triggered breach notification
Until now, clients of Jael have had to store the first-seen rift if they
want to reliably detect breaches. Otherwise, they would get a false
positive if they heard an old message about a breach (eg if you kick
azimuth-tracker). Clay and Gall did this correctly, but Ames did not.
Jael already maintains this state, so I added a notification to the
existing subscription that happens whenever it notices a breach (a diff
or full where the new rift is greater than the old one).
Because this is an issue on the live network, I wrote state adapters
for Gall and Clay. The Gall one just removes the rift from our state,
but the Clay one is much more involved because we have to upgrade
instances of the clad monad that are possibly in progress.
Specifically, since more input is possible than before, we must wrap any
in-progress instances of the monad in a function that handles the
potential new input from Jael. This temporarily preservers a copy of
the old kernel, but only until the current commit/merge/update has
completed.
The real solution for Clay is to factor out those IO-heavy instances to
userspace tapp/async/imp/threads, and if an upgrade happens in the
middle, you should simply restart them.
Fixes #1852
2019-10-24 07:26:38 +03:00
|
|
|
$>(%deal task:able:gall) :: set ethereum source
|
2019-07-04 03:08:23 +03:00
|
|
|
== ::
|
2019-05-25 11:43:13 +03:00
|
|
|
$: %j :: to self
|
2019-08-07 01:42:37 +03:00
|
|
|
$>(%listen task) :: set ethereum source
|
2019-05-25 11:43:13 +03:00
|
|
|
== ::
|
|
|
|
$: @tas ::
|
2019-05-27 10:41:03 +03:00
|
|
|
$% $>(%init vane-task) :: report install
|
2019-05-25 11:43:13 +03:00
|
|
|
== == == ::
|
|
|
|
:: ::
|
2019-08-07 01:42:37 +03:00
|
|
|
+$ peer-sign [=ship =udiff:point] ::
|
|
|
|
:: ::
|
2019-05-25 11:43:13 +03:00
|
|
|
+$ sign :: in result $<-
|
2019-08-07 01:42:37 +03:00
|
|
|
$~ [%a %woot *ship ~] ::
|
|
|
|
$% [%a $>(%woot gift:able:ames)] :: message result
|
|
|
|
$: %g ::
|
|
|
|
$> $? %onto ::
|
|
|
|
%unto ::
|
|
|
|
== ::
|
|
|
|
gift:able:gall ::
|
|
|
|
==
|
2019-05-25 11:43:13 +03:00
|
|
|
== ::
|
2016-11-24 07:25:07 +03:00
|
|
|
-- ::
|
|
|
|
:: ::::
|
|
|
|
:::: # light :: light cores
|
|
|
|
:: ::::
|
|
|
|
=> |%
|
2018-05-29 00:04:33 +03:00
|
|
|
:: :: ++ez
|
|
|
|
:::: ## ethereum^light :: wallet algebra
|
|
|
|
:: ::::
|
|
|
|
++ ez
|
|
|
|
:: simple ethereum-related utility arms.
|
|
|
|
::
|
|
|
|
|%
|
2018-05-30 01:40:00 +03:00
|
|
|
::
|
|
|
|
:: +order-events: sort changes by block and log numbers
|
|
|
|
::
|
2018-05-29 00:04:33 +03:00
|
|
|
++ order-events
|
2018-12-14 00:23:17 +03:00
|
|
|
|= loz=(list (pair event-id diff-azimuth))
|
2018-05-29 00:04:33 +03:00
|
|
|
^+ loz
|
|
|
|
%+ sort loz
|
|
|
|
:: sort by block number, then by event log number,
|
|
|
|
::TODO then by diff priority.
|
|
|
|
|= [[[b1=@ud l1=@ud] *] [[b2=@ud l2=@ud] *]]
|
|
|
|
?. =(b1 b2) (lth b1 b2)
|
|
|
|
?. =(l1 l2) (lth l1 l2)
|
|
|
|
&
|
|
|
|
--
|
2016-11-24 07:25:07 +03:00
|
|
|
--
|
|
|
|
:: ::::
|
|
|
|
:::: # heavy :: heavy engines
|
|
|
|
:: ::::
|
|
|
|
=> |%
|
|
|
|
:: :: ++of
|
|
|
|
:::: ## main^heavy :: main engine
|
|
|
|
:: ::::
|
|
|
|
++ of
|
|
|
|
:: this core handles all top-level %jael semantics,
|
|
|
|
:: changing state and recording moves.
|
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
:: logically we could nest the ++su core within it, but
|
|
|
|
:: we keep them separated for clarity. the ++curd and
|
|
|
|
:: ++cure arms complete relative and absolute effects,
|
|
|
|
:: respectively, at the top level.
|
|
|
|
::
|
|
|
|
:: XX doc
|
2016-11-24 07:25:07 +03:00
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
:: a general pattern here is that we use the ++et core
|
2016-12-16 09:34:01 +03:00
|
|
|
:: to generate absolute effects (++change), then invoke
|
2016-11-24 07:25:07 +03:00
|
|
|
:: ++su to calculate the derived effect of these changes.
|
|
|
|
::
|
2018-05-30 01:40:00 +03:00
|
|
|
:: for ethereum-related events, this is preceded by
|
|
|
|
:: invocation of ++et, which produces ethereum-level
|
|
|
|
:: changes (++chain). these get turned into absolute
|
|
|
|
:: effects by ++cute.
|
|
|
|
::
|
2016-11-24 07:25:07 +03:00
|
|
|
:: arvo issues: should be merged with the top-level
|
|
|
|
:: vane interface when that gets cleaned up a bit.
|
|
|
|
::
|
|
|
|
=| moz/(list move)
|
2018-12-12 11:34:05 +03:00
|
|
|
=| $: $: :: our: identity
|
|
|
|
:: now: current time
|
2016-11-24 07:25:07 +03:00
|
|
|
:: eny: unique entropy
|
|
|
|
::
|
2018-12-12 11:34:05 +03:00
|
|
|
our=ship
|
2018-12-06 00:41:21 +03:00
|
|
|
now=@da
|
|
|
|
eny=@uvJ
|
2016-11-24 07:25:07 +03:00
|
|
|
==
|
|
|
|
:: all vane state
|
|
|
|
::
|
|
|
|
state
|
|
|
|
==
|
|
|
|
:: lex: all durable state
|
|
|
|
:: moz: pending actions
|
|
|
|
::
|
|
|
|
=* lex ->
|
|
|
|
|%
|
|
|
|
:: :: ++abet:of
|
|
|
|
++ abet :: resolve
|
|
|
|
[(flop moz) lex]
|
2018-10-12 19:48:52 +03:00
|
|
|
:: :: ++sein:of
|
2019-08-07 01:42:37 +03:00
|
|
|
++ emit
|
|
|
|
|= =move
|
|
|
|
+>.$(moz [move moz])
|
|
|
|
::
|
|
|
|
++ poke-watch
|
|
|
|
|= [hen=duct app=term =purl:eyre]
|
|
|
|
%- emit
|
|
|
|
:* hen
|
|
|
|
%pass
|
|
|
|
/[app]/poke
|
|
|
|
%g
|
|
|
|
%deal
|
|
|
|
[our our]
|
|
|
|
app
|
|
|
|
%poke
|
|
|
|
%azimuth-tracker-poke
|
|
|
|
!>([%watch (crip (en-purl:html purl))])
|
|
|
|
==
|
|
|
|
::
|
2018-10-12 19:48:52 +03:00
|
|
|
++ sein :: sponsor
|
|
|
|
|= who=ship
|
|
|
|
^- ship
|
|
|
|
:: XX save %dawn sponsor in .own.sub, check there
|
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
=/ pot (~(get by pos.zim.pki) who)
|
2018-12-14 00:23:17 +03:00
|
|
|
?: ?& ?=(^ pot)
|
2019-08-07 01:42:37 +03:00
|
|
|
?=(^ sponsor.u.pot)
|
2018-10-12 19:48:52 +03:00
|
|
|
==
|
2019-08-07 01:42:37 +03:00
|
|
|
u.sponsor.u.pot
|
2018-10-15 09:23:34 +03:00
|
|
|
(^sein:title who)
|
2018-10-12 19:48:52 +03:00
|
|
|
:: :: ++saxo:of
|
|
|
|
++ saxo :: sponsorship chain
|
|
|
|
|= who/ship
|
|
|
|
^- (list ship)
|
|
|
|
=/ dad (sein who)
|
|
|
|
[who ?:(=(who dad) ~ $(who dad))]
|
2016-11-24 07:25:07 +03:00
|
|
|
:: :: ++call:of
|
|
|
|
++ call :: invoke
|
|
|
|
|= $: :: hen: event cause
|
|
|
|
:: tac: event data
|
|
|
|
::
|
|
|
|
hen/duct
|
|
|
|
tac/task
|
|
|
|
==
|
|
|
|
^+ +>
|
|
|
|
?- -.tac
|
|
|
|
::
|
2018-09-07 04:41:16 +03:00
|
|
|
:: boot from keys
|
2018-10-29 22:38:14 +03:00
|
|
|
:: $: $dawn
|
|
|
|
:: =seed
|
2018-12-21 17:59:12 +03:00
|
|
|
:: spon=ship
|
2019-08-07 01:42:37 +03:00
|
|
|
:: czar=(map ship [=rift =life =pass])
|
2018-10-29 22:38:14 +03:00
|
|
|
:: turf=(list turf)}
|
|
|
|
:: bloq=@ud
|
|
|
|
:: node=purl
|
|
|
|
:: ==
|
2018-09-07 04:41:16 +03:00
|
|
|
::
|
|
|
|
%dawn
|
2018-12-12 11:34:05 +03:00
|
|
|
:: single-homed
|
2018-10-15 22:51:53 +03:00
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
~| [our who.seed.tac]
|
2018-12-12 11:34:05 +03:00
|
|
|
?> =(our who.seed.tac)
|
2018-10-29 22:38:14 +03:00
|
|
|
:: save our boot block
|
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
=. boq.own.pki bloq.tac
|
2018-10-29 22:38:14 +03:00
|
|
|
:: save our ethereum gateway (required for galaxies)
|
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
=. nod.own.pki
|
|
|
|
%+ fall node.tac
|
|
|
|
(need (de-purl:html 'http://eth-mainnet.urbit.org:8545'))
|
2018-10-16 03:39:55 +03:00
|
|
|
:: save our parent signature (only for moons)
|
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
=. sig.own.pki sig.seed.tac
|
2019-08-07 23:54:47 +03:00
|
|
|
:: load our initial public key
|
2018-10-16 03:39:55 +03:00
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
=. pos.zim.pki
|
2018-10-16 03:39:55 +03:00
|
|
|
=/ cub (nol:nu:crub:crypto key.seed.tac)
|
2019-08-07 01:42:37 +03:00
|
|
|
%+ ~(put by pos.zim.pki)
|
2018-10-16 03:39:55 +03:00
|
|
|
our
|
2019-10-16 03:16:04 +03:00
|
|
|
=/ spon-ship
|
|
|
|
=/ flopped-spon (flop spon.tac)
|
|
|
|
?~(flopped-spon ~ `ship.i.flopped-spon)
|
2019-08-21 02:41:50 +03:00
|
|
|
[1 lyf.seed.tac (my [lyf.seed.tac [1 pub:ex:cub]] ~) spon-ship]
|
2019-08-07 01:42:37 +03:00
|
|
|
:: our initial private key
|
2018-09-07 04:41:16 +03:00
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
=. lyf.own.pki lyf.seed.tac
|
|
|
|
=. jaw.own.pki (my [lyf.seed.tac key.seed.tac] ~)
|
|
|
|
:: XX save sponsor in .own.pki
|
|
|
|
:: XX reconcile with .dns.eth
|
|
|
|
:: set initial domains
|
|
|
|
::
|
|
|
|
=. tuf.own.pki turf.tac
|
2018-09-07 04:41:16 +03:00
|
|
|
:: our initial galaxy table as a +map from +life to +public
|
|
|
|
::
|
2019-08-21 02:41:50 +03:00
|
|
|
=/ spon-points=(list [ship point])
|
|
|
|
%+ turn spon.tac
|
|
|
|
|= [=ship az-point=point:azimuth]
|
|
|
|
~| [%sponsor-point az-point]
|
|
|
|
?> ?=(^ net.az-point)
|
|
|
|
:* ship
|
|
|
|
continuity-number.u.net.az-point
|
|
|
|
life.u.net.az-point
|
|
|
|
(malt [life.u.net.az-point 1 pass.u.net.az-point] ~)
|
|
|
|
?. has.sponsor.u.net.az-point
|
2019-08-07 01:42:37 +03:00
|
|
|
~
|
2019-08-21 02:41:50 +03:00
|
|
|
`who.sponsor.u.net.az-point
|
2019-08-07 01:42:37 +03:00
|
|
|
==
|
|
|
|
=/ points=(map =ship =point)
|
2018-09-07 04:41:16 +03:00
|
|
|
%- ~(run by czar.tac)
|
2019-08-07 01:42:37 +03:00
|
|
|
|= [=a=rift =a=life =a=pass]
|
|
|
|
^- point
|
|
|
|
[a-rift a-life (malt [a-life 1 a-pass] ~) ~]
|
|
|
|
=. points
|
2019-08-21 02:41:50 +03:00
|
|
|
(~(gas by points) spon-points)
|
2018-09-07 04:41:16 +03:00
|
|
|
=. +>.$
|
|
|
|
%- curd =< abet
|
2019-08-07 23:54:47 +03:00
|
|
|
(public-keys:~(feel su hen our pki etn) %full points)
|
2018-10-04 09:43:40 +03:00
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
:: start subscriptions
|
|
|
|
::
|
2019-11-13 08:55:15 +03:00
|
|
|
:: get everything from azimuth-tracker because jael subscriptions
|
|
|
|
:: seem to be flaky for now
|
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
=. +>.$ (poke-watch hen %azimuth-tracker nod.own.pki)
|
|
|
|
=. +>.$
|
2019-11-13 08:55:15 +03:00
|
|
|
%- curd =< abet
|
|
|
|
(sources:~(feel su hen our pki etn) ~ [%| %azimuth-tracker])
|
2018-10-04 09:43:40 +03:00
|
|
|
::
|
2018-09-07 04:41:16 +03:00
|
|
|
=. moz
|
|
|
|
%+ weld moz
|
|
|
|
:: order is crucial!
|
|
|
|
::
|
2018-10-18 08:27:24 +03:00
|
|
|
:: %dill must init after %gall
|
|
|
|
:: the %give init (for unix) must be after %dill init
|
|
|
|
:: %jael init must be deferred (makes http requests)
|
2018-09-07 04:41:16 +03:00
|
|
|
::
|
|
|
|
^- (list move)
|
2019-08-07 01:42:37 +03:00
|
|
|
:~ [hen %give %init our]
|
2019-07-04 02:01:45 +03:00
|
|
|
[hen %slip %e %init our]
|
2018-10-18 08:27:24 +03:00
|
|
|
[hen %slip %d %init our]
|
|
|
|
[hen %slip %g %init our]
|
2018-09-07 04:41:16 +03:00
|
|
|
[hen %slip %c %init our]
|
|
|
|
[hen %slip %a %init our]
|
|
|
|
==
|
|
|
|
+>.$
|
|
|
|
::
|
2018-09-15 08:38:22 +03:00
|
|
|
:: boot fake
|
2018-12-12 11:50:40 +03:00
|
|
|
:: [%fake =ship]
|
2018-09-15 08:38:22 +03:00
|
|
|
::
|
|
|
|
%fake
|
2018-12-12 11:34:05 +03:00
|
|
|
:: single-homed
|
2018-10-15 22:51:53 +03:00
|
|
|
::
|
2018-12-12 11:50:40 +03:00
|
|
|
?> =(our ship.tac)
|
2018-10-16 03:39:55 +03:00
|
|
|
:: fake keys are deterministically derived from the ship
|
|
|
|
::
|
|
|
|
=/ cub (pit:nu:crub:crypto 512 our)
|
|
|
|
:: our initial public key
|
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
=. pos.zim.pki
|
|
|
|
%+ ~(put by pos.zim.pki)
|
|
|
|
our
|
|
|
|
[rift=1 life=1 (my [`@ud`1 [`life`1 pub:ex:cub]] ~) `(^sein:title our)]
|
|
|
|
:: our private key
|
2018-09-15 08:38:22 +03:00
|
|
|
::
|
|
|
|
:: Private key updates are disallowed for fake ships,
|
|
|
|
:: so we do this first.
|
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
=. lyf.own.pki 1
|
|
|
|
=. jaw.own.pki (my [1 sec:ex:cub] ~)
|
2018-09-15 08:38:22 +03:00
|
|
|
:: set the fake bit
|
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
=. fak.own.pki &
|
2018-09-15 08:38:22 +03:00
|
|
|
:: initialize other vanes per the usual procedure
|
|
|
|
::
|
|
|
|
:: Except for ourselves!
|
|
|
|
::
|
|
|
|
=. moz
|
|
|
|
%+ weld moz
|
|
|
|
^- (list move)
|
2018-10-18 08:27:24 +03:00
|
|
|
:~ [hen %give %init our]
|
2019-07-04 02:01:45 +03:00
|
|
|
[hen %slip %e %init our]
|
2018-10-18 08:27:24 +03:00
|
|
|
[hen %slip %d %init our]
|
|
|
|
[hen %slip %g %init our]
|
2018-09-15 08:38:22 +03:00
|
|
|
[hen %slip %c %init our]
|
|
|
|
[hen %slip %a %init our]
|
|
|
|
==
|
|
|
|
+>.$
|
|
|
|
::
|
2018-05-16 00:16:29 +03:00
|
|
|
:: set ethereum source
|
2019-08-07 01:42:37 +03:00
|
|
|
:: [%listen whos=(set ship) =source]
|
2016-11-24 07:25:07 +03:00
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
%listen
|
|
|
|
~& [%jael-listen whos source]:tac
|
|
|
|
%- curd =< abet
|
2019-08-07 23:54:47 +03:00
|
|
|
(sources:~(feel su hen our pki etn) [whos source]:tac)
|
2016-11-24 07:25:07 +03:00
|
|
|
::
|
|
|
|
:: cancel all trackers from duct
|
2019-08-07 01:42:37 +03:00
|
|
|
:: {$nuke whos=(set ship)}
|
2016-11-24 07:25:07 +03:00
|
|
|
::
|
|
|
|
$nuke
|
2019-08-07 01:42:37 +03:00
|
|
|
=/ ships=(list ship)
|
|
|
|
%~ tap in
|
|
|
|
%- ~(int in whos.tac)
|
|
|
|
(~(get ju yen.zim.pki) hen)
|
|
|
|
=. ney.zim.pki
|
|
|
|
|- ^- (jug ship duct)
|
|
|
|
?~ ships
|
|
|
|
ney.zim.pki
|
|
|
|
(~(del ju $(ships t.ships)) i.ships hen)
|
|
|
|
=. yen.zim.pki
|
|
|
|
|- ^- (jug duct ship)
|
|
|
|
?~ ships
|
|
|
|
yen.zim.pki
|
|
|
|
(~(del ju $(ships t.ships)) hen i.ships)
|
2019-08-20 20:22:52 +03:00
|
|
|
=? nel.zim.pki ?=(~ whos.tac)
|
|
|
|
(~(del in nel.zim.pki) hen)
|
2019-08-07 01:42:37 +03:00
|
|
|
?^ whos.tac
|
|
|
|
+>.$
|
|
|
|
%_ +>.$
|
|
|
|
yen.own.pki (~(del in yen.own.pki) hen)
|
2016-11-24 07:25:07 +03:00
|
|
|
==
|
|
|
|
::
|
2019-08-08 01:15:25 +03:00
|
|
|
:: update private keys
|
|
|
|
::
|
|
|
|
%rekey
|
|
|
|
%- curd =< abet
|
|
|
|
(private-keys:~(feel su hen our pki etn) life.tac ring.tac)
|
|
|
|
::
|
2019-08-08 03:36:25 +03:00
|
|
|
:: update private keys
|
|
|
|
::
|
|
|
|
%moon
|
|
|
|
?. =(%earl (clan:title ship.tac))
|
|
|
|
~& [%not-moon ship.tac]
|
|
|
|
+>.$
|
|
|
|
?. =(our (^sein:title ship.tac))
|
|
|
|
~& [%not-our-moon ship.tac]
|
|
|
|
+>.$
|
|
|
|
%- curd =< abet
|
|
|
|
(~(new-event su hen our pki etn) [ship udiff]:tac)
|
|
|
|
::
|
2018-06-01 01:31:45 +03:00
|
|
|
:: watch public keys
|
2019-08-07 01:42:37 +03:00
|
|
|
:: [%public-keys ships=(set ship)]
|
2018-06-01 01:31:45 +03:00
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
%public-keys
|
2018-06-01 01:31:45 +03:00
|
|
|
%- curd =< abet
|
2019-08-07 23:54:47 +03:00
|
|
|
(~(public-keys ~(feed su hen our pki etn) hen) ships.tac)
|
2018-06-01 01:31:45 +03:00
|
|
|
::
|
2018-08-30 03:05:34 +03:00
|
|
|
:: seen after breach
|
|
|
|
:: [%meet our=ship who=ship]
|
|
|
|
::
|
|
|
|
%meet
|
2019-08-07 01:42:37 +03:00
|
|
|
+>.$
|
2018-08-30 03:05:34 +03:00
|
|
|
::
|
2018-10-04 09:43:40 +03:00
|
|
|
:: XX should be a subscription
|
|
|
|
:: XX reconcile with .dns.eth
|
|
|
|
:: request domains
|
|
|
|
:: [%turf ~]
|
|
|
|
::
|
|
|
|
%turf
|
2018-10-17 19:42:53 +03:00
|
|
|
:: ships with real keys must have domains,
|
|
|
|
:: those with fake keys must not
|
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
~| [fak.own.pki tuf.own.pki]
|
|
|
|
?< =(fak.own.pki ?=(^ tuf.own.pki))
|
|
|
|
+>.$(moz [[hen %give %turf tuf.own.pki] moz])
|
2018-10-04 09:43:40 +03:00
|
|
|
::
|
2019-02-01 10:37:00 +03:00
|
|
|
:: learn of kernel upgrade
|
|
|
|
:: [%vega ~]
|
|
|
|
::
|
|
|
|
%vega
|
2019-09-27 23:00:37 +03:00
|
|
|
+>.$::
|
|
|
|
:: in response to memory pressure
|
|
|
|
:: [%trim p=@ud]
|
|
|
|
::
|
|
|
|
%trim
|
2019-02-01 10:37:00 +03:00
|
|
|
+>.$
|
|
|
|
::
|
2016-11-24 07:25:07 +03:00
|
|
|
:: watch private keys
|
2019-08-07 01:42:37 +03:00
|
|
|
:: {$private-keys $~}
|
2018-05-17 22:48:17 +03:00
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
%private-keys
|
2019-08-07 23:54:47 +03:00
|
|
|
(curd abet:~(private-keys ~(feed su hen our pki etn) hen))
|
2019-01-30 01:41:55 +03:00
|
|
|
::
|
|
|
|
%wegh
|
|
|
|
%_ +>
|
|
|
|
moz
|
|
|
|
:_ moz
|
|
|
|
^- move
|
|
|
|
:^ hen %give %mass
|
|
|
|
^- mass
|
|
|
|
:+ %jael %|
|
2019-08-07 01:42:37 +03:00
|
|
|
:~ pki+&+pki
|
2019-01-30 01:41:55 +03:00
|
|
|
etn+&+etn
|
2019-01-30 03:38:27 +03:00
|
|
|
dot+&+lex
|
2019-01-30 01:41:55 +03:00
|
|
|
==
|
|
|
|
==
|
2016-11-24 07:25:07 +03:00
|
|
|
::
|
|
|
|
:: authenticated remote request
|
|
|
|
:: {$west p/ship q/path r/*}
|
|
|
|
::
|
|
|
|
$west
|
2018-12-13 01:02:37 +03:00
|
|
|
=* her p.tac
|
2019-01-15 01:04:13 +03:00
|
|
|
=/ mes (message r.tac)
|
2016-11-24 07:25:07 +03:00
|
|
|
?- -.mes
|
|
|
|
::
|
2018-05-17 22:48:17 +03:00
|
|
|
:: cancel trackers
|
2019-08-07 01:42:37 +03:00
|
|
|
:: [%nuke whos=(set ship)]
|
2018-05-17 22:48:17 +03:00
|
|
|
::
|
|
|
|
%nuke
|
2019-08-07 01:42:37 +03:00
|
|
|
=. moz [[hen %give %mack ~] moz]
|
2018-05-17 22:48:17 +03:00
|
|
|
$(tac mes)
|
|
|
|
::
|
2018-06-01 01:34:21 +03:00
|
|
|
:: view ethereum events
|
2019-08-07 01:42:37 +03:00
|
|
|
:: [%public-keys whos=(set ship)]
|
2018-05-16 00:16:29 +03:00
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
%public-keys
|
|
|
|
=. moz [[hen %give %mack ~] moz]
|
|
|
|
$(tac mes)
|
2018-05-22 00:10:27 +03:00
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
:: receive keys result
|
|
|
|
:: [%public-keys-result =public-keys-result]
|
2018-05-22 00:10:27 +03:00
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
%public-keys-result
|
2018-05-29 00:04:33 +03:00
|
|
|
=. moz [[hen %give %mack ~] moz]
|
2019-08-07 01:42:37 +03:00
|
|
|
%- curd =< abet
|
2019-08-07 23:54:47 +03:00
|
|
|
(public-keys:~(feel su hen our pki etn) public-keys-result.mes)
|
2016-11-24 07:25:07 +03:00
|
|
|
==
|
|
|
|
==
|
2018-05-29 00:04:33 +03:00
|
|
|
::
|
|
|
|
++ take
|
|
|
|
|= [tea=wire hen=duct hin=sign]
|
|
|
|
^+ +>
|
|
|
|
?- hin
|
|
|
|
[%a %woot *]
|
2018-11-07 09:40:07 +03:00
|
|
|
?~ q.hin +>.$
|
2018-05-29 00:04:33 +03:00
|
|
|
?~ u.q.hin ~&(%ares-fine +>.$)
|
|
|
|
~& [%woot-bad p.u.u.q.hin]
|
|
|
|
~_ q.u.u.q.hin
|
|
|
|
::TODO fail:et
|
|
|
|
+>.$
|
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
[%g %onto *]
|
|
|
|
~& [%jael-onto tea hin]
|
2019-04-10 06:15:37 +03:00
|
|
|
+>.$
|
2018-05-29 00:04:33 +03:00
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
[%g %unto *]
|
|
|
|
?- +>-.hin
|
|
|
|
$quit ~|([%jael-unexpected-quit tea hin] !!)
|
|
|
|
$http-response ~|([%jael-unexpected-http-response tea hin] !!)
|
|
|
|
$coup
|
|
|
|
?~ p.p.+>.hin
|
|
|
|
+>.$
|
|
|
|
%- (slog leaf+"jael-bad-coup" u.p.p.+>.hin)
|
|
|
|
+>.$
|
|
|
|
::
|
|
|
|
$reap
|
|
|
|
?~ p.p.+>.hin
|
|
|
|
+>.$
|
|
|
|
%- (slog u.p.p.+>.hin)
|
|
|
|
~|([%jael-unexpected-reap tea hin] +>.$)
|
|
|
|
::
|
|
|
|
$diff
|
|
|
|
?> ?=([@ *] tea)
|
|
|
|
=* app i.tea
|
|
|
|
=/ =peer-sign ;;(peer-sign q.q.p.p.+>.hin)
|
|
|
|
%. [hen tea app]
|
|
|
|
=< pump
|
|
|
|
%- curd =< abet
|
2019-08-07 23:54:47 +03:00
|
|
|
(~(new-event su hen our pki etn) peer-sign)
|
2019-08-07 01:42:37 +03:00
|
|
|
==
|
2018-05-29 00:04:33 +03:00
|
|
|
==
|
2016-11-24 07:25:07 +03:00
|
|
|
:: :: ++curd:of
|
|
|
|
++ curd :: relative moves
|
2018-10-26 00:37:04 +03:00
|
|
|
|= $: moz/(list move)
|
2019-08-07 01:42:37 +03:00
|
|
|
pki/state-pki
|
2018-10-26 00:37:04 +03:00
|
|
|
etn/state-eth-node
|
|
|
|
==
|
2019-08-07 23:54:47 +03:00
|
|
|
+>(pki pki, etn etn, moz (weld (flop moz) ^moz))
|
2018-10-30 21:41:35 +03:00
|
|
|
:: :: ++wind:of
|
2019-08-07 01:42:37 +03:00
|
|
|
++ pump
|
|
|
|
|= [hen=duct =wire app=term]
|
|
|
|
(emit [hen %pass wire %g %deal [our our] app %pump ~])
|
2016-11-24 07:25:07 +03:00
|
|
|
--
|
|
|
|
:: :: ++su
|
|
|
|
:::: ## relative^heavy :: subjective engine
|
|
|
|
:: ::::
|
|
|
|
++ su
|
2016-12-16 09:34:01 +03:00
|
|
|
:: the ++su core handles all derived state,
|
2016-11-24 07:25:07 +03:00
|
|
|
:: subscriptions, and actions.
|
|
|
|
::
|
2018-05-24 17:54:35 +03:00
|
|
|
:: ++feed:su registers subscriptions.
|
2016-11-24 07:25:07 +03:00
|
|
|
::
|
|
|
|
:: ++feel:su checks if a ++change should notify
|
|
|
|
:: any subscribers.
|
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
=| moz=(list move)
|
|
|
|
=| $: hen=duct
|
|
|
|
our=ship
|
|
|
|
state-pki
|
2018-05-29 00:04:33 +03:00
|
|
|
state-eth-node
|
2016-11-24 07:25:07 +03:00
|
|
|
==
|
|
|
|
:: moz: moves in reverse order
|
2019-08-07 01:42:37 +03:00
|
|
|
:: pki: relative urbit state
|
2016-11-24 07:25:07 +03:00
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
=* pki ->+<
|
2019-08-07 23:54:47 +03:00
|
|
|
=* etn ->+>
|
2016-11-24 07:25:07 +03:00
|
|
|
|%
|
2019-08-07 01:42:37 +03:00
|
|
|
++ this-su .
|
2016-11-24 07:25:07 +03:00
|
|
|
:: :: ++abet:su
|
|
|
|
++ abet :: resolve
|
2019-08-07 23:54:47 +03:00
|
|
|
[(flop moz) pki etn]
|
2016-11-24 07:25:07 +03:00
|
|
|
:: :: ++exec:su
|
2019-08-07 01:42:37 +03:00
|
|
|
++ emit
|
|
|
|
|= =move
|
|
|
|
+>.$(moz [move moz])
|
|
|
|
::
|
2016-11-24 07:25:07 +03:00
|
|
|
++ exec :: mass gift
|
|
|
|
|= {yen/(set duct) cad/card}
|
2017-02-13 22:58:49 +03:00
|
|
|
=/ noy ~(tap in yen)
|
2019-08-07 01:42:37 +03:00
|
|
|
|- ^+ this-su
|
|
|
|
?~ noy this-su
|
2016-11-24 07:25:07 +03:00
|
|
|
$(noy t.noy, moz [[i.noy cad] moz])
|
2018-05-29 21:20:25 +03:00
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
++ emit-peer
|
|
|
|
|= [app=term =path]
|
|
|
|
%- emit
|
|
|
|
:* hen
|
|
|
|
%pass
|
|
|
|
[app path]
|
|
|
|
%g
|
|
|
|
%deal
|
|
|
|
[our our]
|
|
|
|
app
|
|
|
|
%peer
|
|
|
|
path
|
|
|
|
==
|
|
|
|
::
|
|
|
|
++ peer
|
|
|
|
|= [app=term whos=(set ship)]
|
|
|
|
?: =(~ whos)
|
|
|
|
(emit-peer app /)
|
|
|
|
=/ whol=(list ship) ~(tap in whos)
|
|
|
|
|- ^+ this-su
|
|
|
|
?~ whol this-su
|
|
|
|
=. this-su (emit-peer app /(scot %p i.whol))
|
|
|
|
$(whol t.whol)
|
|
|
|
::
|
|
|
|
++ public-keys-give
|
|
|
|
|= [yen=(set duct) =public-keys-result]
|
2018-05-29 21:20:25 +03:00
|
|
|
=+ yez=~(tap in yen)
|
2019-08-07 01:42:37 +03:00
|
|
|
|- ^+ this-su
|
|
|
|
?~ yez this-su
|
|
|
|
=* d i.yez
|
|
|
|
=. this-su
|
|
|
|
?. &(?=([[%a @ @ *] *] d) !=(%pubs i.t.i.d))
|
|
|
|
%- emit
|
|
|
|
[d %give %public-keys public-keys-result]
|
|
|
|
=/ our (slav %p i.t.i.d)
|
|
|
|
=/ who (slav %p i.t.t.i.d)
|
|
|
|
=/ =message [%public-keys-result public-keys-result]
|
|
|
|
%- emit
|
|
|
|
:^ d
|
|
|
|
%pass
|
|
|
|
/public-keys-result
|
2019-07-12 00:41:43 +03:00
|
|
|
^- note
|
2019-08-07 01:42:37 +03:00
|
|
|
[%a %want who /j/public-keys-result message]
|
2019-07-12 00:41:43 +03:00
|
|
|
$(yez t.yez)
|
2018-11-03 03:05:41 +03:00
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
++ get-source
|
|
|
|
|= who=@p
|
|
|
|
^- source
|
|
|
|
=/ ship-source (~(get by ship-sources.etn) who)
|
|
|
|
?^ ship-source
|
|
|
|
(~(got by sources) u.ship-source)
|
|
|
|
?: =((clan:title who) %earl)
|
|
|
|
[%& (^sein:title who)]
|
|
|
|
(~(got by sources) default-source.etn)
|
|
|
|
::
|
|
|
|
++ get-source-id
|
|
|
|
|= =source
|
|
|
|
^- [source-id _this-su]
|
|
|
|
=/ source-reverse (~(get by sources-reverse) source)
|
|
|
|
?^ source-reverse
|
|
|
|
[u.source-reverse this-su]
|
|
|
|
:- top-source-id.etn
|
|
|
|
%_ this-su
|
|
|
|
top-source-id.etn +(top-source-id.etn)
|
|
|
|
sources.etn (~(put by sources) top-source-id.etn source)
|
|
|
|
sources-reverse.etn (~(put by sources-reverse) source top-source-id.etn)
|
2018-11-03 03:05:41 +03:00
|
|
|
==
|
2019-08-07 01:42:37 +03:00
|
|
|
::
|
|
|
|
++ new-event
|
|
|
|
|= [=a=ship =a=udiff:point]
|
|
|
|
^+ this-su
|
|
|
|
=/ a-point=point (~(gut by pos.zim.pki) a-ship *point)
|
|
|
|
=/ a-diff=(unit diff:point) (udiff-to-diff:point a-udiff a-point)
|
|
|
|
?~ a-diff
|
|
|
|
this-su
|
|
|
|
(public-keys:feel %diff a-ship u.a-diff)
|
|
|
|
::
|
2019-08-20 20:22:52 +03:00
|
|
|
++ subscribers-on-ship
|
|
|
|
|= =ship
|
|
|
|
^- (set duct)
|
|
|
|
=/ specific-subs (~(get ju ney.zim) ship)
|
2019-08-20 20:58:06 +03:00
|
|
|
=/ general-subs=(set duct)
|
|
|
|
?: ?=(?(%czar %king %duke) (clan:title ship))
|
|
|
|
nel.zim
|
|
|
|
~
|
2019-08-20 20:22:52 +03:00
|
|
|
(~(uni in specific-subs) general-subs)
|
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
++ feed
|
2016-11-24 07:25:07 +03:00
|
|
|
|_ :: hen: subscription source
|
|
|
|
::
|
|
|
|
hen/duct
|
2018-06-01 01:31:45 +03:00
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
:: Handle subscription to public-keys
|
|
|
|
::
|
|
|
|
++ public-keys
|
|
|
|
|= whos=(set ship)
|
|
|
|
?: fak.own.pki
|
|
|
|
(public-keys:fake whos)
|
|
|
|
:: Subscribe to parent of moons
|
|
|
|
::
|
|
|
|
=. ..feed
|
|
|
|
=/ moons=(jug ship ship)
|
|
|
|
%- ~(gas ju *(jug spon=ship who=ship))
|
|
|
|
%+ murn ~(tap in whos)
|
|
|
|
|= who=ship
|
|
|
|
^- (unit [spon=ship child=ship])
|
|
|
|
?. =(%earl (clan:title who))
|
|
|
|
~
|
|
|
|
?: (~(has by ship-sources) who)
|
|
|
|
~
|
|
|
|
`[(^sein:title who) who]
|
|
|
|
=/ moonl=(list [spon=ship ships=(set ship)])
|
|
|
|
~(tap by moons)
|
|
|
|
|- ^+ ..feed
|
|
|
|
?~ moonl
|
|
|
|
..feed
|
2019-08-08 03:36:25 +03:00
|
|
|
?: =(our spon.i.moonl)
|
2019-08-07 01:42:37 +03:00
|
|
|
$(moonl t.moonl)
|
2019-08-08 03:36:25 +03:00
|
|
|
=. ..feed (sources:feel ships.i.moonl [%& spon.i.moonl])
|
|
|
|
$(moonl t.moonl)
|
2019-08-07 01:42:37 +03:00
|
|
|
:: Add to subscriber list
|
|
|
|
::
|
|
|
|
=. ney.zim
|
|
|
|
=/ whol=(list ship) ~(tap in whos)
|
|
|
|
|- ^- (jug ship duct)
|
|
|
|
?~ whol
|
|
|
|
ney.zim
|
|
|
|
(~(put ju $(whol t.whol)) i.whol hen)
|
|
|
|
=. yen.zim
|
|
|
|
%- ~(gas ju yen.zim)
|
|
|
|
%+ turn ~(tap in whos)
|
|
|
|
|= who=ship
|
|
|
|
[hen who]
|
2019-08-20 20:22:52 +03:00
|
|
|
=? nel.zim ?=(~ whos)
|
|
|
|
(~(put in nel.zim) hen)
|
2019-08-07 01:42:37 +03:00
|
|
|
:: Give initial result
|
|
|
|
::
|
|
|
|
=/ =public-keys-result
|
|
|
|
:- %full
|
|
|
|
?: =(~ whos)
|
|
|
|
pos.zim
|
|
|
|
%- my ^- (list (pair ship point))
|
|
|
|
%+ murn
|
|
|
|
~(tap in whos)
|
|
|
|
|= who=ship
|
|
|
|
^- (unit (pair ship point))
|
|
|
|
=/ pub (~(get by pos.zim) who)
|
|
|
|
?~ pub ~
|
|
|
|
?: =(0 life.u.pub) ~
|
|
|
|
`[who u.pub]
|
|
|
|
=. ..feed (public-keys-give (sy hen ~) public-keys-result)
|
|
|
|
..feed
|
|
|
|
::
|
|
|
|
:: Handle subscription to private-keys
|
|
|
|
::
|
|
|
|
++ private-keys
|
2016-11-24 07:25:07 +03:00
|
|
|
%_ ..feed
|
2019-08-07 01:42:37 +03:00
|
|
|
moz [[hen %give %private-keys [lyf jaw]:own] moz]
|
2016-11-24 07:25:07 +03:00
|
|
|
yen.own (~(put in yen.own) hen)
|
|
|
|
==
|
2018-05-29 00:04:33 +03:00
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
++ fake
|
|
|
|
?> fak.own.pki
|
2018-09-15 08:38:22 +03:00
|
|
|
|%
|
2019-08-07 01:42:37 +03:00
|
|
|
++ public-keys
|
|
|
|
|= whos=(set ship)
|
|
|
|
=/ whol=(list ship) ~(tap in whos)
|
|
|
|
=/ passes
|
|
|
|
|- ^- (list [who=ship =pass])
|
|
|
|
?~ whol
|
|
|
|
~
|
|
|
|
=/ cub (pit:nu:crub:crypto 512 i.whol)
|
|
|
|
:- [i.whol pub:ex:cub]
|
|
|
|
$(whol t.whol)
|
|
|
|
=/ points=(list (pair ship point))
|
|
|
|
%+ turn passes
|
|
|
|
|= [who=ship =pass]
|
|
|
|
^- [who=ship =point]
|
|
|
|
[who [rift=1 life=1 (my [1 1 pass] ~) `(^sein:title who)]]
|
|
|
|
=. moz [[hen %give %public-keys %full (my points)] moz]
|
2018-10-15 22:51:53 +03:00
|
|
|
..feel
|
2019-08-07 01:42:37 +03:00
|
|
|
--
|
2016-11-24 07:25:07 +03:00
|
|
|
--
|
2019-08-07 01:42:37 +03:00
|
|
|
::
|
|
|
|
++ feel
|
2016-11-24 07:25:07 +03:00
|
|
|
|%
|
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
:: Update public-keys
|
2016-11-24 07:25:07 +03:00
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
++ public-keys
|
|
|
|
|= =public-keys-result
|
|
|
|
^+ ..feel
|
|
|
|
?: ?=(%full -.public-keys-result)
|
|
|
|
=/ pointl=(list [who=ship =point])
|
|
|
|
~(tap by points.public-keys-result)
|
|
|
|
|- ^+ ..feel
|
|
|
|
?~ pointl
|
2019-11-06 23:50:03 +03:00
|
|
|
..feel(pos.zim (~(uni by pos.zim) points.public-keys-result))
|
jael: provide edge-triggered breach notification
Until now, clients of Jael have had to store the first-seen rift if they
want to reliably detect breaches. Otherwise, they would get a false
positive if they heard an old message about a breach (eg if you kick
azimuth-tracker). Clay and Gall did this correctly, but Ames did not.
Jael already maintains this state, so I added a notification to the
existing subscription that happens whenever it notices a breach (a diff
or full where the new rift is greater than the old one).
Because this is an issue on the live network, I wrote state adapters
for Gall and Clay. The Gall one just removes the rift from our state,
but the Clay one is much more involved because we have to upgrade
instances of the clad monad that are possibly in progress.
Specifically, since more input is possible than before, we must wrap any
in-progress instances of the monad in a function that handles the
potential new input from Jael. This temporarily preservers a copy of
the old kernel, but only until the current commit/merge/update has
completed.
The real solution for Clay is to factor out those IO-heavy instances to
userspace tapp/async/imp/threads, and if an upgrade happens in the
middle, you should simply restart them.
Fixes #1852
2019-10-24 07:26:38 +03:00
|
|
|
:: if changing rift upward, then signal a breach
|
|
|
|
::
|
|
|
|
=? ..feel
|
|
|
|
=/ point
|
|
|
|
(~(get by pos.zim) who.i.pointl)
|
|
|
|
?& ?=(^ point)
|
|
|
|
(gth rift.point.i.pointl rift.u.point)
|
|
|
|
==
|
|
|
|
%+ public-keys-give
|
|
|
|
(subscribers-on-ship who.i.pointl)
|
|
|
|
[%breach who.i.pointl]
|
2019-11-15 01:46:14 +03:00
|
|
|
=. ..feel
|
|
|
|
%+ public-keys-give
|
|
|
|
(subscribers-on-ship who.i.pointl)
|
|
|
|
[%full (my i.pointl ~)]
|
|
|
|
$(pointl t.pointl)
|
|
|
|
::
|
jael: provide edge-triggered breach notification
Until now, clients of Jael have had to store the first-seen rift if they
want to reliably detect breaches. Otherwise, they would get a false
positive if they heard an old message about a breach (eg if you kick
azimuth-tracker). Clay and Gall did this correctly, but Ames did not.
Jael already maintains this state, so I added a notification to the
existing subscription that happens whenever it notices a breach (a diff
or full where the new rift is greater than the old one).
Because this is an issue on the live network, I wrote state adapters
for Gall and Clay. The Gall one just removes the rift from our state,
but the Clay one is much more involved because we have to upgrade
instances of the clad monad that are possibly in progress.
Specifically, since more input is possible than before, we must wrap any
in-progress instances of the monad in a function that handles the
potential new input from Jael. This temporarily preservers a copy of
the old kernel, but only until the current commit/merge/update has
completed.
The real solution for Clay is to factor out those IO-heavy instances to
userspace tapp/async/imp/threads, and if an upgrade happens in the
middle, you should simply restart them.
Fixes #1852
2019-10-24 07:26:38 +03:00
|
|
|
?: ?=(%breach -.public-keys-result)
|
|
|
|
:: we calculate our own breaches based on our local state
|
|
|
|
::
|
|
|
|
..feel
|
2019-08-07 01:42:37 +03:00
|
|
|
=* who who.public-keys-result
|
|
|
|
=/ a-diff=diff:point diff.public-keys-result
|
|
|
|
=/ maybe-point (~(get by pos.zim) who)
|
|
|
|
=/ =point (fall maybe-point *point)
|
jael: provide edge-triggered breach notification
Until now, clients of Jael have had to store the first-seen rift if they
want to reliably detect breaches. Otherwise, they would get a false
positive if they heard an old message about a breach (eg if you kick
azimuth-tracker). Clay and Gall did this correctly, but Ames did not.
Jael already maintains this state, so I added a notification to the
existing subscription that happens whenever it notices a breach (a diff
or full where the new rift is greater than the old one).
Because this is an issue on the live network, I wrote state adapters
for Gall and Clay. The Gall one just removes the rift from our state,
but the Clay one is much more involved because we have to upgrade
instances of the clad monad that are possibly in progress.
Specifically, since more input is possible than before, we must wrap any
in-progress instances of the monad in a function that handles the
potential new input from Jael. This temporarily preservers a copy of
the old kernel, but only until the current commit/merge/update has
completed.
The real solution for Clay is to factor out those IO-heavy instances to
userspace tapp/async/imp/threads, and if an upgrade happens in the
middle, you should simply restart them.
Fixes #1852
2019-10-24 07:26:38 +03:00
|
|
|
:: if changing rift upward, then signal a breach
|
|
|
|
::
|
|
|
|
=? ..feel
|
|
|
|
?& ?=(%rift -.a-diff)
|
|
|
|
(gth to.a-diff rift.point)
|
|
|
|
==
|
|
|
|
%+ public-keys-give
|
|
|
|
(subscribers-on-ship who)
|
|
|
|
[%breach who]
|
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
=. point
|
|
|
|
?- -.a-diff
|
|
|
|
%spon point(sponsor to.a-diff)
|
|
|
|
%rift point(rift to.a-diff)
|
|
|
|
%keys
|
|
|
|
%_ point
|
|
|
|
life life.to.a-diff
|
|
|
|
keys
|
|
|
|
%+ ~(put by keys.point)
|
|
|
|
life.to.a-diff
|
|
|
|
[crypto-suite pass]:to.a-diff
|
2018-06-01 18:14:35 +03:00
|
|
|
==
|
2018-10-26 00:37:04 +03:00
|
|
|
==
|
jael: provide edge-triggered breach notification
Until now, clients of Jael have had to store the first-seen rift if they
want to reliably detect breaches. Otherwise, they would get a false
positive if they heard an old message about a breach (eg if you kick
azimuth-tracker). Clay and Gall did this correctly, but Ames did not.
Jael already maintains this state, so I added a notification to the
existing subscription that happens whenever it notices a breach (a diff
or full where the new rift is greater than the old one).
Because this is an issue on the live network, I wrote state adapters
for Gall and Clay. The Gall one just removes the rift from our state,
but the Clay one is much more involved because we have to upgrade
instances of the clad monad that are possibly in progress.
Specifically, since more input is possible than before, we must wrap any
in-progress instances of the monad in a function that handles the
potential new input from Jael. This temporarily preservers a copy of
the old kernel, but only until the current commit/merge/update has
completed.
The real solution for Clay is to factor out those IO-heavy instances to
userspace tapp/async/imp/threads, and if an upgrade happens in the
middle, you should simply restart them.
Fixes #1852
2019-10-24 07:26:38 +03:00
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
=. pos.zim (~(put by pos.zim) who point)
|
|
|
|
%+ public-keys-give
|
2019-08-20 20:22:52 +03:00
|
|
|
(subscribers-on-ship who)
|
2019-08-07 01:42:37 +03:00
|
|
|
?~ maybe-point
|
|
|
|
[%full (my [who point]~)]
|
|
|
|
[%diff who a-diff]
|
2016-11-24 07:25:07 +03:00
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
:: Update private-keys
|
2018-10-12 19:48:52 +03:00
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
++ private-keys
|
|
|
|
|= [=life =ring]
|
|
|
|
^+ ..feel
|
|
|
|
?: &(=(lyf.own life) =((~(get by jaw.own) life) `ring))
|
|
|
|
..feel
|
|
|
|
=. lyf.own life
|
|
|
|
=. jaw.own (~(put by jaw.own) life ring)
|
|
|
|
(exec yen.own [%give %private-keys lyf.own jaw.own])
|
2018-10-26 00:37:04 +03:00
|
|
|
::
|
2019-08-08 03:36:25 +03:00
|
|
|
:: Change sources for ships
|
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
++ sources
|
|
|
|
|= [whos=(set ship) =source]
|
|
|
|
^+ ..feel
|
|
|
|
?: ?=(%& -.source)
|
|
|
|
=/ send-message
|
|
|
|
|= =message
|
|
|
|
[hen %pass /public-keys %a %want p.source /j/public-keys message]
|
|
|
|
(emit (send-message %public-keys whos))
|
|
|
|
=^ =source-id this-su (get-source-id source)
|
|
|
|
=. ..feed
|
|
|
|
?~ whos
|
|
|
|
..feed(default-source.etn source-id)
|
|
|
|
=/ whol=(list ship) ~(tap in `(set ship)`whos)
|
|
|
|
=. ship-sources.etn
|
|
|
|
|- ^- (map ship ^source-id)
|
|
|
|
?~ whol
|
|
|
|
ship-sources.etn
|
|
|
|
(~(put by $(whol t.whol)) i.whol source-id)
|
|
|
|
=. ship-sources-reverse.etn
|
|
|
|
%- ~(gas ju ship-sources-reverse.etn)
|
|
|
|
(turn whol |=(=ship [source-id ship]))
|
|
|
|
..feed
|
|
|
|
(peer p.source whos)
|
|
|
|
--
|
2018-05-16 21:48:20 +03:00
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
:: No-op
|
2018-05-30 01:40:00 +03:00
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
++ meet
|
|
|
|
|= [who=ship =life =pass]
|
2018-11-03 01:31:31 +03:00
|
|
|
^+ +>
|
2019-08-07 01:42:37 +03:00
|
|
|
+>.$
|
2018-05-16 00:16:29 +03:00
|
|
|
--
|
2017-04-23 06:13:14 +03:00
|
|
|
--
|
2016-11-24 07:25:07 +03:00
|
|
|
:: ::::
|
|
|
|
:::: # vane :: interface
|
|
|
|
:: ::::
|
|
|
|
::
|
|
|
|
:: lex: all durable %jael state
|
|
|
|
::
|
|
|
|
=| lex/state
|
2016-12-16 09:34:01 +03:00
|
|
|
|= $: ::
|
2018-12-06 00:41:21 +03:00
|
|
|
:: our: identity
|
2016-11-24 07:25:07 +03:00
|
|
|
:: now: current time
|
|
|
|
:: eny: unique entropy
|
|
|
|
:: ski: namespace resolver
|
|
|
|
::
|
2018-12-06 00:41:21 +03:00
|
|
|
our=ship
|
|
|
|
now=@da
|
|
|
|
eny=@uvJ
|
|
|
|
ski=sley
|
2016-11-24 07:25:07 +03:00
|
|
|
==
|
2019-04-11 04:49:20 +03:00
|
|
|
^?
|
2016-11-24 07:25:07 +03:00
|
|
|
|%
|
|
|
|
:: :: ++call
|
|
|
|
++ call :: request
|
|
|
|
|= $: :: hen: cause of this event
|
|
|
|
:: hic: event data
|
|
|
|
::
|
|
|
|
hen/duct
|
2018-05-22 00:10:27 +03:00
|
|
|
hic/(hypo (hobo task:able))
|
2016-11-24 07:25:07 +03:00
|
|
|
==
|
2018-12-01 22:31:54 +03:00
|
|
|
^- [(list move) _..^$]
|
2018-12-12 11:34:05 +03:00
|
|
|
=/ =task:able
|
|
|
|
?. ?=($soft -.q.hic)
|
|
|
|
q.hic
|
2019-01-15 01:04:13 +03:00
|
|
|
(task:able p.q.hic)
|
2018-12-12 11:34:05 +03:00
|
|
|
=^ did lex
|
|
|
|
abet:(~(call of [our now eny] lex) hen task)
|
2016-11-24 07:25:07 +03:00
|
|
|
[did ..^$]
|
|
|
|
:: :: ++load
|
|
|
|
++ load :: upgrade
|
|
|
|
|= $: :: old: previous state
|
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
:: old/*
|
2016-11-24 07:25:07 +03:00
|
|
|
old/state
|
|
|
|
==
|
|
|
|
^+ ..^$
|
2019-08-07 01:42:37 +03:00
|
|
|
:: ..^$
|
2016-11-24 07:25:07 +03:00
|
|
|
..^$(lex old)
|
|
|
|
:: :: ++scry
|
|
|
|
++ scry :: inspect
|
|
|
|
|= $: :: fur: event security
|
|
|
|
:: ren: access mode
|
|
|
|
:: why: owner
|
|
|
|
:: syd: desk (branch)
|
|
|
|
:: lot: case (version)
|
|
|
|
:: tyl: rest of path
|
|
|
|
::
|
|
|
|
fur/(unit (set monk))
|
2016-12-16 09:34:01 +03:00
|
|
|
ren/@tas
|
|
|
|
why/shop
|
|
|
|
syd/desk
|
|
|
|
lot/coin
|
2016-11-24 07:25:07 +03:00
|
|
|
tyl/spur
|
|
|
|
==
|
|
|
|
^- (unit (unit cage))
|
2018-11-01 06:46:55 +03:00
|
|
|
:: XX review for security, stability, cases other than now
|
2018-10-12 19:48:52 +03:00
|
|
|
::
|
2016-12-13 22:02:38 +03:00
|
|
|
?. =(lot [%$ %da now]) ~
|
2018-10-12 19:48:52 +03:00
|
|
|
?. =(%$ ren) [~ ~]
|
|
|
|
?+ syd
|
|
|
|
~
|
2018-11-01 06:46:55 +03:00
|
|
|
::
|
|
|
|
%code
|
|
|
|
?. ?=([@ ~] tyl) [~ ~]
|
2019-08-07 01:42:37 +03:00
|
|
|
?. =([%& our] why)
|
2018-11-01 06:46:55 +03:00
|
|
|
[~ ~]
|
|
|
|
=/ who (slaw %p i.tyl)
|
|
|
|
?~ who [~ ~]
|
2019-08-07 01:42:37 +03:00
|
|
|
=/ sec (~(got by jaw.own.pki.lex) lyf.own.pki.lex)
|
2018-11-01 06:46:55 +03:00
|
|
|
=/ cub (nol:nu:crub:crypto sec)
|
|
|
|
:: XX use pac:ex:cub?
|
|
|
|
::
|
|
|
|
``[%noun !>((end 6 1 (shaf %pass (shax sec:ex:cub))))]
|
2018-10-12 19:48:52 +03:00
|
|
|
::
|
|
|
|
%life
|
|
|
|
?. ?=([@ ~] tyl) [~ ~]
|
2019-08-07 01:42:37 +03:00
|
|
|
?. =([%& our] why)
|
2018-10-12 19:48:52 +03:00
|
|
|
[~ ~]
|
|
|
|
=/ who (slaw %p i.tyl)
|
|
|
|
?~ who [~ ~]
|
|
|
|
:: fake ships always have life=1
|
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
?: fak.own.pki.lex
|
2018-10-12 19:48:52 +03:00
|
|
|
``[%atom !>(1)]
|
|
|
|
?: =(u.who p.why)
|
2019-08-07 01:42:37 +03:00
|
|
|
``[%atom !>(lyf.own.pki.lex)]
|
|
|
|
=/ pub (~(get by pos.zim.pki.lex) u.who)
|
2018-10-12 19:48:52 +03:00
|
|
|
?~ pub ~
|
|
|
|
``[%atom !>(life.u.pub)]
|
2019-02-02 00:46:09 +03:00
|
|
|
::
|
|
|
|
%rift
|
|
|
|
?. ?=([@ ~] tyl) [~ ~]
|
2019-08-07 01:42:37 +03:00
|
|
|
?. =([%& our] why)
|
2019-02-02 00:46:09 +03:00
|
|
|
[~ ~]
|
|
|
|
=/ who (slaw %p i.tyl)
|
|
|
|
?~ who [~ ~]
|
|
|
|
:: fake ships always have rift=1
|
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
?: fak.own.pki.lex
|
2019-02-02 00:46:09 +03:00
|
|
|
``[%atom !>(1)]
|
2019-08-07 01:42:37 +03:00
|
|
|
=/ pos (~(get by pos.zim.pki.lex) u.who)
|
2019-02-02 00:46:09 +03:00
|
|
|
?~ pos ~
|
2019-08-07 01:42:37 +03:00
|
|
|
``[%atom !>(rift.u.pos)]
|
2019-08-10 00:07:43 +03:00
|
|
|
::
|
|
|
|
%vein
|
|
|
|
?. ?=([@ ~] tyl) [~ ~]
|
|
|
|
?. &(?=(%& -.why) =(p.why our))
|
|
|
|
[~ ~]
|
|
|
|
=/ lyf (slaw %ud i.tyl)
|
|
|
|
?~ lyf [~ ~]
|
|
|
|
::
|
|
|
|
?~ r=(~(get by jaw.own.pki.lex) u.lyf)
|
|
|
|
[~ ~]
|
|
|
|
::
|
|
|
|
[~ ~ %noun !>(u.r)]
|
2018-10-16 02:55:13 +03:00
|
|
|
::
|
|
|
|
%deed
|
|
|
|
?. ?=([@ @ ~] tyl) [~ ~]
|
2018-12-12 11:34:05 +03:00
|
|
|
?. &(?=(%& -.why) =(p.why our))
|
2018-10-16 02:55:13 +03:00
|
|
|
[~ ~]
|
|
|
|
=/ who (slaw %p i.tyl)
|
|
|
|
=/ lyf (slaw %ud i.t.tyl)
|
|
|
|
?~ who [~ ~]
|
|
|
|
?~ lyf [~ ~]
|
2018-10-18 01:56:41 +03:00
|
|
|
::
|
2019-08-10 00:07:43 +03:00
|
|
|
?: fak.own.pki.lex
|
|
|
|
=/ cub (pit:nu:crub:crypto 512 u.who)
|
|
|
|
:^ ~ ~ %noun
|
|
|
|
!> `deed:ames`[1 pub:ex:cub ~]
|
|
|
|
::
|
|
|
|
=/ rac (clan:title u.who)
|
2018-10-18 01:56:41 +03:00
|
|
|
?: ?=(%pawn rac)
|
|
|
|
?. =(u.who p.why)
|
|
|
|
[~ ~]
|
|
|
|
?. =(1 u.lyf)
|
|
|
|
[~ ~]
|
2019-08-07 01:42:37 +03:00
|
|
|
=/ sec (~(got by jaw.own.pki.lex) u.lyf)
|
2018-10-18 01:56:41 +03:00
|
|
|
=/ cub (nol:nu:crub:crypto sec)
|
|
|
|
=/ sig (sign:as:cub (shaf %self (sham [u.who 1 pub:ex:cub])))
|
|
|
|
:^ ~ ~ %noun
|
|
|
|
!> ^- deed:ames
|
|
|
|
[1 pub:ex:cub `sig]
|
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
=/ pub (~(get by pos.zim.pki.lex) u.who)
|
2018-12-19 22:36:05 +03:00
|
|
|
?~ pub
|
|
|
|
~
|
|
|
|
?: (gth u.lyf life.u.pub)
|
|
|
|
~
|
2019-08-07 01:42:37 +03:00
|
|
|
=/ pas (~(get by keys.u.pub) u.lyf)
|
2018-12-19 22:36:05 +03:00
|
|
|
?~ pas
|
|
|
|
~
|
2018-10-16 02:55:13 +03:00
|
|
|
:^ ~ ~ %noun
|
2019-08-07 01:42:37 +03:00
|
|
|
!> `deed:ames`[u.lyf pass.u.pas ~]
|
2018-10-12 19:48:52 +03:00
|
|
|
::
|
|
|
|
%earl
|
2019-08-07 01:42:37 +03:00
|
|
|
?. ?=([@ @ ~] tyl) [~ ~]
|
|
|
|
?. =([%& our] why)
|
2018-10-12 19:48:52 +03:00
|
|
|
[~ ~]
|
|
|
|
=/ who (slaw %p i.tyl)
|
|
|
|
=/ lyf (slaw %ud i.t.tyl)
|
|
|
|
?~ who [~ ~]
|
|
|
|
?~ lyf [~ ~]
|
2019-08-07 01:42:37 +03:00
|
|
|
?: (gth u.lyf lyf.own.pki.lex)
|
2018-10-12 19:48:52 +03:00
|
|
|
~
|
2019-08-07 01:42:37 +03:00
|
|
|
?: (lth u.lyf lyf.own.pki.lex)
|
2018-10-12 19:48:52 +03:00
|
|
|
[~ ~]
|
|
|
|
:: XX check that who/lyf hasn't been booted
|
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
=/ sec (~(got by jaw.own.pki.lex) u.lyf)
|
|
|
|
=/ moon-sec (shaf %earl (sham our u.lyf sec u.who))
|
|
|
|
=/ cub (pit:nu:crub:crypto 128 moon-sec)
|
|
|
|
=/ =seed [u.who 1 sec:ex:cub ~]
|
|
|
|
``[%seed !>(seed)]
|
2018-10-12 19:48:52 +03:00
|
|
|
::
|
|
|
|
%sein
|
|
|
|
?. ?=([@ ~] tyl) [~ ~]
|
2019-08-07 01:42:37 +03:00
|
|
|
?. =([%& our] why)
|
2018-10-12 19:48:52 +03:00
|
|
|
[~ ~]
|
|
|
|
=/ who (slaw %p i.tyl)
|
|
|
|
?~ who [~ ~]
|
|
|
|
:^ ~ ~ %atom
|
|
|
|
!> ^- ship
|
2018-12-12 11:34:05 +03:00
|
|
|
(~(sein of [our now eny] lex) u.who)
|
2018-10-12 19:48:52 +03:00
|
|
|
::
|
|
|
|
%saxo
|
|
|
|
?. ?=([@ ~] tyl) [~ ~]
|
2019-08-07 01:42:37 +03:00
|
|
|
?. =([%& our] why)
|
2018-10-12 19:48:52 +03:00
|
|
|
[~ ~]
|
|
|
|
=/ who (slaw %p i.tyl)
|
|
|
|
?~ who [~ ~]
|
|
|
|
:^ ~ ~ %noun
|
|
|
|
!> ^- (list ship)
|
2018-12-12 11:34:05 +03:00
|
|
|
(~(saxo of [our now eny] lex) u.who)
|
2019-01-16 02:50:51 +03:00
|
|
|
::
|
2019-08-07 01:42:37 +03:00
|
|
|
%sources
|
2019-01-16 02:50:51 +03:00
|
|
|
?. ?=(~ tyl) [~ ~]
|
|
|
|
:^ ~ ~ %noun !>
|
2019-08-07 01:42:37 +03:00
|
|
|
etn.lex
|
2019-04-12 04:01:35 +03:00
|
|
|
::
|
|
|
|
%turf
|
|
|
|
?. ?=(~ tyl) [~ ~]
|
2019-08-07 01:42:37 +03:00
|
|
|
[~ ~ %noun !>(tuf.own.pki.lex)]
|
2018-10-12 19:48:52 +03:00
|
|
|
==
|
2016-11-24 07:25:07 +03:00
|
|
|
:: :: ++stay
|
|
|
|
++ stay :: preserve
|
|
|
|
lex
|
|
|
|
:: :: ++take
|
|
|
|
++ take :: accept
|
|
|
|
|= $: :: tea: order
|
|
|
|
:: hen: cause
|
|
|
|
:: hin: result
|
|
|
|
::
|
2016-12-16 09:34:01 +03:00
|
|
|
tea/wire
|
|
|
|
hen/duct
|
2018-05-16 00:16:29 +03:00
|
|
|
hin/(hypo sign)
|
2016-11-24 07:25:07 +03:00
|
|
|
==
|
2018-12-01 22:31:54 +03:00
|
|
|
^- [(list move) _..^$]
|
2018-12-12 11:34:05 +03:00
|
|
|
=^ did lex abet:(~(take of [our now eny] lex) tea hen q.hin)
|
2018-05-29 00:04:33 +03:00
|
|
|
[did ..^$]
|
2016-11-24 07:25:07 +03:00
|
|
|
--
|