mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-24 12:27:18 +00:00
700f5fee8c
* add context to beacon APIs * add TODO to merge GET and POST methods * fix linter action Co-authored-by: kasey <489222+kasey@users.noreply.github.com> Co-authored-by: james-prysm <90280386+james-prysm@users.noreply.github.com>
250 lines
8.3 KiB
Go
250 lines
8.3 KiB
Go
package beacon_api
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"strconv"
|
|
"testing"
|
|
|
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
"github.com/golang/mock/gomock"
|
|
rpcmiddleware "github.com/prysmaticlabs/prysm/v3/beacon-chain/rpc/apimiddleware"
|
|
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
|
"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 attestationDataEndpoint = "/eth/v1/validator/attestation_data"
|
|
|
|
func TestGetAttestationData_ValidAttestation(t *testing.T) {
|
|
ctx := context.Background()
|
|
expectedSlot := uint64(5)
|
|
expectedCommitteeIndex := uint64(6)
|
|
expectedBeaconBlockRoot := "0x0636045df9bdda3ab96592cf5389032c8ec3977f911e2b53509b348dfe164d4d"
|
|
expectedSourceEpoch := uint64(7)
|
|
expectedSourceRoot := "0xd4bcbdefc8156e85247681086e8050e5d2d5d1bf076a25f6decd99250f3a378d"
|
|
expectedTargetEpoch := uint64(8)
|
|
expectedTargetRoot := "0x246590e8e4c2a9bd13cc776ecc7025bc432219f076e80b27267b8fa0456dc821"
|
|
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
jsonRestHandler := mock.NewMockjsonRestHandler(ctrl)
|
|
produceAttestationDataResponseJson := rpcmiddleware.ProduceAttestationDataResponseJson{}
|
|
|
|
jsonRestHandler.EXPECT().GetRestJsonResponse(
|
|
ctx,
|
|
fmt.Sprintf("/eth/v1/validator/attestation_data?committee_index=%d&slot=%d", expectedCommitteeIndex, expectedSlot),
|
|
&produceAttestationDataResponseJson,
|
|
).Return(
|
|
nil,
|
|
nil,
|
|
).SetArg(
|
|
2,
|
|
rpcmiddleware.ProduceAttestationDataResponseJson{
|
|
Data: &rpcmiddleware.AttestationDataJson{
|
|
Slot: strconv.FormatUint(expectedSlot, 10),
|
|
CommitteeIndex: strconv.FormatUint(expectedCommitteeIndex, 10),
|
|
BeaconBlockRoot: expectedBeaconBlockRoot,
|
|
Source: &rpcmiddleware.CheckpointJson{
|
|
Epoch: strconv.FormatUint(expectedSourceEpoch, 10),
|
|
Root: expectedSourceRoot,
|
|
},
|
|
Target: &rpcmiddleware.CheckpointJson{
|
|
Epoch: strconv.FormatUint(expectedTargetEpoch, 10),
|
|
Root: expectedTargetRoot,
|
|
},
|
|
},
|
|
},
|
|
).Times(1)
|
|
|
|
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
|
|
resp, err := validatorClient.getAttestationData(ctx, types.Slot(expectedSlot), types.CommitteeIndex(expectedCommitteeIndex))
|
|
assert.NoError(t, err)
|
|
|
|
require.NotNil(t, resp)
|
|
assert.Equal(t, expectedBeaconBlockRoot, hexutil.Encode(resp.BeaconBlockRoot))
|
|
assert.Equal(t, expectedCommitteeIndex, uint64(resp.CommitteeIndex))
|
|
assert.Equal(t, expectedSlot, uint64(resp.Slot))
|
|
|
|
require.NotNil(t, resp.Source)
|
|
assert.Equal(t, expectedSourceEpoch, uint64(resp.Source.Epoch))
|
|
assert.Equal(t, expectedSourceRoot, hexutil.Encode(resp.Source.Root))
|
|
|
|
require.NotNil(t, resp.Target)
|
|
assert.Equal(t, expectedTargetEpoch, uint64(resp.Target.Epoch))
|
|
assert.Equal(t, expectedTargetRoot, hexutil.Encode(resp.Target.Root))
|
|
}
|
|
|
|
func TestGetAttestationData_InvalidData(t *testing.T) {
|
|
ctx := context.Background()
|
|
|
|
testCases := []struct {
|
|
name string
|
|
generateData func() rpcmiddleware.ProduceAttestationDataResponseJson
|
|
expectedErrorMessage string
|
|
}{
|
|
{
|
|
name: "nil attestation data",
|
|
generateData: func() rpcmiddleware.ProduceAttestationDataResponseJson {
|
|
return rpcmiddleware.ProduceAttestationDataResponseJson{
|
|
Data: nil,
|
|
}
|
|
},
|
|
expectedErrorMessage: "attestation data is nil",
|
|
},
|
|
{
|
|
name: "invalid committee index",
|
|
generateData: func() rpcmiddleware.ProduceAttestationDataResponseJson {
|
|
attestation := generateValidAttestation(1, 2)
|
|
attestation.Data.CommitteeIndex = "foo"
|
|
return attestation
|
|
},
|
|
expectedErrorMessage: "failed to parse attestation committee index: foo",
|
|
},
|
|
{
|
|
name: "invalid block root",
|
|
generateData: func() rpcmiddleware.ProduceAttestationDataResponseJson {
|
|
attestation := generateValidAttestation(1, 2)
|
|
attestation.Data.BeaconBlockRoot = "foo"
|
|
return attestation
|
|
},
|
|
expectedErrorMessage: "invalid beacon block root: foo",
|
|
},
|
|
{
|
|
name: "invalid slot",
|
|
generateData: func() rpcmiddleware.ProduceAttestationDataResponseJson {
|
|
attestation := generateValidAttestation(1, 2)
|
|
attestation.Data.Slot = "foo"
|
|
return attestation
|
|
},
|
|
expectedErrorMessage: "failed to parse attestation slot: foo",
|
|
},
|
|
{
|
|
name: "nil source",
|
|
generateData: func() rpcmiddleware.ProduceAttestationDataResponseJson {
|
|
attestation := generateValidAttestation(1, 2)
|
|
attestation.Data.Source = nil
|
|
return attestation
|
|
},
|
|
expectedErrorMessage: "attestation source is nil",
|
|
},
|
|
{
|
|
name: "invalid source epoch",
|
|
generateData: func() rpcmiddleware.ProduceAttestationDataResponseJson {
|
|
attestation := generateValidAttestation(1, 2)
|
|
attestation.Data.Source.Epoch = "foo"
|
|
return attestation
|
|
},
|
|
expectedErrorMessage: "failed to parse attestation source epoch: foo",
|
|
},
|
|
{
|
|
name: "invalid source root",
|
|
generateData: func() rpcmiddleware.ProduceAttestationDataResponseJson {
|
|
attestation := generateValidAttestation(1, 2)
|
|
attestation.Data.Source.Root = "foo"
|
|
return attestation
|
|
},
|
|
expectedErrorMessage: "invalid attestation source root: foo",
|
|
},
|
|
{
|
|
name: "nil target",
|
|
generateData: func() rpcmiddleware.ProduceAttestationDataResponseJson {
|
|
attestation := generateValidAttestation(1, 2)
|
|
attestation.Data.Target = nil
|
|
return attestation
|
|
},
|
|
expectedErrorMessage: "attestation target is nil",
|
|
},
|
|
{
|
|
name: "invalid target epoch",
|
|
generateData: func() rpcmiddleware.ProduceAttestationDataResponseJson {
|
|
attestation := generateValidAttestation(1, 2)
|
|
attestation.Data.Target.Epoch = "foo"
|
|
return attestation
|
|
},
|
|
expectedErrorMessage: "failed to parse attestation target epoch: foo",
|
|
},
|
|
{
|
|
name: "invalid target root",
|
|
generateData: func() rpcmiddleware.ProduceAttestationDataResponseJson {
|
|
attestation := generateValidAttestation(1, 2)
|
|
attestation.Data.Target.Root = "foo"
|
|
return attestation
|
|
},
|
|
expectedErrorMessage: "invalid attestation target root: foo",
|
|
},
|
|
}
|
|
|
|
for _, testCase := range testCases {
|
|
t.Run(testCase.name, func(t *testing.T) {
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
produceAttestationDataResponseJson := rpcmiddleware.ProduceAttestationDataResponseJson{}
|
|
jsonRestHandler := mock.NewMockjsonRestHandler(ctrl)
|
|
jsonRestHandler.EXPECT().GetRestJsonResponse(
|
|
ctx,
|
|
"/eth/v1/validator/attestation_data?committee_index=2&slot=1",
|
|
&produceAttestationDataResponseJson,
|
|
).Return(
|
|
nil,
|
|
nil,
|
|
).SetArg(
|
|
2,
|
|
testCase.generateData(),
|
|
).Times(1)
|
|
|
|
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
|
|
_, err := validatorClient.getAttestationData(ctx, 1, 2)
|
|
assert.ErrorContains(t, testCase.expectedErrorMessage, err)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetAttestationData_JsonResponseError(t *testing.T) {
|
|
const slot = types.Slot(1)
|
|
const committeeIndex = types.CommitteeIndex(2)
|
|
|
|
ctx := context.Background()
|
|
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
jsonRestHandler := mock.NewMockjsonRestHandler(ctrl)
|
|
produceAttestationDataResponseJson := rpcmiddleware.ProduceAttestationDataResponseJson{}
|
|
jsonRestHandler.EXPECT().GetRestJsonResponse(
|
|
ctx,
|
|
fmt.Sprintf("/eth/v1/validator/attestation_data?committee_index=%d&slot=%d", committeeIndex, slot),
|
|
&produceAttestationDataResponseJson,
|
|
).Return(
|
|
nil,
|
|
errors.New("some specific json response error"),
|
|
).Times(1)
|
|
|
|
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
|
|
_, err := validatorClient.getAttestationData(ctx, slot, committeeIndex)
|
|
assert.ErrorContains(t, "failed to get json response", err)
|
|
assert.ErrorContains(t, "some specific json response error", err)
|
|
}
|
|
|
|
func generateValidAttestation(slot uint64, committeeIndex uint64) rpcmiddleware.ProduceAttestationDataResponseJson {
|
|
return rpcmiddleware.ProduceAttestationDataResponseJson{
|
|
Data: &rpcmiddleware.AttestationDataJson{
|
|
Slot: strconv.FormatUint(slot, 10),
|
|
CommitteeIndex: strconv.FormatUint(committeeIndex, 10),
|
|
BeaconBlockRoot: "0x5ecf3bff35e39d5f75476d42950d549f81fa93038c46b6652ae89ae1f7ad834f",
|
|
Source: &rpcmiddleware.CheckpointJson{
|
|
Epoch: "3",
|
|
Root: "0x9023c9e64f23c1d451d5073c641f5f69597c2ad7d82f6f16e67d703e0ce5db8b",
|
|
},
|
|
Target: &rpcmiddleware.CheckpointJson{
|
|
Epoch: "4",
|
|
Root: "0xb154d46803b15b458ca822466547b054bc124338c6ee1d9c433dcde8c4457cca",
|
|
},
|
|
},
|
|
}
|
|
}
|