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
This commit is contained in:
Philip Monk 2019-10-23 21:26:38 -07:00
parent 3210acd4de
commit 9ddc04143a
No known key found for this signature in database
GPG Key ID: B66E1F02604E44EC
6 changed files with 286 additions and 116 deletions

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d7997612e16e8edd5ad9dc641960f14e85676279d307a23b077e7a935f9fd1cd
size 17388075
oid sha256:07fec92f344d9949bfc293a851c3b531289d1e16eacaad9aabcd95ca499179c3
size 17482291

View File

@ -1453,10 +1453,8 @@
?. ?=([%pubs @ ~] tea)
~& [%strange-pubs tea]
[~ +>.$]
?: ?& ?=(%diff -.public-keys-result.sih)
?=(%rift -.diff.public-keys-result.sih)
==
(sink hen [who [from to]:diff]:public-keys-result.sih)
?: ?=(%breach -.public-keys-result.sih)
(sink hen who.public-keys-result.sih)
?: ?& ?=(%diff -.public-keys-result.sih)
!?=(%keys -.diff.public-keys-result.sih)
==
@ -1534,7 +1532,7 @@
==
::
++ sink
|= [hen=duct who=ship from=rift to=rift]
|= [hen=duct who=ship]
^- [(list move) _+>]
?: =(our who)
[[(print hen who ", you have sunk") ~] +>.$]

View File

