Curved Glossy Dragonfly
High
During a zero-height export, the migration code withdraws validator commission but panics on any error, including the ErrNoValidatorCommission
error that is returned when a validator has zero commission. This inadvertently blocks the entire export process if even a single validator has no commission to withdraw, causing a potential chain restart failure.
In the snippet below, the code calls app.DistrKeeper.WithdrawValidatorCommission(ctx, valBz)
inside a loop of all validators:
// withdraw all validator commission
err := app.StakingKeeper.IterateValidators(ctx, func(_ int64, val stakingtypes.ValidatorI) (stop bool) {
valBz, err := app.StakingKeeper.ValidatorAddressCodec().StringToBytes(val.GetOperator())
if err != nil {
panic(err)
}
if _, err = app.DistrKeeper.WithdrawValidatorCommission(ctx, valBz); err != nil {
panic(err) // <-- Panics on ErrNoValidatorCommission
}
return false
})
if err != nil {
panic(err)
}
If any validator has no commission, WithdrawValidatorCommission
returns ErrNoValidatorCommission
, which in turn triggers the panic(err)
line. This means a single validator with zero commission can derail the entire zero-height export process. Instead of continuing gracefully (or ignoring “no commission” cases), the code treats it as a critical error and panics, preventing a successful export.
- The chain restart or migration relying on zero-height export may fail completely, as the export process will not proceed if one validator lacks commission.
- This effectively blocks upgrades, forks, or testnets derived from the chain’s current state.
- Operators who attempt to re-launch the chain using the zero-height export risk being unable to generate the required genesis file, creating downtime or forcing them to manually remove validators’ zero commissions before export.
Change the error handling to specifically ignore or handle ErrNoValidatorCommission. Instead of panicking unconditionally on any error, check if the error is truly critical
diff --git a/app/export.go b/app/export.go
index 1234567..89abcde 100644
--- a/app/export.go
+++ b/app/export.go
@@ -43,10 +43,18 @@ func (app *BabylonApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAdd
valBz, err := app.StakingKeeper.ValidatorAddressCodec().StringToBytes(val.GetOperator())
if err != nil {
panic(err)
}
- if _, err = app.DistrKeeper.WithdrawValidatorCommission(ctx, valBz); err != nil {
- panic(err)
+ // Attempt to withdraw commission; ignore the "no commission" error
+ if _, wthErr := app.DistrKeeper.WithdrawValidatorCommission(ctx, valBz); wthErr != nil {
+ if errors.Is(wthErr, types.ErrNoValidatorCommission) {
+ // No commission to withdraw is not a fatal error, skip
+ return false
+ } else {
+ // Panic on any other unexpected errors
+ panic(wthErr)
+ }
}
return false
})