From 4a7d7b5f1edc6187573a0ae922861b26d7f176b8 Mon Sep 17 00:00:00 2001 From: Nazar Hussain Date: Tue, 28 Jul 2026 17:16:03 +0500 Subject: [PATCH 1/2] Compute real aggregate pubkeys when BLS verification is disabled 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 #5376 and #5400. --- tests/core/pyspec/eth_consensus_specs/utils/bls.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth_consensus_specs/utils/bls.py b/tests/core/pyspec/eth_consensus_specs/utils/bls.py index f924741755..939d46c49b 100644 --- a/tests/core/pyspec/eth_consensus_specs/utils/bls.py +++ b/tests/core/pyspec/eth_consensus_specs/utils/bls.py @@ -185,7 +185,10 @@ def Sign(SK, message): return signature_point.to_compressed_bytes() -@only_with_bls(alt_return=STUB_PUBKEY) +# Note: no `only_with_bls` here. Pubkey aggregation is not signature +# verification: its result is written into the beacon state (e.g. by +# `get_next_sync_committee`), so it must be computed for real even when +# BLS verification is disabled, or clients cannot reproduce state roots. def AggregatePKs(pubkeys): aggregate = _aggregate_pubkey_points(pubkeys) assert aggregate is not None, f"empty or invalid pubkeys: {pubkeys!r}" From ebd58d30e71e86d523763e71395d5dba6dbd6d19 Mon Sep 17 00:00:00 2001 From: Nazar Hussain Date: Tue, 28 Jul 2026 17:38:40 +0500 Subject: [PATCH 2/2] Update the doc comments to explain the reasoning better --- tests/core/pyspec/eth_consensus_specs/utils/bls.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/core/pyspec/eth_consensus_specs/utils/bls.py b/tests/core/pyspec/eth_consensus_specs/utils/bls.py index 939d46c49b..149aa2780c 100644 --- a/tests/core/pyspec/eth_consensus_specs/utils/bls.py +++ b/tests/core/pyspec/eth_consensus_specs/utils/bls.py @@ -185,10 +185,10 @@ def Sign(SK, message): return signature_point.to_compressed_bytes() -# Note: no `only_with_bls` here. Pubkey aggregation is not signature -# verification: its result is written into the beacon state (e.g. by -# `get_next_sync_committee`), so it must be computed for real even when -# BLS verification is disabled, or clients cannot reproduce state roots. +# Pubkey aggregation must be computed even when BLS is inactive: unlike +# signature verification, its result is data written into the beacon state +# (e.g. `next_sync_committee.aggregate_pubkey`), which clients must be able +# to reproduce regardless of the `bls_setting` in use. def AggregatePKs(pubkeys): aggregate = _aggregate_pubkey_points(pubkeys) assert aggregate is not None, f"empty or invalid pubkeys: {pubkeys!r}"