package rpc import ( "context" "fmt" "strings" "testing" "github.com/gogo/protobuf/proto" "github.com/prysmaticlabs/prysm/beacon-chain/internal" pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" ) func TestBeaconChainServer_ListValidatorBalances(t *testing.T) { db := internal.SetupDB(t) defer internal.TeardownDB(t, db) count := 100 balances := make([]uint64, count) validators := make([]*ethpb.Validator, 0, count) for i := 0; i < count; i++ { if err := db.SaveValidatorIndex([]byte{byte(i)}, i); err != nil { t.Fatal(err) } balances[i] = uint64(i) validators = append(validators, ðpb.Validator{PublicKey: []byte{byte(i)}}) } if err := db.SaveState( context.Background(), &pbp2p.BeaconState{Validators: validators, Balances: balances}); err != nil { t.Fatal(err) } bs := &BeaconChainServer{ beaconDB: db, } tests := []struct { req *ethpb.GetValidatorBalancesRequest res *ethpb.ValidatorBalances }{ {req: ðpb.GetValidatorBalancesRequest{PublicKeys: [][]byte{{99}}}, res: ðpb.ValidatorBalances{Balances: []*ethpb.ValidatorBalances_Balance{{ Index: 99, PublicKey: []byte{99}, Balance: 99}}, }}, {req: ðpb.GetValidatorBalancesRequest{Indices: []uint64{1, 2, 3}}, res: ðpb.ValidatorBalances{Balances: []*ethpb.ValidatorBalances_Balance{ {Index: 1, PublicKey: []byte{1}, Balance: 1}, {Index: 2, PublicKey: []byte{2}, Balance: 2}, {Index: 3, PublicKey: []byte{3}, Balance: 3}}, }}, {req: ðpb.GetValidatorBalancesRequest{PublicKeys: [][]byte{{10}, {11}, {12}}}, res: ðpb.ValidatorBalances{Balances: []*ethpb.ValidatorBalances_Balance{ {Index: 10, PublicKey: []byte{10}, Balance: 10}, {Index: 11, PublicKey: []byte{11}, Balance: 11}, {Index: 12, PublicKey: []byte{12}, Balance: 12}}, }}, {req: ðpb.GetValidatorBalancesRequest{PublicKeys: [][]byte{{2}, {3}}, Indices: []uint64{3, 4}}, // Duplication res: ðpb.ValidatorBalances{Balances: []*ethpb.ValidatorBalances_Balance{ {Index: 2, PublicKey: []byte{2}, Balance: 2}, {Index: 3, PublicKey: []byte{3}, Balance: 3}, {Index: 4, PublicKey: []byte{4}, Balance: 4}}, }}, } for _, test := range tests { res, err := bs.ListValidatorBalances(context.Background(), test.req) if err != nil { t.Fatal(err) } if !proto.Equal(res, test.res) { t.Error("Incorrect respond of validator balances") } } } func TestBeaconChainServer_ListValidatorBalancesOutOfRange(t *testing.T) { db := internal.SetupDB(t) defer internal.TeardownDB(t, db) count := 1 balances := make([]uint64, count) validators := make([]*ethpb.Validator, 0, count) for i := 0; i < count; i++ { if err := db.SaveValidatorIndex([]byte{byte(i)}, i); err != nil { t.Fatal(err) } balances[i] = uint64(i) validators = append(validators, ðpb.Validator{PublicKey: []byte{byte(i)}}) } if err := db.SaveState( context.Background(), &pbp2p.BeaconState{Validators: validators, Balances: balances}); err != nil { t.Fatal(err) } bs := &BeaconChainServer{ beaconDB: db, } req := ðpb.GetValidatorBalancesRequest{Indices: []uint64{uint64(count)}} wanted := fmt.Sprintf("validator index %d >= balance list %d", count, len(balances)) if _, err := bs.ListValidatorBalances(context.Background(), req); !strings.Contains(err.Error(), wanted) { t.Errorf("Expected error %v, received %v", wanted, err) } }