refactor: remove panic usage in keeper methods (#18636)

This commit is contained in:
Likhita Polavarapu 2023-12-12 15:21:23 +05:30 committed by GitHub
parent c4d816c7cd
commit 38f40c42f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 124 additions and 98 deletions

View File

@ -53,6 +53,11 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Improvements
* (x/bank) [#18636](https://github.com/cosmos/cosmos-sdk/pull/18636) `SendCoinsFromModuleToAccount`, `SendCoinsFromModuleToModule`, `SendCoinsFromAccountToModule`, `DelegateCoinsFromAccountToModule`, `UndelegateCoinsFromModuleToAccount`, `MintCoins` and `BurnCoins` methods now returns an error instead of panicking if any module accounts does not exist or unauthorized.
* (x/distribution) [#18636](https://github.com/cosmos/cosmos-sdk/pull/18636) `CalculateDelegationRewards` and `DelegationTotalRewards` methods no longer panics on any sanity checks and instead returns appropriate errors.
* (x/slashing) [#18636](https://github.com/cosmos/cosmos-sdk/pull/18636) `JailUntil` and `Tombstone` methods no longer panics if the signing info does not exist for the validator but instead returns error.
* (x/staking) [#18636](https://github.com/cosmos/cosmos-sdk/pull/18636) `IterateBondedValidatorsByPower`, `GetDelegatorBonded`, `Delegate`, `Unbond`, `Slash`, `Jail`, `SlashRedelegation`, `ApplyAndReturnValidatorSetUpdates` methods no longer panics on any kind of errors but instead returns appropriate errors.
* Usage of `Must...` kind of functions are avoided in keeper methods.
* (client/keys) [#18687](https://github.com/cosmos/cosmos-sdk/pull/18687) Improve `<appd> keys mnemonic` by displaying mnemonic discreetly on an alternate screen and adding `--indiscreet` option to disable it.
* (client/keys) [#18663](https://github.com/cosmos/cosmos-sdk/pull/18663) Improve `<appd> keys add` by displaying mnemonic discreetly on an alternate screen and adding `--indiscreet` option to disable it.
* (types) [#18440](https://github.com/cosmos/cosmos-sdk/pull/18440) Add `AmountOfNoValidation` to `sdk.DecCoins`.

View File

@ -258,14 +258,14 @@ func (k BaseKeeper) SetDenomMetaData(ctx context.Context, denomMetaData types.Me
}
// SendCoinsFromModuleToAccount transfers coins from a ModuleAccount to an AccAddress.
// It will panic if the module account does not exist. An error is returned if
// An error is returned if the module account does not exist or if
// the recipient address is black-listed or if sending the tokens fails.
func (k BaseKeeper) SendCoinsFromModuleToAccount(
ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins,
) error {
senderAddr := k.ak.GetModuleAddress(senderModule)
if senderAddr == nil {
panic(errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", senderModule))
return errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", senderModule)
}
if k.BlockedAddr(recipientAddr) {
@ -276,74 +276,74 @@ func (k BaseKeeper) SendCoinsFromModuleToAccount(
}
// SendCoinsFromModuleToModule transfers coins from a ModuleAccount to another.
// It will panic if either module account does not exist.
// An error is returned if either module accounts does not exist.
func (k BaseKeeper) SendCoinsFromModuleToModule(
ctx context.Context, senderModule, recipientModule string, amt sdk.Coins,
) error {
senderAddr := k.ak.GetModuleAddress(senderModule)
if senderAddr == nil {
panic(errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", senderModule))
return errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", senderModule)
}
recipientAcc := k.ak.GetModuleAccount(ctx, recipientModule)
if recipientAcc == nil {
panic(errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", recipientModule))
return errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", recipientModule)
}
return k.SendCoins(ctx, senderAddr, recipientAcc.GetAddress(), amt)
}
// SendCoinsFromAccountToModule transfers coins from an AccAddress to a ModuleAccount.
// It will panic if the module account does not exist.
// An error is returned if the module account does not exist.
func (k BaseKeeper) SendCoinsFromAccountToModule(
ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins,
) error {
recipientAcc := k.ak.GetModuleAccount(ctx, recipientModule)
if recipientAcc == nil {
panic(errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", recipientModule))
return errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", recipientModule)
}
return k.SendCoins(ctx, senderAddr, recipientAcc.GetAddress(), amt)
}
// DelegateCoinsFromAccountToModule delegates coins and transfers them from a
// delegator account to a module account. It will panic if the module account
// delegator account to a module account. An error is returned if the module account
// does not exist or is unauthorized.
func (k BaseKeeper) DelegateCoinsFromAccountToModule(
ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins,
) error {
recipientAcc := k.ak.GetModuleAccount(ctx, recipientModule)
if recipientAcc == nil {
panic(errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", recipientModule))
return errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", recipientModule)
}
if !recipientAcc.HasPermission(authtypes.Staking) {
panic(errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "module account %s does not have permissions to receive delegated coins", recipientModule))
return errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "module account %s does not have permissions to receive delegated coins", recipientModule)
}
return k.DelegateCoins(ctx, senderAddr, recipientAcc.GetAddress(), amt)
}
// UndelegateCoinsFromModuleToAccount undelegates the unbonding coins and transfers
// them from a module account to the delegator account. It will panic if the
// them from a module account to the delegator account. An error is returned if the
// module account does not exist or is unauthorized.
func (k BaseKeeper) UndelegateCoinsFromModuleToAccount(
ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins,
) error {
acc := k.ak.GetModuleAccount(ctx, senderModule)
if acc == nil {
panic(errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", senderModule))
return errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", senderModule)
}
if !acc.HasPermission(authtypes.Staking) {
panic(errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "module account %s does not have permissions to undelegate coins", senderModule))
return errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "module account %s does not have permissions to undelegate coins", senderModule)
}
return k.UndelegateCoins(ctx, acc.GetAddress(), recipientAddr, amt)
}
// MintCoins creates new coins from thin air and adds it to the module account.
// It will panic if the module account does not exist or is unauthorized.
// An error is returned if the module account does not exist or is unauthorized.
func (k BaseKeeper) MintCoins(ctx context.Context, moduleName string, amounts sdk.Coins) error {
sdkCtx := sdk.UnwrapSDKContext(ctx)
@ -354,11 +354,11 @@ func (k BaseKeeper) MintCoins(ctx context.Context, moduleName string, amounts sd
}
acc := k.ak.GetModuleAccount(ctx, moduleName)
if acc == nil {
panic(errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", moduleName))
return errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", moduleName)
}
if !acc.HasPermission(authtypes.Minter) {
panic(errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "module account %s does not have permissions to mint tokens", moduleName))
return errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "module account %s does not have permissions to mint tokens", moduleName)
}
err = k.addCoins(ctx, acc.GetAddress(), amounts)
@ -387,7 +387,7 @@ func (k BaseKeeper) MintCoins(ctx context.Context, moduleName string, amounts sd
}
// BurnCoins burns coins deletes coins from the balance of the module account.
// It will panic if the module account does not exist or is unauthorized.
// An error is returned if the module account does not exist or is unauthorized.
func (k BaseKeeper) BurnCoins(ctx context.Context, address []byte, amounts sdk.Coins) error {
acc := k.ak.GetAccount(ctx, address)
if acc == nil {

View File

@ -396,20 +396,17 @@ func (suite *KeeperTestSuite) TestSupply_DelegateUndelegateCoins() {
require.NoError(keeper.SendCoinsFromModuleToAccount(ctx, banktypes.MintModuleName, holderAcc.GetAddress(), initCoins))
authKeeper.EXPECT().GetModuleAddress("").Return(nil)
require.Panics(func() {
_ = keeper.SendCoinsFromModuleToAccount(ctx, "", holderAcc.GetAddress(), initCoins)
})
err := keeper.SendCoinsFromModuleToAccount(ctx, "", holderAcc.GetAddress(), initCoins)
require.Error(err)
authKeeper.EXPECT().GetModuleAddress(burnerAcc.Name).Return(burnerAcc.GetAddress())
authKeeper.EXPECT().GetModuleAccount(ctx, "").Return(nil)
require.Panics(func() {
_ = keeper.SendCoinsFromModuleToModule(ctx, authtypes.Burner, "", initCoins)
})
err = keeper.SendCoinsFromModuleToModule(ctx, authtypes.Burner, "", initCoins)
require.Error(err)
authKeeper.EXPECT().GetModuleAddress("").Return(nil)
require.Panics(func() {
_ = keeper.SendCoinsFromModuleToAccount(ctx, "", baseAcc.GetAddress(), initCoins)
})
err = keeper.SendCoinsFromModuleToAccount(ctx, "", baseAcc.GetAddress(), initCoins)
require.Error(err)
authKeeper.EXPECT().GetModuleAddress(holderAcc.Name).Return(holderAcc.GetAddress())
authKeeper.EXPECT().GetAccount(suite.ctx, holderAcc.GetAddress()).Return(holderAcc)
@ -456,20 +453,17 @@ func (suite *KeeperTestSuite) TestSupply_SendCoins() {
require.NoError(keeper.SendCoinsFromModuleToAccount(ctx, banktypes.MintModuleName, holderAcc.GetAddress(), initCoins))
authKeeper.EXPECT().GetModuleAddress("").Return(nil)
require.Panics(func() {
_ = keeper.SendCoinsFromModuleToModule(ctx, "", holderAcc.GetName(), initCoins)
})
err := keeper.SendCoinsFromModuleToModule(ctx, "", holderAcc.GetName(), initCoins)
require.Error(err)
authKeeper.EXPECT().GetModuleAddress(burnerAcc.Name).Return(burnerAcc.GetAddress())
authKeeper.EXPECT().GetModuleAccount(ctx, "").Return(nil)
require.Panics(func() {
_ = keeper.SendCoinsFromModuleToModule(ctx, authtypes.Burner, "", initCoins)
})
err = keeper.SendCoinsFromModuleToModule(ctx, authtypes.Burner, "", initCoins)
require.Error(err)
authKeeper.EXPECT().GetModuleAddress("").Return(nil)
require.Panics(func() {
_ = keeper.SendCoinsFromModuleToAccount(ctx, "", baseAcc.GetAddress(), initCoins)
})
err = keeper.SendCoinsFromModuleToAccount(ctx, "", baseAcc.GetAddress(), initCoins)
require.Error(err)
authKeeper.EXPECT().GetModuleAddress(holderAcc.Name).Return(holderAcc.GetAddress())
authKeeper.EXPECT().GetAccount(suite.ctx, holderAcc.GetAddress()).Return(holderAcc)
@ -508,16 +502,21 @@ func (suite *KeeperTestSuite) TestSupply_MintCoins() {
require.NoError(err)
authKeeper.EXPECT().GetModuleAccount(ctx, "").Return(nil)
require.Panics(func() { _ = keeper.MintCoins(ctx, "", initCoins) }, "no module account")
err = keeper.MintCoins(ctx, "", initCoins)
require.Error(err)
require.ErrorContains(err, "module account does not exist")
suite.mockMintCoins(burnerAcc)
require.Panics(func() { _ = keeper.MintCoins(ctx, authtypes.Burner, initCoins) }, "invalid permission")
err = keeper.MintCoins(ctx, authtypes.Burner, initCoins)
require.Error(err)
require.ErrorContains(err, fmt.Sprintf("module account %s does not have permissions to mint tokens: unauthorized", authtypes.Burner))
suite.mockMintCoins(minterAcc)
require.Error(keeper.MintCoins(ctx, authtypes.Minter, sdk.Coins{sdk.Coin{Denom: "denom", Amount: math.NewInt(-10)}}), "insufficient coins")
authKeeper.EXPECT().GetModuleAccount(ctx, randomPerm).Return(nil)
require.Panics(func() { _ = keeper.MintCoins(ctx, randomPerm, initCoins) })
err = keeper.MintCoins(ctx, randomPerm, initCoins)
require.Error(err)
suite.mockMintCoins(minterAcc)
require.NoError(keeper.MintCoins(ctx, authtypes.Minter, initCoins))

View File

@ -51,17 +51,17 @@ func (k Keeper) calculateDelegationRewardsBetween(ctx context.Context, val sdk.V
) (sdk.DecCoins, error) {
// sanity check
if startingPeriod > endingPeriod {
panic("startingPeriod cannot be greater than endingPeriod")
return sdk.DecCoins{}, fmt.Errorf("startingPeriod cannot be greater than endingPeriod")
}
// sanity check
if stake.IsNegative() {
panic("stake should not be negative")
return sdk.DecCoins{}, fmt.Errorf("stake should not be negative")
}
valBz, err := k.stakingKeeper.ValidatorAddressCodec().StringToBytes(val.GetOperator())
if err != nil {
panic(err)
return sdk.DecCoins{}, err
}
// return staking * (ending - starting)
@ -77,7 +77,7 @@ func (k Keeper) calculateDelegationRewardsBetween(ctx context.Context, val sdk.V
difference := ending.CumulativeRewardRatio.Sub(starting.CumulativeRewardRatio)
if difference.IsAnyNegative() {
panic("negative rewards should not be possible")
return sdk.DecCoins{}, fmt.Errorf("negative rewards should not be possible")
}
// note: necessary to truncate so we don't allow withdrawing more rewards than owed
rewards := difference.MulDecTruncate(stake)
@ -123,6 +123,7 @@ func (k Keeper) CalculateDelegationRewards(ctx context.Context, val sdk.Validato
// Slashes this block happened after reward allocation, but we have to account
// for them for the stake sanity check below.
endingHeight := uint64(sdkCtx.BlockHeight())
var iterErr error
if endingHeight > startingHeight {
err = k.IterateValidatorSlashEventsBetween(ctx, valAddr, startingHeight, endingHeight,
func(height uint64, event types.ValidatorSlashEvent) (stop bool) {
@ -130,7 +131,8 @@ func (k Keeper) CalculateDelegationRewards(ctx context.Context, val sdk.Validato
if endingPeriod > startingPeriod {
delRewards, err := k.calculateDelegationRewardsBetween(ctx, val, startingPeriod, endingPeriod, stake)
if err != nil {
panic(err)
iterErr = err
return true
}
rewards = rewards.Add(delRewards...)
@ -142,6 +144,9 @@ func (k Keeper) CalculateDelegationRewards(ctx context.Context, val sdk.Validato
return false
},
)
if iterErr != nil {
return sdk.DecCoins{}, iterErr
}
if err != nil {
return sdk.DecCoins{}, err
}
@ -178,10 +183,10 @@ func (k Keeper) CalculateDelegationRewards(ctx context.Context, val sdk.Validato
if stake.LTE(currentStake.Add(marginOfErr)) {
stake = currentStake
} else {
panic(fmt.Sprintf("calculated final stake for delegator %s greater than current stake"+
return sdk.DecCoins{}, fmt.Errorf("calculated final stake for delegator %s greater than current stake"+
"\n\tfinal stake:\t%s"+
"\n\tcurrent stake:\t%s",
del.GetDelegatorAddr(), stake, currentStake))
del.GetDelegatorAddr(), stake, currentStake)
}
}

View File

@ -264,27 +264,32 @@ func (k Querier) DelegationTotalRewards(ctx context.Context, req *types.QueryDel
return nil, err
}
var iterErr error
err = k.stakingKeeper.IterateDelegations(
ctx, delAdr,
func(_ int64, del sdk.DelegationI) (stop bool) {
valAddr, err := k.stakingKeeper.ValidatorAddressCodec().StringToBytes(del.GetValidatorAddr())
if err != nil {
panic(err)
iterErr = err
return true
}
val, err := k.stakingKeeper.Validator(ctx, valAddr)
if err != nil {
panic(err)
iterErr = err
return true
}
endingPeriod, err := k.IncrementValidatorPeriod(ctx, val)
if err != nil {
panic(err)
iterErr = err
return true
}
delReward, err := k.CalculateDelegationRewards(ctx, val, del, endingPeriod)
if err != nil {
panic(err)
iterErr = err
return true
}
delRewards = append(delRewards, types.NewDelegationDelegatorReward(del.GetValidatorAddr(), delReward))
@ -292,6 +297,9 @@ func (k Querier) DelegationTotalRewards(ctx context.Context, req *types.QueryDel
return false
},
)
if iterErr != nil {
return nil, iterErr
}
if err != nil {
return nil, err
}

View File

@ -430,6 +430,7 @@ func TestTally(t *testing.T) {
}
return nil
})
// Submit and activate a proposal
proposal, err := govKeeper.SubmitProposal(ctx, TestProposal, "", "title", "summary", delAddrs[0], tt.proposalType)
require.NoError(t, err)

View File

@ -3,6 +3,7 @@ package keeper
import (
"context"
"errors"
"fmt"
"time"
"github.com/bits-and-blooms/bitset"
@ -22,23 +23,22 @@ func (k Keeper) HasValidatorSigningInfo(ctx context.Context, consAddr sdk.ConsAd
}
// JailUntil attempts to set a validator's JailedUntil attribute in its signing
// info. It will panic if the signing info does not exist for the validator.
// info.
func (k Keeper) JailUntil(ctx context.Context, consAddr sdk.ConsAddress, jailTime time.Time) error {
signInfo, err := k.ValidatorSigningInfo.Get(ctx, consAddr)
if err != nil {
return errorsmod.Wrap(err, "cannot jail validator that does not have any signing information")
return errorsmod.Wrap(err, fmt.Sprintf("cannot jail validator with consensus address %s that does not have any signing information", consAddr.String()))
}
signInfo.JailedUntil = jailTime
return k.ValidatorSigningInfo.Set(ctx, consAddr, signInfo)
}
// Tombstone attempts to tombstone a validator. It will panic if signing info for
// the given validator does not exist.
// Tombstone attempts to tombstone a validator.
func (k Keeper) Tombstone(ctx context.Context, consAddr sdk.ConsAddress) error {
signInfo, err := k.ValidatorSigningInfo.Get(ctx, consAddr)
if err != nil {
return types.ErrNoSigningInfoFound.Wrap("cannot tombstone validator that does not have any signing information")
return types.ErrNoSigningInfoFound.Wrap(fmt.Sprintf("cannot tombstone validator with consensus address %s that does not have any signing information", consAddr.String()))
}
if signInfo.Tombstoned {

View File

@ -2,6 +2,7 @@ package keeper
import (
"context"
"fmt"
"cosmossdk.io/collections"
storetypes "cosmossdk.io/store/types"
@ -56,8 +57,10 @@ func (k Keeper) IterateBondedValidatorsByPower(ctx context.Context, fn func(inde
i := int64(0)
for ; iterator.Valid() && i < int64(maxValidators); iterator.Next() {
address := iterator.Value()
validator := k.mustGetValidator(ctx, address)
validator, err := k.GetValidator(ctx, address)
if err != nil {
return fmt.Errorf("validator record not found for address: %s", sdk.ValAddress(address).String())
}
if validator.IsBonded() {
stop := fn(i, validator) // XXX is this safe will the validator unexposed fields be able to get written to?
if stop {

View File

@ -216,10 +216,12 @@ func (k Keeper) GetDelegatorUnbonding(ctx context.Context, delegator sdk.AccAddr
func (k Keeper) GetDelegatorBonded(ctx context.Context, delegator sdk.AccAddress) (math.Int, error) {
bonded := math.LegacyZeroDec()
var iterErr error
err := k.IterateDelegatorDelegations(ctx, delegator, func(delegation types.Delegation) bool {
validatorAddr, err := k.validatorAddressCodec.StringToBytes(delegation.ValidatorAddress)
if err != nil {
panic(err) // shouldn't happen
iterErr = err
return true
}
validator, err := k.GetValidator(ctx, validatorAddr)
if err == nil {
@ -229,6 +231,9 @@ func (k Keeper) GetDelegatorBonded(ctx context.Context, delegator sdk.AccAddress
}
return false
})
if iterErr != nil {
return bonded.RoundInt(), iterErr
}
return bonded.RoundInt(), err
}
@ -717,7 +722,7 @@ func (k Keeper) Delegate(
// all non bonded
if subtractAccount {
if tokenSrc == types.Bonded {
panic("delegation token source cannot be bonded")
return math.LegacyZeroDec(), fmt.Errorf("delegation token source cannot be bonded; expected Unbonded or Unbonding, got Bonded")
}
var sendName string
@ -728,7 +733,7 @@ func (k Keeper) Delegate(
case validator.IsUnbonding(), validator.IsUnbonded():
sendName = types.NotBondedPoolName
default:
panic("invalid validator status")
return math.LegacyZeroDec(), fmt.Errorf("invalid validator status: %v", validator.Status)
}
bondDenom, err := k.BondDenom(ctx)
@ -760,7 +765,7 @@ func (k Keeper) Delegate(
return math.LegacyDec{}, err
}
default:
panic("unknown token source bond status")
return math.LegacyZeroDec(), fmt.Errorf("unknown token source bond status: %v", tokenSrc)
}
}
@ -832,9 +837,12 @@ func (k Keeper) Unbond(
validator.TokensFromShares(delegation.Shares).TruncateInt().LT(validator.MinSelfDelegation) {
err = k.jailValidator(ctx, validator)
if err != nil {
return amount, err
return amount, fmt.Errorf("failed to jail validator: %v", err)
}
validator, err = k.GetValidator(ctx, valbz)
if err != nil {
return amount, fmt.Errorf("validator record not found for address: %X", valbz)
}
validator = k.mustGetValidator(ctx, valbz)
}
if delegation.Shares.IsZero() {
@ -906,7 +914,7 @@ func (k Keeper) getBeginInfo(
return validator.UnbondingTime, validator.UnbondingHeight, false, nil
default:
panic(fmt.Sprintf("unknown validator status: %s", validator.Status))
return completionTime, height, false, fmt.Errorf("unknown validator status: %v", validator.Status)
}
}

View File

@ -356,7 +356,7 @@ func (s *KeeperTestSuite) TestUnbondingDelegationsMigrationToColls() {
},
},
}
bz := stakingtypes.MustMarshalUBD(s.cdc, ubd)
bz := s.cdc.MustMarshal(&ubd)
s.ctx.KVStore(s.key).Set(getUBDKey(delAddrs[i], valAddrs[i]), bz)
s.ctx.KVStore(s.key).Set(getUBDByValIndexKey(delAddrs[i], valAddrs[i]), []byte{})
},
@ -444,7 +444,7 @@ func (s *KeeperTestSuite) TestValidatorsMigrationToColls() {
Commission: stakingtypes.NewCommission(math.LegacyZeroDec(), math.LegacyZeroDec(), math.LegacyZeroDec()),
MinSelfDelegation: math.ZeroInt(),
}
valBz := stakingtypes.MustMarshalValidator(s.cdc, &val)
valBz := s.cdc.MustMarshal(&val)
// legacy Set method
s.ctx.KVStore(s.key).Set(getValidatorKey(valAddrs[i]), valBz)
},

View File

@ -57,7 +57,7 @@ func (k Keeper) Slash(ctx context.Context, consAddr sdk.ConsAddress, infractionH
// Log the slash attempt for future reference (maybe we should tag it too)
conStr, err := k.consensusAddressCodec.BytesToString(consAddr)
if err != nil {
panic(err)
return math.NewInt(0), err
}
logger.Error(
@ -191,7 +191,7 @@ func (k Keeper) Slash(ctx context.Context, consAddr sdk.ConsAddress, infractionH
return math.NewInt(0), err
}
default:
panic("invalid validator status")
return math.NewInt(0), fmt.Errorf("invalid validator status")
}
logger.Info(
@ -210,7 +210,10 @@ func (k Keeper) SlashWithInfractionReason(ctx context.Context, consAddr sdk.Cons
// jail a validator
func (k Keeper) Jail(ctx context.Context, consAddr sdk.ConsAddress) error {
validator := k.mustGetValidatorByConsAddr(ctx, consAddr)
validator, err := k.GetValidatorByConsAddr(ctx, consAddr)
if err != nil {
return fmt.Errorf("validator with consensus-Address %s not found", consAddr)
}
if err := k.jailValidator(ctx, validator); err != nil {
return err
}
@ -222,7 +225,10 @@ func (k Keeper) Jail(ctx context.Context, consAddr sdk.ConsAddress) error {
// unjail a validator
func (k Keeper) Unjail(ctx context.Context, consAddr sdk.ConsAddress) error {
validator := k.mustGetValidatorByConsAddr(ctx, consAddr)
validator, err := k.GetValidatorByConsAddr(ctx, consAddr)
if err != nil {
return fmt.Errorf("validator with consensus-Address %s not found", consAddr)
}
if err := k.unjailValidator(ctx, validator); err != nil {
return err
}
@ -363,7 +369,7 @@ func (k Keeper) SlashRedelegation(ctx context.Context, srcValidator types.Valida
case dstValidator.IsUnbonded() || dstValidator.IsUnbonding():
notBondedBurnedAmount = notBondedBurnedAmount.Add(tokensToBurn)
default:
panic("unknown validator status")
return math.ZeroInt(), fmt.Errorf("unknown validator status")
}
}

View File

@ -156,10 +156,13 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx context.Context) (updates
// everything that is iterated in this loop is becoming or already a
// part of the bonded validator set
valAddr := sdk.ValAddress(iterator.Value())
validator := k.mustGetValidator(ctx, valAddr)
validator, err := k.GetValidator(ctx, valAddr)
if err != nil {
return nil, fmt.Errorf("validator record not found for address: %X", valAddr)
}
if validator.Jailed {
panic("should never retrieve a jailed validator from the power store")
return nil, fmt.Errorf("should never retrieve a jailed validator from the power store")
}
// if we get to a zero-power validator (which we don't bond),
@ -185,7 +188,7 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx context.Context) (updates
case validator.IsBonded():
// no state change
default:
panic("unexpected validator status")
return nil, fmt.Errorf("unexpected validator status")
}
// fetch the old power bytes
@ -218,7 +221,10 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx context.Context) (updates
}
for _, valAddrBytes := range noLongerBonded {
validator := k.mustGetValidator(ctx, sdk.ValAddress(valAddrBytes))
validator, err := k.GetValidator(ctx, sdk.ValAddress(valAddrBytes))
if err != nil {
return nil, fmt.Errorf("validator record not found for address: %X", sdk.ValAddress(valAddrBytes))
}
validator, err = k.bondedToUnbonding(ctx, validator)
if err != nil {
return nil, err
@ -274,7 +280,7 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx context.Context) (updates
func (k Keeper) bondedToUnbonding(ctx context.Context, validator types.Validator) (types.Validator, error) {
if !validator.IsBonded() {
panic(fmt.Sprintf("bad state transition bondedToUnbonding, validator: %v\n", validator))
return types.Validator{}, fmt.Errorf("bad state transition bondedToUnbonding, validator: %v", validator)
}
return k.BeginUnbondingValidator(ctx, validator)
@ -282,7 +288,7 @@ func (k Keeper) bondedToUnbonding(ctx context.Context, validator types.Validator
func (k Keeper) unbondingToBonded(ctx context.Context, validator types.Validator) (types.Validator, error) {
if !validator.IsUnbonding() {
panic(fmt.Sprintf("bad state transition unbondingToBonded, validator: %v\n", validator))
return types.Validator{}, fmt.Errorf("bad state transition unbondingToBonded, validator: %v", validator)
}
return k.bondValidator(ctx, validator)
@ -290,7 +296,7 @@ func (k Keeper) unbondingToBonded(ctx context.Context, validator types.Validator
func (k Keeper) unbondedToBonded(ctx context.Context, validator types.Validator) (types.Validator, error) {
if !validator.IsUnbonded() {
panic(fmt.Sprintf("bad state transition unbondedToBonded, validator: %v\n", validator))
return types.Validator{}, fmt.Errorf("bad state transition unbondedToBonded, validator: %v", validator)
}
return k.bondValidator(ctx, validator)
@ -388,7 +394,7 @@ func (k Keeper) BeginUnbondingValidator(ctx context.Context, validator types.Val
// sanity check
if validator.Status != types.Bonded {
panic(fmt.Sprintf("should not already be unbonded or unbonding, validator: %v\n", validator))
return validator, fmt.Errorf("should not already be unbonded or unbonding, validator: %v", validator)
}
id, err := k.IncrementUnbondingID(ctx)

View File

@ -34,15 +34,6 @@ func (k Keeper) GetValidator(ctx context.Context, addr sdk.ValAddress) (validato
return validator, nil
}
func (k Keeper) mustGetValidator(ctx context.Context, addr sdk.ValAddress) types.Validator {
validator, err := k.GetValidator(ctx, addr)
if err != nil {
panic(fmt.Sprintf("validator record not found for address: %X\n", addr))
}
return validator
}
// GetValidatorByConsAddr gets a single validator by consensus address
func (k Keeper) GetValidatorByConsAddr(ctx context.Context, consAddr sdk.ConsAddress) (validator types.Validator, err error) {
opAddr, err := k.ValidatorByConsensusAddress.Get(ctx, consAddr)
@ -57,15 +48,6 @@ func (k Keeper) GetValidatorByConsAddr(ctx context.Context, consAddr sdk.ConsAdd
return k.GetValidator(ctx, opAddr)
}
func (k Keeper) mustGetValidatorByConsAddr(ctx context.Context, consAddr sdk.ConsAddress) types.Validator {
validator, err := k.GetValidatorByConsAddr(ctx, consAddr)
if err != nil {
panic(fmt.Errorf("validator with consensus-Address %s not found", consAddr))
}
return validator
}
// SetValidator sets the main record holding validator details
func (k Keeper) SetValidator(ctx context.Context, validator types.Validator) error {
valBz, err := k.ValidatorAddressCodec().StringToBytes(validator.GetOperator())
@ -317,7 +299,10 @@ func (k Keeper) GetBondedValidatorsByPower(ctx context.Context) ([]types.Validat
i := 0
for ; iterator.Valid() && i < int(maxValidators); iterator.Next() {
address := iterator.Value()
validator := k.mustGetValidator(ctx, address)
validator, err := k.GetValidator(ctx, address)
if err != nil {
return nil, fmt.Errorf("validator record not found for address: %X", address)
}
if validator.IsBonded() {
validators[i] = validator
@ -383,7 +368,7 @@ func (k Keeper) GetLastValidators(ctx context.Context) (validators []types.Valid
err = k.LastValidatorPower.Walk(ctx, nil, func(key []byte, _ gogotypes.Int64Value) (bool, error) {
// sanity check
if i >= int(maxValidators) {
panic("more validators than maxValidators found")
return true, fmt.Errorf("more validators than maxValidators found")
}
validator, err := k.GetValidator(ctx, key)