Merge pull request #6906 from urbit/yu/fix-ames-migration

ames, gall: fix old state migrations
This commit is contained in:
Pyry Kovanen 2024-02-07 16:04:24 +02:00 committed by GitHub
commit 315fe21be8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 181 additions and 182 deletions

View File

@ -483,7 +483,7 @@
++ is-our-bulk
|= [our=ship =ames-state =balk]
^- ?
=- ~? =(| -)
=- ~? =(| -)
[%fine-mismatch our=[rift life]:ames-state her=[her rif lyf]:balk]
-
?& =(our her.balk)
@ -776,18 +776,6 @@
cong=[msg=@ud mem=@ud]
==
::
+$ queued-event-11
$+ queued-event-11
$% [%call =duct wrapped-task=(hobo task-11)]
[%take =wire =duct =sign]
==
::
+$ task-11
$+ task-11
$% [%snub ships=(list ship)]
$<(%snub task)
==
::
+$ ames-state-12
$+ ames-state-12
$: peers=(map ship ship-state-12)
@ -1170,11 +1158,13 @@
$: flow=[%flow (unit dead-timer)]
cork=[%cork (unit dead-timer)]
== ==
::
+$ ship-state-17
$+ ship-state-17
$% [%alien alien-agenda-17]
[%known peer-state-17]
==
::
+$ peer-state-17
$+ peer-state-17
$: $: =symmetric-key
@ -1194,6 +1184,7 @@
corked=(set bone)
keens=(map path keen-state)
==
::
+$ message-pump-state-17
$+ message-pump-state-17
$: current=_`message-num`1
@ -1203,6 +1194,7 @@
queued-message-acks=(map message-num ack)
=packet-pump-state
==
::
+$ ames-state-14 ames-state-16
+$ ames-state-15 ames-state-16
+$ ames-state-16
@ -1216,14 +1208,14 @@
snub=[form=?(%allow %deny) ships=(set ship)]
cong=[msg=@ud mem=@ud]
==
::
+$ alien-agenda-17
$+ alien-agenda
$: messages=(list [=duct =plea])
packets=(set =blob)
heeds=(set duct)
keens=(jug path duct)
==
::
+$ alien-agenda-17
$+ alien-agenda
$: messages=(list [=duct =plea])
packets=(set =blob)
heeds=(set duct)
keens=(jug path duct)
==
::
+$ ship-state-16
$+ ship-state-16
@ -1287,49 +1279,53 @@
counter=@ud
==
::
+$ queued-event-11-and-16
$+ queued-event-11-and-16
$% [%call =duct wrapped-task=(hobo task-11-and-16)]
+$ queued-event-9-til-11
$+ queued-event-9-til-11
$% [%call =duct wrapped-task=(hobo task-9-til-11)]
[%take =wire =duct =sign]
==
::
+$ task-11-and-16
$+ task-11-and-16
$% [%kroc dry=?]
[%keen spar]
[%snub ships=(list ship)]
$<(?(%snub %kroc) task-17)
+$ task-9-til-11
$+ task-9-til-11
$% [%kroc dry=?] :: introduced in state %10, modified in %17
[%snub ships=(list ship)] :: introduced in state %9, modified in %11
$<(?(%snub %kroc %deep %keen) task) :: %deep/%keen introduced later
==
::
+$ task-17
$+ task-17
$% $<(?(%deep %keen) task)
[%keen spar]
$: %deep
+$ queued-event-12-til-16
$+ queued-event-12-til-16
$% [%call =duct wrapped-task=(hobo task-12-til-16)]
[%take =wire =duct =sign]
==
::
+$ task-12-til-16
$+ task-12-til-16
$% [%kroc dry=?] :: introduced in state %10, modified in %17
[%keen spar] :: introduced in state %13, modified in %19
deep-task-14 :: introduced in state %14, modified in %19
$<(?(%kroc %keen %deep) task)
==
::
+$ deep-task-14
$: %deep
$% [%nack =ship =nack=bone =message-blob]
[%sink =ship =target=bone naxplanation=[=message-num =error]]
[%drop =ship =nack=bone =message-num]
[%cork =ship =bone]
[%kill =ship =bone]
== ==
==
== ==
::
+$ queued-event-17
$+ queued-event-17
$% [%call =duct wrapped-task=(hobo task-17)]
+$ queued-event-17-and-18
$+ queued-event-17-and-18
$% [%call =duct wrapped-task=(hobo task-16-and-18)]
[%take =wire =duct =sign]
==
::
+$ queued-event-16
$+ queued-event-16
$% [%call =duct wrapped-task=(hobo task-16)]
[%take =wire =duct =sign]
==
::
+$ task-16
$+ task-16
$% [%kroc dry=?]
$<(%kroc task-17)
+$ task-16-and-18
$+ task-16-and-18
$% [%keen spar] :: introduced in state %13, modified in %19
deep-task-14 :: introduced in state %14, modified in %19
$<(?(%keen %deep) task)
==
:: $bug: debug printing configuration
::
@ -1644,77 +1640,77 @@
==
[%adult state=ames-state-8]
== ==
$: %9
$: %9 :: %snub introduced
$% $: %larva
events=(qeu queued-event-11)
events=(qeu queued-event-9-til-11)
state=ames-state-9
==
[%adult state=ames-state-9]
== ==
$: %10
$: %10 :: %kroc introduced
$% $: %larva
events=(qeu queued-event-11-and-16)
events=(qeu queued-event-9-til-11)
state=ames-state-10
==
[%adult state=ames-state-10]
== ==
$: %11
$% $: %larva
events=(qeu queued-event-11-and-16)
events=(qeu queued-event-9-til-11)
state=ames-state-11
==
[%adult state=ames-state-11]
== ==
$: %12
$: %12 :: %snub modified
$% $: %larva
events=(qeu queued-event-16)
events=(qeu queued-event-12-til-16)
state=ames-state-12
==
[%adult state=ames-state-12]
== ==
$: %13
$% $: %larva
events=(qeu queued-event-16)
$% $: %larva :: %keen introduced
events=(qeu queued-event-12-til-16)
state=ames-state-13
==
[%adult state=ames-state-13]
== ==
$: %14
$: %14 :: %deep introduced
$% $: %larva
events=(qeu queued-event-16)
events=(qeu queued-event-12-til-16)
state=ames-state-14
==
[%adult state=ames-state-14]
== ==
$: %15
$% $: %larva
events=(qeu queued-event-16)
events=(qeu queued-event-12-til-16)
state=ames-state-15
==
[%adult state=ames-state-15]
== ==
$: %16
$% $: %larva
events=(qeu queued-event-16)
events=(qeu queued-event-12-til-16)
state=ames-state-16
==
[%adult state=ames-state-16]
== ==
$: %17
$: %17 :: %kroc modified
$% $: %larva
events=(qeu queued-event-17)
events=(qeu queued-event-17-and-18)
state=ames-state-17
==
[%adult state=ames-state-17]
== ==
$: %18
$% $: %larva
events=(qeu queued-event-17)
events=(qeu queued-event-17-and-18)
state=ames-state-18
==
[%adult state=ames-state-18]
== ==
$: %19
$: %19 :: %keen & %deep modified
$% $: %larva
events=(qeu queued-event)
state=_ames-state.adult-gate
@ -1732,233 +1728,238 @@
::
[%5 %adult *]
=. cached-state `[%5 state.old]
~> %slog.0^leaf/"ames: larva reload"
~> %slog.0^leaf/"ames: larva %5 reload"
larval-gate
::
[%5 %larva *]
~> %slog.0^leaf/"ames: larva: load"
~> %slog.0^leaf/"ames: larva %5 load"
=. cached-state `[%5 state.old]
=. queued-events events.old
larval-gate
::
[%6 %adult *]
=. cached-state `[%6 state.old]
~> %slog.0^leaf/"ames: larva reload"
~> %slog.0^leaf/"ames: larva %6 reload"
larval-gate
::
[%6 %larva *]
~> %slog.0^leaf/"ames: larva: load"
~> %slog.0^leaf/"ames: larva %6 load"
=. cached-state `[%6 state.old]
=. queued-events events.old
larval-gate
::
[%7 %adult *]
=. cached-state `[%7 state.old]
~> %slog.0^leaf/"ames: larva reload"
~> %slog.0^leaf/"ames: larva %7 reload"
larval-gate
::
[%7 %larva *]
~> %slog.0^leaf/"ames: larva: load"
~> %slog.0^leaf/"ames: larva %7 load"
=. queued-events events.old
=. cached-state `[%7 state.old]
larval-gate
::
[%8 %adult *]
=. cached-state `[%8 state.old]
~> %slog.0^leaf/"ames: larva reload"
~> %slog.0^leaf/"ames: larva %8 reload"
larval-gate
::
[%8 %larva *]
~> %slog.0^leaf/"ames: larva: load"
~> %slog.0^leaf/"ames: larva %8 load"
=. cached-state `[%8 state.old]
=. queued-events events.old
larval-gate
::
[%9 %adult *]
=. cached-state `[%9 state.old]
~> %slog.0^leaf/"ames: larva reload"
~> %slog.0^leaf/"ames: larva %9 reload"
larval-gate
::
[%9 %larva *]
~> %slog.0^leaf/"ames: larva: load"
~> %slog.0^leaf/"ames: larva %9 load"
=. cached-state `[%9 state.old]
=. queued-events (event-11-to-12 events.old)
=. queued-events %- event-17-and-18-to-last
%- event-12-til-16-to-17
%- event-9-til-11-to-12
events.old
larval-gate
::
[%10 %adult *]
=. cached-state `[%10 state.old]
~> %slog.0^leaf/"ames: larva reload"
~> %slog.0^leaf/"ames: larva %10 reload"
larval-gate
::
[%10 %larva *]
~> %slog.1^leaf/"ames: larva: load"
~> %slog.1^leaf/"ames: larva %10 load"
=. cached-state `[%10 state.old]
=. queued-events (event-17-to-19 (event-11-to-17 events.old))
=. queued-events %- event-17-and-18-to-last
%- event-12-til-16-to-17
%- event-9-til-11-to-12
events.old
larval-gate
::
[%11 %adult *]
=. cached-state `[%11 state.old]
~> %slog.0^leaf/"ames: larva reload"
~> %slog.0^leaf/"ames: larva %11 reload"
larval-gate
::
[%11 %larva *]
~> %slog.1^leaf/"ames: larva: load"
~> %slog.1^leaf/"ames: larva %11 load"
=. cached-state `[%11 state.old]
=. queued-events (event-17-to-19 (event-11-to-17 events.old))
=. queued-events %- event-17-and-18-to-last
%- event-12-til-16-to-17
%- event-9-til-11-to-12
events.old
larval-gate
::
[%12 %adult *]
=. cached-state `[%12 state.old]
~> %slog.0^leaf/"ames: larva reload"
~> %slog.0^leaf/"ames: larva %12 reload"
larval-gate
::
[%12 %larva *]
~> %slog.1^leaf/"ames: larva: load"
~> %slog.1^leaf/"ames: larva %12 load"
=. cached-state `[%12 state.old]
=. queued-events (event-17-to-19 (event-16-to-17 events.old))
=. queued-events %- event-17-and-18-to-last
%- event-12-til-16-to-17
events.old
larval-gate
::
[%13 %adult *]
=. cached-state `[%13 state.old]
~> %slog.0^leaf/"ames: larva reload"
~> %slog.0^leaf/"ames: larva %13 reload"
larval-gate
::
[%13 %larva *]
~> %slog.1^leaf/"ames: larva: load"
~> %slog.1^leaf/"ames: larva %13 load"
=. cached-state `[%13 state.old]
=. queued-events (event-17-to-19 (event-16-to-17 events.old))
=. queued-events %- event-17-and-18-to-last
%- event-12-til-16-to-17
events.old
larval-gate
::
[%14 %adult *]
=. cached-state `[%14 state.old]
~> %slog.0^leaf/"ames: larva reload"
~> %slog.0^leaf/"ames: larva %14 reload"
larval-gate
::
[%14 %larva *]
~> %slog.1^leaf/"ames: larva: load"
~> %slog.1^leaf/"ames: larva %14 load"
=. cached-state `[%14 state.old]
=. queued-events (event-17-to-19 (event-16-to-17 events.old))
=. queued-events %- event-17-and-18-to-last
%- event-12-til-16-to-17
events.old
larval-gate
::
[%15 %adult *]
=. cached-state `[%15 state.old]
~> %slog.0^leaf/"ames: larva reload"
~> %slog.0^leaf/"ames: larva %15 reload"
larval-gate
::
[%15 %larva *]
~> %slog.1^leaf/"ames: larva: load"
~> %slog.1^leaf/"ames: larva %15 load"
=. cached-state `[%15 state.old]
=. queued-events (event-17-to-19 (event-16-to-17 events.old))
=. queued-events %- event-17-and-18-to-last
%- event-12-til-16-to-17
events.old
larval-gate
::
[%16 %adult *]
=. cached-state `[%16 state.old]
~> %slog.0^leaf/"ames: larva reload"
~> %slog.0^leaf/"ames: larva %16 reload"
larval-gate
::
[%16 %larva *]
~> %slog.1^leaf/"ames: larva: load"
~> %slog.1^leaf/"ames: larva %16 load"
=. cached-state `[%16 state.old]
=. queued-events (event-17-to-19 (event-16-to-17 events.old))
=. queued-events %- event-17-and-18-to-last
%- event-12-til-16-to-17
events.old
larval-gate
::
[%17 %adult *]
=. cached-state `[%17 state.old]
~> %slog.0^leaf/"ames: larva reload"
~> %slog.0^leaf/"ames: larva %17 reload"
larval-gate
::
[%17 %larva *]
~> %slog.1^leaf/"ames: larva: load"
~> %slog.1^leaf/"ames: larva %17 load"
=. cached-state `[%17 state.old]
=. queued-events (event-17-to-19 events.old)
=. queued-events (event-17-and-18-to-last events.old)
larval-gate
::
[%18 %adult *]
=. cached-state `[%18 state.old]
~> %slog.0^leaf/"ames: larva reload"
~> %slog.0^leaf/"ames: larva %18 reload"
larval-gate
::
[%18 %larva *]
~> %slog.1^leaf/"ames: larva: load"
~> %slog.1^leaf/"ames: larva %18 load"
=. cached-state `[%18 state.old]
=. queued-events (event-17-to-19 events.old)
=. queued-events (event-17-and-18-to-last events.old)
larval-gate
::
[%19 %adult *] (load:adult-core %19 state.old)
::
[%19 %larva *]
~> %slog.1^leaf/"ames: larva: load"
~> %slog.1^leaf/"ames: larva %19 load"
=. queued-events events.old
=. adult-gate (load:adult-core %19 state.old)
larval-gate
==
::
++ event-11-to-12
|= events=(qeu queued-event-11)
^- (qeu queued-event)
:: "+rep:in on a +qeu looks strange, but works fine."
::
++ event-9-til-11-to-12
|= events=(qeu queued-event-9-til-11)
^- (qeu queued-event-12-til-16)
%- ~(rep in events)
|= [e=queued-event-11 q=(qeu queued-event)]
%- ~(put to q) ^- queued-event
|= [e=queued-event-9-til-11 q=(qeu queued-event-12-til-16)]
%- ~(put to q) ^- queued-event-12-til-16
?. ?=(%call -.e) e
=/ task=task-11 ((harden task-11) wrapped-task.e)
%= e
wrapped-task ?.(?=(%snub -.task) task [%snub %deny ships.task])
==
::
++ event-11-to-17
|= events=(qeu queued-event-11-and-16)
^- (qeu queued-event-17)
%- ~(rep in events)
|= [e=queued-event-11-and-16 q=(qeu queued-event-17)]
%- ~(put to q) ^- queued-event-17
?. ?=(%call -.e) e
=/ task=task-11-and-16 ((harden task-11-and-16) wrapped-task.e)
=/ task=task-9-til-11 ((harden task-9-til-11) wrapped-task.e)
%= e
wrapped-task
^- task-12-til-16
?+ -.task task
%snub [%snub %deny ships.task]
%kroc [%kroc ~]
==
==
::
++ event-16-to-17
|= events=(qeu queued-event-16)
^- (qeu queued-event-17)
++ event-12-til-16-to-17
|= events=(qeu queued-event-12-til-16)
^- (qeu queued-event-17-and-18)
%- ~(rep in events)
|= [e=queued-event-16 q=(qeu queued-event-17)]
%- ~(put to q) ^- queued-event-17
|= [e=queued-event-12-til-16 q=(qeu queued-event-17-and-18)]
%- ~(put to q) ^- queued-event-17-and-18
?. ?=(%call -.e) e
=/ task=task-16 ((harden task-16) wrapped-task.e)
=/ task=task-12-til-16 ((harden task-12-til-16) wrapped-task.e)
%= e
wrapped-task
^- task-17
?+ -.task task
%kroc [%kroc ~]
==
^- task-16-and-18
?. ?=(%kroc -.task) task
[%kroc ~]
==
::
++ event-17-to-19
|= events=(qeu queued-event-17)
++ event-17-and-18-to-last
|= events=(qeu queued-event-17-and-18)
^- (qeu queued-event)
%- ~(rep in events)
|= [e=queued-event-17 q=(qeu queued-event)]
|= [e=queued-event-17-and-18 q=(qeu queued-event)]
%- ~(put to q) ^- queued-event
?. ?=(%call -.e) e
=/ task=task-17 ((harden task-17) wrapped-task.e)
%= e
wrapped-task
?: ?=(%keen -.task)
=/ task=task-16-and-18 ((harden task-16-and-18) wrapped-task.e)
%= e
wrapped-task
^- ^task
?: ?=(%keen -.task)
[%keen ~ +.task]
?. ?=([%deep %nack *] task) task
=/ msg =>([cue=cue arg=message-blob.task] ~+((cue arg)))
=/ hed
?: =(1 (end 0 nack-bone.task))
?: =(0 (end 0 (rsh 0 nack-bone.task)))
%boon
%naxplanation
%plea
?. =(1 (end 0 nack-bone.task))
%plea
?: =(0 (end 0 (rsh 0 nack-bone.task)))
%boon
%naxplanation
[%deep %nack ship.task nack-bone.task ;;(message [hed msg])]
==
--
@ -1993,13 +1994,9 @@
15+(state-14-to-15:load:adult-core +.u.cached-state)
=? u.cached-state ?=(%15 -.u.cached-state)
16+(state-15-to-16:load:adult-core +.u.cached-state)
=? u.cached-state ?=(%16 -.u.cached-state)
17+(state-16-to-17:load:adult-core +.u.cached-state)
=^ moz u.cached-state
?. ?=(%17 -.u.cached-state) [~ u.cached-state]
:_ [%18 +.u.cached-state]
~> %slog.0^leaf/"ames: init dead flow consolidation timer"
:- [[/ames]~ %pass /dead-flow %b %wait `@da`(add now ~m2)]
?. ?=(%16 -.u.cached-state) [~ u.cached-state]
:_ 17+(state-16-to-17:load:adult-core +.u.cached-state)
?^ moz moz :: if we have just added the timer in state-7-to-8, skip
=; recork-timer=(list [@da duct])
?^ recork-timer ~
@ -2662,7 +2659,7 @@
=/ [key=@ ,path] (~(got by chain.u.per) (slav %ud idx.wire))
=/ raw=@t
(dy:crub:crypto key (slav %uv cyf.rest.path.s))
=/ pax=path
=/ pax=path
(stab raw)
=; dat=(unit (unit page))
(emit duct [%give %near [ship.s pax] dat])
@ -3236,7 +3233,7 @@
|= =path
^+ event-core
=/ key=@ (shaz eny) :: TODO: check key width
=/ num=@ud
=/ num=@ud
?~ latest=(pry:on:chain chain.ames-state)
1
.+(key.u.latest)
@ -3282,7 +3279,7 @@
(emit duct %pass wir %a %keen ~ ship lav)
:: XX: key exchange over ames forces all encrypted scries to be
:: to a known peer
?> ?=(~ sec)
?> ?=(~ sec)
%^ enqueue-alien-todo ship ship-state
|= todos=alien-agenda
todos(keens (~(put ju keens.todos) path duct))
@ -5634,6 +5631,7 @@
==
--
==
::
++ state-18-to-19
|= old=ames-state-18
^- ^ames-state
@ -5645,7 +5643,7 @@
%- ~(run by peers.old)
|= s=ship-state-17
^- ship-state
?: ?=(%alien -.s)
?: ?=(%alien -.s)
%= s
keens [keens.s ~]
==
@ -5657,11 +5655,11 @@
%- ~(urn by snd.+.s)
|= [=bone m=message-pump-state-17]
=/ hed
?: =(1 (end 0 bone))
?: =(0 (end 0 (rsh 0 bone)))
%boon
%naxplanation
%plea
?. =(1 (end 0 bone))
%plea
?: =(0 (end 0 (rsh 0 bone)))
%boon
%naxplanation
%= m
unsent-messages
=* um unsent-messages.m
@ -5698,7 +5696,7 @@
[%fine %shut kef=@ enc=@ ~]
=/ key-idx (slav %ud kef.tyl)
=/ key (got:on:chain chain.ames-state (slav %ud kef.tyl))
=/ pat=(unit path)
=/ pat=(unit path)
(rush `@t`(dy:crub:crypto key.key (slav %uv enc.tyl)) stap)
?~ pat
[~ ~]
@ -5708,7 +5706,7 @@
~& key-validation-failed/[u.pat key-idx chain.ames-state]
[~ ~]
=/ res (rof [~ ~] /ames (as-omen:balk u.blk))
?~ res
?~ res
~& %bailing-close
[~ ~]
?~ u.res

