diff --git a/pkg/tasks/check_consensus_attestation_stats/task.go b/pkg/tasks/check_consensus_attestation_stats/task.go index 89b374c4..b4d7efa5 100644 --- a/pkg/tasks/check_consensus_attestation_stats/task.go +++ b/pkg/tasks/check_consensus_attestation_stats/task.go @@ -499,14 +499,19 @@ 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 } - 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 @@ -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]