From 8f8d2d36c01e1405cd9547a138cb11bc7b650150 Mon Sep 17 00:00:00 2001 From: Raul Jordan Date: Thu, 21 Nov 2019 14:29:24 -0600 Subject: [PATCH] Filter ListValidators by Active in RPC (#4061) * update workspace * include active filter * fix up latest changes to match naming * better comments, fix evaluators * latest master * filter items * filter only active validators --- beacon-chain/rpc/beacon/validators.go | 26 ++++++++--- beacon-chain/rpc/beacon/validators_test.go | 52 ++++++++++++++++++++++ 2 files changed, 71 insertions(+), 7 deletions(-) diff --git a/beacon-chain/rpc/beacon/validators.go b/beacon-chain/rpc/beacon/validators.go index 55797724d0..f1a61d3794 100644 --- a/beacon-chain/rpc/beacon/validators.go +++ b/beacon-chain/rpc/beacon/validators.go @@ -187,10 +187,10 @@ func (bs *Server) ListValidators( requestedEpoch = q.Epoch } - validators := headState.Validators + vals := headState.Validators if requestedEpoch < currentEpoch { - stopIdx := len(validators) - for idx, val := range validators { + stopIdx := len(vals) + for idx, val := range vals { // The first time we see a validator with an activation epoch > the requested epoch, // we know this validator is from the future relative to what the request wants. if val.ActivationEpoch > requestedEpoch { @@ -198,7 +198,7 @@ func (bs *Server) ListValidators( break } } - validators = validators[:stopIdx] + vals = vals[:stopIdx] } else if requestedEpoch > currentEpoch { // Otherwise, we are requesting data from the future and we return an error. return nil, status.Errorf( @@ -209,8 +209,20 @@ func (bs *Server) ListValidators( ) } - validatorCount := len(validators) - // If there are no validators, we simply return a response specifying this. + // Filter active validators if the request specifies it. + res := vals + if req.Active { + filteredValidators := make([]*ethpb.Validator, 0) + for _, val := range vals { + if helpers.IsActiveValidator(val, requestedEpoch) { + filteredValidators = append(filteredValidators, val) + } + } + res = filteredValidators + } + + validatorCount := len(res) + // If there are no items, we simply return a response specifying this. // Otherwise, attempting to paginate 0 validators below would result in an error. if validatorCount == 0 { return ðpb.Validators{ @@ -230,7 +242,7 @@ func (bs *Server) ListValidators( } return ðpb.Validators{ - Validators: validators[start:end], + Validators: res[start:end], TotalSize: int32(validatorCount), NextPageToken: nextPageToken, }, nil diff --git a/beacon-chain/rpc/beacon/validators_test.go b/beacon-chain/rpc/beacon/validators_test.go index 4fb76542a2..9766c78724 100644 --- a/beacon-chain/rpc/beacon/validators_test.go +++ b/beacon-chain/rpc/beacon/validators_test.go @@ -430,6 +430,58 @@ func TestServer_ListValidators_NoResults(t *testing.T) { } } +func TestServer_ListValidators_OnlyActiveValidators(t *testing.T) { + db := dbTest.SetupDB(t) + defer dbTest.TeardownDB(t, db) + + ctx := context.Background() + count := 100 + balances := make([]uint64, count) + validators := make([]*ethpb.Validator, count) + activeValidators := make([]*ethpb.Validator, 0) + for i := 0; i < count; i++ { + if err := db.SaveValidatorIndex(ctx, [48]byte{byte(i)}, uint64(i)); err != nil { + t.Fatal(err) + } + balances[i] = params.BeaconConfig().MaxEffectiveBalance + + // We mark even validators as active, and odd validators as inactive. + if i%2 == 0 { + val := ðpb.Validator{ + PublicKey: []byte{byte(i)}, + ActivationEpoch: 0, + ExitEpoch: params.BeaconConfig().FarFutureEpoch, + } + validators[i] = val + activeValidators = append(activeValidators, val) + } else { + validators[i] = ðpb.Validator{ + PublicKey: []byte{byte(i)}, + ActivationEpoch: 0, + ExitEpoch: 0, + } + } + } + headState := &pbp2p.BeaconState{Validators: validators, Balances: balances} + + bs := &Server{ + HeadFetcher: &mock.ChainService{ + State: headState, + }, + } + + received, err := bs.ListValidators(context.Background(), ðpb.ListValidatorsRequest{ + Active: true, + }) + if err != nil { + t.Fatal(err) + } + + if !reflect.DeepEqual(activeValidators, received.Validators) { + t.Errorf("Wanted %v, received %v", activeValidators, received.Validators) + } +} + func TestServer_ListValidators_NoPagination(t *testing.T) { db := dbTest.SetupDB(t) defer dbTest.TeardownDB(t, db)