From 06b7f967e28a5d4715d6254aff1181969dac01d5 Mon Sep 17 00:00:00 2001 From: Jun Song Date: Fri, 26 Jun 2026 16:14:02 +0900 Subject: [PATCH 1/2] Use `aggregationBitsOffset` for calculating vote count post-Electra --- pkg/tasks/check_consensus_attestation_stats/task.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/tasks/check_consensus_attestation_stats/task.go b/pkg/tasks/check_consensus_attestation_stats/task.go index 89b374c4..4786ae01 100644 --- a/pkg/tasks/check_consensus_attestation_stats/task.go +++ b/pkg/tasks/check_consensus_attestation_stats/task.go @@ -506,7 +506,7 @@ func (t *Task) aggregateEpochVotes(ctx context.Context, epoch uint64) []*epochVo continue } - voteAmt, voteCnt, committeeSize := t.aggregateAttestationVotes(votes, uint64(attData.Slot), committee, attAggregationBits, 0) + voteAmt, voteCnt, committeeSize := t.aggregateAttestationVotes(votes, uint64(attData.Slot), committee, attAggregationBits, aggregationBitsOffset) voteAmount += voteAmt voteCount += voteCnt aggregationBitsOffset += committeeSize From 715a92e30333afb7f3f6b73f109c5a8f367c3cca Mon Sep 17 00:00:00 2001 From: Jun Song Date: Fri, 26 Jun 2026 16:14:36 +0900 Subject: [PATCH 2/2] Add `committeeBitSet`: length(`MAX_COMMITTEES_PER_SLOT`)-agnostic bit check --- pkg/tasks/check_consensus_attestation_stats/task.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/pkg/tasks/check_consensus_attestation_stats/task.go b/pkg/tasks/check_consensus_attestation_stats/task.go index 4786ae01..b4d7efa5 100644 --- a/pkg/tasks/check_consensus_attestation_stats/task.go +++ b/pkg/tasks/check_consensus_attestation_stats/task.go @@ -499,10 +499,15 @@ func (t *Task) aggregateEpochVotes(ctx context.Context, epoch uint64) []*epochVo continue } + // committeeBits is a bitfield.Bitvector64, whose BitAt only works at + // the mainnet 8-byte size; under smaller presets it is shorter, so we + // test the bits length-agnostically (see committeeBitSet). + committeeBitsBytes := []byte(committeeBits) + aggregationBitsOffset := uint64(0) for committee := uint64(0); committee < specs.MaxCommitteesPerSlot; committee++ { - if !committeeBits.BitAt(committee) { + if !committeeBitSet(committeeBitsBytes, committee) { continue } @@ -559,6 +564,12 @@ func (t *Task) aggregateEpochVotes(ctx context.Context, epoch uint64) []*epochVo return votes } +// committeeBitSet reports whether the committee-th bit is set in b. +func committeeBitSet(b []byte, committee uint64) bool { + byteIdx := committee / 8 + return byteIdx < uint64(len(b)) && b[byteIdx]&(1<<(committee%8)) != 0 +} + func (t *Task) aggregateAttestationVotes(votes *epochVotes, slot, committee uint64, aggregationBits bitfield.Bitfield, aggregationBitsOffset uint64) (voteAmount, voteCount, validatorCount uint64) { attKey := fmt.Sprintf("%v-%v", slot, committee) voteValidators := votes.attesterDuties.duties[attKey]