diff --git a/validator/client/beacon-api/BUILD.bazel b/validator/client/beacon-api/BUILD.bazel index e3c598dd3f..e93866a048 100644 --- a/validator/client/beacon-api/BUILD.bazel +++ b/validator/client/beacon-api/BUILD.bazel @@ -5,6 +5,8 @@ go_library( srcs = [ "activation.go", "attestation_data.go", + "attester_slashings.go", + "attester_slashings_helpers.go", "beacon_api_beacon_chain_client.go", "beacon_api_helpers.go", "beacon_api_node_client.go", @@ -65,6 +67,8 @@ go_test( srcs = [ "activation_test.go", "attestation_data_test.go", + "attester_slashings_helpers_test.go", + "attester_slashings_test.go", "beacon_api_helpers_test.go", "beacon_api_validator_client_test.go", "beacon_block_converter_test.go", diff --git a/validator/client/beacon-api/attester_slashings.go b/validator/client/beacon-api/attester_slashings.go new file mode 100644 index 0000000000..6414fe1eeb --- /dev/null +++ b/validator/client/beacon-api/attester_slashings.go @@ -0,0 +1,73 @@ +package beacon_api + +import ( + "context" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/rpc/apimiddleware" + "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives" + ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1" +) + +func (c beaconApiSlasherClient) getSlashableAttestations(ctx context.Context, in *ethpb.IndexedAttestation) (*ethpb.AttesterSlashingResponse, error) { + attesterSlashingsPoolResponse := apimiddleware.AttesterSlashingsPoolResponseJson{} + if _, err := c.jsonRestHandler.GetRestJsonResponse(ctx, "/eth/v1/beacon/pool/attester_slashings", &attesterSlashingsPoolResponse); err != nil { + return nil, errors.Wrap(err, "failed to get attester slashings") + } + + attesterSlashings, err := convertAttesterSlashingsToProto(attesterSlashingsPoolResponse.Data) + if err != nil { + return nil, errors.Wrap(err, "failed to convert attester slashings") + } + + type mapKey struct { + targetEpoch primitives.Epoch + attestingIndex uint64 + } + + // Make a map of the requested attesting indices to easily filter them + attestingIndicesMap := make(map[mapKey]bool, len(in.AttestingIndices)) + for _, attestingIndex := range in.AttestingIndices { + attestingIndicesMap[mapKey{ + targetEpoch: in.Data.Target.Epoch, + attestingIndex: attestingIndex, + }] = true + } + + filteredAttesterSlashings := make([]*ethpb.AttesterSlashing, 0) + for _, attesterSlashing := range attesterSlashings { + // Keep the intersection of the Attestation_1 and Attestion_2 attesting indices + attestingIndices1Map := make(map[uint64]bool, len(attesterSlashing.Attestation_1.AttestingIndices)) + for _, attestingIndex := range attesterSlashing.Attestation_1.AttestingIndices { + attestingIndices1Map[attestingIndex] = true + } + + attestingIndicesIntersection := make([]uint64, 0, len(attesterSlashing.Attestation_1.AttestingIndices)) + for _, attestingIndex := range attesterSlashing.Attestation_2.AttestingIndices { + if _, ok := attestingIndices1Map[attestingIndex]; ok { + attestingIndicesIntersection = append(attestingIndicesIntersection, attestingIndex) + } + } + + for _, attestingIndex := range attestingIndicesIntersection { + _, foundAttestation1Match := attestingIndicesMap[mapKey{ + targetEpoch: attesterSlashing.Attestation_1.Data.Target.Epoch, + attestingIndex: attestingIndex, + }] + + _, foundAttestation2Match := attestingIndicesMap[mapKey{ + targetEpoch: attesterSlashing.Attestation_2.Data.Target.Epoch, + attestingIndex: attestingIndex, + }] + + if foundAttestation1Match || foundAttestation2Match { + filteredAttesterSlashings = append(filteredAttesterSlashings, attesterSlashing) + break + } + } + } + + return ðpb.AttesterSlashingResponse{ + AttesterSlashings: filteredAttesterSlashings, + }, nil +} diff --git a/validator/client/beacon-api/attester_slashings_helpers.go b/validator/client/beacon-api/attester_slashings_helpers.go new file mode 100644 index 0000000000..ca1c766f27 --- /dev/null +++ b/validator/client/beacon-api/attester_slashings_helpers.go @@ -0,0 +1,70 @@ +package beacon_api + +import ( + "strconv" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/rpc/apimiddleware" + ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1" +) + +func convertAttesterSlashingsToProto(jsonAttesterSlashings []*apimiddleware.AttesterSlashingJson) ([]*ethpb.AttesterSlashing, error) { + attesterSlashings := make([]*ethpb.AttesterSlashing, len(jsonAttesterSlashings)) + + for index, jsonAttesterSlashing := range jsonAttesterSlashings { + if jsonAttesterSlashing == nil { + return nil, errors.Errorf("attester slashing at index `%d` is nil", index) + } + + attestation1, err := convertIndexedAttestationToProto(jsonAttesterSlashing.Attestation_1) + if err != nil { + return nil, errors.Wrap(err, "failed to get attestation 1") + } + + attestation2, err := convertIndexedAttestationToProto(jsonAttesterSlashing.Attestation_2) + if err != nil { + return nil, errors.Wrap(err, "failed to get attestation 2") + } + + attesterSlashings[index] = ðpb.AttesterSlashing{ + Attestation_1: attestation1, + Attestation_2: attestation2, + } + } + + return attesterSlashings, nil +} + +func convertIndexedAttestationToProto(jsonAttestation *apimiddleware.IndexedAttestationJson) (*ethpb.IndexedAttestation, error) { + if jsonAttestation == nil { + return nil, errors.New("indexed attestation is nil") + } + + attestingIndices := make([]uint64, len(jsonAttestation.AttestingIndices)) + + for index, jsonAttestingIndex := range jsonAttestation.AttestingIndices { + attestingIndex, err := strconv.ParseUint(jsonAttestingIndex, 10, 64) + if err != nil { + return nil, errors.Wrapf(err, "failed to parse attesting index `%s`", jsonAttestingIndex) + } + + attestingIndices[index] = attestingIndex + } + + signature, err := hexutil.Decode(jsonAttestation.Signature) + if err != nil { + return nil, errors.Wrapf(err, "failed to decode attestation signature `%s`", jsonAttestation.Signature) + } + + attestationData, err := convertAttestationDataToProto(jsonAttestation.Data) + if err != nil { + return nil, errors.Wrap(err, "failed to get attestation data") + } + + return ðpb.IndexedAttestation{ + AttestingIndices: attestingIndices, + Data: attestationData, + Signature: signature, + }, nil +} diff --git a/validator/client/beacon-api/attester_slashings_helpers_test.go b/validator/client/beacon-api/attester_slashings_helpers_test.go new file mode 100644 index 0000000000..563261fe12 --- /dev/null +++ b/validator/client/beacon-api/attester_slashings_helpers_test.go @@ -0,0 +1,223 @@ +package beacon_api + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/rpc/apimiddleware" + ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v3/testing/assert" + "github.com/prysmaticlabs/prysm/v3/testing/require" +) + +func TestBeaconBlockProtoHelpers_ConvertAttesterSlashingsToProto(t *testing.T) { + testCases := []struct { + name string + generateInput func() []*apimiddleware.AttesterSlashingJson + expectedResult []*ethpb.AttesterSlashing + expectedErrorMessage string + }{ + { + name: "nil attester slashing", + expectedErrorMessage: "attester slashing at index `0` is nil", + generateInput: func() []*apimiddleware.AttesterSlashingJson { + return []*apimiddleware.AttesterSlashingJson{ + nil, + } + }, + }, + { + name: "bad attestation 1", + expectedErrorMessage: "failed to get attestation 1", + generateInput: func() []*apimiddleware.AttesterSlashingJson { + return []*apimiddleware.AttesterSlashingJson{ + { + Attestation_1: nil, + Attestation_2: nil, + }, + } + }, + }, + { + name: "bad attestation 2", + expectedErrorMessage: "failed to get attestation 2", + generateInput: func() []*apimiddleware.AttesterSlashingJson { + input := generateAttesterSlashingsJson() + input[0].Attestation_2 = nil + return input + }, + }, + { + name: "valid", + generateInput: generateAttesterSlashingsJson, + expectedResult: generateAttesterSlashingsProto(), + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + result, err := convertAttesterSlashingsToProto(testCase.generateInput()) + + if testCase.expectedResult != nil { + require.NoError(t, err) + assert.DeepEqual(t, testCase.expectedResult, result) + } else if testCase.expectedErrorMessage != "" { + assert.ErrorContains(t, testCase.expectedErrorMessage, err) + } + }) + } +} + +func generateAttesterSlashingsJson() []*apimiddleware.AttesterSlashingJson { + return []*apimiddleware.AttesterSlashingJson{ + { + Attestation_1: &apimiddleware.IndexedAttestationJson{ + AttestingIndices: []string{"1", "2"}, + Data: &apimiddleware.AttestationDataJson{ + Slot: "3", + CommitteeIndex: "4", + BeaconBlockRoot: hexutil.Encode([]byte{5}), + Source: &apimiddleware.CheckpointJson{ + Epoch: "6", + Root: hexutil.Encode([]byte{7}), + }, + Target: &apimiddleware.CheckpointJson{ + Epoch: "8", + Root: hexutil.Encode([]byte{9}), + }, + }, + Signature: hexutil.Encode([]byte{10}), + }, + Attestation_2: &apimiddleware.IndexedAttestationJson{ + AttestingIndices: []string{"11", "12"}, + Data: &apimiddleware.AttestationDataJson{ + Slot: "13", + CommitteeIndex: "14", + BeaconBlockRoot: hexutil.Encode([]byte{15}), + Source: &apimiddleware.CheckpointJson{ + Epoch: "16", + Root: hexutil.Encode([]byte{17}), + }, + Target: &apimiddleware.CheckpointJson{ + Epoch: "18", + Root: hexutil.Encode([]byte{19}), + }, + }, + Signature: hexutil.Encode([]byte{20}), + }, + }, + { + Attestation_1: &apimiddleware.IndexedAttestationJson{ + AttestingIndices: []string{"21", "22"}, + Data: &apimiddleware.AttestationDataJson{ + Slot: "23", + CommitteeIndex: "24", + BeaconBlockRoot: hexutil.Encode([]byte{25}), + Source: &apimiddleware.CheckpointJson{ + Epoch: "26", + Root: hexutil.Encode([]byte{27}), + }, + Target: &apimiddleware.CheckpointJson{ + Epoch: "28", + Root: hexutil.Encode([]byte{29}), + }, + }, + Signature: hexutil.Encode([]byte{30}), + }, + Attestation_2: &apimiddleware.IndexedAttestationJson{ + AttestingIndices: []string{"31", "32"}, + Data: &apimiddleware.AttestationDataJson{ + Slot: "33", + CommitteeIndex: "34", + BeaconBlockRoot: hexutil.Encode([]byte{35}), + Source: &apimiddleware.CheckpointJson{ + Epoch: "36", + Root: hexutil.Encode([]byte{37}), + }, + Target: &apimiddleware.CheckpointJson{ + Epoch: "38", + Root: hexutil.Encode([]byte{39}), + }, + }, + Signature: hexutil.Encode([]byte{40}), + }, + }, + } +} + +func generateAttesterSlashingsProto() []*ethpb.AttesterSlashing { + return []*ethpb.AttesterSlashing{ + { + Attestation_1: ðpb.IndexedAttestation{ + AttestingIndices: []uint64{1, 2}, + Data: ðpb.AttestationData{ + Slot: 3, + CommitteeIndex: 4, + BeaconBlockRoot: []byte{5}, + Source: ðpb.Checkpoint{ + Epoch: 6, + Root: []byte{7}, + }, + Target: ðpb.Checkpoint{ + Epoch: 8, + Root: []byte{9}, + }, + }, + Signature: []byte{10}, + }, + Attestation_2: ðpb.IndexedAttestation{ + AttestingIndices: []uint64{11, 12}, + Data: ðpb.AttestationData{ + Slot: 13, + CommitteeIndex: 14, + BeaconBlockRoot: []byte{15}, + Source: ðpb.Checkpoint{ + Epoch: 16, + Root: []byte{17}, + }, + Target: ðpb.Checkpoint{ + Epoch: 18, + Root: []byte{19}, + }, + }, + Signature: []byte{20}, + }, + }, + { + Attestation_1: ðpb.IndexedAttestation{ + AttestingIndices: []uint64{21, 22}, + Data: ðpb.AttestationData{ + Slot: 23, + CommitteeIndex: 24, + BeaconBlockRoot: []byte{25}, + Source: ðpb.Checkpoint{ + Epoch: 26, + Root: []byte{27}, + }, + Target: ðpb.Checkpoint{ + Epoch: 28, + Root: []byte{29}, + }, + }, + Signature: []byte{30}, + }, + Attestation_2: ðpb.IndexedAttestation{ + AttestingIndices: []uint64{31, 32}, + Data: ðpb.AttestationData{ + Slot: 33, + CommitteeIndex: 34, + BeaconBlockRoot: []byte{35}, + Source: ðpb.Checkpoint{ + Epoch: 36, + Root: []byte{37}, + }, + Target: ðpb.Checkpoint{ + Epoch: 38, + Root: []byte{39}, + }, + }, + Signature: []byte{40}, + }, + }, + } +} diff --git a/validator/client/beacon-api/attester_slashings_test.go b/validator/client/beacon-api/attester_slashings_test.go new file mode 100644 index 0000000000..8009fc94e2 --- /dev/null +++ b/validator/client/beacon-api/attester_slashings_test.go @@ -0,0 +1,167 @@ +package beacon_api + +import ( + "context" + "testing" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/golang/mock/gomock" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/rpc/apimiddleware" + ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v3/testing/assert" + "github.com/prysmaticlabs/prysm/v3/testing/require" + "github.com/prysmaticlabs/prysm/v3/validator/client/beacon-api/mock" +) + +const getSlashableAttestationsTestEndpoint = "/eth/v1/beacon/pool/attester_slashings" + +func TestGetSlashableAttestations_Valid(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + ctx := context.Background() + + jsonAttesterSlashings := &apimiddleware.AttesterSlashingsPoolResponseJson{} + + jsonRestHandler := mock.NewMockjsonRestHandler(ctrl) + jsonRestHandler.EXPECT().GetRestJsonResponse( + ctx, + getSlashableAttestationsTestEndpoint, + jsonAttesterSlashings, + ).Return( + nil, + nil, + ).SetArg( + 2, + apimiddleware.AttesterSlashingsPoolResponseJson{ + Data: []*apimiddleware.AttesterSlashingJson{ + { + Attestation_1: &apimiddleware.IndexedAttestationJson{ + AttestingIndices: []string{"1", "2", "3", "4"}, + Data: &apimiddleware.AttestationDataJson{ + Slot: "5", + CommitteeIndex: "6", + BeaconBlockRoot: hexutil.Encode([]byte{7}), + Source: &apimiddleware.CheckpointJson{ + Epoch: "8", + Root: hexutil.Encode([]byte{9}), + }, + Target: &apimiddleware.CheckpointJson{ + Epoch: "10", + Root: hexutil.Encode([]byte{11}), + }, + }, + Signature: hexutil.Encode([]byte{12}), + }, + Attestation_2: &apimiddleware.IndexedAttestationJson{ + AttestingIndices: []string{"3", "4", "13", "14"}, + Data: &apimiddleware.AttestationDataJson{ + Slot: "15", + CommitteeIndex: "16", + BeaconBlockRoot: hexutil.Encode([]byte{17}), + Source: &apimiddleware.CheckpointJson{ + Epoch: "18", + Root: hexutil.Encode([]byte{19}), + }, + Target: &apimiddleware.CheckpointJson{ + Epoch: "10", + Root: hexutil.Encode([]byte{21}), + }, + }, + Signature: hexutil.Encode([]byte{22}), + }, + }, + { + Attestation_1: &apimiddleware.IndexedAttestationJson{ + AttestingIndices: []string{"23", "24"}, + Data: &apimiddleware.AttestationDataJson{ + Slot: "25", + CommitteeIndex: "26", + BeaconBlockRoot: hexutil.Encode([]byte{27}), + Source: &apimiddleware.CheckpointJson{ + Epoch: "28", + Root: hexutil.Encode([]byte{29}), + }, + Target: &apimiddleware.CheckpointJson{ + Epoch: "30", + Root: hexutil.Encode([]byte{31}), + }, + }, + Signature: hexutil.Encode([]byte{32}), + }, + Attestation_2: &apimiddleware.IndexedAttestationJson{ + AttestingIndices: []string{"33", "34"}, + Data: &apimiddleware.AttestationDataJson{ + Slot: "35", + CommitteeIndex: "36", + BeaconBlockRoot: hexutil.Encode([]byte{37}), + Source: &apimiddleware.CheckpointJson{ + Epoch: "38", + Root: hexutil.Encode([]byte{39}), + }, + Target: &apimiddleware.CheckpointJson{ + Epoch: "40", + Root: hexutil.Encode([]byte{41}), + }, + }, + Signature: hexutil.Encode([]byte{42}), + }, + }, + }, + }, + ).Times(1) + + slasherClient := beaconApiSlasherClient{jsonRestHandler: jsonRestHandler} + + expectedAttesterSlashingResponse := ðpb.AttesterSlashingResponse{ + AttesterSlashings: []*ethpb.AttesterSlashing{ + { + Attestation_1: ðpb.IndexedAttestation{ + AttestingIndices: []uint64{1, 2, 3, 4}, + Data: ðpb.AttestationData{ + Slot: 5, + CommitteeIndex: 6, + BeaconBlockRoot: []byte{7}, + Source: ðpb.Checkpoint{ + Epoch: 8, + Root: []byte{9}, + }, + Target: ðpb.Checkpoint{ + Epoch: 10, + Root: []byte{11}, + }, + }, + Signature: []byte{12}, + }, + Attestation_2: ðpb.IndexedAttestation{ + AttestingIndices: []uint64{3, 4, 13, 14}, + Data: ðpb.AttestationData{ + Slot: 15, + CommitteeIndex: 16, + BeaconBlockRoot: []byte{17}, + Source: ðpb.Checkpoint{ + Epoch: 18, + Root: []byte{19}, + }, + Target: ðpb.Checkpoint{ + Epoch: 10, + Root: []byte{21}, + }, + }, + Signature: []byte{22}, + }, + }, + }, + } + + attesterSlashingResponse, err := slasherClient.getSlashableAttestations(ctx, ðpb.IndexedAttestation{ + AttestingIndices: []uint64{13, 2, 14, 4, 3, 1, 23, 24, 33, 34}, + Data: ðpb.AttestationData{ + Target: ðpb.Checkpoint{ + Epoch: 10, + }, + }, + }) + + require.NoError(t, err) + assert.DeepEqual(t, expectedAttesterSlashingResponse, attesterSlashingResponse) +} diff --git a/validator/client/beacon-api/beacon_api_slasher_client.go b/validator/client/beacon-api/beacon_api_slasher_client.go index e072774ab6..1589b2e776 100644 --- a/validator/client/beacon-api/beacon_api_slasher_client.go +++ b/validator/client/beacon-api/beacon_api_slasher_client.go @@ -2,6 +2,7 @@ package beacon_api import ( "context" + "encoding/json" "net/http" "time" @@ -15,12 +16,30 @@ type beaconApiSlasherClient struct { } func (c beaconApiSlasherClient) IsSlashableAttestation(ctx context.Context, in *ethpb.IndexedAttestation) (*ethpb.AttesterSlashingResponse, error) { - if c.fallbackClient != nil { - return c.fallbackClient.IsSlashableAttestation(ctx, in) + grpcResult, err := c.fallbackClient.IsSlashableAttestation(ctx, in) + if err != nil { + return nil, err } - // TODO: Implement me - panic("beaconApiSlasherClient.IsSlashableAttestation is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiSlasherClientWithFallback.") + restResult, err := c.getSlashableAttestations(ctx, in) + if err != nil { + return nil, err + } + + marshalledGrpcResult, err := json.Marshal(grpcResult) + if err != nil { + return nil, err + } + + marshalledRestResult, err := json.Marshal(restResult) + if err != nil { + return nil, err + } + + log.Errorf("***************GRPC RESULT: %s", string(marshalledGrpcResult)) + log.Errorf("***************REST RESULT: %s", string(marshalledRestResult)) + + return c.getSlashableAttestations(ctx, in) } func (c beaconApiSlasherClient) IsSlashableBlock(ctx context.Context, in *ethpb.SignedBeaconBlockHeader) (*ethpb.ProposerSlashingResponse, error) { diff --git a/validator/client/beacon-api/beacon_block_proto_helpers.go b/validator/client/beacon-api/beacon_block_proto_helpers.go index c8f2a6976a..8bef94a80a 100644 --- a/validator/client/beacon-api/beacon_block_proto_helpers.go +++ b/validator/client/beacon-api/beacon_block_proto_helpers.go @@ -89,66 +89,6 @@ func convertProposerSlashingSignedHeaderToProto(signedHeader *apimiddleware.Sign }, nil } -func convertAttesterSlashingsToProto(jsonAttesterSlashings []*apimiddleware.AttesterSlashingJson) ([]*ethpb.AttesterSlashing, error) { - attesterSlashings := make([]*ethpb.AttesterSlashing, len(jsonAttesterSlashings)) - - for index, jsonAttesterSlashing := range jsonAttesterSlashings { - if jsonAttesterSlashing == nil { - return nil, errors.Errorf("attester slashing at index `%d` is nil", index) - } - - attestation1, err := convertIndexedAttestationToProto(jsonAttesterSlashing.Attestation_1) - if err != nil { - return nil, errors.Wrap(err, "failed to get attestation 1") - } - - attestation2, err := convertIndexedAttestationToProto(jsonAttesterSlashing.Attestation_2) - if err != nil { - return nil, errors.Wrap(err, "failed to get attestation 2") - } - - attesterSlashings[index] = ðpb.AttesterSlashing{ - Attestation_1: attestation1, - Attestation_2: attestation2, - } - } - - return attesterSlashings, nil -} - -func convertIndexedAttestationToProto(jsonAttestation *apimiddleware.IndexedAttestationJson) (*ethpb.IndexedAttestation, error) { - if jsonAttestation == nil { - return nil, errors.New("indexed attestation is nil") - } - - attestingIndices := make([]uint64, len(jsonAttestation.AttestingIndices)) - - for index, jsonAttestingIndex := range jsonAttestation.AttestingIndices { - attestingIndex, err := strconv.ParseUint(jsonAttestingIndex, 10, 64) - if err != nil { - return nil, errors.Wrapf(err, "failed to parse attesting index `%s`", jsonAttestingIndex) - } - - attestingIndices[index] = attestingIndex - } - - signature, err := hexutil.Decode(jsonAttestation.Signature) - if err != nil { - return nil, errors.Wrapf(err, "failed to decode attestation signature `%s`", jsonAttestation.Signature) - } - - attestationData, err := convertAttestationDataToProto(jsonAttestation.Data) - if err != nil { - return nil, errors.Wrap(err, "failed to get attestation data") - } - - return ðpb.IndexedAttestation{ - AttestingIndices: attestingIndices, - Data: attestationData, - Signature: signature, - }, nil -} - func convertCheckpointToProto(jsonCheckpoint *apimiddleware.CheckpointJson) (*ethpb.Checkpoint, error) { if jsonCheckpoint == nil { return nil, errors.New("checkpoint is nil") diff --git a/validator/client/beacon-api/beacon_block_proto_helpers_test.go b/validator/client/beacon-api/beacon_block_proto_helpers_test.go index 3e56c3b660..9a6cc5a5c3 100644 --- a/validator/client/beacon-api/beacon_block_proto_helpers_test.go +++ b/validator/client/beacon-api/beacon_block_proto_helpers_test.go @@ -219,137 +219,6 @@ func TestBeaconBlockProtoHelpers_ConvertProposerSlashingSignedHeaderToProto(t *t } } -func TestBeaconBlockProtoHelpers_ConvertAttesterSlashingsToProto(t *testing.T) { - testCases := []struct { - name string - generateInput func() []*apimiddleware.AttesterSlashingJson - expectedResult []*ethpb.AttesterSlashing - expectedErrorMessage string - }{ - { - name: "nil attester slashing", - expectedErrorMessage: "attester slashing at index `0` is nil", - generateInput: func() []*apimiddleware.AttesterSlashingJson { - return []*apimiddleware.AttesterSlashingJson{ - nil, - } - }, - }, - { - name: "bad attestation 1", - expectedErrorMessage: "failed to get attestation 1", - generateInput: func() []*apimiddleware.AttesterSlashingJson { - return []*apimiddleware.AttesterSlashingJson{ - { - Attestation_1: nil, - Attestation_2: nil, - }, - } - }, - }, - { - name: "bad attestation 2", - expectedErrorMessage: "failed to get attestation 2", - generateInput: func() []*apimiddleware.AttesterSlashingJson { - input := generateAttesterSlashings() - input[0].Attestation_2 = nil - return input - }, - }, - { - name: "valid", - generateInput: generateAttesterSlashings, - expectedResult: []*ethpb.AttesterSlashing{ - { - Attestation_1: ðpb.IndexedAttestation{ - AttestingIndices: []uint64{1, 2}, - Data: ðpb.AttestationData{ - Slot: 3, - CommitteeIndex: 4, - BeaconBlockRoot: []byte{5}, - Source: ðpb.Checkpoint{ - Epoch: 6, - Root: []byte{7}, - }, - Target: ðpb.Checkpoint{ - Epoch: 8, - Root: []byte{9}, - }, - }, - Signature: []byte{10}, - }, - Attestation_2: ðpb.IndexedAttestation{ - AttestingIndices: []uint64{11, 12}, - Data: ðpb.AttestationData{ - Slot: 13, - CommitteeIndex: 14, - BeaconBlockRoot: []byte{15}, - Source: ðpb.Checkpoint{ - Epoch: 16, - Root: []byte{17}, - }, - Target: ðpb.Checkpoint{ - Epoch: 18, - Root: []byte{19}, - }, - }, - Signature: []byte{20}, - }, - }, - { - Attestation_1: ðpb.IndexedAttestation{ - AttestingIndices: []uint64{21, 22}, - Data: ðpb.AttestationData{ - Slot: 23, - CommitteeIndex: 24, - BeaconBlockRoot: []byte{25}, - Source: ðpb.Checkpoint{ - Epoch: 26, - Root: []byte{27}, - }, - Target: ðpb.Checkpoint{ - Epoch: 28, - Root: []byte{29}, - }, - }, - Signature: []byte{30}, - }, - Attestation_2: ðpb.IndexedAttestation{ - AttestingIndices: []uint64{31, 32}, - Data: ðpb.AttestationData{ - Slot: 33, - CommitteeIndex: 34, - BeaconBlockRoot: []byte{35}, - Source: ðpb.Checkpoint{ - Epoch: 36, - Root: []byte{37}, - }, - Target: ðpb.Checkpoint{ - Epoch: 38, - Root: []byte{39}, - }, - }, - Signature: []byte{40}, - }, - }, - }, - }, - } - - for _, testCase := range testCases { - t.Run(testCase.name, func(t *testing.T) { - result, err := convertAttesterSlashingsToProto(testCase.generateInput()) - - if testCase.expectedResult != nil { - require.NoError(t, err) - assert.DeepEqual(t, testCase.expectedResult, result) - } else if testCase.expectedErrorMessage != "" { - assert.ErrorContains(t, testCase.expectedErrorMessage, err) - } - }) - } -} - func TestBeaconBlockProtoHelpers_ConvertAttestationToProto(t *testing.T) { testCases := []struct { name string @@ -1143,83 +1012,6 @@ func generateSignedBeaconBlockHeader() *apimiddleware.SignedBeaconBlockHeaderJso } } -func generateAttesterSlashings() []*apimiddleware.AttesterSlashingJson { - return []*apimiddleware.AttesterSlashingJson{ - { - Attestation_1: &apimiddleware.IndexedAttestationJson{ - AttestingIndices: []string{"1", "2"}, - Data: &apimiddleware.AttestationDataJson{ - Slot: "3", - CommitteeIndex: "4", - BeaconBlockRoot: hexutil.Encode([]byte{5}), - Source: &apimiddleware.CheckpointJson{ - Epoch: "6", - Root: hexutil.Encode([]byte{7}), - }, - Target: &apimiddleware.CheckpointJson{ - Epoch: "8", - Root: hexutil.Encode([]byte{9}), - }, - }, - Signature: hexutil.Encode([]byte{10}), - }, - Attestation_2: &apimiddleware.IndexedAttestationJson{ - AttestingIndices: []string{"11", "12"}, - Data: &apimiddleware.AttestationDataJson{ - Slot: "13", - CommitteeIndex: "14", - BeaconBlockRoot: hexutil.Encode([]byte{15}), - Source: &apimiddleware.CheckpointJson{ - Epoch: "16", - Root: hexutil.Encode([]byte{17}), - }, - Target: &apimiddleware.CheckpointJson{ - Epoch: "18", - Root: hexutil.Encode([]byte{19}), - }, - }, - Signature: hexutil.Encode([]byte{20}), - }, - }, - { - Attestation_1: &apimiddleware.IndexedAttestationJson{ - AttestingIndices: []string{"21", "22"}, - Data: &apimiddleware.AttestationDataJson{ - Slot: "23", - CommitteeIndex: "24", - BeaconBlockRoot: hexutil.Encode([]byte{25}), - Source: &apimiddleware.CheckpointJson{ - Epoch: "26", - Root: hexutil.Encode([]byte{27}), - }, - Target: &apimiddleware.CheckpointJson{ - Epoch: "28", - Root: hexutil.Encode([]byte{29}), - }, - }, - Signature: hexutil.Encode([]byte{30}), - }, - Attestation_2: &apimiddleware.IndexedAttestationJson{ - AttestingIndices: []string{"31", "32"}, - Data: &apimiddleware.AttestationDataJson{ - Slot: "33", - CommitteeIndex: "34", - BeaconBlockRoot: hexutil.Encode([]byte{35}), - Source: &apimiddleware.CheckpointJson{ - Epoch: "36", - Root: hexutil.Encode([]byte{37}), - }, - Target: &apimiddleware.CheckpointJson{ - Epoch: "38", - Root: hexutil.Encode([]byte{39}), - }, - }, - Signature: hexutil.Encode([]byte{40}), - }, - }, - } -} - func generateIndexedAttestation() *apimiddleware.IndexedAttestationJson { return &apimiddleware.IndexedAttestationJson{ AttestingIndices: []string{"1", "2"},