@ -299,8 +299,7 @@
:: Foreign desk data.
::
++ rung
$: rit=rift :: rift of 1st contact
rus=(map desk rede) :: neighbor desks
$: rus=(map desk rede) :: neighbor desks
==
::
:: Hash of a commit, for lookup in the object store (hut.ran)
@ -533,12 +532,6 @@
$: @tas :: by any
$>(%crud vane-task) :: XX strange
== == ::
--
::
:: Old state types for ++load
::
=> |%
+$ raft-1 raft
-- =>
:: %utilities
::
@ -2663,8 +2656,6 @@
:: save foreign +rede
::
=/ run (~(gut by hoy.ruf) her *rung)
=? rit.run =(0 rit.run)
(fall (rift-scry her) *rift)
=/ rug (~(put by rus.run) syd red)
ruf(hoy (~(put by hoy.ruf) her run(rus rug)))
:: save domestic +room
@ -2674,19 +2665,6 @@
dos.rom (~(put by dos.rom.ruf) syd [qyx dom per pew]:red)
==
::
:: +rift-scry: for a +rift
::
++ rift-scry
|= who=ship
^- (unit rift)
=; rit
?~(rit ~ u.rit)
;; (unit (unit rift))
%- (sloy-light ski)
=/ pur=spur
/(scot %p who)
[[151 %noun] %j our %rift da+now pur]
::
:: Handle `%sing` requests
::
++ aver
@ -4374,16 +4352,209 @@
==
::
++ load
!:
=> |%
+$ axle [%1 ruf-1=raft]
+$ axle
$% [%1 ruf-1=raft-1]
[%2 ruf-2=raft]
==
+$ raft-1
$: rom=room
hoy=(map ship rung-1)
ran=rang
mon=(map term beam)
hez=(unit duct)
cez=(map @ta crew)
cue=(qeu [=duct =task:able])
act=active-write-1
==
::
+$ rung-1
$: rit=rift
rus=(map desk rede-1)
==
::
+$ rede-1
$: lim=@da
ref=(unit rind-1)
qyx=cult
dom=dome
per=regs
pew=regs
==
::
+$ rind-1
$: nix=@ud
bom=(map @ud {p/duct q/rave})
fod=(map duct @ud)
haw=(map mood (unit cage))
pud=update-qeu-1
pur=request-map-1
==
::
+$ update-qeu-1
$: waiting=(qeu [inx=@ud rut=(unit rand)])
$= eval-data
%- unit
$: inx=@ud
rut=(unit rand)
form=(eval-form-1 (unit [lim=@da dome rang]))
==
==
::
+$ request-map-1
(map inx=@ud [=rand (eval-form-1 cage)])
::
+$ active-write-1
%- unit
$: hen=duct
req=task:able
$= eval-data
$% [%commit form=(eval-form-1 [dome rang])]
[%merge form=(eval-form-1 [(set path) dome rang])]
[%mount form=(eval-form-1 [(pair term beam) (map path mime)])]
==
==
::
++ eval-form-1
|* a=mold
,[effects=(list move) form=(clad-form-1 a)]
::
++ clad-form-1
|* a=mold
$-([@da rang sign-1] (clad-output-1 a))
::
++ clad-output-1
|* a=mold
$~ [~ ~ %done *a]
$: notes=(list [path note])
effects=(list move)
$= next
$% [%wait ~]
[%cont self=(clad-form-1 a)]
[%fail err=(pair term tang)]
[%done value=a]
==
==
::
++ sign-1
$~ [%b %wake ~]
$% $: %y
$% [%init-clad ~]
== ==
$: %a
$> $? %send
%woot
==
gift:able:ames
==
$: %b
$% $>(%wake gift:able:behn)
$>(%writ gift:able)
== ==
$: %c
$> $? %mere
%note
%writ
==
gift:able
==
$: %f
$>(%made gift:able:ford)
==
$: %j
[%public-keys =public-keys-result-1]
==
$: @tas
$>(%crud vane-task)
== ==
::
+$ public-keys-result-1
$% [%full points=(map ship point:able:jael)]
[%diff who=ship =diff:point:able:jael]
==
::
++ upgrade-1
|= ruf=raft-1
^- axle
:- %2
%= ruf
act
?~ act.ruf
~
:- ~
%= u.act.ruf
eval-data
?- -.eval-data.u.act.ruf
%commit
:- %commit
%- (upgrade-clad-1 ,[dome rang])
form.eval-data.u.act.ruf
::
%merge
:- %merge
%- (upgrade-clad-1 ,[(set path) dome rang])
form.eval-data.u.act.ruf
::
%mount
:- %mount
%- (upgrade-clad-1 ,[(pair term beam) (map path mime)])
form.eval-data.u.act.ruf
==
==
::
hoy
^- (map ship rung)
%- ~(urn by hoy.ruf)
|= [her=ship rift rus=(map desk rede-1)]
^- rung
%- ~(urn by rus)
|= [syd=desk red=rede-1]
^- rede
?~ ref.red
red
%= red
u.ref
^- rind
%= u.ref.red
pud
^- update-qeu
?~ eval-data.pud.u.ref.red
pud.u.ref.red
%= pud.u.ref.red
form.u.eval-data
%- (upgrade-clad-1 ,(unit [lim=@da dome rang]))
form.u.eval-data.pud.u.ref.red
==
::
pur
%- ~(urn by pur.u.ref.red)
|= [inx=@ud =rand form=(eval-form-1 ,cage)]
[rand ((upgrade-clad-1 ,cage) form)]
==
==
==
::
++ upgrade-clad-1
|* a=mold
|= e-form=(eval-form-1 a)
:- effects.e-form
^+ *form:(clad ,a)
|= cin=clad-input
?: ?=([%j %public-keys %breach *] sign.cin)
[~ ~ %wait ~]
=/ res (form.e-form cin)
?: ?=(%cont -.next.res)
res(self.next ..$(form.e-form self.next.res))
res
--
:: |= *
:: ..^$
:: XX switch back
::
|= old=axle
^+ ..^$
?> ?=(%1 -.old)
%_(..^$ ruf ruf-1.old)
=? old ?=(%1 -.old)
(upgrade-1 ruf-1.old)
?> ?=(%2 -.old)
%_(..^$ ruf ruf-2.old)
::
++ scry :: inspect
|= {fur/(unit (set monk)) ren/@tas why/shop syd/desk lot/coin tyl/path}
@ -4413,7 +4584,7 @@
?: ?=(%& -.u.u.-) ``p.u.u.-
~
::
++ stay [%1 ruf]
++ stay [%2 ruf]
++ take :: accept response
|= [tea=wire hen=duct hin=(hypo sign)]
^+ [*(list move) ..^$]
@ -4473,13 +4644,9 @@
::
?: ?=([%sinks ~] tea)
?> ?=(%public-keys +<.q.hin)
?: ?=(%full -.public-keys-result.q.hin)
[~ ..^$]
?. ?=(%rift -.diff.public-keys-result.q.hin)
?. ?=(%breach -.public-keys-result.q.hin)
[~ ..^$]
=/ who who.public-keys-result.q.hin
=/ to-rift to.diff.public-keys-result.q.hin
::
?: =(our who)
[~ ..^$]
:: Cancel subscriptions
@ -4488,8 +4655,6 @@
(~(get by hoy.ruf) who)
?~ foreign-desk
[~ ..^$]
?: (gte rit.u.foreign-desk to-rift)
[~ ..^$]
=/ cancel-ducts=(list duct)
%- zing ^- (list (list duct))
%+ turn ~(tap by rus.u.foreign-desk)
@ -4634,18 +4799,4 @@
?~ -
`[paf %ins %mime -:!>(*mime) u.mim]
`[paf %mut %mime -:!>(*mime) u.mim]
::
:: +rift-scry: for a +rift
::
++ rift-scry
~% %rift-scry ..is ~
|= who=ship
^- (unit rift)
=; lyf
?~(lyf ~ u.lyf)
;; (unit (unit rift))
%- (sloy-light ski)
=/ pur=spur
/(scot %p who)
[[151 %noun] %j our %rift da+now pur]
--

