Skip to content

Commit

Permalink
Add (lack of) REST implementation for GetFeeRecipientByPubKey (#11991)
Browse files Browse the repository at this point in the history
Co-authored-by: james-prysm <90280386+james-prysm@users.noreply.github.com>
  • Loading branch information
nalepae and james-prysm authored Feb 24, 2023
1 parent 8918e8c commit 08ebc99
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 104 deletions.
9 changes: 2 additions & 7 deletions validator/client/beacon-api/beacon_api_validator_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,8 @@ func (c *beaconApiValidatorClient) GetBeaconBlock(ctx context.Context, in *ethpb
return c.getBeaconBlock(ctx, in.Slot, in.RandaoReveal, in.Graffiti)
}

func (c *beaconApiValidatorClient) GetFeeRecipientByPubKey(ctx context.Context, in *ethpb.FeeRecipientByPubKeyRequest) (*ethpb.FeeRecipientByPubKeyResponse, error) {
if c.fallbackClient != nil {
return c.fallbackClient.GetFeeRecipientByPubKey(ctx, in)
}

// TODO: Implement me
panic("beaconApiValidatorClient.GetFeeRecipientByPubKey is not implemented. To use a fallback client, create this validator with NewBeaconApiValidatorClientWithFallback instead.")
func (c *beaconApiValidatorClient) GetFeeRecipientByPubKey(_ context.Context, _ *ethpb.FeeRecipientByPubKeyRequest) (*ethpb.FeeRecipientByPubKeyResponse, error) {
return nil, nil
}

func (c *beaconApiValidatorClient) GetSyncCommitteeContribution(ctx context.Context, in *ethpb.SyncCommitteeContributionRequest) (*ethpb.SyncCommitteeContribution, error) {
Expand Down
11 changes: 11 additions & 0 deletions validator/client/beacon-api/beacon_api_validator_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
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"
)

Expand Down Expand Up @@ -95,6 +96,16 @@ func TestBeaconApiValidatorClient_GetAttestationDataError(t *testing.T) {
assert.DeepEqual(t, expectedResp, resp)
}

func TestBeaconApiValidatorClient_GetFeeRecipientByPubKey(t *testing.T) {
ctx := context.Background()
validatorClient := beaconApiValidatorClient{}
var expected *ethpb.FeeRecipientByPubKeyResponse = nil

resp, err := validatorClient.GetFeeRecipientByPubKey(ctx, nil)
require.NoError(t, err)
require.Equal(t, expected, resp)
}

func TestBeaconApiValidatorClient_DomainDataValid(t *testing.T) {
const genesisValidatorRoot = "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
epoch := params.BeaconConfig().AltairForkEpoch
Expand Down
39 changes: 20 additions & 19 deletions validator/rpc/standard_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -535,27 +535,15 @@ func (s *Server) ListFeeRecipientByPubkey(ctx context.Context, req *ethpbservice

finalResp := &ethpbservice.GetFeeRecipientByPubkeyResponse{
Data: &ethpbservice.GetFeeRecipientByPubkeyResponse_FeeRecipient{
Pubkey: validatorKey,
Ethaddress: params.BeaconConfig().DefaultFeeRecipient.Bytes(),
Pubkey: validatorKey,
},
}

// If no proposer settings is set, use beacon node default (if possible)
if s.validatorService.ProposerSettings() == nil {
resp, err := s.beaconNodeValidatorClient.GetFeeRecipientByPubKey(ctx, &eth.FeeRecipientByPubKeyRequest{
PublicKey: validatorKey,
})

if resp != nil && len(resp.FeeRecipient) != 0 && err == nil {
finalResp.Data.Ethaddress = resp.FeeRecipient
}

return finalResp, nil
}
proposerSettings := s.validatorService.ProposerSettings()

// If fee recipient is defined for this specific pubkey in proposer configuration, use it
if s.validatorService.ProposerSettings().ProposeConfig != nil {
proposerOption, found := s.validatorService.ProposerSettings().ProposeConfig[bytesutil.ToBytes48(validatorKey)]
if proposerSettings != nil && proposerSettings.ProposeConfig != nil {
proposerOption, found := proposerSettings.ProposeConfig[bytesutil.ToBytes48(validatorKey)]

if found && proposerOption.FeeRecipientConfig != nil {
finalResp.Data.Ethaddress = proposerOption.FeeRecipientConfig.FeeRecipient.Bytes()
Expand All @@ -564,13 +552,26 @@ func (s *Server) ListFeeRecipientByPubkey(ctx context.Context, req *ethpbservice
}

// If fee recipient is defined in default configuration, use it
if s.validatorService.ProposerSettings().DefaultConfig != nil && s.validatorService.ProposerSettings().DefaultConfig.FeeRecipientConfig != nil {
if proposerSettings != nil && proposerSettings.DefaultConfig != nil && proposerSettings.DefaultConfig.FeeRecipientConfig != nil {
finalResp.Data.Ethaddress = s.validatorService.ProposerSettings().DefaultConfig.FeeRecipientConfig.FeeRecipient.Bytes()
return finalResp, nil
}

// Default case
return finalResp, nil
// Else, use the one defined in beacon node
resp, err := s.beaconNodeValidatorClient.GetFeeRecipientByPubKey(ctx, &eth.FeeRecipientByPubKeyRequest{
PublicKey: validatorKey,
})

if err != nil {
return nil, status.Error(codes.Internal, "Failed to retrieve default fee recipient from beacon node")
}

if resp != nil && len(resp.FeeRecipient) != 0 {
finalResp.Data.Ethaddress = resp.FeeRecipient
return finalResp, nil
}

return nil, status.Error(codes.InvalidArgument, "No fee recipient set")
}

// SetFeeRecipientByPubkey updates the eth address mapped to the public key.
Expand Down
138 changes: 60 additions & 78 deletions validator/rpc/standard_api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"testing"

Expand All @@ -13,7 +14,6 @@ import (
"github.com/golang/protobuf/ptypes/empty"
"github.com/google/uuid"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"github.com/pkg/errors"
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
"github.com/prysmaticlabs/prysm/v3/config/params"
validatorserviceconfig "github.com/prysmaticlabs/prysm/v3/config/validator/service"
Expand Down Expand Up @@ -705,34 +705,13 @@ func TestServer_ListFeeRecipientByPubkey(t *testing.T) {
}

tests := []struct {
name string
args *validatorserviceconfig.ProposerSettings
want *want
cached *eth.FeeRecipientByPubKeyResponse
wantErr bool
name string
args *validatorserviceconfig.ProposerSettings
want *want
cached *eth.FeeRecipientByPubKeyResponse
}{
{
name: "ProposerSettings is nil",
args: nil,
want: &want{
EthAddress: "0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9",
},
cached: &eth.FeeRecipientByPubKeyResponse{
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9").Bytes(),
},
wantErr: false,
},
{
name: "ProposerSettings is nil - Beacon node error",
args: nil,
want: &want{
EthAddress: "0x0000000000000000000000000000000000000000",
},
cached: nil,
wantErr: true,
},
{
name: "ProposerSettings.ProposeConfig.FeeRecipientConfig defined for pubkey",
name: "ProposerSettings.ProposeConfig.FeeRecipientConfig defined for pubkey (and ProposerSettings.DefaultConfig.FeeRecipientConfig defined)",
args: &validatorserviceconfig.ProposerSettings{
ProposeConfig: map[[48]byte]*validatorserviceconfig.ProposerOption{
bytesutil.ToBytes48(byteval): {
Expand All @@ -750,7 +729,6 @@ func TestServer_ListFeeRecipientByPubkey(t *testing.T) {
want: &want{
EthAddress: "0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9",
},
wantErr: false,
},
{
name: "ProposerSettings.ProposeConfig.FeeRecipientConfig NOT defined for pubkey and ProposerSettings.DefaultConfig.FeeRecipientConfig defined",
Expand All @@ -765,56 +743,16 @@ func TestServer_ListFeeRecipientByPubkey(t *testing.T) {
want: &want{
EthAddress: "0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9",
},
wantErr: false,
},
{
name: "ProposerSettings.ProposeConfig.FeeRecipientConfig NOT defined for pubkey and ProposerSettings.DefaultConfig is nil",
args: &validatorserviceconfig.ProposerSettings{
ProposeConfig: map[[48]byte]*validatorserviceconfig.ProposerOption{},
DefaultConfig: nil,
},
want: &want{
EthAddress: "0x0000000000000000000000000000000000000000",
},
wantErr: false,
},
{
name: "ProposerSettings.ProposeConfig is nil and ProposerSettings.DefaultConfig is nil",
args: &validatorserviceconfig.ProposerSettings{
ProposeConfig: nil,
DefaultConfig: nil,
},
want: &want{
EthAddress: "0x0000000000000000000000000000000000000000",
},
wantErr: false,
},
{
name: "ProposerSettings.ProposeConfig is nil and ProposerSettings.DefaultConfig.FeeRecipientConfig is nil",
args: &validatorserviceconfig.ProposerSettings{
ProposeConfig: nil,
DefaultConfig: &validatorserviceconfig.ProposerOption{
FeeRecipientConfig: nil,
},
},
want: &want{
EthAddress: "0x0000000000000000000000000000000000000000",
},
wantErr: false,
},
{
name: "ProposerSettings.ProposerConfig.FeeRecipientConfig NOT defined for pubkey, ProposerSettings.DefaultConfig.FeeRecipientConfig defined",
args: &validatorserviceconfig.ProposerSettings{
DefaultConfig: &validatorserviceconfig.ProposerOption{
FeeRecipientConfig: &validatorserviceconfig.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9"),
},
},
},
name: "ProposerSettings is nil and beacon node response is correct",
args: nil,
want: &want{
EthAddress: "0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9",
},
wantErr: false,
cached: &eth.FeeRecipientByPubKeyResponse{
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455012BFEBf6177F1D2e9738D9").Bytes(),
},
},
}
for _, tt := range tests {
Expand All @@ -826,11 +764,7 @@ func TestServer_ListFeeRecipientByPubkey(t *testing.T) {
m.SetProposerSettings(tt.args)

if tt.args == nil {
var err error = nil
if tt.wantErr {
err = errors.New("custom error")
}
mockValidatorClient.EXPECT().GetFeeRecipientByPubKey(gomock.Any(), gomock.Any()).Return(tt.cached, err)
mockValidatorClient.EXPECT().GetFeeRecipientByPubKey(gomock.Any(), gomock.Any()).Return(tt.cached, nil)
}

vs, err := client.NewValidatorService(ctx, &client.Config{
Expand All @@ -851,6 +785,54 @@ func TestServer_ListFeeRecipientByPubkey(t *testing.T) {
}
}

func TestServer_ListFeeRecipientByPubKey_BeaconNodeError(t *testing.T) {
ctx := context.Background()
byteval, err := hexutil.Decode("0xaf2e7ba294e03438ea819bd4033c6c1bf6b04320ee2075b77273c08d02f8a61bcc303c2c06bd3713cb442072ae591493")
require.NoError(t, err)

ctrl := gomock.NewController(t)
mockValidatorClient := mock2.NewMockValidatorClient(ctrl)

mockValidatorClient.EXPECT().GetFeeRecipientByPubKey(gomock.Any(), gomock.Any()).Return(nil, errors.New("custom error"))

vs, err := client.NewValidatorService(ctx, &client.Config{
Validator: &mock.MockValidator{},
})
require.NoError(t, err)

s := &Server{
validatorService: vs,
beaconNodeValidatorClient: mockValidatorClient,
}

_, err = s.ListFeeRecipientByPubkey(ctx, &ethpbservice.PubkeyRequest{Pubkey: byteval})
require.ErrorContains(t, "Failed to retrieve default fee recipient from beacon node", err)
}

func TestServer_ListFeeRecipientByPubKey_NoFeeRecipientSet(t *testing.T) {
ctx := context.Background()
byteval, err := hexutil.Decode("0xaf2e7ba294e03438ea819bd4033c6c1bf6b04320ee2075b77273c08d02f8a61bcc303c2c06bd3713cb442072ae591493")
require.NoError(t, err)

ctrl := gomock.NewController(t)
mockValidatorClient := mock2.NewMockValidatorClient(ctrl)

mockValidatorClient.EXPECT().GetFeeRecipientByPubKey(gomock.Any(), gomock.Any()).Return(nil, nil)

vs, err := client.NewValidatorService(ctx, &client.Config{
Validator: &mock.MockValidator{},
})
require.NoError(t, err)

s := &Server{
validatorService: vs,
beaconNodeValidatorClient: mockValidatorClient,
}

_, err = s.ListFeeRecipientByPubkey(ctx, &ethpbservice.PubkeyRequest{Pubkey: byteval})
require.ErrorContains(t, "No fee recipient set", err)
}

func TestServer_ListFeeRecipientByPubkey_ValidatorServiceNil(t *testing.T) {
ctx := grpc.NewContextWithServerTransportStream(context.Background(), &runtime.ServerTransportStream{})

Expand Down

0 comments on commit 08ebc99

Please sign in to comment.