Compute real aggregate pubkeys when BLS verification is disabled - #5489
Conversation
With `bls_setting: 2`, `AggregatePKs` returned the stub constant `0x2222...22`, which `get_next_sync_committee` then wrote into `state.next_sync_committee.aggregate_pubkey` at sync committee rotations. Unlike signature checks, which clients can skip per `bls_setting`, the aggregate pubkey is data committed into the state, so no real-crypto client can reproduce the block state roots of such vectors. This currently affects the FCR test `is_one_confirmed_fails_recently_activated_validator_voting_in_empty_slot`, the only BLS-disabled test crossing a sync committee period boundary. Key aggregation is not signature verification, so compute it for real regardless of the BLS setting. Anchor states are unaffected because genesis states are created with BLS enabled; regenerated vectors are identical up to the first sync committee rotation. Follow-up to ethereum#5376 and ethereum#5400.
|
I completely understand the motivation. We had this problem with compliance tests and the workaround we used in Teku was not computing but reading the After proposed change there will be a slight increase in computations for Thanks for the proposed change! |
**Motivation** Update spec tests to v1.7.0-alpha.13 FCR fixes proposed from #9690 ([consensus-specs#5489](ethereum/consensus-specs#5489), [consensus-specs#5490](ethereum/consensus-specs#5490)) and complete the missing FCR assertions. **Description** - Unskip `is_one_confirmed_fails_large_validator_slashed`, fixed upstream by [consensus-specs#5490](ethereum/consensus-specs#5490) - Enable the gloas `fast_confirmation` suite — gloas alpha.13 state transition and `get_safe_execution_block_hash` landed via #9393 - Assert `safe_execution_block_hash` ([consensus-specs#5449](ethereum/consensus-specs#5449)) and the `FastConfirmationStore` variables, exposed via `IForkChoice.getFastConfirmationStore()` (debug API endpoint in a follow-up PR) - Skip vectors blocked on upstream vector artifacts, documented inline; the schedule-related ones are already fixed upstream ([consensus-specs#5498](ethereum/consensus-specs#5498), [consensus-specs#5499](ethereum/consensus-specs#5499)) and unskip on the next spec-tests release `fast_confirmation` (minimal): 1416 passed / 20 skipped / 0 failed. Full spec suites green: minimal 70,899 passed, mainnet 13,586 passed, 0 failures. Refs #9690 **AI Assistance Disclosure** - [x] I have read the [contributor guidelines](https://github.com/ChainSafe/lodestar/blob/unstable/CONTRIBUTING.md#ai-assistance-notice) and disclosed my usage of AI below. Implemented and verified with AI assistance (Claude Code); all changes reviewed and tests executed locally. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Motivation
All
fast_confirmationtest vectors are generated withbls_setting: 2(introduced in #5376 for generation speed). With BLS inactive, the pyspec stubsAggregatePKsvia@only_with_bls(alt_return=STUB_PUBKEY), so it returns the constant0x2222…22instead of a real aggregate.This is fine for signatures:
bls_setting: 2tells clients to skip signature verification, and they can honor that. The aggregate public key is different — it is data committed into the beacon state, not the result of a verification. At every sync committee rotation,get_next_sync_committeewrites theAggregatePKsoutput intostate.next_sync_committee.aggregate_pubkey. A client replaying such a vector computes the real aggregate during its state transition and arrives at a different state root, so block import fails with an invalid state root. Noreal-crypto client can pass such a vector, and no
bls_settingvalue can make it pass — the stub constant is effectively a generator-private convention. (Even a fake-crypto build wouldn't match: e.g. Lighthouse'sfake_cryptoaggregate is the infinity pubkey, not
0x2222…22.)Concretely, this breaks
is_one_confirmed_fails_recently_activated_validator_voting_in_empty_slot(added in #5400), currently the only BLS-disabled test that runs long enough to cross a sync committee period boundary (slot 64 on minimal).Change
Remove the
only_with_blsstub fromAggregatePKsso key aggregation is always computed for real, regardless of the BLS setting. Key aggregation is not signature verification, so it should not be gated onbls_active.Validation
Regenerated
is_one_confirmed_fails_recently_activated_validator_voting_in_empty_slot(electra/minimal) before and after the change: the anchor state and all files up to slot 63 are byte-identical; divergence starts exactly at slot 64 (the first sync committee rotation), where the real aggregate replaces the stub. The pyspec test itself passes unchanged, so FCR logic is unaffected — only the state roots change, to values that real-crypto clients can now reproduce.