View File

@ -72,15 +72,12 @@
==
--
|%
:: +state-old: upgrade path
::
++ state-old ?(state)
:: +state: all state
::
++ state
$: :: state version
::
%0
%1
:: agents by ship
::
=agents
@ -127,10 +124,7 @@
:: +foreign: foreign connections
::
++ foreign
$: :: rift of first contact
::
=rift
:: index
$: :: index
::
index=@ud
:: by duct
@ -475,8 +469,7 @@
=? mo-core !(~(has by contacts.agents.state) ship)
=/ =note-arvo [%j %public-keys (silt ship ~)]
=. moves [[system-duct.agents.state %pass /sys/jael note-arvo] moves]
=/ =rift (fall (mo-rift-scry ship) *rift)
=/ =foreign [rift 1 ~ ~]
=/ =foreign [1 ~ ~]
=. contacts.agents.state
(~(put by contacts.agents.state) ship foreign)
mo-core
@ -508,18 +501,6 @@
?~ contact
~
`(~(got by duct-map.u.contact) index)
:: +mo-rift-scry: for a +rift
::
++ mo-rift-scry
|= who=ship
^- (unit rift)
=; rit
?~(rit ~ u.rit)
;; (unit (unit rift))
%- (sloy-light ska)
=/ pur=spur
/(scot %p who)
[[151 %noun] %j our %rift da+now pur]
:: +mo-cancel-jael: cancel jael subscription
::
++ mo-cancel-jael
@ -571,36 +552,9 @@
^+ mo-core
?> ?=([%j %public-keys *] sign-arvo)
?> ?=([%jael ~] path)
?: ?=(%full -.public-keys-result.sign-arvo)
=/ ships=(list [=ship =point:able:jael])
~(tap by points.public-keys-result.sign-arvo)
|- ^+ mo-core
?~ ships
mo-core
=. mo-core
=/ contact=(unit foreign)
(~(get by contacts.agents.state) ship.i.ships)
?~ contact
=/ =tank
leaf+"gall: unexpected jael update for {<ship.i.ships>}, cancelling"
%- (slog tank ~)
(mo-cancel-jael ship.i.ships)
?: (lte rift.point.i.ships rift.u.contact)
mo-core
(mo-breach ship.i.ships)
$(ships t.ships)
?. ?=(%rift -.diff.public-keys-result.sign-arvo)
?. ?=(%breach -.public-keys-result.sign-arvo)
mo-core
=/ =ship who.public-keys-result.sign-arvo
=/ contact=(unit foreign) (~(get by contacts.agents.state) ship)
?~ contact
=/ =tank
leaf+"gall: unexpected jael update for {<ship>}, cancelling"
%- (slog tank ~)
(mo-cancel-jael ship)
?: (lte to.diff.public-keys-result.sign-arvo rift.u.contact)
mo-core
(mo-breach ship)
(mo-breach who.public-keys-result.sign-arvo)
:: +mo-handle-sys-core: receive a core from %ford.
::
++ mo-handle-sys-core
@ -2537,12 +2491,52 @@
:: +load: recreate vane
::
++ load
|= =state-old
=> |%
+$ all-states
$% state-0
state-1
==
::
+$ state-0
$: %0
=agents-0
==
::
+$ agents-0
$: system-duct=duct
contacts=(map ship foreign-0)
running=(map term agent)
blocked=(map term blocked)
==
::
+$ foreign-0
$: =rift
index=@ud
index-map=(map duct @ud)
duct-map=(map @ud duct)
==
::
++ upgrade-0
|= s=state-0
^- state-1
:- %1
%= +.s
contacts.agents-0
%- ~(run by contacts.agents-0.s)
|= foreign-0
^- foreign
[index index-map duct-map]
==
::
++ state-1 ^state
--
|= old=all-states
^+ gall-payload
::
?- -.state-old
%0 gall-payload(state state-old)
==
=? old ?=(%0 -.old)
(upgrade-0 old)
?> ?=(%1 -.old)
gall-payload(state old)
:: +scry: standard scry
::
++ scry

View File

@ -62,7 +62,7 @@
+$ message :: message to her jael
$% [%nuke whos=(set ship)] :: cancel trackers
[%public-keys whos=(set ship)] :: view ethereum events
[%public-keys-result =public-keys-result] :: tmp workaround
[%public-keys-result =public-keys-result] ::
== ::
+$ card :: i/o action
(wind note gift) ::
@ -76,7 +76,7 @@
$>(%want task:able:ames) :: send message
== ::
$: %g :: to self
$>(%deal task:able:gall) :: set ethereum source
$>(%deal task:able:gall) :: set ethereum source
== ::
$: %j :: to self
$>(%listen task) :: set ethereum source
@ -810,13 +810,38 @@
|- ^+ ..feel
?~ pointl
..feel
:: 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]
%+ public-keys-give
(subscribers-on-ship who.i.pointl)
[%full (my i.pointl ~)]
?: ?=(%breach -.public-keys-result)
:: we calculate our own breaches based on our local state
::
..feel
=* 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)
:: 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]
::
=. point
?- -.a-diff
%spon point(sponsor to.a-diff)
@ -830,6 +855,7 @@
[crypto-suite pass]:to.a-diff
==
==
::
=. pos.zim (~(put by pos.zim) who point)
%+ public-keys-give
(subscribers-on-ship who)

View File

@ -2067,15 +2067,16 @@
+$ public-keys-result
$% [%full points=(map ship point)]
[%diff who=ship =diff:point]
[%breach who=ship]
==
:: ::
++ gift :: out result <-$
$% [%init p=ship] :: report install unix
[%mass p=mass] :: memory usage report
[%mack p=(unit tang)] :: message n/ack
[%turf turf=(list turf)] :: domains
[%private-keys =life vein=(map life ring)] :: private keys
[%public-keys =public-keys-result] :: ethereum changes
[%turf turf=(list turf)] :: domains
== ::
:: +seed: private boot parameters
::