github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/rpc/prysm/v1alpha1/beacon/validators_test.go (about)

     1  package beacon
     2  
     3  import (
     4  	"context"
     5  	"encoding/binary"
     6  	"fmt"
     7  	"sort"
     8  	"strconv"
     9  	"testing"
    10  	"time"
    11  
    12  	types "github.com/prysmaticlabs/eth2-types"
    13  	"github.com/prysmaticlabs/go-bitfield"
    14  	mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
    15  	"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
    16  	"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
    17  	"github.com/prysmaticlabs/prysm/beacon-chain/db"
    18  	dbTest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
    19  	iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
    20  	"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
    21  	"github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
    22  	mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing"
    23  	pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
    24  	ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
    25  	"github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper"
    26  	"github.com/prysmaticlabs/prysm/shared/bytesutil"
    27  	"github.com/prysmaticlabs/prysm/shared/cmd"
    28  	"github.com/prysmaticlabs/prysm/shared/params"
    29  	"github.com/prysmaticlabs/prysm/shared/testutil"
    30  	"github.com/prysmaticlabs/prysm/shared/testutil/assert"
    31  	"github.com/prysmaticlabs/prysm/shared/testutil/require"
    32  	"github.com/prysmaticlabs/prysm/shared/timeutils"
    33  	"google.golang.org/protobuf/proto"
    34  	"google.golang.org/protobuf/types/known/emptypb"
    35  )
    36  
    37  const (
    38  	errNoEpochInfoError = "Cannot retrieve information about an epoch in the future"
    39  )
    40  
    41  func TestServer_GetValidatorActiveSetChanges_CannotRequestFutureEpoch(t *testing.T) {
    42  	beaconDB := dbTest.SetupDB(t)
    43  	ctx := context.Background()
    44  	st, err := testutil.NewBeaconState()
    45  	require.NoError(t, err)
    46  	require.NoError(t, st.SetSlot(0))
    47  	bs := &Server{
    48  		GenesisTimeFetcher: &mock.ChainService{},
    49  		HeadFetcher: &mock.ChainService{
    50  			State: st,
    51  		},
    52  		BeaconDB: beaconDB,
    53  	}
    54  
    55  	wanted := errNoEpochInfoError
    56  	_, err = bs.GetValidatorActiveSetChanges(
    57  		ctx,
    58  		&ethpb.GetValidatorActiveSetChangesRequest{
    59  			QueryFilter: &ethpb.GetValidatorActiveSetChangesRequest_Epoch{
    60  				Epoch: helpers.SlotToEpoch(bs.GenesisTimeFetcher.CurrentSlot()) + 1,
    61  			},
    62  		},
    63  	)
    64  	assert.ErrorContains(t, wanted, err)
    65  }
    66  
    67  func TestServer_ListValidatorBalances_CannotRequestFutureEpoch(t *testing.T) {
    68  	beaconDB := dbTest.SetupDB(t)
    69  	ctx := context.Background()
    70  
    71  	st, err := testutil.NewBeaconState()
    72  	require.NoError(t, err)
    73  	require.NoError(t, st.SetSlot(0))
    74  	bs := &Server{
    75  		BeaconDB: beaconDB,
    76  		HeadFetcher: &mock.ChainService{
    77  			State: st,
    78  		},
    79  		GenesisTimeFetcher: &mock.ChainService{},
    80  	}
    81  
    82  	wanted := errNoEpochInfoError
    83  	_, err = bs.ListValidatorBalances(
    84  		ctx,
    85  		&ethpb.ListValidatorBalancesRequest{
    86  			QueryFilter: &ethpb.ListValidatorBalancesRequest_Epoch{
    87  				Epoch: helpers.SlotToEpoch(bs.GenesisTimeFetcher.CurrentSlot()) + 1,
    88  			},
    89  		},
    90  	)
    91  	assert.ErrorContains(t, wanted, err)
    92  }
    93  
    94  func TestServer_ListValidatorBalances_NoResults(t *testing.T) {
    95  	beaconDB := dbTest.SetupDB(t)
    96  
    97  	ctx := context.Background()
    98  	st, err := testutil.NewBeaconState()
    99  	require.NoError(t, err)
   100  	require.NoError(t, st.SetSlot(0))
   101  	bs := &Server{
   102  		GenesisTimeFetcher: &mock.ChainService{},
   103  		StateGen:           stategen.New(beaconDB),
   104  	}
   105  
   106  	headState, err := testutil.NewBeaconState()
   107  	require.NoError(t, err)
   108  	b := testutil.NewBeaconBlock()
   109  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b)))
   110  	gRoot, err := b.Block.HashTreeRoot()
   111  	require.NoError(t, err)
   112  	require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
   113  	require.NoError(t, beaconDB.SaveState(ctx, headState, gRoot))
   114  
   115  	wanted := &ethpb.ValidatorBalances{
   116  		Balances:      make([]*ethpb.ValidatorBalances_Balance, 0),
   117  		TotalSize:     int32(0),
   118  		NextPageToken: strconv.Itoa(0),
   119  	}
   120  	res, err := bs.ListValidatorBalances(
   121  		ctx,
   122  		&ethpb.ListValidatorBalancesRequest{
   123  			QueryFilter: &ethpb.ListValidatorBalancesRequest_Epoch{
   124  				Epoch: 0,
   125  			},
   126  		},
   127  	)
   128  	require.NoError(t, err)
   129  	if !proto.Equal(wanted, res) {
   130  		t.Errorf("Wanted %v, received %v", wanted, res)
   131  	}
   132  }
   133  
   134  func TestServer_ListValidatorBalances_DefaultResponse_NoArchive(t *testing.T) {
   135  	beaconDB := dbTest.SetupDB(t)
   136  	ctx := context.Background()
   137  
   138  	numItems := 100
   139  	validators := make([]*ethpb.Validator, numItems)
   140  	balances := make([]uint64, numItems)
   141  	balancesResponse := make([]*ethpb.ValidatorBalances_Balance, numItems)
   142  	for i := 0; i < numItems; i++ {
   143  		validators[i] = &ethpb.Validator{
   144  			PublicKey:             pubKey(uint64(i)),
   145  			WithdrawalCredentials: make([]byte, 32),
   146  		}
   147  		balances[i] = params.BeaconConfig().MaxEffectiveBalance
   148  		balancesResponse[i] = &ethpb.ValidatorBalances_Balance{
   149  			PublicKey: pubKey(uint64(i)),
   150  			Index:     types.ValidatorIndex(i),
   151  			Balance:   params.BeaconConfig().MaxEffectiveBalance,
   152  			Status:    "EXITED",
   153  		}
   154  	}
   155  	st, err := testutil.NewBeaconState()
   156  	require.NoError(t, err)
   157  	require.NoError(t, st.SetSlot(0))
   158  	require.NoError(t, st.SetValidators(validators))
   159  	require.NoError(t, st.SetBalances(balances))
   160  	b := testutil.NewBeaconBlock()
   161  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b)))
   162  	gRoot, err := b.Block.HashTreeRoot()
   163  	require.NoError(t, err)
   164  	require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
   165  	require.NoError(t, beaconDB.SaveState(ctx, st, gRoot))
   166  	bs := &Server{
   167  		GenesisTimeFetcher: &mock.ChainService{},
   168  		StateGen:           stategen.New(beaconDB),
   169  		HeadFetcher: &mock.ChainService{
   170  			State: st,
   171  		},
   172  	}
   173  	res, err := bs.ListValidatorBalances(
   174  		ctx,
   175  		&ethpb.ListValidatorBalancesRequest{
   176  			QueryFilter: &ethpb.ListValidatorBalancesRequest_Epoch{Epoch: 0},
   177  		},
   178  	)
   179  	require.NoError(t, err)
   180  	assert.DeepEqual(t, balancesResponse, res.Balances)
   181  }
   182  
   183  func TestServer_ListValidatorBalances_PaginationOutOfRange(t *testing.T) {
   184  	beaconDB := dbTest.SetupDB(t)
   185  	ctx := context.Background()
   186  
   187  	_, _, headState := setupValidators(t, beaconDB, 100)
   188  	b := testutil.NewBeaconBlock()
   189  	gRoot, err := b.Block.HashTreeRoot()
   190  	require.NoError(t, err)
   191  	require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
   192  	require.NoError(t, beaconDB.SaveState(ctx, headState, gRoot))
   193  
   194  	bs := &Server{
   195  		GenesisTimeFetcher: &mock.ChainService{},
   196  		StateGen:           stategen.New(beaconDB),
   197  		HeadFetcher: &mock.ChainService{
   198  			State: headState,
   199  		},
   200  	}
   201  
   202  	wanted := fmt.Sprintf("page start %d >= list %d", 200, len(headState.Balances()))
   203  	_, err = bs.ListValidatorBalances(context.Background(), &ethpb.ListValidatorBalancesRequest{
   204  		PageToken:   strconv.Itoa(2),
   205  		PageSize:    100,
   206  		QueryFilter: &ethpb.ListValidatorBalancesRequest_Epoch{Epoch: 0},
   207  	})
   208  	assert.ErrorContains(t, wanted, err)
   209  }
   210  
   211  func TestServer_ListValidatorBalances_ExceedsMaxPageSize(t *testing.T) {
   212  	bs := &Server{}
   213  	exceedsMax := int32(cmd.Get().MaxRPCPageSize + 1)
   214  
   215  	wanted := fmt.Sprintf(
   216  		"Requested page size %d can not be greater than max size %d",
   217  		exceedsMax,
   218  		cmd.Get().MaxRPCPageSize,
   219  	)
   220  	req := &ethpb.ListValidatorBalancesRequest{PageSize: exceedsMax}
   221  	_, err := bs.ListValidatorBalances(context.Background(), req)
   222  	assert.ErrorContains(t, wanted, err)
   223  }
   224  
   225  func pubKey(i uint64) []byte {
   226  	pubKey := make([]byte, params.BeaconConfig().BLSPubkeyLength)
   227  	binary.LittleEndian.PutUint64(pubKey, i)
   228  	return pubKey
   229  }
   230  
   231  func TestServer_ListValidatorBalances_Pagination_Default(t *testing.T) {
   232  	beaconDB := dbTest.SetupDB(t)
   233  	ctx := context.Background()
   234  
   235  	_, _, headState := setupValidators(t, beaconDB, 100)
   236  	b := testutil.NewBeaconBlock()
   237  	gRoot, err := b.Block.HashTreeRoot()
   238  	require.NoError(t, err)
   239  	require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
   240  	require.NoError(t, beaconDB.SaveState(ctx, headState, gRoot))
   241  
   242  	bs := &Server{
   243  		GenesisTimeFetcher: &mock.ChainService{},
   244  		StateGen:           stategen.New(beaconDB),
   245  		HeadFetcher: &mock.ChainService{
   246  			State: headState,
   247  		},
   248  	}
   249  
   250  	tests := []struct {
   251  		req *ethpb.ListValidatorBalancesRequest
   252  		res *ethpb.ValidatorBalances
   253  	}{
   254  		{req: &ethpb.ListValidatorBalancesRequest{PublicKeys: [][]byte{pubKey(99)}, QueryFilter: &ethpb.ListValidatorBalancesRequest_Epoch{Epoch: 0}},
   255  			res: &ethpb.ValidatorBalances{
   256  				Balances: []*ethpb.ValidatorBalances_Balance{
   257  					{Index: 99, PublicKey: pubKey(99), Balance: 99, Status: "EXITED"},
   258  				},
   259  				NextPageToken: "",
   260  				TotalSize:     1,
   261  			},
   262  		},
   263  		{req: &ethpb.ListValidatorBalancesRequest{Indices: []types.ValidatorIndex{1, 2, 3}, QueryFilter: &ethpb.ListValidatorBalancesRequest_Epoch{Epoch: 0}},
   264  			res: &ethpb.ValidatorBalances{
   265  				Balances: []*ethpb.ValidatorBalances_Balance{
   266  					{Index: 1, PublicKey: pubKey(1), Balance: 1, Status: "EXITED"},
   267  					{Index: 2, PublicKey: pubKey(2), Balance: 2, Status: "EXITED"},
   268  					{Index: 3, PublicKey: pubKey(3), Balance: 3, Status: "EXITED"},
   269  				},
   270  				NextPageToken: "",
   271  				TotalSize:     3,
   272  			},
   273  		},
   274  		{req: &ethpb.ListValidatorBalancesRequest{PublicKeys: [][]byte{pubKey(10), pubKey(11), pubKey(12)}, QueryFilter: &ethpb.ListValidatorBalancesRequest_Epoch{Epoch: 0}},
   275  			res: &ethpb.ValidatorBalances{
   276  				Balances: []*ethpb.ValidatorBalances_Balance{
   277  					{Index: 10, PublicKey: pubKey(10), Balance: 10, Status: "EXITED"},
   278  					{Index: 11, PublicKey: pubKey(11), Balance: 11, Status: "EXITED"},
   279  					{Index: 12, PublicKey: pubKey(12), Balance: 12, Status: "EXITED"},
   280  				},
   281  				NextPageToken: "",
   282  				TotalSize:     3,
   283  			}},
   284  		{req: &ethpb.ListValidatorBalancesRequest{PublicKeys: [][]byte{pubKey(2), pubKey(3)}, Indices: []types.ValidatorIndex{3, 4}, QueryFilter: &ethpb.ListValidatorBalancesRequest_Epoch{Epoch: 0}}, // Duplication
   285  			res: &ethpb.ValidatorBalances{
   286  				Balances: []*ethpb.ValidatorBalances_Balance{
   287  					{Index: 2, PublicKey: pubKey(2), Balance: 2, Status: "EXITED"},
   288  					{Index: 3, PublicKey: pubKey(3), Balance: 3, Status: "EXITED"},
   289  					{Index: 4, PublicKey: pubKey(4), Balance: 4, Status: "EXITED"},
   290  				},
   291  				NextPageToken: "",
   292  				TotalSize:     3,
   293  			}},
   294  		{req: &ethpb.ListValidatorBalancesRequest{PublicKeys: [][]byte{{}}, Indices: []types.ValidatorIndex{3, 4}, QueryFilter: &ethpb.ListValidatorBalancesRequest_Epoch{Epoch: 0}}, // Public key has a blank value
   295  			res: &ethpb.ValidatorBalances{
   296  				Balances: []*ethpb.ValidatorBalances_Balance{
   297  					{Index: 3, PublicKey: pubKey(3), Balance: 3, Status: "EXITED"},
   298  					{Index: 4, PublicKey: pubKey(4), Balance: 4, Status: "EXITED"},
   299  				},
   300  				NextPageToken: "",
   301  				TotalSize:     2,
   302  			}},
   303  	}
   304  	for _, test := range tests {
   305  		res, err := bs.ListValidatorBalances(context.Background(), test.req)
   306  		require.NoError(t, err)
   307  		if !proto.Equal(res, test.res) {
   308  			t.Errorf("Expected %v, received %v", test.res, res)
   309  		}
   310  	}
   311  }
   312  
   313  func TestServer_ListValidatorBalances_Pagination_CustomPageSizes(t *testing.T) {
   314  	beaconDB := dbTest.SetupDB(t)
   315  	ctx := context.Background()
   316  
   317  	count := 1000
   318  	_, _, headState := setupValidators(t, beaconDB, count)
   319  	b := testutil.NewBeaconBlock()
   320  	gRoot, err := b.Block.HashTreeRoot()
   321  	require.NoError(t, err)
   322  	require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
   323  	require.NoError(t, beaconDB.SaveState(ctx, headState, gRoot))
   324  
   325  	bs := &Server{
   326  		GenesisTimeFetcher: &mock.ChainService{},
   327  		StateGen:           stategen.New(beaconDB),
   328  		HeadFetcher: &mock.ChainService{
   329  			State: headState,
   330  		},
   331  	}
   332  
   333  	tests := []struct {
   334  		req *ethpb.ListValidatorBalancesRequest
   335  		res *ethpb.ValidatorBalances
   336  	}{
   337  		{req: &ethpb.ListValidatorBalancesRequest{PageToken: strconv.Itoa(1), PageSize: 3, QueryFilter: &ethpb.ListValidatorBalancesRequest_Epoch{Epoch: 0}},
   338  			res: &ethpb.ValidatorBalances{
   339  				Balances: []*ethpb.ValidatorBalances_Balance{
   340  					{PublicKey: pubKey(3), Index: 3, Balance: uint64(3), Status: "EXITED"},
   341  					{PublicKey: pubKey(4), Index: 4, Balance: uint64(4), Status: "EXITED"},
   342  					{PublicKey: pubKey(5), Index: 5, Balance: uint64(5), Status: "EXITED"}},
   343  				NextPageToken: strconv.Itoa(2),
   344  				TotalSize:     int32(count)}},
   345  		{req: &ethpb.ListValidatorBalancesRequest{PageToken: strconv.Itoa(10), PageSize: 5, QueryFilter: &ethpb.ListValidatorBalancesRequest_Epoch{Epoch: 0}},
   346  			res: &ethpb.ValidatorBalances{
   347  				Balances: []*ethpb.ValidatorBalances_Balance{
   348  					{PublicKey: pubKey(50), Index: 50, Balance: uint64(50), Status: "EXITED"},
   349  					{PublicKey: pubKey(51), Index: 51, Balance: uint64(51), Status: "EXITED"},
   350  					{PublicKey: pubKey(52), Index: 52, Balance: uint64(52), Status: "EXITED"},
   351  					{PublicKey: pubKey(53), Index: 53, Balance: uint64(53), Status: "EXITED"},
   352  					{PublicKey: pubKey(54), Index: 54, Balance: uint64(54), Status: "EXITED"}},
   353  				NextPageToken: strconv.Itoa(11),
   354  				TotalSize:     int32(count)}},
   355  		{req: &ethpb.ListValidatorBalancesRequest{PageToken: strconv.Itoa(33), PageSize: 3, QueryFilter: &ethpb.ListValidatorBalancesRequest_Epoch{Epoch: 0}},
   356  			res: &ethpb.ValidatorBalances{
   357  				Balances: []*ethpb.ValidatorBalances_Balance{
   358  					{PublicKey: pubKey(99), Index: 99, Balance: uint64(99), Status: "EXITED"},
   359  					{PublicKey: pubKey(100), Index: 100, Balance: uint64(100), Status: "EXITED"},
   360  					{PublicKey: pubKey(101), Index: 101, Balance: uint64(101), Status: "EXITED"},
   361  				},
   362  				NextPageToken: "34",
   363  				TotalSize:     int32(count)}},
   364  		{req: &ethpb.ListValidatorBalancesRequest{PageSize: 2, QueryFilter: &ethpb.ListValidatorBalancesRequest_Epoch{Epoch: 0}},
   365  			res: &ethpb.ValidatorBalances{
   366  				Balances: []*ethpb.ValidatorBalances_Balance{
   367  					{PublicKey: pubKey(0), Index: 0, Balance: uint64(0), Status: "EXITED"},
   368  					{PublicKey: pubKey(1), Index: 1, Balance: uint64(1), Status: "EXITED"}},
   369  				NextPageToken: strconv.Itoa(1),
   370  				TotalSize:     int32(count)}},
   371  	}
   372  	for _, test := range tests {
   373  		res, err := bs.ListValidatorBalances(context.Background(), test.req)
   374  		require.NoError(t, err)
   375  		if !proto.Equal(res, test.res) {
   376  			t.Errorf("Expected %v, received %v", test.res, res)
   377  		}
   378  	}
   379  }
   380  
   381  func TestServer_ListValidatorBalances_OutOfRange(t *testing.T) {
   382  	beaconDB := dbTest.SetupDB(t)
   383  
   384  	ctx := context.Background()
   385  	_, _, headState := setupValidators(t, beaconDB, 1)
   386  	b := testutil.NewBeaconBlock()
   387  	gRoot, err := b.Block.HashTreeRoot()
   388  	require.NoError(t, err)
   389  	require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
   390  	require.NoError(t, beaconDB.SaveState(ctx, headState, gRoot))
   391  
   392  	bs := &Server{
   393  		GenesisTimeFetcher: &mock.ChainService{},
   394  		StateGen:           stategen.New(beaconDB),
   395  		HeadFetcher: &mock.ChainService{
   396  			State: headState,
   397  		},
   398  	}
   399  
   400  	req := &ethpb.ListValidatorBalancesRequest{Indices: []types.ValidatorIndex{types.ValidatorIndex(1)}, QueryFilter: &ethpb.ListValidatorBalancesRequest_Epoch{Epoch: 0}}
   401  	wanted := "Validator index 1 >= balance list 1"
   402  	_, err = bs.ListValidatorBalances(context.Background(), req)
   403  	assert.ErrorContains(t, wanted, err)
   404  }
   405  
   406  func TestServer_ListValidators_CannotRequestFutureEpoch(t *testing.T) {
   407  	beaconDB := dbTest.SetupDB(t)
   408  	ctx := context.Background()
   409  
   410  	st, err := testutil.NewBeaconState()
   411  	require.NoError(t, err)
   412  	require.NoError(t, st.SetSlot(0))
   413  	bs := &Server{
   414  		BeaconDB: beaconDB,
   415  		GenesisTimeFetcher: &mock.ChainService{
   416  			// We are in epoch 0.
   417  			Genesis: time.Now(),
   418  		},
   419  		HeadFetcher: &mock.ChainService{
   420  			State: st,
   421  		},
   422  	}
   423  
   424  	wanted := errNoEpochInfoError
   425  	_, err = bs.ListValidators(
   426  		ctx,
   427  		&ethpb.ListValidatorsRequest{
   428  			QueryFilter: &ethpb.ListValidatorsRequest_Epoch{
   429  				Epoch: 1,
   430  			},
   431  		},
   432  	)
   433  	assert.ErrorContains(t, wanted, err)
   434  }
   435  
   436  func TestServer_ListValidators_NoResults(t *testing.T) {
   437  	beaconDB := dbTest.SetupDB(t)
   438  
   439  	ctx := context.Background()
   440  	st, err := testutil.NewBeaconState()
   441  	require.NoError(t, err)
   442  	require.NoError(t, st.SetSlot(0))
   443  	gRoot := [32]byte{'g'}
   444  	require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
   445  	require.NoError(t, beaconDB.SaveState(ctx, st, gRoot))
   446  	bs := &Server{
   447  		BeaconDB: beaconDB,
   448  		GenesisTimeFetcher: &mock.ChainService{
   449  			// We are in epoch 0.
   450  			Genesis: time.Now(),
   451  		},
   452  		HeadFetcher: &mock.ChainService{
   453  			State: st,
   454  		},
   455  		StateGen: stategen.New(beaconDB),
   456  	}
   457  	wanted := &ethpb.Validators{
   458  		ValidatorList: make([]*ethpb.Validators_ValidatorContainer, 0),
   459  		TotalSize:     int32(0),
   460  		NextPageToken: strconv.Itoa(0),
   461  	}
   462  	res, err := bs.ListValidators(
   463  		ctx,
   464  		&ethpb.ListValidatorsRequest{
   465  			QueryFilter: &ethpb.ListValidatorsRequest_Epoch{
   466  				Epoch: 0,
   467  			},
   468  		},
   469  	)
   470  	require.NoError(t, err)
   471  	if !proto.Equal(wanted, res) {
   472  		t.Errorf("Wanted %v, received %v", wanted, res)
   473  	}
   474  }
   475  
   476  func TestServer_ListValidators_OnlyActiveValidators(t *testing.T) {
   477  	ctx := context.Background()
   478  	beaconDB := dbTest.SetupDB(t)
   479  	count := 100
   480  	balances := make([]uint64, count)
   481  	validators := make([]*ethpb.Validator, count)
   482  	activeValidators := make([]*ethpb.Validators_ValidatorContainer, 0)
   483  	for i := 0; i < count; i++ {
   484  		pubKey := pubKey(uint64(i))
   485  		balances[i] = params.BeaconConfig().MaxEffectiveBalance
   486  
   487  		// We mark even validators as active, and odd validators as inactive.
   488  		if i%2 == 0 {
   489  			val := &ethpb.Validator{
   490  				PublicKey:             pubKey,
   491  				WithdrawalCredentials: make([]byte, 32),
   492  				ActivationEpoch:       0,
   493  				ExitEpoch:             params.BeaconConfig().FarFutureEpoch,
   494  			}
   495  			validators[i] = val
   496  			activeValidators = append(activeValidators, &ethpb.Validators_ValidatorContainer{
   497  				Index:     types.ValidatorIndex(i),
   498  				Validator: val,
   499  			})
   500  		} else {
   501  			validators[i] = &ethpb.Validator{
   502  				PublicKey:             pubKey,
   503  				WithdrawalCredentials: make([]byte, 32),
   504  				ActivationEpoch:       0,
   505  				ExitEpoch:             0,
   506  			}
   507  		}
   508  	}
   509  	st, err := testutil.NewBeaconState()
   510  	require.NoError(t, err)
   511  	require.NoError(t, st.SetValidators(validators))
   512  	require.NoError(t, st.SetBalances(balances))
   513  
   514  	bs := &Server{
   515  		HeadFetcher: &mock.ChainService{
   516  			State: st,
   517  		},
   518  		GenesisTimeFetcher: &mock.ChainService{
   519  			// We are in epoch 0.
   520  			Genesis: time.Now(),
   521  		},
   522  		StateGen: stategen.New(beaconDB),
   523  	}
   524  
   525  	b := testutil.NewBeaconBlock()
   526  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b)))
   527  	gRoot, err := b.Block.HashTreeRoot()
   528  	require.NoError(t, err)
   529  	require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
   530  	require.NoError(t, beaconDB.SaveState(ctx, st, gRoot))
   531  
   532  	received, err := bs.ListValidators(ctx, &ethpb.ListValidatorsRequest{
   533  		Active: true,
   534  	})
   535  	require.NoError(t, err)
   536  	assert.DeepEqual(t, activeValidators, received.ValidatorList)
   537  }
   538  
   539  func TestServer_ListValidators_InactiveInTheMiddle(t *testing.T) {
   540  	ctx := context.Background()
   541  	beaconDB := dbTest.SetupDB(t)
   542  	count := 100
   543  	balances := make([]uint64, count)
   544  	validators := make([]*ethpb.Validator, count)
   545  	activeValidators := make([]*ethpb.Validators_ValidatorContainer, 0)
   546  	for i := 0; i < count; i++ {
   547  		pubKey := pubKey(uint64(i))
   548  		balances[i] = params.BeaconConfig().MaxEffectiveBalance
   549  
   550  		// We mark even validators as active, and odd validators as inactive.
   551  		if i%2 == 0 {
   552  			val := &ethpb.Validator{
   553  				PublicKey:             pubKey,
   554  				WithdrawalCredentials: make([]byte, 32),
   555  				ActivationEpoch:       0,
   556  				ExitEpoch:             params.BeaconConfig().FarFutureEpoch,
   557  			}
   558  			validators[i] = val
   559  			activeValidators = append(activeValidators, &ethpb.Validators_ValidatorContainer{
   560  				Index:     types.ValidatorIndex(i),
   561  				Validator: val,
   562  			})
   563  		} else {
   564  			validators[i] = &ethpb.Validator{
   565  				PublicKey:             pubKey,
   566  				WithdrawalCredentials: make([]byte, 32),
   567  				ActivationEpoch:       0,
   568  				ExitEpoch:             0,
   569  			}
   570  		}
   571  	}
   572  
   573  	// Set first validator to be inactive.
   574  	validators[0].ActivationEpoch = params.BeaconConfig().FarFutureEpoch
   575  	activeValidators[0].Validator.ActivationEpoch = params.BeaconConfig().FarFutureEpoch
   576  
   577  	st, err := testutil.NewBeaconState()
   578  	require.NoError(t, err)
   579  	require.NoError(t, st.SetValidators(validators))
   580  	require.NoError(t, st.SetBalances(balances))
   581  
   582  	bs := &Server{
   583  		HeadFetcher: &mock.ChainService{
   584  			State: st,
   585  		},
   586  		GenesisTimeFetcher: &mock.ChainService{
   587  			// We are in epoch 0.
   588  			Genesis: time.Now(),
   589  		},
   590  		StateGen: stategen.New(beaconDB),
   591  	}
   592  
   593  	b := testutil.NewBeaconBlock()
   594  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b)))
   595  	gRoot, err := b.Block.HashTreeRoot()
   596  	require.NoError(t, err)
   597  	require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
   598  	require.NoError(t, beaconDB.SaveState(ctx, st, gRoot))
   599  
   600  	received, err := bs.ListValidators(ctx, &ethpb.ListValidatorsRequest{
   601  		Active: true,
   602  	})
   603  	require.NoError(t, err)
   604  
   605  	require.Equal(t, count/2-1, len(received.ValidatorList))
   606  	require.Equal(t, count/2-1, int(received.TotalSize))
   607  }
   608  
   609  func TestServer_ListValidatorBalances_UnknownValidatorInResponse(t *testing.T) {
   610  	beaconDB := dbTest.SetupDB(t)
   611  	ctx := context.Background()
   612  
   613  	_, _, headState := setupValidators(t, beaconDB, 4)
   614  	b := testutil.NewBeaconBlock()
   615  	gRoot, err := b.Block.HashTreeRoot()
   616  	require.NoError(t, err)
   617  	require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
   618  	require.NoError(t, beaconDB.SaveState(ctx, headState, gRoot))
   619  
   620  	bs := &Server{
   621  		GenesisTimeFetcher: &mock.ChainService{},
   622  		StateGen:           stategen.New(beaconDB),
   623  		HeadFetcher: &mock.ChainService{
   624  			State: headState,
   625  		},
   626  	}
   627  
   628  	nonExistentPubKey := [32]byte{8}
   629  	req := &ethpb.ListValidatorBalancesRequest{
   630  		PublicKeys: [][]byte{
   631  			pubKey(1),
   632  			pubKey(2),
   633  			nonExistentPubKey[:],
   634  		},
   635  		QueryFilter: &ethpb.ListValidatorBalancesRequest_Epoch{Epoch: 0},
   636  	}
   637  
   638  	wanted := &ethpb.ValidatorBalances{
   639  		Balances: []*ethpb.ValidatorBalances_Balance{
   640  			{Status: "UNKNOWN"},
   641  			{Index: 1, PublicKey: pubKey(1), Balance: 1, Status: "EXITED"},
   642  			{Index: 2, PublicKey: pubKey(2), Balance: 2, Status: "EXITED"},
   643  		},
   644  		NextPageToken: "",
   645  		TotalSize:     3,
   646  	}
   647  	res, err := bs.ListValidatorBalances(context.Background(), req)
   648  	require.NoError(t, err)
   649  	if !proto.Equal(res, wanted) {
   650  		t.Errorf("Expected %v, received %v", wanted, res)
   651  	}
   652  }
   653  
   654  func TestServer_ListValidators_NoPagination(t *testing.T) {
   655  	beaconDB := dbTest.SetupDB(t)
   656  
   657  	validators, _, headState := setupValidators(t, beaconDB, 100)
   658  	want := make([]*ethpb.Validators_ValidatorContainer, len(validators))
   659  	for i := 0; i < len(validators); i++ {
   660  		want[i] = &ethpb.Validators_ValidatorContainer{
   661  			Index:     types.ValidatorIndex(i),
   662  			Validator: validators[i],
   663  		}
   664  	}
   665  
   666  	bs := &Server{
   667  		HeadFetcher: &mock.ChainService{
   668  			State: headState,
   669  		},
   670  		GenesisTimeFetcher: &mock.ChainService{
   671  			// We are in epoch 0.
   672  			Genesis: time.Now(),
   673  		},
   674  		FinalizationFetcher: &mock.ChainService{
   675  			FinalizedCheckPoint: &ethpb.Checkpoint{
   676  				Epoch: 0,
   677  			},
   678  		},
   679  		StateGen: stategen.New(beaconDB),
   680  	}
   681  
   682  	received, err := bs.ListValidators(context.Background(), &ethpb.ListValidatorsRequest{})
   683  	require.NoError(t, err)
   684  	assert.DeepSSZEqual(t, want, received.ValidatorList, "Incorrect respond of validators")
   685  }
   686  
   687  func TestServer_ListValidators_StategenNotUsed(t *testing.T) {
   688  	beaconDB := dbTest.SetupDB(t)
   689  
   690  	validators, _, headState := setupValidators(t, beaconDB, 100)
   691  	want := make([]*ethpb.Validators_ValidatorContainer, len(validators))
   692  	for i := 0; i < len(validators); i++ {
   693  		want[i] = &ethpb.Validators_ValidatorContainer{
   694  			Index:     types.ValidatorIndex(i),
   695  			Validator: validators[i],
   696  		}
   697  	}
   698  
   699  	bs := &Server{
   700  		HeadFetcher: &mock.ChainService{
   701  			State: headState,
   702  		},
   703  		GenesisTimeFetcher: &mock.ChainService{
   704  			// We are in epoch 0.
   705  			Genesis: time.Now(),
   706  		},
   707  	}
   708  
   709  	received, err := bs.ListValidators(context.Background(), &ethpb.ListValidatorsRequest{})
   710  	require.NoError(t, err)
   711  	assert.DeepEqual(t, want, received.ValidatorList, "Incorrect respond of validators")
   712  }
   713  
   714  func TestServer_ListValidators_IndicesPubKeys(t *testing.T) {
   715  	beaconDB := dbTest.SetupDB(t)
   716  
   717  	validators, _, headState := setupValidators(t, beaconDB, 100)
   718  	indicesWanted := []types.ValidatorIndex{2, 7, 11, 17}
   719  	pubkeyIndicesWanted := []types.ValidatorIndex{3, 5, 9, 15}
   720  	allIndicesWanted := append(indicesWanted, pubkeyIndicesWanted...)
   721  	want := make([]*ethpb.Validators_ValidatorContainer, len(allIndicesWanted))
   722  	for i, idx := range allIndicesWanted {
   723  		want[i] = &ethpb.Validators_ValidatorContainer{
   724  			Index:     idx,
   725  			Validator: validators[idx],
   726  		}
   727  	}
   728  	sort.Slice(want, func(i int, j int) bool {
   729  		return want[i].Index < want[j].Index
   730  	})
   731  
   732  	bs := &Server{
   733  		HeadFetcher: &mock.ChainService{
   734  			State: headState,
   735  		},
   736  		FinalizationFetcher: &mock.ChainService{
   737  			FinalizedCheckPoint: &ethpb.Checkpoint{
   738  				Epoch: 0,
   739  			},
   740  		},
   741  		GenesisTimeFetcher: &mock.ChainService{
   742  			// We are in epoch 0.
   743  			Genesis: time.Now(),
   744  		},
   745  		StateGen: stategen.New(beaconDB),
   746  	}
   747  
   748  	pubKeysWanted := make([][]byte, len(pubkeyIndicesWanted))
   749  	for i, indice := range pubkeyIndicesWanted {
   750  		pubKeysWanted[i] = pubKey(uint64(indice))
   751  	}
   752  	req := &ethpb.ListValidatorsRequest{
   753  		Indices:    indicesWanted,
   754  		PublicKeys: pubKeysWanted,
   755  	}
   756  	received, err := bs.ListValidators(context.Background(), req)
   757  	require.NoError(t, err)
   758  	assert.DeepEqual(t, want, received.ValidatorList, "Incorrect respond of validators")
   759  }
   760  
   761  func TestServer_ListValidators_Pagination(t *testing.T) {
   762  	beaconDB := dbTest.SetupDB(t)
   763  
   764  	count := 100
   765  	_, _, headState := setupValidators(t, beaconDB, count)
   766  
   767  	bs := &Server{
   768  		BeaconDB: beaconDB,
   769  		HeadFetcher: &mock.ChainService{
   770  			State: headState,
   771  		},
   772  		FinalizationFetcher: &mock.ChainService{
   773  			FinalizedCheckPoint: &ethpb.Checkpoint{
   774  				Epoch: 0,
   775  			},
   776  		},
   777  		GenesisTimeFetcher: &mock.ChainService{
   778  			// We are in epoch 0.
   779  			Genesis: time.Now(),
   780  		},
   781  		StateGen: stategen.New(beaconDB),
   782  	}
   783  
   784  	tests := []struct {
   785  		req *ethpb.ListValidatorsRequest
   786  		res *ethpb.Validators
   787  	}{
   788  		{req: &ethpb.ListValidatorsRequest{PageToken: strconv.Itoa(1), PageSize: 3},
   789  			res: &ethpb.Validators{
   790  				ValidatorList: []*ethpb.Validators_ValidatorContainer{
   791  					{
   792  						Validator: &ethpb.Validator{
   793  							PublicKey:             pubKey(3),
   794  							WithdrawalCredentials: make([]byte, 32),
   795  						},
   796  						Index: 3,
   797  					},
   798  					{
   799  						Validator: &ethpb.Validator{
   800  							PublicKey:             pubKey(4),
   801  							WithdrawalCredentials: make([]byte, 32),
   802  						},
   803  						Index: 4,
   804  					},
   805  					{
   806  						Validator: &ethpb.Validator{
   807  							PublicKey:             pubKey(5),
   808  							WithdrawalCredentials: make([]byte, 32),
   809  						},
   810  						Index: 5,
   811  					},
   812  				},
   813  				NextPageToken: strconv.Itoa(2),
   814  				TotalSize:     int32(count)}},
   815  		{req: &ethpb.ListValidatorsRequest{PageToken: strconv.Itoa(10), PageSize: 5},
   816  			res: &ethpb.Validators{
   817  				ValidatorList: []*ethpb.Validators_ValidatorContainer{
   818  					{
   819  						Validator: &ethpb.Validator{
   820  							PublicKey:             pubKey(50),
   821  							WithdrawalCredentials: make([]byte, 32),
   822  						},
   823  						Index: 50,
   824  					},
   825  					{
   826  						Validator: &ethpb.Validator{
   827  							PublicKey:             pubKey(51),
   828  							WithdrawalCredentials: make([]byte, 32),
   829  						},
   830  						Index: 51,
   831  					},
   832  					{
   833  						Validator: &ethpb.Validator{
   834  							PublicKey:             pubKey(52),
   835  							WithdrawalCredentials: make([]byte, 32),
   836  						},
   837  						Index: 52,
   838  					},
   839  					{
   840  						Validator: &ethpb.Validator{
   841  							PublicKey:             pubKey(53),
   842  							WithdrawalCredentials: make([]byte, 32),
   843  						},
   844  						Index: 53,
   845  					},
   846  					{
   847  						Validator: &ethpb.Validator{
   848  							PublicKey:             pubKey(54),
   849  							WithdrawalCredentials: make([]byte, 32),
   850  						},
   851  						Index: 54,
   852  					},
   853  				},
   854  				NextPageToken: strconv.Itoa(11),
   855  				TotalSize:     int32(count)}},
   856  		{req: &ethpb.ListValidatorsRequest{PageToken: strconv.Itoa(33), PageSize: 3},
   857  			res: &ethpb.Validators{
   858  				ValidatorList: []*ethpb.Validators_ValidatorContainer{
   859  					{
   860  						Validator: &ethpb.Validator{
   861  							PublicKey:             pubKey(99),
   862  							WithdrawalCredentials: make([]byte, 32),
   863  						},
   864  						Index: 99,
   865  					},
   866  				},
   867  				NextPageToken: "",
   868  				TotalSize:     int32(count)}},
   869  		{req: &ethpb.ListValidatorsRequest{PageSize: 2},
   870  			res: &ethpb.Validators{
   871  				ValidatorList: []*ethpb.Validators_ValidatorContainer{
   872  					{
   873  						Validator: &ethpb.Validator{
   874  							PublicKey:             pubKey(0),
   875  							WithdrawalCredentials: make([]byte, 32),
   876  						},
   877  						Index: 0,
   878  					},
   879  					{
   880  						Validator: &ethpb.Validator{
   881  							PublicKey:             pubKey(1),
   882  							WithdrawalCredentials: make([]byte, 32),
   883  						},
   884  						Index: 1,
   885  					},
   886  				},
   887  				NextPageToken: strconv.Itoa(1),
   888  				TotalSize:     int32(count)}},
   889  	}
   890  	for _, test := range tests {
   891  		res, err := bs.ListValidators(context.Background(), test.req)
   892  		require.NoError(t, err)
   893  		if !proto.Equal(res, test.res) {
   894  			t.Errorf("Incorrect validator response, wanted %v, received %v", test.res, res)
   895  		}
   896  	}
   897  }
   898  
   899  func TestServer_ListValidators_PaginationOutOfRange(t *testing.T) {
   900  	beaconDB := dbTest.SetupDB(t)
   901  
   902  	count := 1
   903  	validators, _, headState := setupValidators(t, beaconDB, count)
   904  
   905  	bs := &Server{
   906  		HeadFetcher: &mock.ChainService{
   907  			State: headState,
   908  		},
   909  		FinalizationFetcher: &mock.ChainService{
   910  			FinalizedCheckPoint: &ethpb.Checkpoint{
   911  				Epoch: 0,
   912  			},
   913  		},
   914  		GenesisTimeFetcher: &mock.ChainService{
   915  			// We are in epoch 0.
   916  			Genesis: time.Now(),
   917  		},
   918  		StateGen: stategen.New(beaconDB),
   919  	}
   920  
   921  	req := &ethpb.ListValidatorsRequest{PageToken: strconv.Itoa(1), PageSize: 100}
   922  	wanted := fmt.Sprintf("page start %d >= list %d", req.PageSize, len(validators))
   923  	_, err := bs.ListValidators(context.Background(), req)
   924  	assert.ErrorContains(t, wanted, err)
   925  }
   926  
   927  func TestServer_ListValidators_ExceedsMaxPageSize(t *testing.T) {
   928  	bs := &Server{}
   929  	exceedsMax := int32(cmd.Get().MaxRPCPageSize + 1)
   930  
   931  	wanted := fmt.Sprintf("Requested page size %d can not be greater than max size %d", exceedsMax, cmd.Get().MaxRPCPageSize)
   932  	req := &ethpb.ListValidatorsRequest{PageToken: strconv.Itoa(0), PageSize: exceedsMax}
   933  	_, err := bs.ListValidators(context.Background(), req)
   934  	assert.ErrorContains(t, wanted, err)
   935  }
   936  
   937  func TestServer_ListValidators_DefaultPageSize(t *testing.T) {
   938  	beaconDB := dbTest.SetupDB(t)
   939  
   940  	validators, _, headState := setupValidators(t, beaconDB, 1000)
   941  	want := make([]*ethpb.Validators_ValidatorContainer, len(validators))
   942  	for i := 0; i < len(validators); i++ {
   943  		want[i] = &ethpb.Validators_ValidatorContainer{
   944  			Index:     types.ValidatorIndex(i),
   945  			Validator: validators[i],
   946  		}
   947  	}
   948  
   949  	bs := &Server{
   950  		HeadFetcher: &mock.ChainService{
   951  			State: headState,
   952  		},
   953  		FinalizationFetcher: &mock.ChainService{
   954  			FinalizedCheckPoint: &ethpb.Checkpoint{
   955  				Epoch: 0,
   956  			},
   957  		},
   958  		GenesisTimeFetcher: &mock.ChainService{
   959  			// We are in epoch 0.
   960  			Genesis: time.Now(),
   961  		},
   962  		StateGen: stategen.New(beaconDB),
   963  	}
   964  
   965  	req := &ethpb.ListValidatorsRequest{}
   966  	res, err := bs.ListValidators(context.Background(), req)
   967  	require.NoError(t, err)
   968  
   969  	i := 0
   970  	j := params.BeaconConfig().DefaultPageSize
   971  	assert.DeepEqual(t, want[i:j], res.ValidatorList, "Incorrect respond of validators")
   972  }
   973  
   974  func TestServer_ListValidators_FromOldEpoch(t *testing.T) {
   975  	beaconDB := dbTest.SetupDB(t)
   976  	ctx := context.Background()
   977  
   978  	numEpochs := types.Epoch(30)
   979  	validators := make([]*ethpb.Validator, numEpochs)
   980  	for i := types.Epoch(0); i < numEpochs; i++ {
   981  		validators[i] = &ethpb.Validator{
   982  			ActivationEpoch:       i,
   983  			PublicKey:             make([]byte, 48),
   984  			WithdrawalCredentials: make([]byte, 32),
   985  		}
   986  	}
   987  	want := make([]*ethpb.Validators_ValidatorContainer, len(validators))
   988  	for i := 0; i < len(validators); i++ {
   989  		want[i] = &ethpb.Validators_ValidatorContainer{
   990  			Index:     types.ValidatorIndex(i),
   991  			Validator: validators[i],
   992  		}
   993  	}
   994  
   995  	st, err := testutil.NewBeaconState()
   996  	require.NoError(t, err)
   997  	require.NoError(t, st.SetSlot(20*params.BeaconConfig().SlotsPerEpoch))
   998  	require.NoError(t, st.SetValidators(validators))
   999  	b := testutil.NewBeaconBlock()
  1000  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b)))
  1001  	gRoot, err := b.Block.HashTreeRoot()
  1002  	require.NoError(t, err)
  1003  	require.NoError(t, beaconDB.SaveState(ctx, st, gRoot))
  1004  	require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
  1005  	secondsPerEpoch := params.BeaconConfig().SecondsPerSlot * uint64(params.BeaconConfig().SlotsPerEpoch)
  1006  	bs := &Server{
  1007  		HeadFetcher: &mock.ChainService{
  1008  			State: st,
  1009  		},
  1010  		GenesisTimeFetcher: &mock.ChainService{
  1011  			// We are in epoch 30
  1012  			Genesis: time.Now().Add(time.Duration(-1*int64(30*secondsPerEpoch)) * time.Second),
  1013  		},
  1014  		StateGen: stategen.New(beaconDB),
  1015  	}
  1016  
  1017  	req := &ethpb.ListValidatorsRequest{
  1018  		QueryFilter: &ethpb.ListValidatorsRequest_Genesis{
  1019  			Genesis: true,
  1020  		},
  1021  	}
  1022  	res, err := bs.ListValidators(context.Background(), req)
  1023  	require.NoError(t, err)
  1024  	assert.Equal(t, 30, len(res.ValidatorList))
  1025  
  1026  	req = &ethpb.ListValidatorsRequest{
  1027  		QueryFilter: &ethpb.ListValidatorsRequest_Epoch{
  1028  			Epoch: 20,
  1029  		},
  1030  	}
  1031  	res, err = bs.ListValidators(context.Background(), req)
  1032  	require.NoError(t, err)
  1033  	assert.DeepEqual(t, want, res.ValidatorList, "Incorrect number of validators")
  1034  }
  1035  
  1036  func TestServer_ListValidators_ProcessHeadStateSlots(t *testing.T) {
  1037  	params.UseMinimalConfig()
  1038  
  1039  	beaconDB := dbTest.SetupDB(t)
  1040  	ctx := context.Background()
  1041  
  1042  	headSlot := types.Slot(32)
  1043  	numValidators := params.BeaconConfig().MinGenesisActiveValidatorCount
  1044  	validators := make([]*ethpb.Validator, numValidators)
  1045  	balances := make([]uint64, numValidators)
  1046  	for i := uint64(0); i < numValidators; i++ {
  1047  		validators[i] = &ethpb.Validator{
  1048  			ActivationEpoch:       0,
  1049  			PublicKey:             make([]byte, 48),
  1050  			WithdrawalCredentials: make([]byte, 32),
  1051  			EffectiveBalance:      params.BeaconConfig().MaxEffectiveBalance,
  1052  		}
  1053  		balances[i] = params.BeaconConfig().MaxEffectiveBalance
  1054  	}
  1055  	want := make([]*ethpb.Validators_ValidatorContainer, len(validators))
  1056  	for i := 0; i < len(validators); i++ {
  1057  		want[i] = &ethpb.Validators_ValidatorContainer{
  1058  			Index:     types.ValidatorIndex(i),
  1059  			Validator: validators[i],
  1060  		}
  1061  	}
  1062  
  1063  	st, err := testutil.NewBeaconState()
  1064  	require.NoError(t, err)
  1065  	require.NoError(t, st.SetSlot(headSlot))
  1066  	require.NoError(t, st.SetValidators(validators))
  1067  	require.NoError(t, st.SetBalances(balances))
  1068  	b := testutil.NewBeaconBlock()
  1069  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b)))
  1070  	gRoot, err := b.Block.HashTreeRoot()
  1071  	require.NoError(t, err)
  1072  	require.NoError(t, beaconDB.SaveState(ctx, st, gRoot))
  1073  	require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
  1074  	secondsPerEpoch := params.BeaconConfig().SecondsPerSlot * uint64(params.BeaconConfig().SlotsPerEpoch)
  1075  	bs := &Server{
  1076  		HeadFetcher: &mock.ChainService{
  1077  			State: st,
  1078  		},
  1079  		GenesisTimeFetcher: &mock.ChainService{
  1080  			Genesis: time.Now().Add(time.Duration(-1*int64(secondsPerEpoch)) * time.Second),
  1081  		},
  1082  		StateGen: stategen.New(beaconDB),
  1083  	}
  1084  
  1085  	req := &ethpb.ListValidatorsRequest{
  1086  		QueryFilter: &ethpb.ListValidatorsRequest_Epoch{
  1087  			Epoch: 1,
  1088  		},
  1089  	}
  1090  	res, err := bs.ListValidators(context.Background(), req)
  1091  	require.NoError(t, err)
  1092  	assert.Equal(t, len(want), len(res.ValidatorList), "Incorrect number of validators")
  1093  	for i := 0; i < len(res.ValidatorList); i++ {
  1094  		assert.DeepEqual(t, want[i], res.ValidatorList[i])
  1095  	}
  1096  }
  1097  
  1098  func TestServer_GetValidator(t *testing.T) {
  1099  	count := types.Epoch(30)
  1100  	validators := make([]*ethpb.Validator, count)
  1101  	for i := types.Epoch(0); i < count; i++ {
  1102  		validators[i] = &ethpb.Validator{
  1103  			ActivationEpoch:       i,
  1104  			PublicKey:             pubKey(uint64(i)),
  1105  			WithdrawalCredentials: make([]byte, 32),
  1106  		}
  1107  	}
  1108  
  1109  	st, err := testutil.NewBeaconState()
  1110  	require.NoError(t, err)
  1111  	require.NoError(t, st.SetValidators(validators))
  1112  
  1113  	bs := &Server{
  1114  		HeadFetcher: &mock.ChainService{
  1115  			State: st,
  1116  		},
  1117  	}
  1118  
  1119  	tests := []struct {
  1120  		req       *ethpb.GetValidatorRequest
  1121  		res       *ethpb.Validator
  1122  		wantedErr string
  1123  	}{
  1124  		{
  1125  			req: &ethpb.GetValidatorRequest{
  1126  				QueryFilter: &ethpb.GetValidatorRequest_Index{
  1127  					Index: 0,
  1128  				},
  1129  			},
  1130  			res: validators[0],
  1131  		},
  1132  		{
  1133  			req: &ethpb.GetValidatorRequest{
  1134  				QueryFilter: &ethpb.GetValidatorRequest_Index{
  1135  					Index: types.ValidatorIndex(count - 1),
  1136  				},
  1137  			},
  1138  			res: validators[count-1],
  1139  		},
  1140  		{
  1141  			req: &ethpb.GetValidatorRequest{
  1142  				QueryFilter: &ethpb.GetValidatorRequest_PublicKey{
  1143  					PublicKey: pubKey(5),
  1144  				},
  1145  			},
  1146  			res: validators[5],
  1147  		},
  1148  		{
  1149  			req: &ethpb.GetValidatorRequest{
  1150  				QueryFilter: &ethpb.GetValidatorRequest_PublicKey{
  1151  					PublicKey: []byte("bad-keyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"),
  1152  				},
  1153  			},
  1154  			res:       nil,
  1155  			wantedErr: "No validator matched filter criteria",
  1156  		},
  1157  		{
  1158  			req: &ethpb.GetValidatorRequest{
  1159  				QueryFilter: &ethpb.GetValidatorRequest_Index{
  1160  					Index: types.ValidatorIndex(len(validators)),
  1161  				},
  1162  			},
  1163  			res:       nil,
  1164  			wantedErr: fmt.Sprintf("there are only %d validators", len(validators)),
  1165  		},
  1166  	}
  1167  
  1168  	for _, test := range tests {
  1169  		res, err := bs.GetValidator(context.Background(), test.req)
  1170  		if test.wantedErr != "" {
  1171  			require.ErrorContains(t, test.wantedErr, err)
  1172  		} else {
  1173  			require.NoError(t, err)
  1174  		}
  1175  		assert.DeepEqual(t, test.res, res)
  1176  	}
  1177  }
  1178  
  1179  func TestServer_GetValidatorActiveSetChanges(t *testing.T) {
  1180  	beaconDB := dbTest.SetupDB(t)
  1181  
  1182  	ctx := context.Background()
  1183  	validators := make([]*ethpb.Validator, 8)
  1184  	headState, err := testutil.NewBeaconState()
  1185  	require.NoError(t, err)
  1186  	require.NoError(t, headState.SetSlot(0))
  1187  	require.NoError(t, headState.SetValidators(validators))
  1188  	for i := 0; i < len(validators); i++ {
  1189  		activationEpoch := params.BeaconConfig().FarFutureEpoch
  1190  		withdrawableEpoch := params.BeaconConfig().FarFutureEpoch
  1191  		exitEpoch := params.BeaconConfig().FarFutureEpoch
  1192  		slashed := false
  1193  		balance := params.BeaconConfig().MaxEffectiveBalance
  1194  		// Mark indices divisible by two as activated.
  1195  		if i%2 == 0 {
  1196  			activationEpoch = 0
  1197  		} else if i%3 == 0 {
  1198  			// Mark indices divisible by 3 as slashed.
  1199  			withdrawableEpoch = params.BeaconConfig().EpochsPerSlashingsVector
  1200  			slashed = true
  1201  		} else if i%5 == 0 {
  1202  			// Mark indices divisible by 5 as exited.
  1203  			exitEpoch = 0
  1204  			withdrawableEpoch = params.BeaconConfig().MinValidatorWithdrawabilityDelay
  1205  		} else if i%7 == 0 {
  1206  			// Mark indices divisible by 7 as ejected.
  1207  			exitEpoch = 0
  1208  			withdrawableEpoch = params.BeaconConfig().MinValidatorWithdrawabilityDelay
  1209  			balance = params.BeaconConfig().EjectionBalance
  1210  		}
  1211  		err := headState.UpdateValidatorAtIndex(types.ValidatorIndex(i), &ethpb.Validator{
  1212  			ActivationEpoch:       activationEpoch,
  1213  			PublicKey:             pubKey(uint64(i)),
  1214  			EffectiveBalance:      balance,
  1215  			WithdrawalCredentials: make([]byte, 32),
  1216  			WithdrawableEpoch:     withdrawableEpoch,
  1217  			Slashed:               slashed,
  1218  			ExitEpoch:             exitEpoch,
  1219  		})
  1220  		require.NoError(t, err)
  1221  	}
  1222  	b := testutil.NewBeaconBlock()
  1223  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b)))
  1224  
  1225  	gRoot, err := b.Block.HashTreeRoot()
  1226  	require.NoError(t, err)
  1227  	require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
  1228  	require.NoError(t, beaconDB.SaveState(ctx, headState, gRoot))
  1229  
  1230  	bs := &Server{
  1231  		FinalizationFetcher: &mock.ChainService{
  1232  			FinalizedCheckPoint: &ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)},
  1233  		},
  1234  		GenesisTimeFetcher: &mock.ChainService{},
  1235  		StateGen:           stategen.New(beaconDB),
  1236  	}
  1237  	res, err := bs.GetValidatorActiveSetChanges(ctx, &ethpb.GetValidatorActiveSetChangesRequest{
  1238  		QueryFilter: &ethpb.GetValidatorActiveSetChangesRequest_Genesis{Genesis: true},
  1239  	})
  1240  	require.NoError(t, err)
  1241  	wantedActive := [][]byte{
  1242  		pubKey(0),
  1243  		pubKey(2),
  1244  		pubKey(4),
  1245  		pubKey(6),
  1246  	}
  1247  	wantedActiveIndices := []types.ValidatorIndex{0, 2, 4, 6}
  1248  	wantedExited := [][]byte{
  1249  		pubKey(5),
  1250  	}
  1251  	wantedExitedIndices := []types.ValidatorIndex{5}
  1252  	wantedSlashed := [][]byte{
  1253  		pubKey(3),
  1254  	}
  1255  	wantedSlashedIndices := []types.ValidatorIndex{3}
  1256  	wantedEjected := [][]byte{
  1257  		pubKey(7),
  1258  	}
  1259  	wantedEjectedIndices := []types.ValidatorIndex{7}
  1260  	wanted := &ethpb.ActiveSetChanges{
  1261  		Epoch:               0,
  1262  		ActivatedPublicKeys: wantedActive,
  1263  		ActivatedIndices:    wantedActiveIndices,
  1264  		ExitedPublicKeys:    wantedExited,
  1265  		ExitedIndices:       wantedExitedIndices,
  1266  		SlashedPublicKeys:   wantedSlashed,
  1267  		SlashedIndices:      wantedSlashedIndices,
  1268  		EjectedPublicKeys:   wantedEjected,
  1269  		EjectedIndices:      wantedEjectedIndices,
  1270  	}
  1271  	if !proto.Equal(wanted, res) {
  1272  		t.Errorf("Wanted \n%v, received \n%v", wanted, res)
  1273  	}
  1274  }
  1275  
  1276  func TestServer_GetValidatorQueue_PendingActivation(t *testing.T) {
  1277  	headState, err := v1.InitializeFromProto(&pb.BeaconState{
  1278  		Validators: []*ethpb.Validator{
  1279  			{
  1280  				ActivationEpoch:            helpers.ActivationExitEpoch(0),
  1281  				ActivationEligibilityEpoch: 3,
  1282  				PublicKey:                  pubKey(3),
  1283  				WithdrawalCredentials:      make([]byte, 32),
  1284  			},
  1285  			{
  1286  				ActivationEpoch:            helpers.ActivationExitEpoch(0),
  1287  				ActivationEligibilityEpoch: 2,
  1288  				PublicKey:                  pubKey(2),
  1289  				WithdrawalCredentials:      make([]byte, 32),
  1290  			},
  1291  			{
  1292  				ActivationEpoch:            helpers.ActivationExitEpoch(0),
  1293  				ActivationEligibilityEpoch: 1,
  1294  				PublicKey:                  pubKey(1),
  1295  				WithdrawalCredentials:      make([]byte, 32),
  1296  			},
  1297  		},
  1298  		FinalizedCheckpoint: &ethpb.Checkpoint{
  1299  			Epoch: 0,
  1300  		},
  1301  	})
  1302  	require.NoError(t, err)
  1303  	bs := &Server{
  1304  		HeadFetcher: &mock.ChainService{
  1305  			State: headState,
  1306  		},
  1307  	}
  1308  	res, err := bs.GetValidatorQueue(context.Background(), &emptypb.Empty{})
  1309  	require.NoError(t, err)
  1310  	// We verify the keys are properly sorted by the validators' activation eligibility epoch.
  1311  	wanted := [][]byte{
  1312  		pubKey(1),
  1313  		pubKey(2),
  1314  		pubKey(3),
  1315  	}
  1316  	activeValidatorCount, err := helpers.ActiveValidatorCount(headState, helpers.CurrentEpoch(headState))
  1317  	require.NoError(t, err)
  1318  	wantChurn, err := helpers.ValidatorChurnLimit(activeValidatorCount)
  1319  	require.NoError(t, err)
  1320  	assert.Equal(t, wantChurn, res.ChurnLimit)
  1321  	assert.DeepEqual(t, wanted, res.ActivationPublicKeys)
  1322  	wantedActiveIndices := []types.ValidatorIndex{2, 1, 0}
  1323  	assert.DeepEqual(t, wantedActiveIndices, res.ActivationValidatorIndices)
  1324  }
  1325  
  1326  func TestServer_GetValidatorQueue_ExitedValidatorLeavesQueue(t *testing.T) {
  1327  	validators := []*ethpb.Validator{
  1328  		{
  1329  			ActivationEpoch:   0,
  1330  			ExitEpoch:         params.BeaconConfig().FarFutureEpoch,
  1331  			WithdrawableEpoch: params.BeaconConfig().FarFutureEpoch,
  1332  			PublicKey:         bytesutil.PadTo([]byte("1"), 48),
  1333  		},
  1334  		{
  1335  			ActivationEpoch:   0,
  1336  			ExitEpoch:         4,
  1337  			WithdrawableEpoch: 6,
  1338  			PublicKey:         bytesutil.PadTo([]byte("2"), 48),
  1339  		},
  1340  	}
  1341  
  1342  	headState, err := testutil.NewBeaconState()
  1343  	require.NoError(t, err)
  1344  	require.NoError(t, headState.SetValidators(validators))
  1345  	require.NoError(t, headState.SetFinalizedCheckpoint(&ethpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)}))
  1346  	bs := &Server{
  1347  		HeadFetcher: &mock.ChainService{
  1348  			State: headState,
  1349  		},
  1350  	}
  1351  
  1352  	// First we check if validator with index 1 is in the exit queue.
  1353  	res, err := bs.GetValidatorQueue(context.Background(), &emptypb.Empty{})
  1354  	require.NoError(t, err)
  1355  	wanted := [][]byte{
  1356  		bytesutil.PadTo([]byte("2"), 48),
  1357  	}
  1358  	activeValidatorCount, err := helpers.ActiveValidatorCount(headState, helpers.CurrentEpoch(headState))
  1359  	require.NoError(t, err)
  1360  	wantChurn, err := helpers.ValidatorChurnLimit(activeValidatorCount)
  1361  	require.NoError(t, err)
  1362  	assert.Equal(t, wantChurn, res.ChurnLimit)
  1363  	assert.DeepEqual(t, wanted, res.ExitPublicKeys)
  1364  	wantedExitIndices := []types.ValidatorIndex{1}
  1365  	assert.DeepEqual(t, wantedExitIndices, res.ExitValidatorIndices)
  1366  
  1367  	// Now, we move the state.slot past the exit epoch of the validator, and now
  1368  	// the validator should no longer exist in the queue.
  1369  	require.NoError(t, headState.SetSlot(params.BeaconConfig().SlotsPerEpoch.Mul(uint64(validators[1].ExitEpoch+1))))
  1370  	res, err = bs.GetValidatorQueue(context.Background(), &emptypb.Empty{})
  1371  	require.NoError(t, err)
  1372  	assert.Equal(t, 0, len(res.ExitPublicKeys))
  1373  }
  1374  
  1375  func TestServer_GetValidatorQueue_PendingExit(t *testing.T) {
  1376  	headState, err := v1.InitializeFromProto(&pb.BeaconState{
  1377  		Validators: []*ethpb.Validator{
  1378  			{
  1379  				ActivationEpoch:       0,
  1380  				ExitEpoch:             4,
  1381  				WithdrawableEpoch:     3,
  1382  				PublicKey:             pubKey(3),
  1383  				WithdrawalCredentials: make([]byte, 32),
  1384  			},
  1385  			{
  1386  				ActivationEpoch:       0,
  1387  				ExitEpoch:             4,
  1388  				WithdrawableEpoch:     2,
  1389  				PublicKey:             pubKey(2),
  1390  				WithdrawalCredentials: make([]byte, 32),
  1391  			},
  1392  			{
  1393  				ActivationEpoch:       0,
  1394  				ExitEpoch:             4,
  1395  				WithdrawableEpoch:     1,
  1396  				PublicKey:             pubKey(1),
  1397  				WithdrawalCredentials: make([]byte, 32),
  1398  			},
  1399  		},
  1400  		FinalizedCheckpoint: &ethpb.Checkpoint{
  1401  			Epoch: 0,
  1402  		},
  1403  	})
  1404  	require.NoError(t, err)
  1405  	bs := &Server{
  1406  		HeadFetcher: &mock.ChainService{
  1407  			State: headState,
  1408  		},
  1409  	}
  1410  	res, err := bs.GetValidatorQueue(context.Background(), &emptypb.Empty{})
  1411  	require.NoError(t, err)
  1412  	// We verify the keys are properly sorted by the validators' withdrawable epoch.
  1413  	wanted := [][]byte{
  1414  		pubKey(1),
  1415  		pubKey(2),
  1416  		pubKey(3),
  1417  	}
  1418  	activeValidatorCount, err := helpers.ActiveValidatorCount(headState, helpers.CurrentEpoch(headState))
  1419  	require.NoError(t, err)
  1420  	wantChurn, err := helpers.ValidatorChurnLimit(activeValidatorCount)
  1421  	require.NoError(t, err)
  1422  	assert.Equal(t, wantChurn, res.ChurnLimit)
  1423  	assert.DeepEqual(t, wanted, res.ExitPublicKeys)
  1424  }
  1425  
  1426  func TestServer_GetValidatorParticipation_CannotRequestFutureEpoch(t *testing.T) {
  1427  	beaconDB := dbTest.SetupDB(t)
  1428  
  1429  	ctx := context.Background()
  1430  	headState, err := testutil.NewBeaconState()
  1431  	require.NoError(t, err)
  1432  	require.NoError(t, headState.SetSlot(0))
  1433  	bs := &Server{
  1434  		BeaconDB: beaconDB,
  1435  		HeadFetcher: &mock.ChainService{
  1436  			State: headState,
  1437  		},
  1438  		GenesisTimeFetcher: &mock.ChainService{},
  1439  		StateGen:           stategen.New(beaconDB),
  1440  	}
  1441  
  1442  	wanted := "Cannot retrieve information about an epoch"
  1443  	_, err = bs.GetValidatorParticipation(
  1444  		ctx,
  1445  		&ethpb.GetValidatorParticipationRequest{
  1446  			QueryFilter: &ethpb.GetValidatorParticipationRequest_Epoch{
  1447  				Epoch: helpers.SlotToEpoch(bs.GenesisTimeFetcher.CurrentSlot()) + 1,
  1448  			},
  1449  		},
  1450  	)
  1451  	assert.ErrorContains(t, wanted, err)
  1452  }
  1453  
  1454  func TestServer_GetValidatorParticipation_UnknownState(t *testing.T) {
  1455  	beaconDB := dbTest.SetupDB(t)
  1456  
  1457  	ctx := context.Background()
  1458  	headState, err := testutil.NewBeaconState()
  1459  	require.NoError(t, err)
  1460  	require.NoError(t, headState.SetSlot(0))
  1461  	epoch := types.Epoch(50)
  1462  	slots := params.BeaconConfig().SlotsPerEpoch.Mul(uint64(epoch))
  1463  	mockStateGen := &stategen.MockStateManager{
  1464  		StatesBySlot: map[types.Slot]iface.BeaconState{
  1465  			0: (*v1.BeaconState)(nil),
  1466  		},
  1467  	}
  1468  	bs := &Server{
  1469  		BeaconDB: beaconDB,
  1470  		HeadFetcher: &mock.ChainService{
  1471  			State: headState,
  1472  		},
  1473  		GenesisTimeFetcher: &mock.ChainService{
  1474  			Genesis: time.Now().Add(time.Duration(-1*int64(slots)) * time.Second),
  1475  		},
  1476  		StateGen: mockStateGen,
  1477  	}
  1478  
  1479  	wanted := "Could not set up pre compute instance: failed to initialize precompute: nil inner state"
  1480  	_, err = bs.GetValidatorParticipation(
  1481  		ctx,
  1482  		&ethpb.GetValidatorParticipationRequest{
  1483  			QueryFilter: &ethpb.GetValidatorParticipationRequest_Epoch{
  1484  				Epoch: 1,
  1485  			},
  1486  		},
  1487  	)
  1488  	assert.ErrorContains(t, wanted, err)
  1489  }
  1490  
  1491  func TestServer_GetValidatorParticipation_CurrentAndPrevEpoch(t *testing.T) {
  1492  	helpers.ClearCache()
  1493  	beaconDB := dbTest.SetupDB(t)
  1494  
  1495  	ctx := context.Background()
  1496  	validatorCount := uint64(32)
  1497  
  1498  	validators := make([]*ethpb.Validator, validatorCount)
  1499  	balances := make([]uint64, validatorCount)
  1500  	for i := 0; i < len(validators); i++ {
  1501  		validators[i] = &ethpb.Validator{
  1502  			PublicKey:             bytesutil.ToBytes(uint64(i), 48),
  1503  			WithdrawalCredentials: make([]byte, 32),
  1504  			ExitEpoch:             params.BeaconConfig().FarFutureEpoch,
  1505  			EffectiveBalance:      params.BeaconConfig().MaxEffectiveBalance,
  1506  		}
  1507  		balances[i] = params.BeaconConfig().MaxEffectiveBalance
  1508  	}
  1509  
  1510  	atts := []*pb.PendingAttestation{{
  1511  		Data:            testutil.HydrateAttestationData(&ethpb.AttestationData{}),
  1512  		InclusionDelay:  1,
  1513  		AggregationBits: bitfield.NewBitlist(validatorCount / uint64(params.BeaconConfig().SlotsPerEpoch)),
  1514  	}}
  1515  	headState, err := testutil.NewBeaconState()
  1516  	require.NoError(t, err)
  1517  	require.NoError(t, headState.SetSlot(2*params.BeaconConfig().SlotsPerEpoch-1))
  1518  	require.NoError(t, headState.SetValidators(validators))
  1519  	require.NoError(t, headState.SetBalances(balances))
  1520  	require.NoError(t, headState.AppendCurrentEpochAttestations(atts[0]))
  1521  	require.NoError(t, headState.AppendPreviousEpochAttestations(atts[0]))
  1522  
  1523  	b := testutil.NewBeaconBlock()
  1524  	b.Block.Slot = 16
  1525  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b)))
  1526  	bRoot, err := b.Block.HashTreeRoot()
  1527  	require.NoError(t, beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: bRoot[:]}))
  1528  	require.NoError(t, beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: params.BeaconConfig().ZeroHash[:]}))
  1529  	require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, bRoot))
  1530  	require.NoError(t, err)
  1531  	require.NoError(t, beaconDB.SaveState(ctx, headState, bRoot))
  1532  
  1533  	m := &mock.ChainService{State: headState}
  1534  	offset := int64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot))
  1535  	bs := &Server{
  1536  		BeaconDB:    beaconDB,
  1537  		HeadFetcher: m,
  1538  		StateGen:    stategen.New(beaconDB),
  1539  		GenesisTimeFetcher: &mock.ChainService{
  1540  			Genesis: timeutils.Now().Add(time.Duration(-1*offset) * time.Second),
  1541  		},
  1542  		CanonicalFetcher: &mock.ChainService{
  1543  			CanonicalRoots: map[[32]byte]bool{
  1544  				bRoot: true,
  1545  			},
  1546  		},
  1547  		FinalizationFetcher: &mock.ChainService{FinalizedCheckPoint: &ethpb.Checkpoint{Epoch: 100}},
  1548  	}
  1549  
  1550  	res, err := bs.GetValidatorParticipation(ctx, &ethpb.GetValidatorParticipationRequest{QueryFilter: &ethpb.GetValidatorParticipationRequest_Epoch{Epoch: 1}})
  1551  	require.NoError(t, err)
  1552  
  1553  	wanted := &ethpb.ValidatorParticipation{
  1554  		GlobalParticipationRate:          float32(params.BeaconConfig().EffectiveBalanceIncrement) / float32(validatorCount*params.BeaconConfig().MaxEffectiveBalance),
  1555  		VotedEther:                       params.BeaconConfig().EffectiveBalanceIncrement,
  1556  		EligibleEther:                    validatorCount * params.BeaconConfig().MaxEffectiveBalance,
  1557  		CurrentEpochActiveGwei:           validatorCount * params.BeaconConfig().MaxEffectiveBalance,
  1558  		CurrentEpochAttestingGwei:        params.BeaconConfig().EffectiveBalanceIncrement,
  1559  		CurrentEpochTargetAttestingGwei:  params.BeaconConfig().EffectiveBalanceIncrement,
  1560  		PreviousEpochActiveGwei:          validatorCount * params.BeaconConfig().MaxEffectiveBalance,
  1561  		PreviousEpochAttestingGwei:       params.BeaconConfig().EffectiveBalanceIncrement,
  1562  		PreviousEpochTargetAttestingGwei: params.BeaconConfig().EffectiveBalanceIncrement,
  1563  		PreviousEpochHeadAttestingGwei:   params.BeaconConfig().EffectiveBalanceIncrement,
  1564  	}
  1565  	assert.DeepEqual(t, true, res.Finalized, "Incorrect validator participation respond")
  1566  	assert.DeepEqual(t, wanted, res.Participation, "Incorrect validator participation respond")
  1567  }
  1568  
  1569  func TestServer_GetValidatorParticipation_OrphanedUntilGenesis(t *testing.T) {
  1570  	helpers.ClearCache()
  1571  	params.UseMainnetConfig()
  1572  
  1573  	beaconDB := dbTest.SetupDB(t)
  1574  	ctx := context.Background()
  1575  	validatorCount := uint64(100)
  1576  
  1577  	validators := make([]*ethpb.Validator, validatorCount)
  1578  	balances := make([]uint64, validatorCount)
  1579  	for i := 0; i < len(validators); i++ {
  1580  		validators[i] = &ethpb.Validator{
  1581  			PublicKey:             bytesutil.ToBytes(uint64(i), 48),
  1582  			WithdrawalCredentials: make([]byte, 32),
  1583  			ExitEpoch:             params.BeaconConfig().FarFutureEpoch,
  1584  			EffectiveBalance:      params.BeaconConfig().MaxEffectiveBalance,
  1585  		}
  1586  		balances[i] = params.BeaconConfig().MaxEffectiveBalance
  1587  	}
  1588  
  1589  	atts := []*pb.PendingAttestation{{
  1590  		Data:            testutil.HydrateAttestationData(&ethpb.AttestationData{}),
  1591  		InclusionDelay:  1,
  1592  		AggregationBits: bitfield.NewBitlist(validatorCount / uint64(params.BeaconConfig().SlotsPerEpoch)),
  1593  	}}
  1594  	headState, err := testutil.NewBeaconState()
  1595  	require.NoError(t, err)
  1596  	require.NoError(t, headState.SetSlot(2*params.BeaconConfig().SlotsPerEpoch-1))
  1597  	require.NoError(t, headState.SetValidators(validators))
  1598  	require.NoError(t, headState.SetBalances(balances))
  1599  	require.NoError(t, headState.AppendCurrentEpochAttestations(atts[0]))
  1600  	require.NoError(t, headState.AppendPreviousEpochAttestations(atts[0]))
  1601  
  1602  	b := testutil.NewBeaconBlock()
  1603  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b)))
  1604  	bRoot, err := b.Block.HashTreeRoot()
  1605  	require.NoError(t, beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: bRoot[:]}))
  1606  	require.NoError(t, beaconDB.SaveStateSummary(ctx, &pb.StateSummary{Root: params.BeaconConfig().ZeroHash[:]}))
  1607  	require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, bRoot))
  1608  	require.NoError(t, err)
  1609  	require.NoError(t, beaconDB.SaveState(ctx, headState, bRoot))
  1610  
  1611  	m := &mock.ChainService{State: headState}
  1612  	offset := int64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot))
  1613  	bs := &Server{
  1614  		BeaconDB:    beaconDB,
  1615  		HeadFetcher: m,
  1616  		StateGen:    stategen.New(beaconDB),
  1617  		GenesisTimeFetcher: &mock.ChainService{
  1618  			Genesis: timeutils.Now().Add(time.Duration(-1*offset) * time.Second),
  1619  		},
  1620  		CanonicalFetcher: &mock.ChainService{
  1621  			CanonicalRoots: map[[32]byte]bool{
  1622  				bRoot: true,
  1623  			},
  1624  		},
  1625  		FinalizationFetcher: &mock.ChainService{FinalizedCheckPoint: &ethpb.Checkpoint{Epoch: 100}},
  1626  	}
  1627  
  1628  	res, err := bs.GetValidatorParticipation(ctx, &ethpb.GetValidatorParticipationRequest{QueryFilter: &ethpb.GetValidatorParticipationRequest_Epoch{Epoch: 1}})
  1629  	require.NoError(t, err)
  1630  
  1631  	wanted := &ethpb.ValidatorParticipation{
  1632  		GlobalParticipationRate:          float32(params.BeaconConfig().EffectiveBalanceIncrement) / float32(validatorCount*params.BeaconConfig().MaxEffectiveBalance),
  1633  		VotedEther:                       params.BeaconConfig().EffectiveBalanceIncrement,
  1634  		EligibleEther:                    validatorCount * params.BeaconConfig().MaxEffectiveBalance,
  1635  		CurrentEpochActiveGwei:           validatorCount * params.BeaconConfig().MaxEffectiveBalance,
  1636  		CurrentEpochAttestingGwei:        params.BeaconConfig().EffectiveBalanceIncrement,
  1637  		CurrentEpochTargetAttestingGwei:  params.BeaconConfig().EffectiveBalanceIncrement,
  1638  		PreviousEpochActiveGwei:          validatorCount * params.BeaconConfig().MaxEffectiveBalance,
  1639  		PreviousEpochAttestingGwei:       params.BeaconConfig().EffectiveBalanceIncrement,
  1640  		PreviousEpochTargetAttestingGwei: params.BeaconConfig().EffectiveBalanceIncrement,
  1641  		PreviousEpochHeadAttestingGwei:   params.BeaconConfig().EffectiveBalanceIncrement,
  1642  	}
  1643  	assert.DeepEqual(t, true, res.Finalized, "Incorrect validator participation respond")
  1644  	assert.DeepEqual(t, wanted, res.Participation, "Incorrect validator participation respond")
  1645  }
  1646  
  1647  func TestGetValidatorPerformance_Syncing(t *testing.T) {
  1648  	ctx := context.Background()
  1649  
  1650  	bs := &Server{
  1651  		SyncChecker: &mockSync.Sync{IsSyncing: true},
  1652  	}
  1653  
  1654  	wanted := "Syncing to latest head, not ready to respond"
  1655  	_, err := bs.GetValidatorPerformance(ctx, nil)
  1656  	assert.ErrorContains(t, wanted, err)
  1657  }
  1658  
  1659  func TestGetValidatorPerformance_OK(t *testing.T) {
  1660  	helpers.ClearCache()
  1661  	params.UseMinimalConfig()
  1662  	defer params.UseMainnetConfig()
  1663  
  1664  	ctx := context.Background()
  1665  	epoch := types.Epoch(1)
  1666  	headState, err := testutil.NewBeaconState()
  1667  	require.NoError(t, err)
  1668  	require.NoError(t, headState.SetSlot(params.BeaconConfig().SlotsPerEpoch.Mul(uint64(epoch+1))))
  1669  	atts := make([]*pb.PendingAttestation, 3)
  1670  	for i := 0; i < len(atts); i++ {
  1671  		atts[i] = &pb.PendingAttestation{
  1672  			Data: &ethpb.AttestationData{
  1673  				Target: &ethpb.Checkpoint{Root: make([]byte, 32)},
  1674  				Source: &ethpb.Checkpoint{Root: make([]byte, 32)},
  1675  			},
  1676  			AggregationBits: bitfield.Bitlist{},
  1677  			InclusionDelay:  1,
  1678  		}
  1679  		require.NoError(t, headState.AppendPreviousEpochAttestations(atts[i]))
  1680  	}
  1681  	defaultBal := params.BeaconConfig().MaxEffectiveBalance
  1682  	extraBal := params.BeaconConfig().MaxEffectiveBalance + params.BeaconConfig().GweiPerEth
  1683  	balances := []uint64{defaultBal, extraBal, extraBal + params.BeaconConfig().GweiPerEth}
  1684  	require.NoError(t, headState.SetBalances(balances))
  1685  	publicKey1 := bytesutil.ToBytes48([]byte{1})
  1686  	publicKey2 := bytesutil.ToBytes48([]byte{2})
  1687  	publicKey3 := bytesutil.ToBytes48([]byte{3})
  1688  	validators := []*ethpb.Validator{
  1689  		{
  1690  			PublicKey:       publicKey1[:],
  1691  			ActivationEpoch: 5,
  1692  			ExitEpoch:       params.BeaconConfig().FarFutureEpoch,
  1693  		},
  1694  		{
  1695  			PublicKey:        publicKey2[:],
  1696  			EffectiveBalance: defaultBal,
  1697  			ActivationEpoch:  0,
  1698  			ExitEpoch:        params.BeaconConfig().FarFutureEpoch,
  1699  		},
  1700  		{
  1701  			PublicKey:        publicKey3[:],
  1702  			EffectiveBalance: defaultBal,
  1703  			ActivationEpoch:  0,
  1704  			ExitEpoch:        params.BeaconConfig().FarFutureEpoch,
  1705  		},
  1706  	}
  1707  	require.NoError(t, headState.SetValidators(validators))
  1708  	require.NoError(t, headState.SetBalances([]uint64{100, 101, 102}))
  1709  	offset := int64(headState.Slot().Mul(params.BeaconConfig().SecondsPerSlot))
  1710  	bs := &Server{
  1711  		HeadFetcher: &mock.ChainService{
  1712  			State: headState,
  1713  		},
  1714  		GenesisTimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)},
  1715  		SyncChecker:        &mockSync.Sync{IsSyncing: false},
  1716  	}
  1717  	farFuture := params.BeaconConfig().FarFutureSlot
  1718  	want := &ethpb.ValidatorPerformanceResponse{
  1719  		PublicKeys:                    [][]byte{publicKey2[:], publicKey3[:]},
  1720  		CurrentEffectiveBalances:      []uint64{params.BeaconConfig().MaxEffectiveBalance, params.BeaconConfig().MaxEffectiveBalance},
  1721  		InclusionSlots:                []types.Slot{farFuture, farFuture},
  1722  		InclusionDistances:            []types.Slot{farFuture, farFuture},
  1723  		CorrectlyVotedSource:          []bool{false, false},
  1724  		CorrectlyVotedTarget:          []bool{false, false},
  1725  		CorrectlyVotedHead:            []bool{false, false},
  1726  		BalancesBeforeEpochTransition: []uint64{101, 102},
  1727  		BalancesAfterEpochTransition:  []uint64{0, 0},
  1728  		MissingValidators:             [][]byte{publicKey1[:]},
  1729  	}
  1730  
  1731  	res, err := bs.GetValidatorPerformance(ctx, &ethpb.ValidatorPerformanceRequest{
  1732  		PublicKeys: [][]byte{publicKey1[:], publicKey3[:], publicKey2[:]},
  1733  	})
  1734  	require.NoError(t, err)
  1735  	if !proto.Equal(want, res) {
  1736  		t.Errorf("Wanted %v\nReceived %v", want, res)
  1737  	}
  1738  }
  1739  
  1740  func TestGetValidatorPerformance_Indices(t *testing.T) {
  1741  	ctx := context.Background()
  1742  	epoch := types.Epoch(1)
  1743  	defaultBal := params.BeaconConfig().MaxEffectiveBalance
  1744  	extraBal := params.BeaconConfig().MaxEffectiveBalance + params.BeaconConfig().GweiPerEth
  1745  	headState, err := testutil.NewBeaconState()
  1746  	require.NoError(t, err)
  1747  	require.NoError(t, headState.SetSlot(params.BeaconConfig().SlotsPerEpoch.Mul(uint64(epoch+1))))
  1748  	balances := []uint64{defaultBal, extraBal, extraBal + params.BeaconConfig().GweiPerEth}
  1749  	require.NoError(t, headState.SetBalances(balances))
  1750  	publicKey1 := bytesutil.ToBytes48([]byte{1})
  1751  	publicKey2 := bytesutil.ToBytes48([]byte{2})
  1752  	publicKey3 := bytesutil.ToBytes48([]byte{3})
  1753  	validators := []*ethpb.Validator{
  1754  		{
  1755  			PublicKey:       publicKey1[:],
  1756  			ActivationEpoch: 5,
  1757  			ExitEpoch:       params.BeaconConfig().FarFutureEpoch,
  1758  		},
  1759  		{
  1760  			PublicKey:        publicKey2[:],
  1761  			EffectiveBalance: defaultBal,
  1762  			ActivationEpoch:  0,
  1763  			ExitEpoch:        params.BeaconConfig().FarFutureEpoch,
  1764  		},
  1765  		{
  1766  			PublicKey:        publicKey3[:],
  1767  			EffectiveBalance: defaultBal,
  1768  			ActivationEpoch:  0,
  1769  			ExitEpoch:        params.BeaconConfig().FarFutureEpoch,
  1770  		},
  1771  	}
  1772  	require.NoError(t, headState.SetValidators(validators))
  1773  	offset := int64(headState.Slot().Mul(params.BeaconConfig().SecondsPerSlot))
  1774  	bs := &Server{
  1775  		HeadFetcher: &mock.ChainService{
  1776  			// 10 epochs into the future.
  1777  			State: headState,
  1778  		},
  1779  		SyncChecker:        &mockSync.Sync{IsSyncing: false},
  1780  		GenesisTimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)},
  1781  	}
  1782  	c := headState.Copy()
  1783  	vp, bp, err := precompute.New(ctx, c)
  1784  	require.NoError(t, err)
  1785  	vp, bp, err = precompute.ProcessAttestations(ctx, c, vp, bp)
  1786  	require.NoError(t, err)
  1787  	_, err = precompute.ProcessRewardsAndPenaltiesPrecompute(c, bp, vp, precompute.AttestationsDelta, precompute.ProposersDelta)
  1788  	require.NoError(t, err)
  1789  	farFuture := params.BeaconConfig().FarFutureSlot
  1790  	want := &ethpb.ValidatorPerformanceResponse{
  1791  		PublicKeys:                    [][]byte{publicKey2[:], publicKey3[:]},
  1792  		CurrentEffectiveBalances:      []uint64{params.BeaconConfig().MaxEffectiveBalance, params.BeaconConfig().MaxEffectiveBalance},
  1793  		InclusionSlots:                []types.Slot{farFuture, farFuture},
  1794  		InclusionDistances:            []types.Slot{farFuture, farFuture},
  1795  		CorrectlyVotedSource:          []bool{false, false},
  1796  		CorrectlyVotedTarget:          []bool{false, false},
  1797  		CorrectlyVotedHead:            []bool{false, false},
  1798  		BalancesBeforeEpochTransition: []uint64{extraBal, extraBal + params.BeaconConfig().GweiPerEth},
  1799  		BalancesAfterEpochTransition:  []uint64{vp[1].AfterEpochTransitionBalance, vp[2].AfterEpochTransitionBalance},
  1800  		MissingValidators:             [][]byte{publicKey1[:]},
  1801  	}
  1802  
  1803  	res, err := bs.GetValidatorPerformance(ctx, &ethpb.ValidatorPerformanceRequest{
  1804  		Indices: []types.ValidatorIndex{2, 1, 0},
  1805  	})
  1806  	require.NoError(t, err)
  1807  	if !proto.Equal(want, res) {
  1808  		t.Errorf("Wanted %v\nReceived %v", want, res)
  1809  	}
  1810  }
  1811  
  1812  func TestGetValidatorPerformance_IndicesPubkeys(t *testing.T) {
  1813  	ctx := context.Background()
  1814  	epoch := types.Epoch(1)
  1815  	defaultBal := params.BeaconConfig().MaxEffectiveBalance
  1816  	extraBal := params.BeaconConfig().MaxEffectiveBalance + params.BeaconConfig().GweiPerEth
  1817  	headState, err := testutil.NewBeaconState()
  1818  	require.NoError(t, err)
  1819  	require.NoError(t, headState.SetSlot(params.BeaconConfig().SlotsPerEpoch.Mul(uint64(epoch+1))))
  1820  	balances := []uint64{defaultBal, extraBal, extraBal + params.BeaconConfig().GweiPerEth}
  1821  	require.NoError(t, headState.SetBalances(balances))
  1822  	publicKey1 := bytesutil.ToBytes48([]byte{1})
  1823  	publicKey2 := bytesutil.ToBytes48([]byte{2})
  1824  	publicKey3 := bytesutil.ToBytes48([]byte{3})
  1825  	validators := []*ethpb.Validator{
  1826  		{
  1827  			PublicKey:       publicKey1[:],
  1828  			ActivationEpoch: 5,
  1829  			ExitEpoch:       params.BeaconConfig().FarFutureEpoch,
  1830  		},
  1831  		{
  1832  			PublicKey:        publicKey2[:],
  1833  			EffectiveBalance: defaultBal,
  1834  			ActivationEpoch:  0,
  1835  			ExitEpoch:        params.BeaconConfig().FarFutureEpoch,
  1836  		},
  1837  		{
  1838  			PublicKey:        publicKey3[:],
  1839  			EffectiveBalance: defaultBal,
  1840  			ActivationEpoch:  0,
  1841  			ExitEpoch:        params.BeaconConfig().FarFutureEpoch,
  1842  		},
  1843  	}
  1844  	require.NoError(t, headState.SetValidators(validators))
  1845  
  1846  	offset := int64(headState.Slot().Mul(params.BeaconConfig().SecondsPerSlot))
  1847  	bs := &Server{
  1848  		HeadFetcher: &mock.ChainService{
  1849  			// 10 epochs into the future.
  1850  			State: headState,
  1851  		},
  1852  		SyncChecker:        &mockSync.Sync{IsSyncing: false},
  1853  		GenesisTimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)},
  1854  	}
  1855  	c := headState.Copy()
  1856  	vp, bp, err := precompute.New(ctx, c)
  1857  	require.NoError(t, err)
  1858  	vp, bp, err = precompute.ProcessAttestations(ctx, c, vp, bp)
  1859  	require.NoError(t, err)
  1860  	_, err = precompute.ProcessRewardsAndPenaltiesPrecompute(c, bp, vp, precompute.AttestationsDelta, precompute.ProposersDelta)
  1861  	require.NoError(t, err)
  1862  	farFuture := params.BeaconConfig().FarFutureSlot
  1863  	want := &ethpb.ValidatorPerformanceResponse{
  1864  		PublicKeys:                    [][]byte{publicKey2[:], publicKey3[:]},
  1865  		CurrentEffectiveBalances:      []uint64{params.BeaconConfig().MaxEffectiveBalance, params.BeaconConfig().MaxEffectiveBalance},
  1866  		InclusionSlots:                []types.Slot{farFuture, farFuture},
  1867  		InclusionDistances:            []types.Slot{farFuture, farFuture},
  1868  		CorrectlyVotedSource:          []bool{false, false},
  1869  		CorrectlyVotedTarget:          []bool{false, false},
  1870  		CorrectlyVotedHead:            []bool{false, false},
  1871  		BalancesBeforeEpochTransition: []uint64{extraBal, extraBal + params.BeaconConfig().GweiPerEth},
  1872  		BalancesAfterEpochTransition:  []uint64{vp[1].AfterEpochTransitionBalance, vp[2].AfterEpochTransitionBalance},
  1873  		MissingValidators:             [][]byte{publicKey1[:]},
  1874  	}
  1875  	// Index 2 and publicKey3 points to the same validator.
  1876  	// Should not return duplicates.
  1877  	res, err := bs.GetValidatorPerformance(ctx, &ethpb.ValidatorPerformanceRequest{
  1878  		PublicKeys: [][]byte{publicKey1[:], publicKey3[:]}, Indices: []types.ValidatorIndex{1, 2},
  1879  	})
  1880  	require.NoError(t, err)
  1881  	if !proto.Equal(want, res) {
  1882  		t.Errorf("Wanted %v\nReceived %v", want, res)
  1883  	}
  1884  }
  1885  
  1886  func BenchmarkListValidatorBalances(b *testing.B) {
  1887  	b.StopTimer()
  1888  	beaconDB := dbTest.SetupDB(b)
  1889  	ctx := context.Background()
  1890  
  1891  	count := 1000
  1892  	_, _, headState := setupValidators(b, beaconDB, count)
  1893  	bs := &Server{
  1894  		HeadFetcher: &mock.ChainService{
  1895  			State: headState,
  1896  		},
  1897  	}
  1898  
  1899  	req := &ethpb.ListValidatorBalancesRequest{PageSize: 100}
  1900  	b.StartTimer()
  1901  	for i := 0; i < b.N; i++ {
  1902  		_, err := bs.ListValidatorBalances(ctx, req)
  1903  		require.NoError(b, err)
  1904  	}
  1905  }
  1906  
  1907  func setupValidators(t testing.TB, _ db.Database, count int) ([]*ethpb.Validator, []uint64, iface.BeaconState) {
  1908  	balances := make([]uint64, count)
  1909  	validators := make([]*ethpb.Validator, 0, count)
  1910  	for i := 0; i < count; i++ {
  1911  		pubKey := pubKey(uint64(i))
  1912  		balances[i] = uint64(i)
  1913  		validators = append(validators, &ethpb.Validator{
  1914  			PublicKey:             pubKey,
  1915  			WithdrawalCredentials: make([]byte, 32),
  1916  		})
  1917  	}
  1918  	s, err := testutil.NewBeaconState()
  1919  	require.NoError(t, err)
  1920  	require.NoError(t, s.SetValidators(validators))
  1921  	require.NoError(t, s.SetBalances(balances))
  1922  	return validators, balances, s
  1923  }
  1924  
  1925  func TestServer_GetIndividualVotes_RequestFutureSlot(t *testing.T) {
  1926  	ds := &Server{GenesisTimeFetcher: &mock.ChainService{}}
  1927  	req := &ethpb.IndividualVotesRequest{
  1928  		Epoch: helpers.SlotToEpoch(ds.GenesisTimeFetcher.CurrentSlot()) + 1,
  1929  	}
  1930  	wanted := errNoEpochInfoError
  1931  	_, err := ds.GetIndividualVotes(context.Background(), req)
  1932  	assert.ErrorContains(t, wanted, err)
  1933  }
  1934  
  1935  func TestServer_GetIndividualVotes_ValidatorsDontExist(t *testing.T) {
  1936  	params.UseMinimalConfig()
  1937  	defer params.UseMainnetConfig()
  1938  
  1939  	beaconDB := dbTest.SetupDB(t)
  1940  	ctx := context.Background()
  1941  
  1942  	validators := uint64(64)
  1943  	stateWithValidators, _ := testutil.DeterministicGenesisState(t, validators)
  1944  	beaconState, err := testutil.NewBeaconState()
  1945  	require.NoError(t, err)
  1946  	require.NoError(t, beaconState.SetValidators(stateWithValidators.Validators()))
  1947  	require.NoError(t, beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch))
  1948  
  1949  	b := testutil.NewBeaconBlock()
  1950  	b.Block.Slot = params.BeaconConfig().SlotsPerEpoch
  1951  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b)))
  1952  	gRoot, err := b.Block.HashTreeRoot()
  1953  	require.NoError(t, err)
  1954  	gen := stategen.New(beaconDB)
  1955  	require.NoError(t, gen.SaveState(ctx, gRoot, beaconState))
  1956  	require.NoError(t, beaconDB.SaveState(ctx, beaconState, gRoot))
  1957  	require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
  1958  	bs := &Server{
  1959  		StateGen:           gen,
  1960  		GenesisTimeFetcher: &mock.ChainService{},
  1961  	}
  1962  
  1963  	// Test non exist public key.
  1964  	res, err := bs.GetIndividualVotes(ctx, &ethpb.IndividualVotesRequest{
  1965  		PublicKeys: [][]byte{{'a'}},
  1966  		Epoch:      0,
  1967  	})
  1968  	require.NoError(t, err)
  1969  	wanted := &ethpb.IndividualVotesRespond{
  1970  		IndividualVotes: []*ethpb.IndividualVotesRespond_IndividualVote{
  1971  			{PublicKey: []byte{'a'}, ValidatorIndex: types.ValidatorIndex(^uint64(0))},
  1972  		},
  1973  	}
  1974  	assert.DeepEqual(t, wanted, res, "Unexpected response")
  1975  
  1976  	// Test non-existent validator index.
  1977  	res, err = bs.GetIndividualVotes(ctx, &ethpb.IndividualVotesRequest{
  1978  		Indices: []types.ValidatorIndex{100},
  1979  		Epoch:   0,
  1980  	})
  1981  	require.NoError(t, err)
  1982  	wanted = &ethpb.IndividualVotesRespond{
  1983  		IndividualVotes: []*ethpb.IndividualVotesRespond_IndividualVote{
  1984  			{ValidatorIndex: 100},
  1985  		},
  1986  	}
  1987  	assert.DeepEqual(t, wanted, res, "Unexpected response")
  1988  
  1989  	// Test both.
  1990  	res, err = bs.GetIndividualVotes(ctx, &ethpb.IndividualVotesRequest{
  1991  		PublicKeys: [][]byte{{'a'}, {'b'}},
  1992  		Indices:    []types.ValidatorIndex{100, 101},
  1993  		Epoch:      0,
  1994  	})
  1995  	require.NoError(t, err)
  1996  	wanted = &ethpb.IndividualVotesRespond{
  1997  		IndividualVotes: []*ethpb.IndividualVotesRespond_IndividualVote{
  1998  			{PublicKey: []byte{'a'}, ValidatorIndex: types.ValidatorIndex(^uint64(0))},
  1999  			{PublicKey: []byte{'b'}, ValidatorIndex: types.ValidatorIndex(^uint64(0))},
  2000  			{ValidatorIndex: 100},
  2001  			{ValidatorIndex: 101},
  2002  		},
  2003  	}
  2004  	assert.DeepEqual(t, wanted, res, "Unexpected response")
  2005  }
  2006  
  2007  func TestServer_GetIndividualVotes_Working(t *testing.T) {
  2008  	helpers.ClearCache()
  2009  
  2010  	params.UseMinimalConfig()
  2011  	defer params.UseMainnetConfig()
  2012  	beaconDB := dbTest.SetupDB(t)
  2013  	ctx := context.Background()
  2014  
  2015  	validators := uint64(32)
  2016  	stateWithValidators, _ := testutil.DeterministicGenesisState(t, validators)
  2017  	beaconState, err := testutil.NewBeaconState()
  2018  	require.NoError(t, err)
  2019  	require.NoError(t, beaconState.SetValidators(stateWithValidators.Validators()))
  2020  	require.NoError(t, beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch))
  2021  
  2022  	bf := bitfield.NewBitlist(validators / uint64(params.BeaconConfig().SlotsPerEpoch))
  2023  	att1 := testutil.NewAttestation()
  2024  	att1.AggregationBits = bf
  2025  	att2 := testutil.NewAttestation()
  2026  	att2.AggregationBits = bf
  2027  	rt := [32]byte{'A'}
  2028  	att1.Data.Target.Root = rt[:]
  2029  	att1.Data.BeaconBlockRoot = rt[:]
  2030  	br := beaconState.BlockRoots()
  2031  	newRt := [32]byte{'B'}
  2032  	br[0] = newRt[:]
  2033  	require.NoError(t, beaconState.SetBlockRoots(br))
  2034  	att2.Data.Target.Root = rt[:]
  2035  	att2.Data.BeaconBlockRoot = newRt[:]
  2036  	err = beaconState.AppendPreviousEpochAttestations(&pb.PendingAttestation{
  2037  		Data: att1.Data, AggregationBits: bf, InclusionDelay: 1,
  2038  	})
  2039  	require.NoError(t, err)
  2040  	err = beaconState.AppendCurrentEpochAttestations(&pb.PendingAttestation{
  2041  		Data: att2.Data, AggregationBits: bf, InclusionDelay: 1,
  2042  	})
  2043  	require.NoError(t, err)
  2044  
  2045  	b := testutil.NewBeaconBlock()
  2046  	b.Block.Slot = params.BeaconConfig().SlotsPerEpoch
  2047  	require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b)))
  2048  	gRoot, err := b.Block.HashTreeRoot()
  2049  	require.NoError(t, err)
  2050  	gen := stategen.New(beaconDB)
  2051  	require.NoError(t, gen.SaveState(ctx, gRoot, beaconState))
  2052  	require.NoError(t, beaconDB.SaveState(ctx, beaconState, gRoot))
  2053  	require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, gRoot))
  2054  	bs := &Server{
  2055  		StateGen:           gen,
  2056  		GenesisTimeFetcher: &mock.ChainService{},
  2057  	}
  2058  
  2059  	res, err := bs.GetIndividualVotes(ctx, &ethpb.IndividualVotesRequest{
  2060  		Indices: []types.ValidatorIndex{0, 1},
  2061  		Epoch:   0,
  2062  	})
  2063  	require.NoError(t, err)
  2064  	wanted := &ethpb.IndividualVotesRespond{
  2065  		IndividualVotes: []*ethpb.IndividualVotesRespond_IndividualVote{
  2066  			{
  2067  				ValidatorIndex:                   0,
  2068  				PublicKey:                        beaconState.Validators()[0].PublicKey,
  2069  				IsActiveInCurrentEpoch:           true,
  2070  				IsActiveInPreviousEpoch:          true,
  2071  				CurrentEpochEffectiveBalanceGwei: params.BeaconConfig().MaxEffectiveBalance,
  2072  				InclusionSlot:                    params.BeaconConfig().FarFutureSlot,
  2073  				InclusionDistance:                params.BeaconConfig().FarFutureSlot,
  2074  			},
  2075  			{
  2076  				ValidatorIndex:                   1,
  2077  				PublicKey:                        beaconState.Validators()[1].PublicKey,
  2078  				IsActiveInCurrentEpoch:           true,
  2079  				IsActiveInPreviousEpoch:          true,
  2080  				CurrentEpochEffectiveBalanceGwei: params.BeaconConfig().MaxEffectiveBalance,
  2081  				InclusionSlot:                    params.BeaconConfig().FarFutureSlot,
  2082  				InclusionDistance:                params.BeaconConfig().FarFutureSlot,
  2083  			},
  2084  		},
  2085  	}
  2086  	assert.DeepEqual(t, wanted, res, "Unexpected response")
  2087  }
  2088  
  2089  func Test_validatorStatus(t *testing.T) {
  2090  	tests := []struct {
  2091  		name      string
  2092  		validator *ethpb.Validator
  2093  		epoch     types.Epoch
  2094  		want      ethpb.ValidatorStatus
  2095  	}{
  2096  		{
  2097  			name:      "Unknown",
  2098  			validator: nil,
  2099  			epoch:     0,
  2100  			want:      ethpb.ValidatorStatus_UNKNOWN_STATUS,
  2101  		},
  2102  		{
  2103  			name: "Deposited",
  2104  			validator: &ethpb.Validator{
  2105  				ActivationEligibilityEpoch: 1,
  2106  			},
  2107  			epoch: 0,
  2108  			want:  ethpb.ValidatorStatus_DEPOSITED,
  2109  		},
  2110  		{
  2111  			name: "Pending",
  2112  			validator: &ethpb.Validator{
  2113  				ActivationEligibilityEpoch: 0,
  2114  				ActivationEpoch:            1,
  2115  			},
  2116  			epoch: 0,
  2117  			want:  ethpb.ValidatorStatus_PENDING,
  2118  		},
  2119  		{
  2120  			name: "Active",
  2121  			validator: &ethpb.Validator{
  2122  				ActivationEligibilityEpoch: 0,
  2123  				ActivationEpoch:            0,
  2124  				ExitEpoch:                  params.BeaconConfig().FarFutureEpoch,
  2125  			},
  2126  			epoch: 0,
  2127  			want:  ethpb.ValidatorStatus_ACTIVE,
  2128  		},
  2129  		{
  2130  			name: "Slashed",
  2131  			validator: &ethpb.Validator{
  2132  				ActivationEligibilityEpoch: 0,
  2133  				ActivationEpoch:            0,
  2134  				ExitEpoch:                  5,
  2135  				Slashed:                    true,
  2136  			},
  2137  			epoch: 4,
  2138  			want:  ethpb.ValidatorStatus_SLASHING,
  2139  		},
  2140  		{
  2141  			name: "Exiting",
  2142  			validator: &ethpb.Validator{
  2143  				ActivationEligibilityEpoch: 0,
  2144  				ActivationEpoch:            0,
  2145  				ExitEpoch:                  5,
  2146  				Slashed:                    false,
  2147  			},
  2148  			epoch: 4,
  2149  			want:  ethpb.ValidatorStatus_EXITING,
  2150  		},
  2151  		{
  2152  			name: "Exiting",
  2153  			validator: &ethpb.Validator{
  2154  				ActivationEligibilityEpoch: 0,
  2155  				ActivationEpoch:            0,
  2156  				ExitEpoch:                  3,
  2157  				Slashed:                    false,
  2158  			},
  2159  			epoch: 4,
  2160  			want:  ethpb.ValidatorStatus_EXITED,
  2161  		},
  2162  	}
  2163  	for _, tt := range tests {
  2164  		t.Run(tt.name, func(t *testing.T) {
  2165  			if got := validatorStatus(tt.validator, tt.epoch); got != tt.want {
  2166  				t.Errorf("validatorStatus() = %v, want %v", got, tt.want)
  2167  			}
  2168  		})
  2169  	}
  2170  }
  2171  
  2172  func TestServer_isSlotCanonical(t *testing.T) {
  2173  	beaconDB := dbTest.SetupDB(t)
  2174  	ctx := context.Background()
  2175  	var roots [][32]byte
  2176  	cRoots := map[[32]byte]bool{}
  2177  	for i := 1; i < 100; i++ {
  2178  		b := testutil.NewBeaconBlock()
  2179  		b.Block.Slot = types.Slot(i)
  2180  		require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b)))
  2181  		br, err := b.Block.HashTreeRoot()
  2182  		require.NoError(t, err)
  2183  		if i%2 == 0 {
  2184  			cRoots[br] = true
  2185  		}
  2186  		roots = append(roots, br)
  2187  	}
  2188  
  2189  	bs := &Server{
  2190  		BeaconDB: beaconDB,
  2191  		CanonicalFetcher: &mock.ChainService{
  2192  			CanonicalRoots: cRoots,
  2193  		},
  2194  	}
  2195  
  2196  	for i := range roots {
  2197  		slot := types.Slot(i + 1)
  2198  		c, err := bs.isSlotCanonical(ctx, slot)
  2199  		require.NoError(t, err)
  2200  		if slot%2 == 0 {
  2201  			require.Equal(t, true, c)
  2202  		} else {
  2203  			require.Equal(t, false, c)
  2204  		}
  2205  	}
  2206  }
  2207  
  2208  func TestServer_isSlotCanonical_MultipleBlocks(t *testing.T) {
  2209  	beaconDB := dbTest.SetupDB(t)
  2210  	ctx := context.Background()
  2211  	var roots [][32]byte
  2212  	cRoots := map[[32]byte]bool{}
  2213  	for i := 1; i < 100; i++ {
  2214  		b := testutil.NewBeaconBlock()
  2215  		b.Block.Slot = types.Slot(i)
  2216  		require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b)))
  2217  		br, err := b.Block.HashTreeRoot()
  2218  		require.NoError(t, err)
  2219  		if i%2 == 0 {
  2220  			cRoots[br] = true
  2221  			// Save a block in the same slot
  2222  			b = testutil.NewBeaconBlock()
  2223  			b.Block.Slot = types.Slot(i)
  2224  			b.Block.ProposerIndex = 100
  2225  			require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b)))
  2226  		}
  2227  		roots = append(roots, br)
  2228  	}
  2229  
  2230  	bs := &Server{
  2231  		BeaconDB: beaconDB,
  2232  		CanonicalFetcher: &mock.ChainService{
  2233  			CanonicalRoots: cRoots,
  2234  		},
  2235  	}
  2236  
  2237  	for i := range roots {
  2238  		slot := types.Slot(i + 1)
  2239  		c, err := bs.isSlotCanonical(ctx, slot)
  2240  		require.NoError(t, err)
  2241  		if slot%2 == 0 {
  2242  			require.Equal(t, true, c)
  2243  		} else {
  2244  			require.Equal(t, false, c)
  2245  		}
  2246  	}
  2247  }
  2248  
  2249  func TestServer_isSlotCanonicalForSlot0(t *testing.T) {
  2250  	ctx := context.Background()
  2251  	bs := &Server{}
  2252  	c, err := bs.isSlotCanonical(ctx, 0)
  2253  	require.NoError(t, err)
  2254  	require.Equal(t, true, c)
  2255  }