diff --git a/beacon-chain/rpc/beacon/validators.go b/beacon-chain/rpc/beacon/validators.go index 80a9d564ed0e..2e45be2cd25c 100644 --- a/beacon-chain/rpc/beacon/validators.go +++ b/beacon-chain/rpc/beacon/validators.go @@ -272,19 +272,6 @@ func (bs *Server) ListValidators( } } - if requestedEpoch < currentEpoch { - stopIdx := len(validatorList) - for idx, item := range validatorList { - // 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 item.Validator.ActivationEpoch > requestedEpoch { - stopIdx = idx - break - } - } - validatorList = validatorList[:stopIdx] - } - // Filter active validators if the request specifies it. res := validatorList if req.Active { diff --git a/beacon-chain/rpc/beacon/validators_test.go b/beacon-chain/rpc/beacon/validators_test.go index a765d53c93da..6a831a9b3cc4 100644 --- a/beacon-chain/rpc/beacon/validators_test.go +++ b/beacon-chain/rpc/beacon/validators_test.go @@ -528,6 +528,75 @@ func TestServer_ListValidators_OnlyActiveValidators(t *testing.T) { assert.DeepEqual(t, activeValidators, received.ValidatorList) } +func TestServer_ListValidators_InactiveInTheMiddle(t *testing.T) { + ctx := context.Background() + db, _ := dbTest.SetupDB(t) + count := 100 + balances := make([]uint64, count) + validators := make([]*ethpb.Validator, count) + activeValidators := make([]*ethpb.Validators_ValidatorContainer, 0) + for i := 0; i < count; i++ { + pubKey := pubKey(uint64(i)) + balances[i] = params.BeaconConfig().MaxEffectiveBalance + + // We mark even validators as active, and odd validators as inactive. + if i%2 == 0 { + val := ðpb.Validator{ + PublicKey: pubKey, + WithdrawalCredentials: make([]byte, 32), + ActivationEpoch: 0, + ExitEpoch: params.BeaconConfig().FarFutureEpoch, + } + validators[i] = val + activeValidators = append(activeValidators, ðpb.Validators_ValidatorContainer{ + Index: uint64(i), + Validator: val, + }) + } else { + validators[i] = ðpb.Validator{ + PublicKey: pubKey, + WithdrawalCredentials: make([]byte, 32), + ActivationEpoch: 0, + ExitEpoch: 0, + } + } + } + + // Set first validator to be inactive. + validators[0].ActivationEpoch = params.BeaconConfig().FarFutureEpoch + activeValidators[0].Validator.ActivationEpoch = params.BeaconConfig().FarFutureEpoch + + st := testutil.NewBeaconState() + require.NoError(t, st.SetValidators(validators)) + require.NoError(t, st.SetBalances(balances)) + + bs := &Server{ + HeadFetcher: &mock.ChainService{ + State: st, + }, + GenesisTimeFetcher: &mock.ChainService{ + // We are in epoch 0. + Genesis: time.Now(), + }, + StateGen: stategen.New(db, cache.NewStateSummaryCache()), + } + + b := testutil.NewBeaconBlock() + require.NoError(t, db.SaveBlock(ctx, b)) + gRoot, err := b.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, db.SaveGenesisBlockRoot(ctx, gRoot)) + require.NoError(t, db.SaveState(ctx, st, gRoot)) + + received, err := bs.ListValidators(ctx, ðpb.ListValidatorsRequest{ + Active: true, + }) + require.NoError(t, err) + + require.Equal(t, count/2-1, len(received.ValidatorList)) + require.Equal(t, count/2-1, int(received.TotalSize)) +} + func TestServer_ListValidators_NoPagination(t *testing.T) { db, _ := dbTest.SetupDB(t) @@ -910,7 +979,7 @@ func TestServer_ListValidators_FromOldEpoch(t *testing.T) { } res, err := bs.ListValidators(context.Background(), req) require.NoError(t, err) - assert.Equal(t, 1, len(res.ValidatorList)) + assert.Equal(t, 30, len(res.ValidatorList)) req = ðpb.ListValidatorsRequest{ QueryFilter: ðpb.ListValidatorsRequest_Epoch{ @@ -919,7 +988,7 @@ func TestServer_ListValidators_FromOldEpoch(t *testing.T) { } res, err = bs.ListValidators(context.Background(), req) require.NoError(t, err) - assert.DeepEqual(t, want[:21], res.ValidatorList, "Incorrect number of validators") + assert.DeepEqual(t, want, res.ValidatorList, "Incorrect number of validators") } func TestServer_ListValidators_ProcessHeadStateSlots(t *testing.T) {