Bitter Khaki Iguana
Medium
ApplyMatureUnbonding passes wrong context
ApplyMatureUnbonding
uses a modified context with offset UnbondingTime
. However it passes the original context to getAllMatureValidators
.
func (k Keeper) ApplyMatureUnbonding(ctx context.Context, epochNumber uint64) {
sdkCtx := sdk.UnwrapSDKContext(ctx)
// save the current ctx for emitting events and recording lifecycle
currentSdkCtx := sdkCtx
// get the ctx of the last block of the given epoch, while offsetting the time to nullify UnbondingTime
finalizedEpoch, err := k.GetHistoricalEpoch(ctx, epochNumber)
if err != nil {
panic(err)
}
params, err := k.stk.GetParams(ctx)
if err != nil {
panic(err)
}
// nullifies the effect of UnbondingTime in staking module
// NOTE: we offset time in both Header and HeaderInfo for full compatibility
finalizedTime := finalizedEpoch.LastBlockTime.Add(params.UnbondingTime)
headerInfo := sdkCtx.HeaderInfo()
headerInfo.Time = finalizedTime
@> ctx = sdkCtx.WithBlockTime(finalizedTime).WithHeaderInfo(headerInfo)
// unbond all mature validators till the last block of the given epoch
@> matureValidators := k.getAllMatureValidators(sdkCtx)
currentSdkCtx.Logger().Info(fmt.Sprintf("Epoching: start completing the following unbonding validators matured in epoch %d: %v", epochNumber, matureValidators))
if err := k.stk.UnbondAllMatureValidators(ctx); err != nil {
panic(err)
}
// record state update of being UNBONDED for mature validators
@> for _, valAddr := range matureValidators {
if err := k.RecordNewValState(currentSdkCtx, valAddr, types.BondState_UNBONDED); err != nil {
panic(err)
}
}
...
No response
No response
No response
Wrong/incomplete tracking of validator state.
No response
No response