View File

@ -116,7 +116,7 @@
=/ frm (get-farm pos)
?~ frm ~
=. farm u.frm
|-
|-
?: ?=(%coop -.farm)
~[pos]
%- zing
@ -285,7 +285,7 @@
=* tap-plot $
?: ?=(%coop -.farm)
%+ turn ~(tap by q.farm)
|= [=path =plot]
|= [=path =plot]
[(welp wer path) plot]
%+ welp ?~(p.farm ~ [wer u.p.farm]~)
%- zing
@ -526,7 +526,7 @@
agent &+agent
run-nonce (scot %uw (end 5 (shas %yoke-nonce eny)))
::
sky
sky
?~ yak *farm
=| =farm
=. farm (need (~(gas-hutch of-farm farm) ~(tap by cop.u.yak)))
@ -535,7 +535,7 @@
?~ sky farm
=. farm (need (~(put-grow of-farm farm) spur.i.sky [`bob.i.sky ~]))
$(sky t.sky)
==
==
::
=/ old mo-core
=/ wag
@ -839,7 +839,7 @@
=/ =routes [disclosing=~ attributing=[our /]]
=/ ap-core (ap-abed:ap agent.pole routes)
?+ rest.pole ~|(mo-handle-key-bad-wire/wire !!)
[%pug rest=*]
[%pug rest=*]
?> ?=([%ames %stub *] syn)
ap-abet:(ap-stub:ap-core rest.rest.pole [num key]:syn)
::
@ -1170,7 +1170,7 @@
%u [%leave ~]
==
(mo-pass wire %g %deal [ship our /] agent-name deal)
:: +mo-spew: handle request to set verbosity toggles on debug output
::
++ mo-spew
@ -1292,8 +1292,8 @@
?+ syn ~|(weird-sign-ap-take-brood/-.syn !!)
[%ames %boon *]
=/ bud (fall ((soft fine-response) payload.syn) *fine-response)
|-
?~ wis
|-
?~ wis
=. pen.yoke (~(del by pen.yoke) [ship t.wire])
ap-core
?~ bod.bud
@ -1426,7 +1426,7 @@
u.h
*hutch
=. hutch [.+(rev.hutch) num key]
=. sky.yoke
=. sky.yoke
?^ new-sky=(~(put-hutch of-farm sky.yoke) coop hutch)
u.new-sky
sky.yoke
@ -2429,7 +2429,7 @@
[%14 spore-14]
[%15 spore-15]
==
+$ spore-15
+$ spore-15
$+ spore-15
$: system-duct=duct
outstanding=(map [wire duct] (qeu remote-request))
@ -2483,7 +2483,7 @@
old-state=[%| vase]
=beak
marks=(map duct mark)
sky=(map spur farm)
sky=(map spur plot)
== ==
+$ spore-11
$: system-duct=duct
@ -2657,7 +2657,8 @@
|= [a=term e=egg-12]
^- egg-15
?: ?=(%nuke -.e) e
!! :: e(sky [sky.e ken:*$>(%live egg-13)])
::!!
e(sky [sky.e ken:*$>(%live egg-15)])
==
::
++ spore-13-to-14
@ -2715,10 +2716,10 @@
:- ~
=/ m ~(val by fan.p)
%+ gas:on-path *_fan.p
%+ turn
^- (list @)
=/ wit ~(wyt by fan.p)
?: =(0 wit) ~
%+ turn
^- (list @)
=/ wit ~(wyt by fan.p)
?: =(0 wit) ~
(gulf 1 wit)
|= a=@ud
[a (snag (dec a) m)]