Skip to content

fix(sequencer): diagnose why no committee exists instead of a scary log#24760

Open
spalladino wants to merge 4 commits into
merge-train/spartanfrom
spl/a-1423-show-a-nicer-log-when-committee-is-not-yet-formed-on-a-new
Open

fix(sequencer): diagnose why no committee exists instead of a scary log#24760
spalladino wants to merge 4 commits into
merge-train/spartanfrom
spl/a-1423-show-a-nicer-log-when-committee-is-not-yet-formed-on-a-new

Conversation

@spalladino

Copy link
Copy Markdown
Contributor

Context

Operators on a freshly-canonical rollup saw Cannot propose at target slot N since the committee does not exist on L1 and panicked. The message was cryptic and, worse, my first attempt reasoned about it wrong: I assumed validators join at genesis, but they actually join after the rollup is made canonical via governance. Verified against the mainnet incident on 0x91ff…: attester count stayed 0 for ~2 weeks after genesis, then jumped to ~3462 the night the rollup went canonical — so "committee should have formed by epoch 2" was nonsense.

Approach

Diagnose the cause from two cheap live signals the sequencer already has — the current attester count and whether the chain has ever produced a block — rather than any genesis- or governance-time anchor (canonical-registration time is an expensive log scan and predicts validator eligibility, not behavior):

  • count ≥ target → committee is just waiting for the sampling window to advance; expected by current + lag + 1 (info, with ETA).
  • count < target and no blocks ever → bootstrap, waiting for validators to stake (info).
  • count < target but blocks exist → the validator set shrank below the required size on a live chain, a genuine incident (warn).

The chain-tip signal (blocks-ever-produced) is what separates expected bootstrap from a real validator-set regression. The classification is a pure, unit-tested function; the sequencer composes and formats the log. The diagnostic is deduped per epoch (was per slot, so it spammed every ~36–72s) and the extra L1 reads are best-effort so the propose path never throws.

Fixes A-1423

Operators saw "Cannot propose at target slot N since the committee does not
exist on L1" and panicked. Replace it with a diagnosis derived from the live
attester count and whether the chain has ever produced a block:

- enough validators staked -> committee just waiting for the sampling lag (info)
- too few staked and no blocks yet -> bootstrap, waiting for validators (info)
- too few staked but blocks exist -> validator set shrank on a live chain (warn)

Dedupe the log per epoch instead of per slot, and make the diagnostic L1 reads
best-effort so the propose path never throws.
…atSeconds

The "no committee yet" diagnosis reported the epoch a committee should exist by
as currentEpoch + lag + 1 — a moving target that re-added the lag on every check
and never counted down. Replay L1's validator-set sampling rule instead: a
committee for epoch E exists iff at least targetCommitteeSize attesters were
staked at epochStart(E) - lag * epochDuration, so read the historical attester
count (via GSE.getAttesterCountAtTime) at each candidate epoch's sample time and
report the first epoch that actually qualifies. The estimate is now a fixed
epoch whose ETA converges and counts down, tagged by provenance (historical /
projected-future / fallback) so the log wording reflects its confidence.

Also moves formatSeconds out of the sequencer into @aztec/foundation/string.
…ittee.ts

Move logMissingCommittee, estimateFirstCommitteeEpoch, and formatEpochEta out of
the Sequencer class into missing_committee.ts as free functions taking a
MissingCommitteeContext deps object, so the sequencer only wires them in. Drop
the FirstCommitteeEpochProvenance enum: findFirstEpochWithCommittee now returns
EpochNumber | undefined, and the caller reports a bounded epoch when it is
undefined. Behavior-focused tests move alongside the functions.
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.

1 participant