Skip to content

Add bounded council election contract - #516

Open
huangminghuang wants to merge 5 commits into
masterfrom
feature/council
Open

Add bounded council election contract#516
huangminghuang wants to merge 5 commits into
masterfrom
feature/council

Conversation

@huangminghuang

@huangminghuang huangminghuang commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Introduce the sysio.councl system contract, which fills 21 council seats through a deterministic tier-1 → tier-2 → tier-3 nomination and strict-priority voting process.

The contract:

  • associates each seat with one frozen tier-1 node owner and lets that owner nominate first;
  • escalates failed or timed-out attempts to a selected tier-2 owner, then to non-repeating tier-3 owners;
  • elects from three-candidate slates using a greater-than-two-thirds threshold and strict candidate priority;
  • preserves completed council rows as generation history; and
  • provides a governance backstop when automatic escalation is exhausted or requires recovery.

Safety and lifecycle hardening

  • Freeze tier snapshots in bounded batches and resume in deterministic owner order with an identity-deduplicating wrap pass, preserving ROA-churn safety without rescanning the loaded prefix on normal batches.
  • Pin the council and protobuf tier values with compile-time assertions, and require the captured ROA network generation to remain current at finalization.
  • Allow governance to abort a partial LOADING generation through the existing bounded reset/purge cleanup path, in addition to cleaning a completed election.
  • Cap candidate registration and tier snapshot sizes, validate attempt durations, and bill candidate rows to the registering candidate.
  • Replace per-round ballot rows with a bounded vote bitmap and linear tier-3 retry tracking with a lazy Fisher–Yates remap.
  • Use typed election, initialization, tier, and cleanup phases.
  • Treat nomination and voting deadlines as inclusive, while allowing stale nomination/vote actions to settle elapsed state without applying stale input.
  • Authenticate public settle and stir callers before incorporating them into the deterministic entropy accumulator.
  • Add forceback for governance recovery and retain completed council rows while purging ephemeral generation data.
  • Supply Ricardian text for all 13 actions and document the storage, liveness, governance, and entropy tradeoffs.

Efficiency and review follow-up

  • Reduce tier-3 remap reads/writes with try_get/set, fold candidate existence checks into table mutations, and return table-drained state directly from bounded purge passes.
  • Validate the tier-1 roster with sorted in-memory copies instead of repeated KV lookups.
  • Centralize canonical tuple hashing, use the declared slate size and CHAR_BIT, and keep the committed ABI/WASM synchronized with the reviewed source.
  • Address the consolidated Fuego findings F1–F12; the two design-risk items are documented explicitly under Reviewer notes below.

Tests

The focused council suites now contain 45 cases. Coverage includes:

  • candidate RAM billing, removal refunds, handle validation, duplicate/removal errors, registration closure, and the 1,000-candidate cap;
  • initialization authorization, duplicate/incorrect tier-1 rosters, tier and batch validation, tier-2/tier-3 completeness, idempotent loading, and ROA churn during batched loading;
  • aborting, purging, and restarting a partial LOADING generation;
  • tier-1, tier-2, tier-3, and governance output rows, including every persisted council_row field;
  • direct T2-to-BACKSTOP behavior when tier 3 is empty;
  • duplicate voting, stale actions, phase guards, exact deadline boundaries, full-turnout failure, and strict-priority resolution;
  • forceback/forceassign wrong-phase, non-candidate, and already-elected rejection paths;
  • deterministic replay and non-repeating selection across the maximum 1,000-owner tier-3 set;
  • cleanup of candidates, roster, tier-2, tier-3, and remap rows while retaining council history;
  • two complete election generations; and
  • the N == 0 math guard.

Validation

  • Full default build from the dedicated review build tree with Clang 18 and -j30 — passed.
  • contracts_unit_test --run_test='council_math_tests,sysio_councl_tests' -- --sys-vm — 45 cases, no errors.
  • Committed source artifacts match the rebuilt outputs byte-for-byte:
    • WASM SHA-256: d65da356d2563695094c98e6b644c176b284b6f086562fadda2fc2e54a77c653
    • ABI SHA-256: f4fb5f7965e52075457d05dfe23312a44ccfa38c7668fb8283a5bb192f1bf350
  • ABI JSON validation and git diff --check — passed.

Reviewer notes

  • Entropy deliberately excludes block number and timestamp. Authenticated callers can still grind ordering by choosing when and which cheap identity cranks, so proposer selection is deterministic and auditable but not ungrindable. This remains an explicit team sign-off item.
  • A one-member tier reaches threshold through the proposer auto-yes. Because node owners may also register as candidates, that proposer may nominate and immediately seat themselves; the contract intentionally imposes neither an electorate-size floor nor proposer/candidate exclusion. This remains an explicit team sign-off item.
  • Automatic escalation is bounded, but final completion can require governance forceassign; the contract does not promise unconditional wall-clock completion when governance is unavailable.

brianjohnson5972 and others added 4 commits July 7, 2026 16:49
loadtier resumed its staged snapshot by position (skip-count over the
live bytier enumeration). A tier-2/3 owner forcereg'd between batches
that sorted before an already-loaded owner shifted the enumeration, so
the resumed batch re-wrote a snapshotted owner (duplicate) and dropped
the newcomer, while finalizeinit's count cross-check still passed —
silently corrupting the frozen electorate.

Skip owners already present in the snapshot's byowner index instead.
No positional cursor remains to mis-align, and mid-load newcomers are
absorbed by whichever batch encounters them, so t{2,3}_loaded converges
on the live nodecount and finalizeinit stays reachable. This also makes
loadtier genuinely idempotent, matching DESIGN.md §9.

The loadtier_roa_churn_mid_load regression test now passes; wasm
rebuilt, ABI unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Bound candidate and election storage, bill candidate rows to registrants, replace per-round ballots with a vote bitmap, and use a lazy Fisher-Yates remap for tier-3 selection.

Add authenticated settlement and entropy cranks, inclusive deadline handling, stale-action settlement, governance recovery, typed lifecycle state, staged generation cleanup, and complete Ricardian coverage.

Expand contract and property tests across authorization, tier escalation, deterministic replay, maximum owner bounds, cleanup, and multi-generation history retention.
Change-Id: I5116a48073cdfde133c108144034adb85acfdb62
@huangminghuang
huangminghuang requested a review from a team July 30, 2026 17:31

@brianjohnson5972 brianjohnson5972 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good

@huangminghuang
huangminghuang requested a review from heifner July 31, 2026 13:58
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