mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-13 13:43:30 +00:00
Remove Already Exited Validators From Queue (#4695)
* added regression test * fixed the regression test units Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
This commit is contained in:
parent
85a38e6053
commit
f97ac5f0d7
@ -540,7 +540,9 @@ func (bs *Server) GetValidatorQueue(
|
||||
minEpoch := exitQueueEpoch + params.BeaconConfig().MinValidatorWithdrawabilityDelay
|
||||
exitQueueIndices := make([]uint64, 0)
|
||||
for _, valIdx := range awaitingExit {
|
||||
if headState.Validators[valIdx].WithdrawableEpoch < minEpoch {
|
||||
val := headState.Validators[valIdx]
|
||||
// Ensure the validator has not yet exited before adding its index to the exit queue.
|
||||
if val.WithdrawableEpoch < minEpoch && !validatorHasExited(val, helpers.CurrentEpoch(headState)) {
|
||||
exitQueueIndices = append(exitQueueIndices, valIdx)
|
||||
}
|
||||
}
|
||||
@ -611,3 +613,24 @@ func (bs *Server) GetValidatorPerformance(
|
||||
TotalActiveValidators: activeCount,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Determines whether a validator has already exited.
|
||||
func validatorHasExited(validator *ethpb.Validator, currentEpoch uint64) bool {
|
||||
farFutureEpoch := params.BeaconConfig().FarFutureEpoch
|
||||
if currentEpoch < validator.ActivationEligibilityEpoch {
|
||||
return false
|
||||
}
|
||||
if currentEpoch < validator.ActivationEpoch {
|
||||
return false
|
||||
}
|
||||
if validator.ExitEpoch == farFutureEpoch {
|
||||
return false
|
||||
}
|
||||
if currentEpoch < validator.ExitEpoch {
|
||||
if validator.Slashed {
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -1222,6 +1222,67 @@ func TestServer_GetValidatorQueue_PendingActivation(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestServer_GetValidatorQueue_ExitedValidatorLeavesQueue(t *testing.T) {
|
||||
headState := &pbp2p.BeaconState{
|
||||
Validators: []*ethpb.Validator{
|
||||
{
|
||||
ActivationEpoch: 0,
|
||||
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
WithdrawableEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
PublicKey: []byte("1"),
|
||||
},
|
||||
{
|
||||
ActivationEpoch: 0,
|
||||
ExitEpoch: 4,
|
||||
WithdrawableEpoch: 6,
|
||||
PublicKey: []byte("2"),
|
||||
},
|
||||
},
|
||||
FinalizedCheckpoint: ðpb.Checkpoint{
|
||||
Epoch: 0,
|
||||
},
|
||||
}
|
||||
bs := &Server{
|
||||
HeadFetcher: &mock.ChainService{
|
||||
State: headState,
|
||||
},
|
||||
}
|
||||
|
||||
// First we check if validator with index 1 is in the exit queue.
|
||||
res, err := bs.GetValidatorQueue(context.Background(), &ptypes.Empty{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
wanted := [][]byte{
|
||||
[]byte("2"),
|
||||
}
|
||||
activeValidatorCount, err := helpers.ActiveValidatorCount(headState, helpers.CurrentEpoch(headState))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
wantChurn, err := helpers.ValidatorChurnLimit(activeValidatorCount)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if res.ChurnLimit != wantChurn {
|
||||
t.Errorf("Wanted churn %d, received %d", wantChurn, res.ChurnLimit)
|
||||
}
|
||||
if !reflect.DeepEqual(res.ExitPublicKeys, wanted) {
|
||||
t.Errorf("Wanted %v, received %v", wanted, res.ExitPublicKeys)
|
||||
}
|
||||
|
||||
// Now, we move the state.slot past the exit epoch of the validator, and now
|
||||
// the validator should no longer exist in the queue.
|
||||
headState.Slot = helpers.StartSlot(headState.Validators[1].ExitEpoch + 1)
|
||||
res, err = bs.GetValidatorQueue(context.Background(), &ptypes.Empty{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(res.ExitPublicKeys) != 0 {
|
||||
t.Errorf("Wanted empty exit queue, received %v", res.ExitPublicKeys)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServer_GetValidatorQueue_PendingExit(t *testing.T) {
|
||||
headState := &pbp2p.BeaconState{
|
||||
Validators: []*ethpb.Validator{
|
||||
|
Loading…
Reference in New Issue
Block a user