Implement GetValidator RPC Endpoint (#4188)

* include new patch targeting latest ethapis master
* ensure project builds
* Merge branch 'master' into update-all-api
* fix up committees
* Merge branch 'update-all-api' of github.com:prysmaticlabs/prysm into update-all-api
* include latest eth apis
* Merge branch 'master' into update-all-api
* update block tests
* Merge branch 'update-all-api' of github.com:prysmaticlabs/prysm into update-all-api
* Merge branch 'master' into update-all-api
* add todos
* implement get validator rpc
* add test for get validator
* table driven test
* fix up test
* fix confs
* tests for more cases
* fix up tests and add out of range
This commit is contained in:
Raul Jordan
2019-12-03 16:33:34 -08:00
committed by prylabs-bulldozer[bot]
parent c31f46d973
commit 90cbe49496
2 changed files with 129 additions and 3 deletions

View File

@@ -1,6 +1,7 @@
package beacon
import (
"bytes"
"context"
"sort"
"strconv"
@@ -248,11 +249,45 @@ func (bs *Server) ListValidators(
}
// GetValidator information from any validator in the registry by index or public key.
// TODO(#4177): Implement.
func (bs *Server) GetValidator(
_ context.Context, _ *ethpb.GetValidatorRequest,
ctx context.Context, req *ethpb.GetValidatorRequest,
) (*ethpb.Validator, error) {
return nil, status.Error(codes.Unimplemented, "Not yet implemented")
var requestingIndex bool
var index uint64
var pubKey []byte
switch q := req.QueryFilter.(type) {
case *ethpb.GetValidatorRequest_Index:
index = q.Index
requestingIndex = true
case *ethpb.GetValidatorRequest_PublicKey:
pubKey = q.PublicKey
default:
return nil, status.Error(
codes.InvalidArgument,
"Need to specify either validator index or public key in request",
)
}
headState, err := bs.HeadFetcher.HeadState(ctx)
if err != nil {
return nil, status.Error(codes.Internal, "Could not get head state")
}
if requestingIndex {
if index >= uint64(len(headState.Validators)) {
return nil, status.Errorf(
codes.OutOfRange,
"Requesting index %d, but there are only %d validators",
index,
len(headState.Validators),
)
}
return headState.Validators[index], nil
}
for i := 0; i < len(headState.Validators); i++ {
if bytes.Equal(headState.Validators[i].PublicKey, pubKey) {
return headState.Validators[i], nil
}
}
return nil, status.Error(codes.NotFound, "No validator matched filter criteria")
}
// GetValidatorActiveSetChanges retrieves the active set changes for a given epoch.

View File

@@ -806,6 +806,97 @@ func TestServer_ListValidators_FromOldEpoch(t *testing.T) {
}
}
func TestServer_GetValidator(t *testing.T) {
db := dbTest.SetupDB(t)
defer dbTest.TeardownDB(t, db)
count := 30
validators := make([]*ethpb.Validator, count)
for i := 0; i < count; i++ {
validators[i] = &ethpb.Validator{
ActivationEpoch: uint64(i),
PublicKey: []byte(strconv.Itoa(i)),
}
}
bs := &Server{
HeadFetcher: &mock.ChainService{
State: &pbp2p.BeaconState{
Validators: validators,
},
},
}
tests := []struct {
req *ethpb.GetValidatorRequest
res *ethpb.Validator
wantErr bool
err string
}{
{
req: &ethpb.GetValidatorRequest{
QueryFilter: &ethpb.GetValidatorRequest_Index{
Index: 0,
},
},
res: validators[0],
wantErr: false,
},
{
req: &ethpb.GetValidatorRequest{
QueryFilter: &ethpb.GetValidatorRequest_Index{
Index: uint64(count - 1),
},
},
res: validators[count-1],
wantErr: false,
},
{
req: &ethpb.GetValidatorRequest{
QueryFilter: &ethpb.GetValidatorRequest_PublicKey{
PublicKey: []byte(strconv.Itoa(5)),
},
},
res: validators[5],
wantErr: false,
},
{
req: &ethpb.GetValidatorRequest{
QueryFilter: &ethpb.GetValidatorRequest_PublicKey{
PublicKey: []byte("bad-key"),
},
},
res: nil,
wantErr: true,
err: "No validator matched filter criteria",
},
{
req: &ethpb.GetValidatorRequest{
QueryFilter: &ethpb.GetValidatorRequest_Index{
Index: uint64(len(validators)),
},
},
res: nil,
wantErr: true,
err: fmt.Sprintf("there are only %d validators", len(validators)),
},
}
for _, test := range tests {
res, err := bs.GetValidator(context.Background(), test.req)
if test.wantErr && err != nil {
if !strings.Contains(err.Error(), test.err) {
t.Fatalf("Wanted %v, received %v", test.err, err)
}
} else if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(test.res, res) {
t.Errorf("Wanted %v, got %v", test.res, res)
}
}
}
func TestServer_GetValidatorActiveSetChanges_CannotRequestFutureEpoch(t *testing.T) {
db := dbTest.SetupDB(t)
defer dbTest.TeardownDB(t, db)