Repository navigation
refactor!: gate ePBS on Ethereum Gloas fork, remove SSV Fork::CStar - #1090
Conversation
ePBS (Gloas) behavior was gated on a placeholder SSV protocol fork,
Fork::CStar, that had no real schedule entry (only commented-out YAML
examples). That coupled an Ethereum consensus-layer transition to an
SSV-invented fork ordinal and risked activating at the wrong slot.
Gate the Gloas-specific paths on the Ethereum Gloas fork read from the
Lighthouse ChainSpec instead:
active_fork(epoch) >= Fork::CStar
-> spec.fork_name_at_slot::<E>(slot).gloas_enabled()
- Remove the Fork::CStar variant; Fork is now {Alan, Boole}.
- Thread spec: Arc<ChainSpec> into QbftManager and the message Validator
(validator_store already held one).
- Add a RoleNotActiveBeforeEthFork validation failure for PTCAttester
messages received before the Gloas fork.
- Drop the cstar entries from the built-in ssv_fork_schedule.yaml files.
SSV-only concerns (domain types, gossip topics, deprecated roles) still
key off the SSV Fork schedule; only Ethereum-consensus concerns move to
the ChainSpec. BeaconVote/GloasBeaconVote dispatch is unchanged at
runtime, only the source of the fork boundary moves.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@claude, please take a look |
|
Claude finished @shane-moore's task in 5m 31s —— View job PR ReviewSolid, focused refactor. The Gloas boundary genuinely belongs on What looks good
Observations / suggestions (non-blocking)1.
RoleNotActiveBeforeEthFork {
role: Role,
minimum_fork: ForkName,
},The SSV-side variant carries RoleNotActiveBeforeEthFork {
role: Role,
current_fork: ForkName, // spec.fork_name_at_epoch(epoch)
minimum_fork: ForkName,
},
2. The same 4-line helper exists in:
Cross-crate test helpers are awkward to share without a 3. Doc comment on
/// Validates that a role is allowed for the fork active at the given slot.
///
/// Rejects:
/// - AggregatorCommittee before Boole fork (not yet active)
/// - Aggregator and SyncCommittee after Boole fork (deprecated)
The function now also rejects 4.
VerificationI did not run
Recommend confirming Tasks
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## epbs #1090 +/- ##
=======================================
Coverage ? 63.92%
=======================================
Files ? 163
Lines ? 28252
Branches ? 0
=======================================
Hits ? 18061
Misses ? 10191
Partials ? 0
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…or #1090) sigp/anchor#1090 removes the SSV Fork::CStar variant and gates ePBS/Gloas behavior on the Ethereum fork (spec...gloas_enabled()) instead of an SSV-side fork ordinal, so there is no longer a cstar_epoch knob. - Remove the conditional cstar entry from the ssv_fork_schedule.yaml template and the HasCStar/CStarEpoch render data (utils.star). The emitted schedule is now Alan + Boole only, valid on pre- and post-#1090 anchor images alike (we never emitted a cstar entry regardless). - Rewrite the profile/README/CLAUDE narrative: Gloas activates purely from gloas_fork_epoch. The previous "omit cstar_epoch to dodge #1061" guidance no longer applies, because #1090 moves the attestation signing gate to gloas_enabled(), so gloas-at-genesis now drives GloasBeaconVote committee consensus from slot 0. With the sync signing path still unmigrated (sigp/anchor#1061, open), SSV cluster attestations now require an anchor image carrying the #1061 fix; proposals, external-builder bids, and chain-level PTC remain testable regardless. Supersedes the approach in sigp/anchor#1085 (fork reorder). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The pre-refactor PTCAttester gate used RoleNotActiveBeforeFork, which carries current_fork. The new RoleNotActiveBeforeEthFork variant had dropped that field, losing diagnostic info and diverging from its sibling variants. Carry the Ethereum ForkName active at the offending epoch (spec.fork_name_at_epoch(epoch)), computed once and reused for the gloas_enabled() check. Also complete the validate_role_for_fork doc comment, which omitted the PTCAttester-before-Gloas rejection. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@claude, thanks for the review. Addressed in 942c551: 1. 2. 3. 4. qbft_manager imports — confirmed, no change needed. Verification: |
|
Claude finished @shane-moore's task in 1m 13s —— View job Re-review of 942c551All four points land cleanly. Confirmed in the diff: 1. 2. 3. Doc comment ✅ — 4. qbft_manager imports ✅ — confirmed live ( Test compatibility ✅ — LGTM. Nothing else from me — recommend merging once CI is green. Tasks
|
|
Makes sense, lgtm! |
Problem, Evidence, and Context
ePBS (Gloas) behavior on the
epbsbranch is gated behind a placeholder SSV protocol fork,Fork::CStar, that has never had a real schedule entry (only commented-out examples in the built-inssv_fork_schedule.yamlfiles). That couples an Ethereum consensus-layer transition (Gloas / EIP-7732) to an SSV-invented fork ordinal, so the fork boundary effectively lives in two places (the SSV fork schedule and the eth2config.yaml) and can drift, risking ePBS activating at the wrong slot.Our pinned Lighthouse
ChainSpecalready exposes the Gloas boundary directly (gloas_fork_epoch,fork_name_at_slot/fork_name_at_epoch,gloas_enabled()), so the canonical source of truth is already in hand. This aligns with SIP-94, which frames ePBS as an Ethereum-fork-driven change rather than a new SSV network fork.Change Overview
Gate the Gloas-specific paths on the Ethereum Gloas fork from the
ChainSpecinstead of the SSV fork:Fork::CStarvariant;Forkis now{Alan, Boole}.spec: Arc<ChainSpec>intoQbftManagerand the messageValidator(validator_storealready held one).RoleNotActiveBeforeEthForkvalidation failure forPTCAttestermessages received before the Gloas fork.cstarentries from the built-inssv_fork_schedule.yamlfiles.Reading order: start with
common/fork/src/fork.rs+schedule.rs(the variant removal), thenqbft_manager/src/lib.rsandvalidator_store/src/lib.rs(gate swap + dispatch), thenmessage_validator/src/lib.rs(role gate + new failure variant), then the tests.What did NOT change:
BeaconVote<->GloasBeaconVotedispatch behavior, domain types, and gossip topic prefixes. The SSVForkschedule still governs SSV-only concerns (Alan/Boole gates, deprecated roles). Only the source of the Gloas boundary moved, from the SSV fork ordinal to the ethChainSpec.Risks, Trade-offs, and Mitigations
GLOAS_FORK_EPOCHin the eth2 network config. This is the same config that already drives every other Ethereum fork transition (Electra, Fulu), so there is no new operational surface, and it removes the prior risk of the SSV schedule and eth2 config disagreeing.spec.fork_name_at_*(...).gloas_enabled()gate is open-coded at 3 sites rather than wrapped in a helper. This deliberately matches the existing house idiom (metadata_servicegates Electra the same way); a wrapper was not added for 3 callers.Validation
cargo +nightly fmt --all -- --check: clean.cargo check --workspace --all-targets: clean.anchor_validator_store46,message_validator63,qbft_manager31. Theqbft_managerGloas-dispatch andmessage_validatorPTCAttestertests were rewritten to drive the boundary via aspec_with_gloas(Option<epoch>)helper that setsChainSpec::gloas_fork_epoch, covering pre-Gloas, at-activation-boundary, and post-Gloas.epbs(including feat(validator_store): implement sign_payload_attestation #1082sign_payload_attestation) before pushing.Rollback
Pure
git revertrestores theFork::CStargate. No migrations, persisted state, or config changes are involved, andCStarhad no real schedule entry, so there is no runtime/operational impact.Additional Info / Next Steps
Follow-on ePBS attestation/sync work can gate on the same
gloas_enabled()predicate rather than CStar, which also removes the need to keep Gloas on the SSVForkordinal axis.🤖 Generated with Claude Code