Skip to content

flow-batch-operator-slashing: stop cranking chkdispute from the harness - #81

Merged
heifner merged 1 commit into
masterfrom
fix/flow-slashing-drop-harness-chkdispute-crank
Aug 21, 2026
Merged

flow-batch-operator-slashing: stop cranking chkdispute from the harness#81
heifner merged 1 commit into
masterfrom
fix/flow-slashing-drop-harness-chkdispute-crank

Conversation

@heifner

@heifner heifner commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Do not merge before Wire-Network/wire-sysio#582. Without the plugin crank the dispute never resolves and this flow times out. That is the point of the change, and it is also the merge-order constraint.

What this fixes

The dispute step called sysio.chalg::chkdispute itself, inside the resolution poll:

// SlashingScenarioDisputeSteps.ts — crankChkdispute(), removed here
await ctx.wire.getSysioContract(SysioContractName.chalg)
  .actions.chkdispute.invoke({ dispute_id: disputeId }, { authorization: [...] })

So the flow resolved its own dispute and passed whether or not anything in production would. That is exactly what it could not self-supply: nothing in the tree cranked chkdispute (0 references under plugins/), and for a dispute the difference is "the epoch resumes" vs "the epoch stays paused with quorum already reached". The flow was green throughout.

The change

Delete crankChkdispute and its call site. The poll now waits for the production crank — wire-sysio batch_operator_plugin::crank_open_disputes — so a timeout here means nothing tallied the votes, which is the assertion worth having.

Why this flow can still prove it

The three dispop.* are provisioned SBP-less (no daemon) — that is how the 3-way split is forced, and it is why crankChkcons stays: that group genuinely has nothing to drive chkcons, and supplying it is scenario setup, not a stand-in for production behavior.

The bootstrapped batch operators are what make the proof work. They keep their daemons, and they stay opreg-ACTIVE across the dispute — bootstrapped ops bypass termcheck, and a paused epoch runs no recorddel. They fall outside the group after the schbatchgps hand-off, which is exactly why the plugin crank is gated on is_active rather than is_elected. Their tick is what resolves the dispute here.

This is the assumption the A/B run validates. If the flow times out at the resolution step with wire-sysio#582 in, the bootstrapped daemons are not cranking and the gating needs another look.

Verification

  • pnpm build clean
  • pnpm run lint clean
  • pnpm test — 1954/1956. The 2 failures are ClusterBuildDefaultsExternal.test.ts (ENOENT … bind-registry/wire-cluster-ports.lock.lock), confirmed pre-existing: identical failures with this change stashed on the same worktree. Unrelated /tmp lock race; this diff touches only flow-batch-operator-slashing, which has no jest.
  • Worktree under the platform root with sibling links verified (@wireio/sdk-core../wire-libraries-ts/packages/sdk-core, @wireio/opp-typescript-models../wire-sysio/build/opp/typescript).

The dispute step called `sysio.chalg::chkdispute` itself inside the resolution
poll, so the flow resolved its own dispute and passed whether or not anything in
production would. That is the one thing this flow cannot self-supply: nothing in
the tree cranked `chkdispute`, and for a dispute the difference is "the epoch
resumes" vs "the epoch stays paused with quorum already reached".

Drop `crankChkdispute` and its call site. The poll now waits for the production
crank (wire-sysio `batch_operator_plugin::crank_open_disputes`), so a timeout
here means nothing tallied the votes — which is exactly the assertion worth
having. The three `dispop.*` are SBP-less, but the bootstrapped batch operators
keep their daemons and stay opreg-ACTIVE across the dispute (bootstrapped ops
bypass `termcheck`, and a paused epoch runs no `recorddel`), so their plugin
tick is what resolves it.

`crankChkcons` is unchanged — the SBP-less group genuinely has nothing to drive
`chkcons`, and that is scenario setup rather than a production behavior.

REQUIRES wire-sysio#582. Do not merge this before that lands: without
the plugin crank the dispute never resolves and this flow times out.

Change-Id: Ic83621495c52ea432bca8b617a2f47a6a61b14f3
@heifner

heifner commented Aug 21, 2026

Copy link
Copy Markdown
Contributor Author

e2e gate: GREEN — and it proves the crank exists in production

Run 32518249867 · Release · 19:23:48 → 20:13:11 UTC (49 min) · conclusion=success

ref pinned
wire-sysio ba321d5bd14f9dfffa2f6e884f4e08f81ca93ad7 (Wire-Network/wire-sysio#582)
wire-tools-ts 68b71962304b2707e7960bdb36d6e2a0732cb435 (#81)
everything else manifest default
FLOW_INCLUDE set — running ONLY: flow-batch-operator-slashing flow-batch-operator-termination

## E2E flow results
- ✅ batch-operator-slashing (442s)
- ✅ batch-operator-termination (1011s)
All E2E flows passed.

Why this is the proof, not just a green tick

flow-batch-operator-slashing ran with the harness's own crankChkdispute deleted (#81). Its dispute step now only polls for resolution — nothing in the flow tallies the votes. It resolved anyway, so the only thing that could have called sysio.chalg::chkdispute is batch_operator_plugin::crank_open_disputes from #582.

It also settles the open assumption in #81: the bootstrapped batch operators do keep their daemons and stay opreg-ACTIVE across the paused epoch, and their tick reaches the dispute even though schbatchgps has moved them outside the serving group. That is exactly why the crank is gated on is_active rather than is_elected — had it followed chkcons and gated on is_elected, it would not have fired here.

Durations line up with the known-good baseline

Against run 32184443818 (the last green 5-flow gate): slashing 444s → 442s, termination 1012s → 1011s. No added latency, and batch-operator-termination — the flow #573 broke — is unaffected by touching the same plugin file.

Also verified

pnpm test on the #81 worktree: 1956/1956, 225/225 suites, exit 0 (483s, 8 projects). This supersedes the "1954/1956 with 2 pre-existing failures" noted in the #81 description — the two ClusterBuildDefaultsExternal failures are an intermittent /tmp bind-registry lock race, shown pre-existing (identical with the change stashed) and non-deterministic (absent on a clean re-run). Unrelated to either PR; worth its own ticket if it recurs.

Merge order

Wire-Network/wire-sysio#582 first, then #81. Reversed, the flow has no crank and times out.

@heifner
heifner merged commit 401eda8 into master Aug 21, 2026
2 checks passed
@heifner
heifner deleted the fix/flow-slashing-drop-harness-chkdispute-crank branch August 21, 2026 21:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants