diff --git a/.pending/bugfixes/sdk/4619-Close-iterators b/.pending/bugfixes/sdk/4619-Close-iterators new file mode 100644 index 0000000000..62b967a563 --- /dev/null +++ b/.pending/bugfixes/sdk/4619-Close-iterators @@ -0,0 +1,2 @@ +#4619 Close iterators in `GetAllMatureValidatorQueue` and `UnbondAllMatureValidatorQueue` +methods. diff --git a/x/staking/keeper/validator.go b/x/staking/keeper/validator.go index 37fd625899..6506694994 100644 --- a/x/staking/keeper/validator.go +++ b/x/staking/keeper/validator.go @@ -404,19 +404,21 @@ func (k Keeper) DeleteValidatorQueue(ctx sdk.Context, val types.Validator) { // Returns all the validator queue timeslices from time 0 until endTime func (k Keeper) ValidatorQueueIterator(ctx sdk.Context, endTime time.Time) sdk.Iterator { store := ctx.KVStore(k.storeKey) - return store.Iterator(types.ValidatorQueueKey, - sdk.InclusiveEndBytes(types.GetValidatorQueueTimeKey(endTime))) + return store.Iterator(types.ValidatorQueueKey, sdk.InclusiveEndBytes(types.GetValidatorQueueTimeKey(endTime))) } // Returns a concatenated list of all the timeslices before currTime, and deletes the timeslices from the queue func (k Keeper) GetAllMatureValidatorQueue(ctx sdk.Context, currTime time.Time) (matureValsAddrs []sdk.ValAddress) { // gets an iterator for all timeslices from time 0 until the current Blockheader time validatorTimesliceIterator := k.ValidatorQueueIterator(ctx, ctx.BlockHeader().Time) + defer validatorTimesliceIterator.Close() + for ; validatorTimesliceIterator.Valid(); validatorTimesliceIterator.Next() { timeslice := []sdk.ValAddress{} k.cdc.MustUnmarshalBinaryLengthPrefixed(validatorTimesliceIterator.Value(), ×lice) matureValsAddrs = append(matureValsAddrs, timeslice...) } + return matureValsAddrs } @@ -424,22 +426,29 @@ func (k Keeper) GetAllMatureValidatorQueue(ctx sdk.Context, currTime time.Time) func (k Keeper) UnbondAllMatureValidatorQueue(ctx sdk.Context) { store := ctx.KVStore(k.storeKey) validatorTimesliceIterator := k.ValidatorQueueIterator(ctx, ctx.BlockHeader().Time) + defer validatorTimesliceIterator.Close() + for ; validatorTimesliceIterator.Valid(); validatorTimesliceIterator.Next() { timeslice := []sdk.ValAddress{} k.cdc.MustUnmarshalBinaryLengthPrefixed(validatorTimesliceIterator.Value(), ×lice) + for _, valAddr := range timeslice { val, found := k.GetValidator(ctx, valAddr) if !found { panic("validator in the unbonding queue was not found") } + if !val.IsUnbonding() { - panic("unexpected validator in unbonding queue, status was not unbonding") + panic("unexpected validator in unbonding queue; status was not unbonding") } + k.unbondingToUnbonded(ctx, val) + if val.GetDelegatorShares().IsZero() { k.RemoveValidator(ctx, val.OperatorAddress) } } + store.Delete(validatorTimesliceIterator.Key()) } }