package beacon_api import ( "bytes" "context" "encoding/json" "testing" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/golang/mock/gomock" "github.com/pkg/errors" "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 proposeExitTestEndpoint = "/eth/v1/beacon/pool/voluntary_exits" func TestProposeExit_Valid(t *testing.T) { const signature = "0xd0a030a1d6b4f8217062ccc98088fbd908797f107aaa825f2366f090445fa79a6417789aa1d232c4f9b1e56671165bde25eb5586f94fc5677df593b99369684e8f413b1bfbd3fa6f20615244f9381895c71d4f7136c528092a3d03294a98be2d" ctrl := gomock.NewController(t) defer ctrl.Finish() jsonSignedVoluntaryExit := apimiddleware.SignedVoluntaryExitJson{ Exit: &apimiddleware.VoluntaryExitJson{ Epoch: "1", ValidatorIndex: "2", }, Signature: signature, } marshalledVoluntaryExit, err := json.Marshal(jsonSignedVoluntaryExit) require.NoError(t, err) ctx := context.Background() jsonRestHandler := mock.NewMockjsonRestHandler(ctrl) jsonRestHandler.EXPECT().PostRestJson( ctx, proposeExitTestEndpoint, nil, bytes.NewBuffer(marshalledVoluntaryExit), nil, ).Return( nil, nil, ).Times(1) decodedSignature, err := hexutil.Decode(signature) require.NoError(t, err) protoSignedVoluntaryExit := ðpb.SignedVoluntaryExit{ Exit: ðpb.VoluntaryExit{ Epoch: 1, ValidatorIndex: 2, }, Signature: decodedSignature, } expectedExitRoot, err := protoSignedVoluntaryExit.Exit.HashTreeRoot() require.NoError(t, err) validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} exitResponse, err := validatorClient.proposeExit(ctx, protoSignedVoluntaryExit) require.NoError(t, err) assert.DeepEqual(t, expectedExitRoot[:], exitResponse.ExitRoot) } func TestProposeExit_NilSignedVoluntaryExit(t *testing.T) { validatorClient := &beaconApiValidatorClient{} _, err := validatorClient.proposeExit(context.Background(), nil) assert.ErrorContains(t, "signed voluntary exit is nil", err) } func TestProposeExit_NilExit(t *testing.T) { validatorClient := &beaconApiValidatorClient{} _, err := validatorClient.proposeExit(context.Background(), ðpb.SignedVoluntaryExit{}) assert.ErrorContains(t, "exit is nil", err) } func TestProposeExit_BadRequest(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() ctx := context.Background() jsonRestHandler := mock.NewMockjsonRestHandler(ctrl) jsonRestHandler.EXPECT().PostRestJson( ctx, proposeExitTestEndpoint, nil, gomock.Any(), nil, ).Return( nil, errors.New("foo error"), ).Times(1) protoSignedVoluntaryExit := ðpb.SignedVoluntaryExit{ Exit: ðpb.VoluntaryExit{ Epoch: 1, ValidatorIndex: 2, }, Signature: []byte{3}, } validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} _, err := validatorClient.proposeExit(ctx, protoSignedVoluntaryExit) assert.ErrorContains(t, "failed to send POST data to REST endpoint", err) assert.ErrorContains(t, "foo error", err) }