mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 15:37:56 -05:00
fix: use assigned committee index in attestation data after Electra (#15696)
* fix: use assigned committee index in attestation data after Electra * update change log * update add unit test --------- Co-authored-by: james-prysm <90280386+james-prysm@users.noreply.github.com>
This commit is contained in:
3
changelog/muzry_fix_validator_client_committee_index.md
Normal file
3
changelog/muzry_fix_validator_client_committee_index.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Fixed
|
||||
|
||||
- Fixed incorrect attestation data request where the assigned committee index was used after Electra, instead of 0.
|
||||
@@ -71,9 +71,15 @@ func (v *validator) SubmitAttestation(ctx context.Context, slot primitives.Slot,
|
||||
return
|
||||
}
|
||||
|
||||
committeeIndex := duty.CommitteeIndex
|
||||
postElectra := slots.ToEpoch(slot) >= params.BeaconConfig().ElectraForkEpoch
|
||||
if postElectra {
|
||||
committeeIndex = 0
|
||||
}
|
||||
|
||||
req := ðpb.AttestationDataRequest{
|
||||
Slot: slot,
|
||||
CommitteeIndex: duty.CommitteeIndex,
|
||||
CommitteeIndex: committeeIndex,
|
||||
}
|
||||
data, err := v.validatorClient.AttestationData(ctx, req)
|
||||
if err != nil {
|
||||
@@ -95,8 +101,6 @@ func (v *validator) SubmitAttestation(ctx context.Context, slot primitives.Slot,
|
||||
return
|
||||
}
|
||||
|
||||
postElectra := slots.ToEpoch(slot) >= params.BeaconConfig().ElectraForkEpoch
|
||||
|
||||
var indexedAtt ethpb.IndexedAtt
|
||||
if postElectra {
|
||||
indexedAtt = ðpb.IndexedAttestationElectra{
|
||||
|
||||
@@ -104,6 +104,99 @@ func TestAttestToBlockHead_SubmitAttestation_RequestFailure(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubmitAttestation_ElectraCommitteeIndex(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
electraForkEpoch uint64
|
||||
attestationSlot primitives.Slot
|
||||
assignedCommitteeIndex primitives.CommitteeIndex
|
||||
expectedCommitteeIndex primitives.CommitteeIndex
|
||||
isPostElectra bool
|
||||
}{
|
||||
{
|
||||
name: "Pre-Electra uses assigned committee index",
|
||||
electraForkEpoch: 10,
|
||||
attestationSlot: 300,
|
||||
assignedCommitteeIndex: 5,
|
||||
expectedCommitteeIndex: 5,
|
||||
isPostElectra: false,
|
||||
},
|
||||
{
|
||||
name: "Post-Electra uses committee index 0",
|
||||
electraForkEpoch: 1,
|
||||
attestationSlot: 32,
|
||||
assignedCommitteeIndex: 5,
|
||||
expectedCommitteeIndex: 0,
|
||||
isPostElectra: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
for _, isSlashingProtectionMinimal := range [...]bool{false, true} {
|
||||
t.Run(fmt.Sprintf("%s (SlashingProtectionMinimal:%v)", tt.name, isSlashingProtectionMinimal), func(t *testing.T) {
|
||||
params.SetupTestConfigCleanup(t)
|
||||
cfg := params.BeaconConfig().Copy()
|
||||
cfg.ElectraForkEpoch = primitives.Epoch(tt.electraForkEpoch)
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
|
||||
validator, m, validatorKey, finish := setup(t, isSlashingProtectionMinimal)
|
||||
defer finish()
|
||||
validatorIndex := primitives.ValidatorIndex(7)
|
||||
committee := []primitives.ValidatorIndex{0, 3, 4, 2, validatorIndex, 6, 8, 9, 10}
|
||||
var pubKey [fieldparams.BLSPubkeyLength]byte
|
||||
copy(pubKey[:], validatorKey.PublicKey().Marshal())
|
||||
validator.duties = ðpb.ValidatorDutiesContainer{CurrentEpochDuties: []*ethpb.ValidatorDuty{
|
||||
{
|
||||
PublicKey: validatorKey.PublicKey().Marshal(),
|
||||
CommitteeIndex: tt.assignedCommitteeIndex,
|
||||
CommitteeLength: uint64(len(committee)),
|
||||
ValidatorIndex: validatorIndex,
|
||||
},
|
||||
}}
|
||||
|
||||
var capturedRequest *ethpb.AttestationDataRequest
|
||||
// Capture the actual request to verify committee index
|
||||
m.validatorClient.EXPECT().AttestationData(
|
||||
gomock.Any(), // ctx
|
||||
gomock.AssignableToTypeOf(ðpb.AttestationDataRequest{}),
|
||||
).Do(func(_ context.Context, req *ethpb.AttestationDataRequest) {
|
||||
capturedRequest = req
|
||||
}).Return(ðpb.AttestationData{
|
||||
BeaconBlockRoot: make([]byte, fieldparams.RootLength),
|
||||
Target: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)},
|
||||
Source: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)},
|
||||
}, nil)
|
||||
|
||||
m.validatorClient.EXPECT().DomainData(
|
||||
gomock.Any(), // ctx
|
||||
gomock.Any(), // epoch
|
||||
).Times(2).Return(ðpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil)
|
||||
|
||||
if tt.isPostElectra {
|
||||
m.validatorClient.EXPECT().ProposeAttestationElectra(
|
||||
gomock.Any(), // ctx
|
||||
gomock.AssignableToTypeOf(ðpb.SingleAttestation{}),
|
||||
).Return(ðpb.AttestResponse{}, nil)
|
||||
} else {
|
||||
m.validatorClient.EXPECT().ProposeAttestation(
|
||||
gomock.Any(), // ctx
|
||||
gomock.AssignableToTypeOf(ðpb.Attestation{}),
|
||||
).Return(ðpb.AttestResponse{}, nil)
|
||||
}
|
||||
|
||||
validator.SubmitAttestation(t.Context(), tt.attestationSlot, pubKey)
|
||||
|
||||
// Verify the committee index in the request
|
||||
require.NotNil(t, capturedRequest, "AttestationDataRequest should have been called")
|
||||
assert.Equal(t, tt.expectedCommitteeIndex, capturedRequest.CommitteeIndex,
|
||||
"Committee index mismatch: expected %d, got %d", tt.expectedCommitteeIndex, capturedRequest.CommitteeIndex)
|
||||
assert.Equal(t, tt.attestationSlot, capturedRequest.Slot,
|
||||
"Slot should match the provided slot")
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAttestToBlockHead_AttestsCorrectly(t *testing.T) {
|
||||
for _, isSlashingProtectionMinimal := range [...]bool{false, true} {
|
||||
t.Run(fmt.Sprintf("Phase 0 (SlashingProtectionMinimal:%v)", isSlashingProtectionMinimal), func(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user