fix: dispute two-candidate consensus splits - #581
Conversation
Change-Id: I073d15645a2334b4cf0075d8e3f1ecba3a49d0db
Not the same class of change as #573 — but drop the terminality gateReviewed against #573 (closed today), since both descend from the same root: after #569, Reachability inverts#573 needed the ACTIVE roster to fall below This PR's condition needs one operator, not a roster collapse. A 7-member group losing a single member mid-epoch gives That is the same mid-window attrition #573 accepted as residual scope, at even arity instead of arity-1. Blast radius is much smaller#573 mutated group membership, breaking the "window groups are disjoint by construction" invariant that This PR changes only when a dispute opens. No membership, no scheduling, no attestation the outposts position against. The The terminality gate should goThe That is backwards: the case where adjudication is most needed — an operator is gone and the remainder disagree — is the case terminality refuses to adjudicate. The premise behind the gate does not hold either. We do not expect any divergent envelope versions, much less two. Post-boundary, ≥2 distinct versions with no strict majority is already the anomaly — that is the dispute trigger. And the boundary is a deadline, not a checkpoint: an operator that has not delivered by then has burned the entire epoch and is a miss, not a straggler. Resolution then works exactly as intended: Tier-1 votes canonical, Suggested change — this makes the diff smaller, not larger:
Boundary check and majority check are unchanged and both already sit ahead of it. That the silent-operator hole closes without a special case is a good sign the gate was the wrong shape. Two consequences, both accepted1. Once a dispute exists, // If a dispute has been opened for this (outpost, epoch), the dispute-vote flow owns its
// resolution and winner dispatch (via `resolvedisp`). evalcons is a no-op for this bucket
// so a late delivery cannot re-open the dispute or re-dispatch the envelope.So opening a dispute forecloses free automatic resolution by a late delivery. Accepted — post-boundary non-delivery is already a miss. 2. // After the deadline: a quorum of cast votes AND a strict majority of cast votes.
// No plurality / tie-break — an unresolved tally just keeps waiting for more votes.
if (!resolved) return;Past the deadline you still need This is an accepted design decision, not a gap to close. The trade is deliberate: replace "operators must deliver" with "a majority of Tier-1 must vote." Pausing until Tier-1 votes is the correct outcome — the alternatives (plurality, or abandon-and-resume) either pick a winner on weak evidence or hand back the original deadlock. Worth stating explicitly in the PR body so it is a recorded decision rather than an implicit one, and worth confirming the batch-operator crank actually drives Still needs the isolated A/BThe PR body notes the platform-flow gates are pending. That is exactly the state #573 was in before the run that closed it — 659/659 unit green, independent reviews passed, and an earlier GREEN 5-flow gate on a prior commit. It still regressed once the right flow ran against the right head. Same protocol as runs |
Change-Id: Id0cbaa4fa450435cdc928b501a90222f65c2f38e
Change-Id: I510b5f4ee60976920fa494faef70406eeb0f86a7
Summary
sysio.msgch::evalconsopens a Tier-1 dispute after the epoch boundary whenever at least two versions have no strict majority, including a silent otherwise-eligible batch operator.sysio.chalg::opendisputeandmsgchshare a two-candidate floor; a one-version tally remains non-disputable. Pre-boundary and strict-majority paths are unchanged.origin/masterwithout conflicts.Coverage
chkcons→evalcons→opendisputeregressions cover 1–1 and 3–3 ties, verify candidate tallies, resolve via Tier-1, and verify theoutpconswinner.opendisputeaccepts two candidates and still rejects one.Generated artifacts
sysio.chalg.wasm:112d1c92d6c8bca69554bec109527ebfa8156c444a7b54207464ece1b5154652.sysio.msgch.wasm:47a2b9fc64367c393d9fddbc621e62c5e218c51d68258f970a4dd00ecabea25a.origin/mastermerge, a fresh release CDT build again byte-matched both tracked WASMs and ABIs; no further artifact change was needed.Deliberate dispute behavior
evalconsis a no-op for that outpost and epoch; a late delivery cannot re-open or automatically resolve it. Post-boundary non-delivery is treated as a miss.chkdisputehas no timeout escape. Without Tier-1 quorum and strict majority, the dispute remains open and the epoch paused.Validation
contracts_unit_test -- --sys-vmpassed.chkconsregressions passed.git diff --checkpassed.