diff --git a/beacon-chain/slasher/BUILD.bazel b/beacon-chain/slasher/BUILD.bazel index b0f0391ac11..52c52833630 100644 --- a/beacon-chain/slasher/BUILD.bazel +++ b/beacon-chain/slasher/BUILD.bazel @@ -41,6 +41,7 @@ go_library( "//encoding/bytesutil:go_default_library", "//monitoring/tracing/trace:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", "//time/slots:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_prometheus_client_golang//prometheus:go_default_library", @@ -83,6 +84,7 @@ go_test( "//crypto/bls/common:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", "//testing/assert:go_default_library", "//testing/require:go_default_library", "//testing/util:go_default_library", diff --git a/beacon-chain/slasher/chunks.go b/beacon-chain/slasher/chunks.go index 01b5943c66b..8b8ef523aba 100644 --- a/beacon-chain/slasher/chunks.go +++ b/beacon-chain/slasher/chunks.go @@ -11,6 +11,7 @@ import ( slashertypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/slasher/types" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/sirupsen/logrus" ) @@ -232,6 +233,60 @@ func (m *MinSpanChunksSlice) CheckSlashable( surroundingVotesTotal.Inc() + // Both attestations should have the same type. If not, we convert both to Electra attestations. + if existingAttWrapper.IndexedAttestation.Version() != incomingAttWrapper.IndexedAttestation.Version() { + existingAttWrapper = &slashertypes.IndexedAttestationWrapper{ + IndexedAttestation: ðpb.IndexedAttestationElectra{ + AttestingIndices: existingAttWrapper.IndexedAttestation.GetAttestingIndices(), + Data: existingAttWrapper.IndexedAttestation.GetData(), + Signature: existingAttWrapper.IndexedAttestation.GetSignature(), + }, + DataRoot: existingAttWrapper.DataRoot, + } + incomingAttWrapper = &slashertypes.IndexedAttestationWrapper{ + IndexedAttestation: ðpb.IndexedAttestationElectra{ + AttestingIndices: incomingAttWrapper.IndexedAttestation.GetAttestingIndices(), + Data: incomingAttWrapper.IndexedAttestation.GetData(), + Signature: incomingAttWrapper.IndexedAttestation.GetSignature(), + }, + DataRoot: incomingAttWrapper.DataRoot, + } + } + + postElectra := existingAttWrapper.IndexedAttestation.Version() >= version.Electra + if postElectra { + existing, ok := existingAttWrapper.IndexedAttestation.(*ethpb.IndexedAttestationElectra) + if !ok { + return nil, fmt.Errorf( + "existing attestation has wrong type (expected %T, got %T)", + ðpb.IndexedAttestationElectra{}, + existingAttWrapper.IndexedAttestation, + ) + } + incoming, ok := incomingAttWrapper.IndexedAttestation.(*ethpb.IndexedAttestationElectra) + if !ok { + return nil, fmt.Errorf( + "incoming attestation has wrong type (expected %T, got %T)", + ðpb.IndexedAttestationElectra{}, + incomingAttWrapper.IndexedAttestation, + ) + } + slashing := ðpb.AttesterSlashingElectra{ + Attestation_1: existing, + Attestation_2: incoming, + } + + // Ensure the attestation with the lower data root is the first attestation. + if bytes.Compare(existingAttWrapper.DataRoot[:], incomingAttWrapper.DataRoot[:]) > 0 { + slashing = ðpb.AttesterSlashingElectra{ + Attestation_1: incoming, + Attestation_2: existing, + } + } + + return slashing, nil + } + existing, ok := existingAttWrapper.IndexedAttestation.(*ethpb.IndexedAttestation) if !ok { return nil, fmt.Errorf( @@ -328,6 +383,60 @@ func (m *MaxSpanChunksSlice) CheckSlashable( surroundedVotesTotal.Inc() + // Both attestations should have the same type. If not, we convert both to Electra attestations. + if existingAttWrapper.IndexedAttestation.Version() != incomingAttWrapper.IndexedAttestation.Version() { + existingAttWrapper = &slashertypes.IndexedAttestationWrapper{ + IndexedAttestation: ðpb.IndexedAttestationElectra{ + AttestingIndices: existingAttWrapper.IndexedAttestation.GetAttestingIndices(), + Data: existingAttWrapper.IndexedAttestation.GetData(), + Signature: existingAttWrapper.IndexedAttestation.GetSignature(), + }, + DataRoot: existingAttWrapper.DataRoot, + } + incomingAttWrapper = &slashertypes.IndexedAttestationWrapper{ + IndexedAttestation: ðpb.IndexedAttestationElectra{ + AttestingIndices: incomingAttWrapper.IndexedAttestation.GetAttestingIndices(), + Data: incomingAttWrapper.IndexedAttestation.GetData(), + Signature: incomingAttWrapper.IndexedAttestation.GetSignature(), + }, + DataRoot: incomingAttWrapper.DataRoot, + } + } + + postElectra := existingAttWrapper.IndexedAttestation.Version() >= version.Electra + if postElectra { + existing, ok := existingAttWrapper.IndexedAttestation.(*ethpb.IndexedAttestationElectra) + if !ok { + return nil, fmt.Errorf( + "existing attestation has wrong type (expected %T, got %T)", + ðpb.IndexedAttestationElectra{}, + existingAttWrapper.IndexedAttestation, + ) + } + incoming, ok := incomingAttWrapper.IndexedAttestation.(*ethpb.IndexedAttestationElectra) + if !ok { + return nil, fmt.Errorf( + "incoming attestation has wrong type (expected %T, got %T)", + ðpb.IndexedAttestationElectra{}, + incomingAttWrapper.IndexedAttestation, + ) + } + slashing := ðpb.AttesterSlashingElectra{ + Attestation_1: existing, + Attestation_2: incoming, + } + + // Ensure the attestation with the lower data root is the first attestation. + if bytes.Compare(existingAttWrapper.DataRoot[:], incomingAttWrapper.DataRoot[:]) > 0 { + slashing = ðpb.AttesterSlashingElectra{ + Attestation_1: incoming, + Attestation_2: existing, + } + } + + return slashing, nil + } + existing, ok := existingAttWrapper.IndexedAttestation.(*ethpb.IndexedAttestation) if !ok { return nil, fmt.Errorf( diff --git a/beacon-chain/slasher/chunks_test.go b/beacon-chain/slasher/chunks_test.go index 7fc1ab7a650..061b4708976 100644 --- a/beacon-chain/slasher/chunks_test.go +++ b/beacon-chain/slasher/chunks_test.go @@ -9,6 +9,7 @@ import ( slashertypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/slasher/types" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" ) @@ -91,7 +92,7 @@ func TestMinSpanChunksSlice_CheckSlashable(t *testing.T) { validatorIdx := primitives.ValidatorIndex(1) source := primitives.Epoch(1) target := primitives.Epoch(2) - att := createAttestationWrapperEmptySig(t, source, target, nil, nil) + att := createAttestationWrapperEmptySig(t, version.Phase0, source, target, nil, nil) // A faulty chunk should lead to error. chunk := &MinSpanChunksSlice{ @@ -126,7 +127,7 @@ func TestMinSpanChunksSlice_CheckSlashable(t *testing.T) { chunk = EmptyMinSpanChunksSlice(params) source = primitives.Epoch(1) target = primitives.Epoch(2) - att = createAttestationWrapperEmptySig(t, source, target, nil, nil) + att = createAttestationWrapperEmptySig(t, version.Phase0, source, target, nil, nil) chunkIndex := uint64(0) startEpoch := target currentEpoch := target @@ -137,7 +138,7 @@ func TestMinSpanChunksSlice_CheckSlashable(t *testing.T) { // because we DO NOT have an existing attestation record in our database at the min target epoch. source = primitives.Epoch(0) target = primitives.Epoch(3) - surroundingVote := createAttestationWrapperEmptySig(t, source, target, nil, nil) + surroundingVote := createAttestationWrapperEmptySig(t, version.Phase0, source, target, nil, nil) slashing, err = chunk.CheckSlashable(ctx, slasherDB, validatorIdx, surroundingVote) require.NoError(t, err) @@ -146,7 +147,7 @@ func TestMinSpanChunksSlice_CheckSlashable(t *testing.T) { // Next up, we save the old attestation record, then check if the // surrounding vote is indeed slashable. attData := att.IndexedAttestation.GetData() - attRecord := createAttestationWrapperEmptySig(t, attData.Source.Epoch, attData.Target.Epoch, []uint64{uint64(validatorIdx)}, []byte{1}) + attRecord := createAttestationWrapperEmptySig(t, version.Phase0, attData.Source.Epoch, attData.Target.Epoch, []uint64{uint64(validatorIdx)}, []byte{1}) err = slasherDB.SaveAttestationRecordsForValidators( ctx, []*slashertypes.IndexedAttestationWrapper{attRecord}, @@ -158,6 +159,49 @@ func TestMinSpanChunksSlice_CheckSlashable(t *testing.T) { require.NotEqual(t, (*ethpb.AttesterSlashing)(nil), slashing) } +func TestMinSpanChunksSlice_CheckSlashable_DifferentVersions(t *testing.T) { + ctx := context.Background() + slasherDB := dbtest.SetupSlasherDB(t) + params := &Parameters{ + chunkSize: 3, + validatorChunkSize: 2, + historyLength: 3, + } + validatorIdx := primitives.ValidatorIndex(1) + source := primitives.Epoch(1) + target := primitives.Epoch(2) + + // We create a vote with Phase0 version. + att := createAttestationWrapperEmptySig(t, version.Phase0, source, target, nil, nil) + + // We initialize an empty chunks slice and mark an attestation with (source 1, target 2) as attested. + chunk := EmptyMinSpanChunksSlice(params) + chunkIndex := uint64(0) + startEpoch := target + currentEpoch := target + _, err := chunk.Update(chunkIndex, currentEpoch, validatorIdx, startEpoch, target) + require.NoError(t, err) + + // We create a surrounding vote with Electra version. + source = primitives.Epoch(0) + target = primitives.Epoch(3) + surroundingVote := createAttestationWrapperEmptySig(t, version.Electra, source, target, nil, nil) + + // We save the old attestation record, then check if the surrounding vote is indeed slashable. + attData := att.IndexedAttestation.GetData() + attRecord := createAttestationWrapperEmptySig(t, version.Phase0, attData.Source.Epoch, attData.Target.Epoch, []uint64{uint64(validatorIdx)}, []byte{1}) + err = slasherDB.SaveAttestationRecordsForValidators( + ctx, + []*slashertypes.IndexedAttestationWrapper{attRecord}, + ) + require.NoError(t, err) + + slashing, err := chunk.CheckSlashable(ctx, slasherDB, validatorIdx, surroundingVote) + require.NoError(t, err) + // The old record should be converted to Electra and the resulting slashing should be an Electra slashing. + require.NotEqual(t, (*ethpb.AttesterSlashingElectra)(nil), slashing) +} + func TestMaxSpanChunksSlice_CheckSlashable(t *testing.T) { ctx := context.Background() slasherDB := dbtest.SetupSlasherDB(t) @@ -169,7 +213,7 @@ func TestMaxSpanChunksSlice_CheckSlashable(t *testing.T) { validatorIdx := primitives.ValidatorIndex(1) source := primitives.Epoch(1) target := primitives.Epoch(2) - att := createAttestationWrapperEmptySig(t, source, target, nil, nil) + att := createAttestationWrapperEmptySig(t, version.Phase0, source, target, nil, nil) // A faulty chunk should lead to error. chunk := &MaxSpanChunksSlice{ @@ -204,7 +248,7 @@ func TestMaxSpanChunksSlice_CheckSlashable(t *testing.T) { chunk = EmptyMaxSpanChunksSlice(params) source = primitives.Epoch(0) target = primitives.Epoch(3) - att = createAttestationWrapperEmptySig(t, source, target, nil, nil) + att = createAttestationWrapperEmptySig(t, version.Phase0, source, target, nil, nil) chunkIndex := uint64(0) startEpoch := source currentEpoch := target @@ -215,7 +259,7 @@ func TestMaxSpanChunksSlice_CheckSlashable(t *testing.T) { // because we DO NOT have an existing attestation record in our database at the max target epoch. source = primitives.Epoch(1) target = primitives.Epoch(2) - surroundedVote := createAttestationWrapperEmptySig(t, source, target, nil, nil) + surroundedVote := createAttestationWrapperEmptySig(t, version.Phase0, source, target, nil, nil) slashing, err = chunk.CheckSlashable(ctx, slasherDB, validatorIdx, surroundedVote) require.NoError(t, err) @@ -226,7 +270,7 @@ func TestMaxSpanChunksSlice_CheckSlashable(t *testing.T) { attData := att.IndexedAttestation.GetData() signingRoot := [32]byte{1} attRecord := createAttestationWrapperEmptySig( - t, attData.Source.Epoch, attData.Target.Epoch, []uint64{uint64(validatorIdx)}, signingRoot[:], + t, version.Phase0, attData.Source.Epoch, attData.Target.Epoch, []uint64{uint64(validatorIdx)}, signingRoot[:], ) err = slasherDB.SaveAttestationRecordsForValidators( ctx, @@ -239,6 +283,49 @@ func TestMaxSpanChunksSlice_CheckSlashable(t *testing.T) { require.NotEqual(t, (*ethpb.AttesterSlashing)(nil), slashing) } +func TestMaxSpanChunksSlice_CheckSlashable_DifferentVersions(t *testing.T) { + ctx := context.Background() + slasherDB := dbtest.SetupSlasherDB(t) + params := &Parameters{ + chunkSize: 4, + validatorChunkSize: 2, + historyLength: 4, + } + validatorIdx := primitives.ValidatorIndex(1) + source := primitives.Epoch(0) + target := primitives.Epoch(3) + + // We create a vote with Phase0 version. + att := createAttestationWrapperEmptySig(t, version.Phase0, source, target, nil, nil) + + // We initialize an empty chunks slice and mark an attestation with (source 0, target 3) as attested. + chunk := EmptyMinSpanChunksSlice(params) + chunkIndex := uint64(0) + startEpoch := target + currentEpoch := target + _, err := chunk.Update(chunkIndex, currentEpoch, validatorIdx, startEpoch, target) + require.NoError(t, err) + + // We create a surrounded vote with Electra version. + source = primitives.Epoch(1) + target = primitives.Epoch(2) + surroundedVote := createAttestationWrapperEmptySig(t, version.Electra, source, target, nil, nil) + + // We save the old attestation record, then check if the sorrounded vote is indeed slashable. + attData := att.IndexedAttestation.GetData() + attRecord := createAttestationWrapperEmptySig(t, version.Phase0, attData.Source.Epoch, attData.Target.Epoch, []uint64{uint64(validatorIdx)}, []byte{1}) + err = slasherDB.SaveAttestationRecordsForValidators( + ctx, + []*slashertypes.IndexedAttestationWrapper{attRecord}, + ) + require.NoError(t, err) + + slashing, err := chunk.CheckSlashable(ctx, slasherDB, validatorIdx, surroundedVote) + require.NoError(t, err) + // The old record should be converted to Electra and the resulting slashing should be an Electra slashing. + require.NotEqual(t, (*ethpb.AttesterSlashingElectra)(nil), slashing) +} + func TestMinSpanChunksSlice_Update_MultipleChunks(t *testing.T) { // Let's set H = historyLength = 2, meaning a min span // will hold 2 epochs worth of attesting history. Then we set C = 2 meaning we will diff --git a/beacon-chain/slasher/detect_attestations.go b/beacon-chain/slasher/detect_attestations.go index bbfc1238b20..a064cb3ab14 100644 --- a/beacon-chain/slasher/detect_attestations.go +++ b/beacon-chain/slasher/detect_attestations.go @@ -11,6 +11,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "golang.org/x/exp/maps" ) @@ -193,33 +194,86 @@ func (s *Service) checkDoubleVotes( // This is a double vote. doubleVotesTotal.Inc() - existing, ok := existingAttWrapper.IndexedAttestation.(*ethpb.IndexedAttestation) - if !ok { - return nil, fmt.Errorf( - "existing attestation has wrong type (expected %T, got %T)", - ðpb.IndexedAttestation{}, - existingAttWrapper.IndexedAttestation, - ) - } - incoming, ok := incomingAttWrapper.IndexedAttestation.(*ethpb.IndexedAttestation) - if !ok { - return nil, fmt.Errorf( - "incoming attestation has wrong type (expected %T, got %T)", - ðpb.IndexedAttestation{}, - incomingAttWrapper.IndexedAttestation, - ) + var slashing ethpb.AttSlashing + + // Both attestations should have the same type. If not, we convert both to Electra attestations. + if existingAttWrapper.IndexedAttestation.Version() != incomingAttWrapper.IndexedAttestation.Version() { + existingAttWrapper = &slashertypes.IndexedAttestationWrapper{ + IndexedAttestation: ðpb.IndexedAttestationElectra{ + AttestingIndices: existingAttWrapper.IndexedAttestation.GetAttestingIndices(), + Data: existingAttWrapper.IndexedAttestation.GetData(), + Signature: existingAttWrapper.IndexedAttestation.GetSignature(), + }, + DataRoot: existingAttWrapper.DataRoot, + } + incomingAttWrapper = &slashertypes.IndexedAttestationWrapper{ + IndexedAttestation: ðpb.IndexedAttestationElectra{ + AttestingIndices: incomingAttWrapper.IndexedAttestation.GetAttestingIndices(), + Data: incomingAttWrapper.IndexedAttestation.GetData(), + Signature: incomingAttWrapper.IndexedAttestation.GetSignature(), + }, + DataRoot: incomingAttWrapper.DataRoot, + } } - slashing := ðpb.AttesterSlashing{ - Attestation_1: existing, - Attestation_2: incoming, - } + postElectra := existingAttWrapper.IndexedAttestation.Version() >= version.Electra + if postElectra { + existing, ok := existingAttWrapper.IndexedAttestation.(*ethpb.IndexedAttestationElectra) + if !ok { + return nil, fmt.Errorf( + "existing attestation has wrong type (expected %T, got %T)", + ðpb.IndexedAttestationElectra{}, + existingAttWrapper.IndexedAttestation, + ) + } + incoming, ok := incomingAttWrapper.IndexedAttestation.(*ethpb.IndexedAttestationElectra) + if !ok { + return nil, fmt.Errorf( + "incoming attestation has wrong type (expected %T, got %T)", + ðpb.IndexedAttestationElectra{}, + incomingAttWrapper.IndexedAttestation, + ) + } + slashing = ðpb.AttesterSlashingElectra{ + Attestation_1: existing, + Attestation_2: incoming, + } - // Ensure the attestation with the lower data root is the first attestation. - if bytes.Compare(existingAttWrapper.DataRoot[:], incomingAttWrapper.DataRoot[:]) > 0 { + // Ensure the attestation with the lower data root is the first attestation. + if bytes.Compare(existingAttWrapper.DataRoot[:], incomingAttWrapper.DataRoot[:]) > 0 { + slashing = ðpb.AttesterSlashingElectra{ + Attestation_1: incoming, + Attestation_2: existing, + } + } + } else { + existing, ok := existingAttWrapper.IndexedAttestation.(*ethpb.IndexedAttestation) + if !ok { + return nil, fmt.Errorf( + "existing attestation has wrong type (expected %T, got %T)", + ðpb.IndexedAttestation{}, + existingAttWrapper.IndexedAttestation, + ) + } + incoming, ok := incomingAttWrapper.IndexedAttestation.(*ethpb.IndexedAttestation) + if !ok { + return nil, fmt.Errorf( + "incoming attestation has wrong type (expected %T, got %T)", + ðpb.IndexedAttestation{}, + incomingAttWrapper.IndexedAttestation, + ) + } slashing = ðpb.AttesterSlashing{ - Attestation_1: incoming, - Attestation_2: existing, + Attestation_1: existing, + Attestation_2: incoming, + } + + // Ensure the attestation with the lower data root is the first attestation. + if bytes.Compare(existingAttWrapper.DataRoot[:], incomingAttWrapper.DataRoot[:]) > 0 { + slashing = ðpb.AttesterSlashing{ + Attestation_1: incoming, + Attestation_2: existing, + } } } @@ -245,33 +299,86 @@ func (s *Service) checkDoubleVotes( wrapper_1 := doubleVote.Wrapper_1 wrapper_2 := doubleVote.Wrapper_2 - att_1, ok := wrapper_1.IndexedAttestation.(*ethpb.IndexedAttestation) - if !ok { - return nil, fmt.Errorf( - "first attestation has wrong type (expected %T, got %T)", - ðpb.IndexedAttestation{}, - wrapper_1.IndexedAttestation, - ) - } - att_2, ok := wrapper_2.IndexedAttestation.(*ethpb.IndexedAttestation) - if !ok { - return nil, fmt.Errorf( - "second attestation has wrong type (expected %T, got %T)", - ðpb.IndexedAttestation{}, - wrapper_2.IndexedAttestation, - ) + var slashing ethpb.AttSlashing + + // Both attestations should have the same type. If not, we convert both to Electra attestations. + if wrapper_1.IndexedAttestation.Version() != wrapper_2.IndexedAttestation.Version() { + wrapper_1 = &slashertypes.IndexedAttestationWrapper{ + IndexedAttestation: ðpb.IndexedAttestationElectra{ + AttestingIndices: wrapper_1.IndexedAttestation.GetAttestingIndices(), + Data: wrapper_1.IndexedAttestation.GetData(), + Signature: wrapper_1.IndexedAttestation.GetSignature(), + }, + DataRoot: wrapper_1.DataRoot, + } + wrapper_2 = &slashertypes.IndexedAttestationWrapper{ + IndexedAttestation: ðpb.IndexedAttestationElectra{ + AttestingIndices: wrapper_2.IndexedAttestation.GetAttestingIndices(), + Data: wrapper_2.IndexedAttestation.GetData(), + Signature: wrapper_2.IndexedAttestation.GetSignature(), + }, + DataRoot: wrapper_2.DataRoot, + } } - slashing := ðpb.AttesterSlashing{ - Attestation_1: att_1, - Attestation_2: att_2, - } + postElectra := wrapper_1.IndexedAttestation.Version() >= version.Electra + if postElectra { + att_1, ok := wrapper_1.IndexedAttestation.(*ethpb.IndexedAttestationElectra) + if !ok { + return nil, fmt.Errorf( + "first attestation has wrong type (expected %T, got %T)", + ðpb.IndexedAttestationElectra{}, + wrapper_1.IndexedAttestation, + ) + } + att_2, ok := wrapper_2.IndexedAttestation.(*ethpb.IndexedAttestationElectra) + if !ok { + return nil, fmt.Errorf( + "second attestation has wrong type (expected %T, got %T)", + ðpb.IndexedAttestationElectra{}, + wrapper_2.IndexedAttestation, + ) + } + slashing = ðpb.AttesterSlashingElectra{ + Attestation_1: att_1, + Attestation_2: att_2, + } - // Ensure the attestation with the lower data root is the first attestation. - if bytes.Compare(wrapper_1.DataRoot[:], wrapper_2.DataRoot[:]) > 0 { + // Ensure the attestation with the lower data root is the first attestation. + if bytes.Compare(wrapper_1.DataRoot[:], wrapper_2.DataRoot[:]) > 0 { + slashing = ðpb.AttesterSlashingElectra{ + Attestation_1: att_2, + Attestation_2: att_1, + } + } + } else { + att_1, ok := wrapper_1.IndexedAttestation.(*ethpb.IndexedAttestation) + if !ok { + return nil, fmt.Errorf( + "first attestation has wrong type (expected %T, got %T)", + ðpb.IndexedAttestation{}, + wrapper_1.IndexedAttestation, + ) + } + att_2, ok := wrapper_2.IndexedAttestation.(*ethpb.IndexedAttestation) + if !ok { + return nil, fmt.Errorf( + "second attestation has wrong type (expected %T, got %T)", + ðpb.IndexedAttestation{}, + wrapper_2.IndexedAttestation, + ) + } slashing = ðpb.AttesterSlashing{ - Attestation_1: att_2, - Attestation_2: att_1, + Attestation_1: att_1, + Attestation_2: att_2, + } + + // Ensure the attestation with the lower data root is the first attestation. + if bytes.Compare(wrapper_1.DataRoot[:], wrapper_2.DataRoot[:]) > 0 { + slashing = ðpb.AttesterSlashing{ + Attestation_1: att_2, + Attestation_2: att_1, + } } } diff --git a/beacon-chain/slasher/detect_attestations_test.go b/beacon-chain/slasher/detect_attestations_test.go index 0026f36877f..52cb20c0b95 100644 --- a/beacon-chain/slasher/detect_attestations_test.go +++ b/beacon-chain/slasher/detect_attestations_test.go @@ -20,6 +20,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/crypto/bls/common" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/util" @@ -30,6 +31,7 @@ import ( func Test_processAttestations(t *testing.T) { type ( attestationInfo struct { + ver int source primitives.Epoch target primitives.Epoch indices []uint64 @@ -37,6 +39,7 @@ func Test_processAttestations(t *testing.T) { } slashingInfo struct { + ver int attestationInfo_1 *attestationInfo attestationInfo_2 *attestationInfo } @@ -58,13 +61,14 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{2}}, + {ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, + {ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{2}}, }, expectedSlashingsInfo: []*slashingInfo{ { - attestationInfo_1: &attestationInfo{source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, - attestationInfo_2: &attestationInfo{source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{2}}, + ver: version.Phase0, + attestationInfo_1: &attestationInfo{ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, + attestationInfo_2: &attestationInfo{ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{2}}, }, }, }, @@ -76,19 +80,20 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, + {ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, }, expectedSlashingsInfo: nil, }, { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{2}}, + {ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{2}}, }, expectedSlashingsInfo: []*slashingInfo{ { - attestationInfo_1: &attestationInfo{source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, - attestationInfo_2: &attestationInfo{source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{2}}, + ver: version.Phase0, + attestationInfo_1: &attestationInfo{ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, + attestationInfo_2: &attestationInfo{ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{2}}, }, }, }, @@ -100,8 +105,8 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, + {ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, + {ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, }, expectedSlashingsInfo: nil, }, @@ -113,14 +118,14 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, + {ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, }, expectedSlashingsInfo: nil, }, { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, + {ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, }, expectedSlashingsInfo: nil, }, @@ -132,13 +137,14 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - {source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: []*slashingInfo{ { - attestationInfo_1: &attestationInfo{source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - attestationInfo_2: &attestationInfo{source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + ver: version.Phase0, + attestationInfo_1: &attestationInfo{ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + attestationInfo_2: &attestationInfo{ver: version.Phase0, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, }, }, @@ -150,19 +156,20 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: []*slashingInfo{ { - attestationInfo_1: &attestationInfo{source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - attestationInfo_2: &attestationInfo{source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + ver: version.Phase0, + attestationInfo_1: &attestationInfo{ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + attestationInfo_2: &attestationInfo{ver: version.Phase0, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, }, }, @@ -174,13 +181,14 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 1000, attestationsInfo: []*attestationInfo{ - {source: 50, target: 51, indices: []uint64{0}, beaconBlockRoot: nil}, - {source: 0, target: 1000, indices: []uint64{0}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 50, target: 51, indices: []uint64{0}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 0, target: 1000, indices: []uint64{0}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: []*slashingInfo{ { - attestationInfo_1: &attestationInfo{source: 0, target: 1000, indices: []uint64{0}, beaconBlockRoot: nil}, - attestationInfo_2: &attestationInfo{source: 50, target: 51, indices: []uint64{0}, beaconBlockRoot: nil}, + ver: version.Phase0, + attestationInfo_1: &attestationInfo{ver: version.Phase0, source: 0, target: 1000, indices: []uint64{0}, beaconBlockRoot: nil}, + attestationInfo_2: &attestationInfo{ver: version.Phase0, source: 50, target: 51, indices: []uint64{0}, beaconBlockRoot: nil}, }, }, }, @@ -192,19 +200,20 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 1000, attestationsInfo: []*attestationInfo{ - {source: 50, target: 51, indices: []uint64{0}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 50, target: 51, indices: []uint64{0}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, { currentEpoch: 1000, attestationsInfo: []*attestationInfo{ - {source: 0, target: 1000, indices: []uint64{0}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 0, target: 1000, indices: []uint64{0}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: []*slashingInfo{ { - attestationInfo_1: &attestationInfo{source: 0, target: 1000, indices: []uint64{0}, beaconBlockRoot: nil}, - attestationInfo_2: &attestationInfo{source: 50, target: 51, indices: []uint64{0}, beaconBlockRoot: nil}, + ver: version.Phase0, + attestationInfo_1: &attestationInfo{ver: version.Phase0, source: 0, target: 1000, indices: []uint64{0}, beaconBlockRoot: nil}, + attestationInfo_2: &attestationInfo{ver: version.Phase0, source: 50, target: 51, indices: []uint64{0}, beaconBlockRoot: nil}, }, }, }, @@ -216,13 +225,14 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: []*slashingInfo{ { - attestationInfo_1: &attestationInfo{source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - attestationInfo_2: &attestationInfo{source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + ver: version.Phase0, + attestationInfo_1: &attestationInfo{ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + attestationInfo_2: &attestationInfo{ver: version.Phase0, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, }, }, @@ -234,19 +244,20 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: []*slashingInfo{ { - attestationInfo_1: &attestationInfo{source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - attestationInfo_2: &attestationInfo{source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + ver: version.Phase0, + attestationInfo_1: &attestationInfo{ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + attestationInfo_2: &attestationInfo{ver: version.Phase0, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, }, }, @@ -258,13 +269,14 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - {source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: []*slashingInfo{ { - attestationInfo_1: &attestationInfo{source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - attestationInfo_2: &attestationInfo{source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + ver: version.Phase0, + attestationInfo_1: &attestationInfo{ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + attestationInfo_2: &attestationInfo{ver: version.Phase0, source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, }, }, @@ -276,19 +288,20 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: []*slashingInfo{ { - attestationInfo_1: &attestationInfo{source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - attestationInfo_2: &attestationInfo{source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + ver: version.Phase0, + attestationInfo_1: &attestationInfo{ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + attestationInfo_2: &attestationInfo{ver: version.Phase0, source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, }, }, @@ -300,8 +313,8 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0}, beaconBlockRoot: nil}, - {source: 0, target: 3, indices: []uint64{1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 1, target: 2, indices: []uint64{0}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 0, target: 3, indices: []uint64{1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, @@ -313,14 +326,14 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 1, target: 2, indices: []uint64{0}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 0, target: 3, indices: []uint64{1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, @@ -332,8 +345,8 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - {source: 1, target: 2, indices: []uint64{2, 3}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 1, target: 2, indices: []uint64{2, 3}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, @@ -345,14 +358,14 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{2, 3}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 1, target: 2, indices: []uint64{2, 3}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, @@ -364,8 +377,8 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0}, beaconBlockRoot: nil}, - {source: 1, target: 2, indices: []uint64{params.BeaconConfig().MinGenesisActiveValidatorCount - 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 0, target: 3, indices: []uint64{0}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 1, target: 2, indices: []uint64{params.BeaconConfig().MinGenesisActiveValidatorCount - 1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, @@ -377,14 +390,14 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 0, target: 3, indices: []uint64{0}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{params.BeaconConfig().MinGenesisActiveValidatorCount - 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 1, target: 2, indices: []uint64{params.BeaconConfig().MinGenesisActiveValidatorCount - 1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, @@ -396,8 +409,8 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0}, beaconBlockRoot: nil}, - {source: 1, target: 2, indices: []uint64{params.BeaconConfig().MinGenesisActiveValidatorCount - 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 0, target: 3, indices: []uint64{0}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 1, target: 2, indices: []uint64{params.BeaconConfig().MinGenesisActiveValidatorCount - 1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, @@ -409,14 +422,14 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 0, target: 3, indices: []uint64{0}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{params.BeaconConfig().MinGenesisActiveValidatorCount - 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 1, target: 2, indices: []uint64{params.BeaconConfig().MinGenesisActiveValidatorCount - 1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, @@ -428,8 +441,8 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - {source: 2, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 2, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, @@ -441,14 +454,14 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 2, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 2, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, @@ -460,8 +473,8 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - {source: 2, target: 4, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 2, target: 4, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, @@ -473,14 +486,14 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 2, target: 4, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 2, target: 4, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, @@ -492,8 +505,8 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - {source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, @@ -505,14 +518,14 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, @@ -524,8 +537,8 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - {source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, @@ -537,19 +550,57 @@ func Test_processAttestations(t *testing.T) { { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, }, expectedSlashingsInfo: nil, }, }, }, + { + name: "Electra: Same target with different signing roots - single step", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: version.Electra, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, + {ver: version.Electra, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{2}}, + }, + expectedSlashingsInfo: []*slashingInfo{ + { + ver: version.Electra, + attestationInfo_1: &attestationInfo{ver: version.Electra, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, + attestationInfo_2: &attestationInfo{ver: version.Electra, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{2}}, + }, + }, + }, + }, + }, + { + name: "Phase0 & Electra: Same target with different signing roots - single step", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, + {ver: version.Electra, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{2}}, + }, + expectedSlashingsInfo: []*slashingInfo{ + { + ver: version.Electra, + attestationInfo_1: &attestationInfo{ver: version.Electra, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, + attestationInfo_2: &attestationInfo{ver: version.Electra, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{2}}, + }, + }, + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -629,6 +680,7 @@ func Test_processAttestations(t *testing.T) { // Create a wrapped attestation. attestationWrapper := createAttestationWrapper( t, + attestationInfo.ver, domain, privateKeys, attestationInfo.source, @@ -642,12 +694,13 @@ func Test_processAttestations(t *testing.T) { } // Build expected attester slashings. - expectedSlashings := make(map[[fieldparams.RootLength]byte]*ethpb.AttesterSlashing, len(step.expectedSlashingsInfo)) + expectedSlashings := make(map[[fieldparams.RootLength]byte]ethpb.AttSlashing, len(step.expectedSlashingsInfo)) for _, slashingInfo := range step.expectedSlashingsInfo { // Create attestations. wrapper_1 := createAttestationWrapper( t, + slashingInfo.attestationInfo_1.ver, domain, privateKeys, slashingInfo.attestationInfo_1.source, @@ -658,6 +711,7 @@ func Test_processAttestations(t *testing.T) { wrapper_2 := createAttestationWrapper( t, + slashingInfo.attestationInfo_2.ver, domain, privateKeys, slashingInfo.attestationInfo_2.source, @@ -667,9 +721,18 @@ func Test_processAttestations(t *testing.T) { ) // Create the attester slashing. - expectedSlashing := ðpb.AttesterSlashing{ - Attestation_1: wrapper_1.IndexedAttestation.(*ethpb.IndexedAttestation), - Attestation_2: wrapper_2.IndexedAttestation.(*ethpb.IndexedAttestation), + var expectedSlashing ethpb.AttSlashing + + if slashingInfo.ver >= version.Electra { + expectedSlashing = ðpb.AttesterSlashingElectra{ + Attestation_1: wrapper_1.IndexedAttestation.(*ethpb.IndexedAttestationElectra), + Attestation_2: wrapper_2.IndexedAttestation.(*ethpb.IndexedAttestationElectra), + } + } else { + expectedSlashing = ðpb.AttesterSlashing{ + Attestation_1: wrapper_1.IndexedAttestation.(*ethpb.IndexedAttestation), + Attestation_2: wrapper_2.IndexedAttestation.(*ethpb.IndexedAttestation), + } } root, err := expectedSlashing.HashTreeRoot() @@ -757,7 +820,7 @@ func Test_processQueuedAttestations_MultipleChunkIndices(t *testing.T) { } var sr [32]byte copy(sr[:], fmt.Sprintf("%d", i)) - att := createAttestationWrapperEmptySig(t, source, target, []uint64{0}, sr[:]) + att := createAttestationWrapperEmptySig(t, version.Phase0, source, target, []uint64{0}, sr[:]) s.attsQueue = newAttestationsQueue() s.attsQueue.push(att) slot, err := slots.EpochStart(i) @@ -814,8 +877,8 @@ func Test_processQueuedAttestations_OverlappingChunkIndices(t *testing.T) { }() // We create two attestations fully spanning chunk indices 0 and chunk 1 - att1 := createAttestationWrapperEmptySig(t, primitives.Epoch(slasherParams.chunkSize-2), primitives.Epoch(slasherParams.chunkSize), []uint64{0, 1}, nil) - att2 := createAttestationWrapperEmptySig(t, primitives.Epoch(slasherParams.chunkSize-1), primitives.Epoch(slasherParams.chunkSize+1), []uint64{0, 1}, nil) + att1 := createAttestationWrapperEmptySig(t, version.Phase0, primitives.Epoch(slasherParams.chunkSize-2), primitives.Epoch(slasherParams.chunkSize), []uint64{0, 1}, nil) + att2 := createAttestationWrapperEmptySig(t, version.Phase0, primitives.Epoch(slasherParams.chunkSize-1), primitives.Epoch(slasherParams.chunkSize+1), []uint64{0, 1}, nil) // We attempt to process the batch. s.attsQueue = newAttestationsQueue() @@ -1152,7 +1215,7 @@ func Test_applyAttestationForValidator_MinSpanChunk(t *testing.T) { // We apply attestation with (source 1, target 2) for our validator. source := primitives.Epoch(1) target := primitives.Epoch(2) - att := createAttestationWrapperEmptySig(t, source, target, nil, nil) + att := createAttestationWrapperEmptySig(t, version.Phase0, source, target, nil, nil) slashing, err := srv.applyAttestationForValidator( ctx, chunksByChunkIdx, @@ -1175,7 +1238,7 @@ func Test_applyAttestationForValidator_MinSpanChunk(t *testing.T) { // expect a slashable offense to be returned. source = primitives.Epoch(0) target = primitives.Epoch(3) - slashableAtt := createAttestationWrapperEmptySig(t, source, target, nil, nil) + slashableAtt := createAttestationWrapperEmptySig(t, version.Phase0, source, target, nil, nil) slashing, err = srv.applyAttestationForValidator( ctx, chunksByChunkIdx, @@ -1209,7 +1272,7 @@ func Test_applyAttestationForValidator_MaxSpanChunk(t *testing.T) { // We apply attestation with (source 0, target 3) for our validator. source := primitives.Epoch(0) target := primitives.Epoch(3) - att := createAttestationWrapperEmptySig(t, source, target, nil, nil) + att := createAttestationWrapperEmptySig(t, version.Phase0, source, target, nil, nil) slashing, err := srv.applyAttestationForValidator( ctx, chunksByChunkIdx, @@ -1232,7 +1295,7 @@ func Test_applyAttestationForValidator_MaxSpanChunk(t *testing.T) { // expect a slashable offense to be returned. source = primitives.Epoch(1) target = primitives.Epoch(2) - slashableAtt := createAttestationWrapperEmptySig(t, source, target, nil, nil) + slashableAtt := createAttestationWrapperEmptySig(t, version.Phase0, source, target, nil, nil) slashing, err = srv.applyAttestationForValidator( ctx, chunksByChunkIdx, @@ -1347,7 +1410,7 @@ func TestService_processQueuedAttestations(t *testing.T) { require.NoError(t, err) s.attsQueue.extend([]*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 1, []uint64{0, 1} /* indices */, nil /* signingRoot */), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 1, []uint64{0, 1} /* indices */, nil /* signingRoot */), }) ctx, cancel := context.WithCancel(context.Background()) tickerChan := make(chan primitives.Slot) @@ -1482,6 +1545,7 @@ func runAttestationsBenchmark(b *testing.B, s *Service, numAtts, numValidators u copy(signingRoot[:], fmt.Sprintf("%d", i)) atts[i] = createAttestationWrapperEmptySig( b, + version.Phase0, source, target, /* target */ indices, /* indices */ @@ -1546,7 +1610,7 @@ func Benchmark_checkSurroundVotes(b *testing.B) { // Create the attestation wrapper. // This benchmark assume that all validators produced the exact same head, source and target votes. - attWrapper := createAttestationWrapperEmptySig(b, sourceEpoch, targetEpoch, validatorIndexes, nil) + attWrapper := createAttestationWrapperEmptySig(b, version.Phase0, sourceEpoch, targetEpoch, validatorIndexes, nil) attWrappers := []*slashertypes.IndexedAttestationWrapper{attWrapper} // Run the benchmark. @@ -1566,6 +1630,7 @@ func Benchmark_checkSurroundVotes(b *testing.B) { // The signature of the returned wrapped attestation is empty. func createAttestationWrapperEmptySig( t testing.TB, + ver int, source, target primitives.Epoch, indices []uint64, beaconBlockRoot []byte, @@ -1585,6 +1650,17 @@ func createAttestationWrapperEmptySig( dataRoot, err := data.HashTreeRoot() require.NoError(t, err) + if ver >= version.Electra { + return &slashertypes.IndexedAttestationWrapper{ + IndexedAttestation: ðpb.IndexedAttestationElectra{ + AttestingIndices: indices, + Data: data, + Signature: params.BeaconConfig().EmptySignature[:], + }, + DataRoot: dataRoot, + } + } + return &slashertypes.IndexedAttestationWrapper{ IndexedAttestation: ðpb.IndexedAttestation{ AttestingIndices: indices, @@ -1601,6 +1677,7 @@ func createAttestationWrapperEmptySig( // if validatorIndice = indices[i], then the corresponding private key is privateKeys[validatorIndice]. func createAttestationWrapper( t testing.TB, + ver int, domain []byte, privateKeys []common.SecretKey, source, target primitives.Epoch, @@ -1648,6 +1725,17 @@ func createAttestationWrapper( signature := bls.AggregateSignatures(signatures).Marshal() // Create the attestation wrapper. + if ver >= version.Electra { + return &slashertypes.IndexedAttestationWrapper{ + IndexedAttestation: ðpb.IndexedAttestationElectra{ + AttestingIndices: indices, + Data: attestationData, + Signature: signature, + }, + DataRoot: attestationDataRoot, + } + } + return &slashertypes.IndexedAttestationWrapper{ IndexedAttestation: ðpb.IndexedAttestation{ AttestingIndices: indices, diff --git a/beacon-chain/slasher/helpers_test.go b/beacon-chain/slasher/helpers_test.go index 0b628419530..3fff33f9247 100644 --- a/beacon-chain/slasher/helpers_test.go +++ b/beacon-chain/slasher/helpers_test.go @@ -9,6 +9,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/require" logTest "github.com/sirupsen/logrus/hooks/test" ) @@ -32,13 +33,13 @@ func TestService_groupByValidatorChunkIndex(t *testing.T) { validatorChunkSize: 2, }, atts: []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 0, []uint64{0, 1}, nil), - createAttestationWrapperEmptySig(t, 0, 0, []uint64{0, 1}, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, []uint64{0, 1}, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, []uint64{0, 1}, nil), }, want: map[uint64][]*slashertypes.IndexedAttestationWrapper{ 0: { - createAttestationWrapperEmptySig(t, 0, 0, []uint64{0, 1}, nil), - createAttestationWrapperEmptySig(t, 0, 0, []uint64{0, 1}, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, []uint64{0, 1}, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, []uint64{0, 1}, nil), }, }, }, @@ -48,17 +49,17 @@ func TestService_groupByValidatorChunkIndex(t *testing.T) { validatorChunkSize: 2, }, atts: []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 0, []uint64{0, 2, 4}, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, []uint64{0, 2, 4}, nil), }, want: map[uint64][]*slashertypes.IndexedAttestationWrapper{ 0: { - createAttestationWrapperEmptySig(t, 0, 0, []uint64{0, 2, 4}, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, []uint64{0, 2, 4}, nil), }, 1: { - createAttestationWrapperEmptySig(t, 0, 0, []uint64{0, 2, 4}, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, []uint64{0, 2, 4}, nil), }, 2: { - createAttestationWrapperEmptySig(t, 0, 0, []uint64{0, 2, 4}, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, []uint64{0, 2, 4}, nil), }, }, }, @@ -95,13 +96,13 @@ func TestService_groupByChunkIndex(t *testing.T) { historyLength: 3, }, atts: []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 0, nil, nil), - createAttestationWrapperEmptySig(t, 1, 0, nil, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, nil, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 1, 0, nil, nil), }, want: map[uint64][]*slashertypes.IndexedAttestationWrapper{ 0: { - createAttestationWrapperEmptySig(t, 0, 0, nil, nil), - createAttestationWrapperEmptySig(t, 1, 0, nil, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, nil, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 1, 0, nil, nil), }, }, }, @@ -112,17 +113,17 @@ func TestService_groupByChunkIndex(t *testing.T) { historyLength: 3, }, atts: []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 0, nil, nil), - createAttestationWrapperEmptySig(t, 1, 0, nil, nil), - createAttestationWrapperEmptySig(t, 2, 0, nil, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, nil, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 1, 0, nil, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 2, 0, nil, nil), }, want: map[uint64][]*slashertypes.IndexedAttestationWrapper{ 0: { - createAttestationWrapperEmptySig(t, 0, 0, nil, nil), - createAttestationWrapperEmptySig(t, 1, 0, nil, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, nil, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 1, 0, nil, nil), }, 1: { - createAttestationWrapperEmptySig(t, 2, 0, nil, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 2, 0, nil, nil), }, }, }, @@ -207,7 +208,7 @@ func TestService_filterAttestations(t *testing.T) { { name: "Source > target gets dropped", input: []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 1, 0, []uint64{1}, make([]byte, 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 1, 0, []uint64{1}, make([]byte, 32)), }, inputEpoch: 0, wantedDropped: 1, @@ -215,33 +216,33 @@ func TestService_filterAttestations(t *testing.T) { { name: "Source < target is valid", input: []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 1, []uint64{1}, make([]byte, 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 1, []uint64{1}, make([]byte, 32)), }, inputEpoch: 1, wantedValid: []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 1, []uint64{1}, make([]byte, 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 1, []uint64{1}, make([]byte, 32)), }, wantedDropped: 0, }, { name: "Source == target is valid", input: []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 0, []uint64{1}, make([]byte, 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, []uint64{1}, make([]byte, 32)), }, inputEpoch: 1, wantedValid: []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 0, []uint64{1}, make([]byte, 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, []uint64{1}, make([]byte, 32)), }, wantedDropped: 0, }, { name: "Attestation from the future is deferred", input: []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 2, []uint64{1}, make([]byte, 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 2, []uint64{1}, make([]byte, 32)), }, inputEpoch: 1, wantedDeferred: []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 2, []uint64{1}, make([]byte, 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 2, []uint64{1}, make([]byte, 32)), }, wantedDropped: 0, }, @@ -271,22 +272,22 @@ func Test_logSlashingEvent(t *testing.T) { { name: "Surrounding vote", slashing: ðpb.AttesterSlashing{ - Attestation_1: createAttestationWrapperEmptySig(t, 0, 0, nil, nil).IndexedAttestation.(*ethpb.IndexedAttestation), - Attestation_2: createAttestationWrapperEmptySig(t, 0, 0, nil, nil).IndexedAttestation.(*ethpb.IndexedAttestation), + Attestation_1: createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, nil, nil).IndexedAttestation.(*ethpb.IndexedAttestation), + Attestation_2: createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, nil, nil).IndexedAttestation.(*ethpb.IndexedAttestation), }, }, { name: "Surrounded vote", slashing: ðpb.AttesterSlashing{ - Attestation_1: createAttestationWrapperEmptySig(t, 0, 0, nil, nil).IndexedAttestation.(*ethpb.IndexedAttestation), - Attestation_2: createAttestationWrapperEmptySig(t, 0, 0, nil, nil).IndexedAttestation.(*ethpb.IndexedAttestation), + Attestation_1: createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, nil, nil).IndexedAttestation.(*ethpb.IndexedAttestation), + Attestation_2: createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, nil, nil).IndexedAttestation.(*ethpb.IndexedAttestation), }, }, { name: "Double vote", slashing: ðpb.AttesterSlashing{ - Attestation_1: createAttestationWrapperEmptySig(t, 0, 0, nil, nil).IndexedAttestation.(*ethpb.IndexedAttestation), - Attestation_2: createAttestationWrapperEmptySig(t, 0, 0, nil, nil).IndexedAttestation.(*ethpb.IndexedAttestation), + Attestation_1: createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, nil, nil).IndexedAttestation.(*ethpb.IndexedAttestation), + Attestation_2: createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, nil, nil).IndexedAttestation.(*ethpb.IndexedAttestation), }, }, } diff --git a/beacon-chain/slasher/queue_test.go b/beacon-chain/slasher/queue_test.go index 04350ae36b5..03295cc2ea8 100644 --- a/beacon-chain/slasher/queue_test.go +++ b/beacon-chain/slasher/queue_test.go @@ -5,6 +5,7 @@ import ( slashertypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/slasher/types" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/require" ) @@ -12,8 +13,8 @@ func Test_attestationsQueue(t *testing.T) { t.Run("push_and_dequeue", func(tt *testing.T) { attQueue := newAttestationsQueue() wantedAtts := []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 1, []uint64{1}, make([]byte, 32)), - createAttestationWrapperEmptySig(t, 1, 2, []uint64{1}, make([]byte, 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 1, []uint64{1}, make([]byte, 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 1, 2, []uint64{1}, make([]byte, 32)), } attQueue.push(wantedAtts[0]) attQueue.push(wantedAtts[1]) @@ -27,8 +28,8 @@ func Test_attestationsQueue(t *testing.T) { t.Run("extend_and_dequeue", func(tt *testing.T) { attQueue := newAttestationsQueue() wantedAtts := []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 1, []uint64{1}, make([]byte, 32)), - createAttestationWrapperEmptySig(t, 1, 2, []uint64{1}, make([]byte, 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 1, []uint64{1}, make([]byte, 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 1, 2, []uint64{1}, make([]byte, 32)), } attQueue.extend(wantedAtts) require.DeepEqual(t, 2, attQueue.size()) diff --git a/beacon-chain/slasher/receive_test.go b/beacon-chain/slasher/receive_test.go index 3bb389be3b7..4b66ac2fe2d 100644 --- a/beacon-chain/slasher/receive_test.go +++ b/beacon-chain/slasher/receive_test.go @@ -13,6 +13,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/util" @@ -38,8 +39,8 @@ func TestSlasher_receiveAttestations_OK(t *testing.T) { }() firstIndices := []uint64{1, 2, 3} secondIndices := []uint64{4, 5, 6} - att1 := createAttestationWrapperEmptySig(t, 1, 2, firstIndices, nil) - att2 := createAttestationWrapperEmptySig(t, 1, 2, secondIndices, nil) + att1 := createAttestationWrapperEmptySig(t, version.Phase0, 1, 2, firstIndices, nil) + att2 := createAttestationWrapperEmptySig(t, version.Phase0, 1, 2, secondIndices, nil) wrappedAtt1 := &slashertypes.WrappedIndexedAtt{IndexedAtt: att1.IndexedAttestation} wrappedAtt2 := &slashertypes.WrappedIndexedAtt{IndexedAtt: att2.IndexedAttestation} indexedAttsChan <- wrappedAtt1 @@ -67,14 +68,14 @@ func TestService_pruneSlasherDataWithinSlidingWindow_AttestationsPruned(t *testi // Setup attestations for 2 validators at each epoch for epochs 0, 1, 2, 3. err := slasherDB.SaveAttestationRecordsForValidators(ctx, []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 0, []uint64{0}, bytesutil.PadTo([]byte("0a"), 32)), - createAttestationWrapperEmptySig(t, 0, 0, []uint64{1}, bytesutil.PadTo([]byte("0b"), 32)), - createAttestationWrapperEmptySig(t, 0, 1, []uint64{0}, bytesutil.PadTo([]byte("1a"), 32)), - createAttestationWrapperEmptySig(t, 0, 1, []uint64{1}, bytesutil.PadTo([]byte("1b"), 32)), - createAttestationWrapperEmptySig(t, 0, 2, []uint64{0}, bytesutil.PadTo([]byte("2a"), 32)), - createAttestationWrapperEmptySig(t, 0, 2, []uint64{1}, bytesutil.PadTo([]byte("2b"), 32)), - createAttestationWrapperEmptySig(t, 0, 3, []uint64{0}, bytesutil.PadTo([]byte("3a"), 32)), - createAttestationWrapperEmptySig(t, 0, 3, []uint64{1}, bytesutil.PadTo([]byte("3b"), 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, []uint64{0}, bytesutil.PadTo([]byte("0a"), 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, []uint64{1}, bytesutil.PadTo([]byte("0b"), 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 1, []uint64{0}, bytesutil.PadTo([]byte("1a"), 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 1, []uint64{1}, bytesutil.PadTo([]byte("1b"), 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 2, []uint64{0}, bytesutil.PadTo([]byte("2a"), 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 2, []uint64{1}, bytesutil.PadTo([]byte("2b"), 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 3, []uint64{0}, bytesutil.PadTo([]byte("3a"), 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 3, []uint64{1}, bytesutil.PadTo([]byte("3b"), 32)), }) require.NoError(t, err) @@ -95,8 +96,8 @@ func TestService_pruneSlasherDataWithinSlidingWindow_AttestationsPruned(t *testi // Setup attestations for 2 validators at epoch 4. err = slasherDB.SaveAttestationRecordsForValidators(ctx, []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 4, []uint64{0}, bytesutil.PadTo([]byte("4a"), 32)), - createAttestationWrapperEmptySig(t, 0, 4, []uint64{1}, bytesutil.PadTo([]byte("4b"), 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 4, []uint64{0}, bytesutil.PadTo([]byte("4a"), 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 4, []uint64{1}, bytesutil.PadTo([]byte("4b"), 32)), }) require.NoError(t, err) @@ -224,7 +225,7 @@ func TestSlasher_receiveAttestations_OnlyValidAttestations(t *testing.T) { firstIndices := []uint64{1, 2, 3} secondIndices := []uint64{4, 5, 6} // Add a valid attestation. - validAtt := createAttestationWrapperEmptySig(t, 1, 2, firstIndices, nil) + validAtt := createAttestationWrapperEmptySig(t, version.Phase0, 1, 2, firstIndices, nil) wrappedValidAtt := &slashertypes.WrappedIndexedAtt{IndexedAtt: validAtt.IndexedAttestation} indexedAttsChan <- wrappedValidAtt // Send an invalid, bad attestation which will not diff --git a/validator/client/attest.go b/validator/client/attest.go index 0c2f92a83cc..a7c11411037 100644 --- a/validator/client/attest.go +++ b/validator/client/attest.go @@ -139,18 +139,14 @@ func (v *validator) SubmitAttestation(ctx context.Context, slot primitives.Slot, return } - // TODO: Extend to Electra - phase0Att, ok := indexedAtt.(*ethpb.IndexedAttestation) - if ok { - // Send the attestation to the beacon node. - if err := v.db.SlashableAttestationCheck(ctx, phase0Att, pubKey, signingRoot, v.emitAccountMetrics, ValidatorAttestFailVec); err != nil { - log.WithError(err).Error("Failed attestation slashing protection check") - log.WithFields( - attestationLogFields(pubKey, indexedAtt), - ).Debug("Attempted slashable attestation details") - tracing.AnnotateError(span, err) - return - } + // Send the attestation to the beacon node. + if err := v.db.SlashableAttestationCheck(ctx, indexedAtt, pubKey, signingRoot, v.emitAccountMetrics, ValidatorAttestFailVec); err != nil { + log.WithError(err).Error("Failed attestation slashing protection check") + log.WithFields( + attestationLogFields(pubKey, indexedAtt), + ).Debug("Attempted slashable attestation details") + tracing.AnnotateError(span, err) + return } aggregationBitfield := bitfield.NewBitlist(uint64(len(duty.Committee)))