diff --git a/x/gov/keeper/tally_test.go b/x/gov/keeper/tally_test.go index 3999c2b218c3..9e2a5fa38730 100644 --- a/x/gov/keeper/tally_test.go +++ b/x/gov/keeper/tally_test.go @@ -410,7 +410,9 @@ func TestTallyJailedValidator(t *testing.T) { _ = staking.EndBlocker(ctx, app.StakingKeeper) - app.StakingKeeper.Jail(ctx, sdk.ConsAddress(val2.GetConsPubKey().Address())) + consKey, err := val2.GetConsPubKey() + require.NoError(t, err) + app.StakingKeeper.Jail(ctx, sdk.ConsAddress(consKey.Address())) tp := TestProposal proposal, err := app.GovKeeper.SubmitProposal(ctx, tp) diff --git a/x/slashing/keeper/unjail.go b/x/slashing/keeper/unjail.go index a8dab94d25d4..23a9121e5472 100644 --- a/x/slashing/keeper/unjail.go +++ b/x/slashing/keeper/unjail.go @@ -33,8 +33,10 @@ func (k Keeper) Unjail(ctx sdk.Context, validatorAddr sdk.ValAddress) error { return types.ErrValidatorNotJailed } - consAddr := sdk.ConsAddress(validator.GetConsPubKey().Address()) - + consAddr, err := validator.GetConsAddr() + if err != nil { + return err + } // If the validator has a ValidatorSigningInfo object that signals that the // validator was bonded and so we must check that the validator is not tombstoned // and can be unjailed at the current block. diff --git a/x/slashing/simulation/operations.go b/x/slashing/simulation/operations.go index e30dd900ed10..74bc6c91b390 100644 --- a/x/slashing/simulation/operations.go +++ b/x/slashing/simulation/operations.go @@ -65,7 +65,11 @@ func SimulateMsgUnjail(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Kee return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgUnjail, "validator is not jailed"), nil, nil } - consAddr := sdk.ConsAddress(validator.GetConsPubKey().Address()) + cons, err := validator.GetConsPubKey() + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgUnjail, "unable to get validator consensus key"), nil, err + } + consAddr := sdk.ConsAddress(cons.Address()) info, found := k.GetValidatorSigningInfo(ctx, consAddr) if !found { return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgUnjail, "unable to find validator signing info"), nil, nil // skip diff --git a/x/slashing/simulation/operations_test.go b/x/slashing/simulation/operations_test.go index b09ed30579f2..da70301c1388 100644 --- a/x/slashing/simulation/operations_test.go +++ b/x/slashing/simulation/operations_test.go @@ -67,7 +67,8 @@ func TestSimulateMsgUnjail(t *testing.T) { // setup validator0 by consensus address app.StakingKeeper.SetValidatorByConsAddr(ctx, validator0) - val0ConsAddress := sdk.ConsAddress(validator0.GetConsPubKey().Address()) + val0ConsAddress, err := validator0.GetConsAddr() + require.NoError(t, err) info := types.NewValidatorSigningInfo(val0ConsAddress, int64(4), int64(3), time.Unix(2, 0), false, int64(10)) app.SlashingKeeper.SetValidatorSigningInfo(ctx, val0ConsAddress, info) diff --git a/x/staking/genesis.go b/x/staking/genesis.go index e55c32e551b4..617c2a075b34 100644 --- a/x/staking/genesis.go +++ b/x/staking/genesis.go @@ -220,14 +220,22 @@ func validateGenesisStateValidators(validators []types.Validator) (err error) { for i := 0; i < len(validators); i++ { val := validators[i] - strKey := string(val.GetConsPubKey().Bytes()) + consPk, err := val.GetConsPubKey() + if err != nil { + return err + } + consAddr, err := val.GetConsAddr() + if err != nil { + return err + } + strKey := string(consPk.Bytes()) if _, ok := addrMap[strKey]; ok { - return fmt.Errorf("duplicate validator in genesis state: moniker %v, address %v", val.Description.Moniker, val.GetConsAddr()) + return fmt.Errorf("duplicate validator in genesis state: moniker %v, address %v", val.Description.Moniker, consAddr) } if val.Jailed && val.IsBonded() { - return fmt.Errorf("validator is bonded and jailed in genesis state: moniker %v, address %v", val.Description.Moniker, val.GetConsAddr()) + return fmt.Errorf("validator is bonded and jailed in genesis state: moniker %v, address %v", val.Description.Moniker, consAddr) } if val.DelegatorShares.IsZero() && !val.IsUnbonding() { diff --git a/x/staking/genesis_test.go b/x/staking/genesis_test.go index 40fe8a11b41c..918a009cc788 100644 --- a/x/staking/genesis_test.go +++ b/x/staking/genesis_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" @@ -44,10 +45,10 @@ func TestInitGenesis(t *testing.T) { validators := make([]types.Validator, 2) var delegations []types.Delegation - pk0, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeConsPub, PKs[0]) + pk0, err := codectypes.PackAny(PKs[0]) require.NoError(t, err) - pk1, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeConsPub, PKs[1]) + pk1, err := codectypes.PackAny(PKs[1]) require.NoError(t, err) // initialize the validators diff --git a/x/staking/handler_test.go b/x/staking/handler_test.go index 22c773339131..89a2d7507ec0 100644 --- a/x/staking/handler_test.go +++ b/x/staking/handler_test.go @@ -130,7 +130,9 @@ func TestDuplicatesMsgCreateValidator(t *testing.T) { validator := tstaking.CheckValidator(addr1, types.Bonded, false) assert.Equal(t, addr1.String(), validator.OperatorAddress) - assert.Equal(t, pk1.(cryptotypes.IntoTmPubKey).AsTmPubKey(), validator.GetConsPubKey()) + consKey, err := validator.GetConsPubKey() + require.NoError(t, err) + assert.Equal(t, pk1.(cryptotypes.IntoTmPubKey).AsTmPubKey(), consKey) assert.Equal(t, valTokens, validator.BondedTokens()) assert.Equal(t, valTokens.ToDec(), validator.DelegatorShares) assert.Equal(t, types.Description{}, validator.Description) @@ -150,7 +152,9 @@ func TestDuplicatesMsgCreateValidator(t *testing.T) { validator = tstaking.CheckValidator(addr2, types.Bonded, false) assert.Equal(t, addr2.String(), validator.OperatorAddress) - assert.Equal(t, pk2.(cryptotypes.IntoTmPubKey).AsTmPubKey(), validator.GetConsPubKey()) + consPk, err := validator.GetConsPubKey() + require.NoError(t, err) + assert.Equal(t, pk2.(cryptotypes.IntoTmPubKey).AsTmPubKey(), consPk) assert.True(sdk.IntEq(t, valTokens, validator.Tokens)) assert.True(sdk.DecEq(t, valTokens.ToDec(), validator.DelegatorShares)) assert.Equal(t, types.Description{}, validator.Description) diff --git a/x/staking/keeper/val_state_change.go b/x/staking/keeper/val_state_change.go index 083efb694032..b5c13a623786 100644 --- a/x/staking/keeper/val_state_change.go +++ b/x/staking/keeper/val_state_change.go @@ -205,7 +205,7 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx sdk.Context) (updates []ab // Validator state transitions -func (k Keeper) bondedToUnbonding(ctx sdk.Context, validator types.Validator) types.Validator { +func (k Keeper) bondedToUnbonding(ctx sdk.Context, validator types.Validator) (types.Validator, error) { if !validator.IsBonded() { panic(fmt.Sprintf("bad state transition bondedToUnbonding, validator: %v\n", validator)) } @@ -213,7 +213,7 @@ func (k Keeper) bondedToUnbonding(ctx sdk.Context, validator types.Validator) ty return k.beginUnbondingValidator(ctx, validator) } -func (k Keeper) unbondingToBonded(ctx sdk.Context, validator types.Validator) types.Validator { +func (k Keeper) unbondingToBonded(ctx sdk.Context, validator types.Validator) (types.Validator, error) { if !validator.IsUnbonding() { panic(fmt.Sprintf("bad state transition unbondingToBonded, validator: %v\n", validator)) } @@ -221,7 +221,7 @@ func (k Keeper) unbondingToBonded(ctx sdk.Context, validator types.Validator) ty return k.bondValidator(ctx, validator) } -func (k Keeper) unbondedToBonded(ctx sdk.Context, validator types.Validator) types.Validator { +func (k Keeper) unbondedToBonded(ctx sdk.Context, validator types.Validator) (types.Validator, error) { if !validator.IsUnbonded() { panic(fmt.Sprintf("bad state transition unbondedToBonded, validator: %v\n", validator)) } @@ -229,7 +229,7 @@ func (k Keeper) unbondedToBonded(ctx sdk.Context, validator types.Validator) typ return k.bondValidator(ctx, validator) } -// switches a validator from unbonding state to unbonded state +// UnbondingToUnbonded switches a validator from unbonding state to unbonded state func (k Keeper) UnbondingToUnbonded(ctx sdk.Context, validator types.Validator) types.Validator { if !validator.IsUnbonding() { panic(fmt.Sprintf("bad state transition unbondingToBonded, validator: %v\n", validator)) @@ -261,7 +261,7 @@ func (k Keeper) unjailValidator(ctx sdk.Context, validator types.Validator) { } // perform all the store operations for when a validator status becomes bonded -func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types.Validator { +func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) (types.Validator, error) { // delete the validator by power index, as the key will change k.DeleteValidatorByPowerIndex(ctx, validator) @@ -275,13 +275,17 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types. k.DeleteValidatorQueue(ctx, validator) // trigger hook - k.AfterValidatorBonded(ctx, validator.GetConsAddr(), validator.GetOperator()) + consAddr, err := validator.GetConsAddr() + if err != nil { + return validator, err + } + k.AfterValidatorBonded(ctx, consAddr, validator.GetOperator()) - return validator + return validator, err } // perform all the store operations for when a validator begins unbonding -func (k Keeper) beginUnbondingValidator(ctx sdk.Context, validator types.Validator) types.Validator { +func (k Keeper) beginUnbondingValidator(ctx sdk.Context, validator types.Validator) (types.Validator, error) { params := k.GetParams(ctx) // delete the validator by power index, as the key will change @@ -306,9 +310,13 @@ func (k Keeper) beginUnbondingValidator(ctx sdk.Context, validator types.Validat k.InsertUnbondingValidatorQueue(ctx, validator) // trigger hook - k.AfterValidatorBeginUnbonding(ctx, validator.GetConsAddr(), validator.GetOperator()) + consAddr, err := validator.GetConsAddr() + if err != nil { + return validator, err + } + k.AfterValidatorBeginUnbonding(ctx, consAddr, validator.GetOperator()) - return validator + return validator, nil } // perform all the store operations for when a validator status becomes unbonded diff --git a/x/staking/types/exported.go b/x/staking/types/exported.go index 02f97dccea49..06407e432c11 100644 --- a/x/staking/types/exported.go +++ b/x/staking/types/exported.go @@ -21,8 +21,8 @@ type ValidatorI interface { IsUnbonded() bool // check if has status unbonded IsUnbonding() bool // check if has status unbonding GetOperator() sdk.ValAddress // operator address to receive/return validators coins - GetConsPubKey() crypto.PubKey // validation consensus pubkey - GetConsAddr() sdk.ConsAddress // validation consensus address + GetConsPubKey() (crypto.PubKey, error) // validation consensus pubkey + GetConsAddr() (sdk.ConsAddress, error) // validation consensus address GetTokens() sdk.Int // validation tokens GetBondedTokens() sdk.Int // validator bonded tokens GetConsensusPower() int64 // validation power in tendermint diff --git a/x/staking/types/validator.go b/x/staking/types/validator.go index 3a7beff1691f..f31c8899911c 100644 --- a/x/staking/types/validator.go +++ b/x/staking/types/validator.go @@ -234,7 +234,11 @@ func (d Description) EnsureLength() (Description, error) { // ABCIValidatorUpdate returns an abci.ValidatorUpdate from a staking validator type // with the full validator power func (v Validator) ABCIValidatorUpdate() abci.ValidatorUpdate { - pk, err := encoding.PubKeyToProto(v.GetConsPubKey()) + consPk, err := v.GetConsPubKey() + if err != nil { + panic(err) + } + pk, err := encoding.PubKeyToProto(consPk) if err != nil { panic(err) } @@ -248,7 +252,11 @@ func (v Validator) ABCIValidatorUpdate() abci.ValidatorUpdate { // ABCIValidatorUpdateZero returns an abci.ValidatorUpdate from a staking validator type // with zero power used for validator updates. func (v Validator) ABCIValidatorUpdateZero() abci.ValidatorUpdate { - pk, err := encoding.PubKeyToProto(v.GetConsPubKey()) + consPk, err := v.GetConsPubKey() + if err != nil { + panic(err) + } + pk, err := encoding.PubKeyToProto(consPk) if err != nil { panic(err) } @@ -439,21 +447,34 @@ func (v Validator) GetOperator() sdk.ValAddress { } return addr } -func (v Validator) GetConsPubKey() crypto.PubKey { + +// GetConsPubKey casts Validator.ConsensusPubkey to crypto.PubKey +func (v Validator) GetConsPubKey() (crypto.PubKey, error) { + pk, ok := v.ConsensusPubkey.GetCachedValue().(cryptotypes.PubKey) + if !ok { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "Expecting crypto.PubKey, got %T", pk) + } + // The way things are refactored now, v.ConsensusPubkey is sometimes a TM // ed25519 pubkey, sometimes our own ed25519 pubkey. This is very ugly and // inconsistent. // Luckily, here we coerce it into a TM ed25519 pubkey always, as this // pubkey will be passed into TM (eg calling encoding.PubKeyToProto). - pk := sdk.MustGetPubKeyFromBech32(sdk.Bech32PubKeyTypeConsPub, v.ConsensusPubkey) - if intoTmPk, ok := pk.(cryptotypes.IntoTmPubKey); ok { - return intoTmPk.AsTmPubKey() + return intoTmPk.AsTmPubKey(), nil } + return pk, nil +} - return pk +// GetConsAddr extracts Consensus key address +func (v Validator) GetConsAddr() (sdk.ConsAddress, error) { + pk, err := v.GetConsPubKey() + if err != nil { + return sdk.ConsAddress{}, err + } + return sdk.ConsAddress(pk.Address()), nil } -func (v Validator) GetConsAddr() sdk.ConsAddress { return sdk.ConsAddress(v.GetConsPubKey().Address()) } + func (v Validator) GetTokens() sdk.Int { return v.Tokens } func (v Validator) GetBondedTokens() sdk.Int { return v.BondedTokens() } func (v Validator) GetConsensusPower() int64 { return v.ConsensusPower() }