refactor(staking): add missing msgServer tests and move ValidateBasic() logic to msgServer (#15820)

This commit is contained in:
Likhita Polavarapu 2023-04-14 20:24:29 +05:30 committed by GitHub
parent d7c8353989
commit 7132a7624e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 1152 additions and 496 deletions

View File

@ -87,6 +87,7 @@ func TestUnJailNotBonded(t *testing.T) {
amt := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 50)
msg := tstaking.CreateValidatorMsg(addr, val, amt)
msg.MinSelfDelegation = amt
msg.Description = stakingtypes.Description{Moniker: "TestValidator"}
res, err := tstaking.CreateValidatorWithMsg(f.ctx, msg)
assert.NilError(t, err)
assert.Assert(t, res != nil)

View File

@ -76,47 +76,58 @@ func TestCancelUnbondingDelegation(t *testing.T) {
assert.DeepEqual(t, ubd, resUnbond)
testCases := []struct {
Name string
ExceptErr bool
name string
exceptErr bool
req types.MsgCancelUnbondingDelegation
expErrMsg string
}{
{
Name: "invalid height",
ExceptErr: true,
name: "entry not found at height",
exceptErr: true,
req: types.MsgCancelUnbondingDelegation{
DelegatorAddress: resUnbond.DelegatorAddress,
ValidatorAddress: resUnbond.ValidatorAddress,
Amount: sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdk.NewInt(4)),
CreationHeight: 11,
},
expErrMsg: "unbonding delegation entry is not found at block height",
},
{
name: "invalid height",
exceptErr: true,
req: types.MsgCancelUnbondingDelegation{
DelegatorAddress: resUnbond.DelegatorAddress,
ValidatorAddress: resUnbond.ValidatorAddress,
Amount: sdk.NewCoin(stakingKeeper.BondDenom(ctx), sdk.NewInt(4)),
CreationHeight: 0,
},
expErrMsg: "unbonding delegation entry is not found at block height",
expErrMsg: "invalid height",
},
{
Name: "invalid coin",
ExceptErr: true,
name: "invalid coin",
exceptErr: true,
req: types.MsgCancelUnbondingDelegation{
DelegatorAddress: resUnbond.DelegatorAddress,
ValidatorAddress: resUnbond.ValidatorAddress,
Amount: sdk.NewCoin("dump_coin", sdk.NewInt(4)),
CreationHeight: 0,
CreationHeight: 10,
},
expErrMsg: "invalid coin denomination",
},
{
Name: "validator not exists",
ExceptErr: true,
name: "validator not exists",
exceptErr: true,
req: types.MsgCancelUnbondingDelegation{
DelegatorAddress: resUnbond.DelegatorAddress,
ValidatorAddress: sdk.ValAddress(sdk.AccAddress("asdsad")).String(),
Amount: unbondingAmount,
CreationHeight: 0,
CreationHeight: 10,
},
expErrMsg: "validator does not exist",
},
{
Name: "invalid delegator address",
ExceptErr: true,
name: "invalid delegator address",
exceptErr: true,
req: types.MsgCancelUnbondingDelegation{
DelegatorAddress: "invalid_delegator_addrtess",
ValidatorAddress: resUnbond.ValidatorAddress,
@ -126,8 +137,8 @@ func TestCancelUnbondingDelegation(t *testing.T) {
expErrMsg: "decoding bech32 failed",
},
{
Name: "invalid amount",
ExceptErr: true,
name: "invalid amount",
exceptErr: true,
req: types.MsgCancelUnbondingDelegation{
DelegatorAddress: resUnbond.DelegatorAddress,
ValidatorAddress: resUnbond.ValidatorAddress,
@ -137,8 +148,8 @@ func TestCancelUnbondingDelegation(t *testing.T) {
expErrMsg: "amount is greater than the unbonding delegation entry balance",
},
{
Name: "success",
ExceptErr: false,
name: "success",
exceptErr: false,
req: types.MsgCancelUnbondingDelegation{
DelegatorAddress: resUnbond.DelegatorAddress,
ValidatorAddress: resUnbond.ValidatorAddress,
@ -147,8 +158,8 @@ func TestCancelUnbondingDelegation(t *testing.T) {
},
},
{
Name: "success",
ExceptErr: false,
name: "success",
exceptErr: false,
req: types.MsgCancelUnbondingDelegation{
DelegatorAddress: resUnbond.DelegatorAddress,
ValidatorAddress: resUnbond.ValidatorAddress,
@ -159,9 +170,9 @@ func TestCancelUnbondingDelegation(t *testing.T) {
}
for _, testCase := range testCases {
t.Run(testCase.Name, func(t *testing.T) {
t.Run(testCase.name, func(t *testing.T) {
_, err := msgServer.CancelUnbondingDelegation(ctx, &testCase.req)
if testCase.ExceptErr {
if testCase.exceptErr {
assert.ErrorContains(t, err, testCase.expErrMsg)
} else {
assert.NilError(t, err)

View File

@ -7,6 +7,7 @@ import (
"time"
cmttypes "github.com/cometbft/cometbft/types"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
@ -110,12 +111,8 @@ func (b *GenesisBuilder) GenTx(privVal secp256k1.PrivKey, val cmttypes.GenesisVa
if err != nil {
panic(err)
}
_, err = sdk.ValAddressFromBech32(msg.ValidatorAddress)
if err != nil {
panic(err)
}
if err := msg.ValidateBasic(); err != nil {
if err := msg.Validate(); err != nil {
panic(err)
}

View File

@ -4,6 +4,7 @@ import (
"fmt"
"cosmossdk.io/math"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/distribution/keeper"
@ -12,7 +13,7 @@ import (
func CreateValidator(pk cryptotypes.PubKey, stake math.Int) (stakingtypes.Validator, error) {
valConsAddr := sdk.GetConsAddress(pk)
val, err := stakingtypes.NewValidator(sdk.ValAddress(valConsAddr), pk, stakingtypes.Description{})
val, err := stakingtypes.NewValidator(sdk.ValAddress(valConsAddr), pk, stakingtypes.Description{Moniker: "TestValidator"})
val.Tokens = stake
val.DelegatorShares = math.LegacyNewDecFromInt(val.Tokens)
return val, err

View File

@ -379,7 +379,7 @@ func newBuildCreateValidatorMsg(clientCtx client.Context, txf tx.Factory, fs *fl
if err != nil {
return txf, nil, err
}
if err := msg.ValidateBasic(); err != nil {
if err := msg.Validate(); err != nil {
return txf, nil, err
}

View File

@ -1,6 +1,7 @@
package keeper_test
import (
"errors"
"testing"
"cosmossdk.io/math"
@ -52,6 +53,9 @@ func (s *KeeperTestSuite) SetupTest() {
accountKeeper.EXPECT().GetModuleAddress(stakingtypes.NotBondedPoolName).Return(notBondedAcc.GetAddress())
accountKeeper.EXPECT().StringToBytes(authtypes.NewModuleAddress(govtypes.ModuleName).String()).Return(authtypes.NewModuleAddress(govtypes.ModuleName), nil).AnyTimes()
accountKeeper.EXPECT().BytesToString(authtypes.NewModuleAddress(govtypes.ModuleName)).Return(authtypes.NewModuleAddress(govtypes.ModuleName).String(), nil).AnyTimes()
accountKeeper.EXPECT().StringToBytes("").Return(nil, errors.New("empty address string is not allowed")).AnyTimes()
accountKeeper.EXPECT().StringToBytes("invalid").Return(nil, errors.New("invalid bech32 string")).AnyTimes()
bankKeeper := stakingtestutil.NewMockBankKeeper(ctrl)
keeper := stakingkeeper.NewKeeper(

View File

@ -5,12 +5,13 @@ import (
"strconv"
"time"
errorsmod "cosmossdk.io/errors"
"cosmossdk.io/math"
"github.com/armon/go-metrics"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
errorsmod "cosmossdk.io/errors"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -33,13 +34,17 @@ var _ types.MsgServer = msgServer{}
// CreateValidator defines a method for creating a new validator
func (k msgServer) CreateValidator(goCtx context.Context, msg *types.MsgCreateValidator) (*types.MsgCreateValidatorResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
valAddr, err := sdk.ValAddressFromBech32(msg.ValidatorAddress)
if err != nil {
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid validator address: %s", err)
}
if err := msg.Validate(); err != nil {
return nil, err
}
ctx := sdk.UnwrapSDKContext(goCtx)
if msg.Commission.Rate.LT(k.MinCommissionRate(ctx)) {
return nil, errorsmod.Wrapf(types.ErrCommissionLTMinRate, "cannot set validator commission to less than minimum rate of %s", k.MinCommissionRate(ctx))
}
@ -134,11 +139,30 @@ func (k msgServer) CreateValidator(goCtx context.Context, msg *types.MsgCreateVa
// EditValidator defines a method for editing an existing validator
func (k msgServer) EditValidator(goCtx context.Context, msg *types.MsgEditValidator) (*types.MsgEditValidatorResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
valAddr, err := sdk.ValAddressFromBech32(msg.ValidatorAddress)
if err != nil {
return nil, err
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid validator address: %s", err)
}
if msg.Description == (types.Description{}) {
return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "empty description")
}
if msg.MinSelfDelegation != nil && !msg.MinSelfDelegation.IsPositive() {
return nil, errorsmod.Wrap(
sdkerrors.ErrInvalidRequest,
"minimum self delegation must be a positive integer",
)
}
if msg.CommissionRate != nil {
if msg.CommissionRate.GT(math.LegacyOneDec()) || msg.CommissionRate.IsNegative() {
return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "commission rate must be between 0 and 1 (inclusive)")
}
}
ctx := sdk.UnwrapSDKContext(goCtx)
// validator must already be registered
validator, found := k.GetValidator(ctx, valAddr)
if !found {
@ -194,20 +218,28 @@ func (k msgServer) EditValidator(goCtx context.Context, msg *types.MsgEditValida
// Delegate defines a method for performing a delegation of coins from a delegator to a validator
func (k msgServer) Delegate(goCtx context.Context, msg *types.MsgDelegate) (*types.MsgDelegateResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
valAddr, valErr := sdk.ValAddressFromBech32(msg.ValidatorAddress)
if valErr != nil {
return nil, valErr
}
validator, found := k.GetValidator(ctx, valAddr)
if !found {
return nil, types.ErrNoValidatorFound
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid validator address: %s", valErr)
}
delegatorAddress, err := k.authKeeper.StringToBytes(msg.DelegatorAddress)
if err != nil {
return nil, err
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid delegator address: %s", err)
}
if !msg.Amount.IsValid() || !msg.Amount.Amount.IsPositive() {
return nil, errorsmod.Wrap(
sdkerrors.ErrInvalidRequest,
"invalid delegation amount",
)
}
ctx := sdk.UnwrapSDKContext(goCtx)
validator, found := k.GetValidator(ctx, valAddr)
if !found {
return nil, types.ErrNoValidatorFound
}
bondDenom := k.BondDenom(ctx)
@ -248,15 +280,30 @@ func (k msgServer) Delegate(goCtx context.Context, msg *types.MsgDelegate) (*typ
// BeginRedelegate defines a method for performing a redelegation of coins from a delegator and source validator to a destination validator
func (k msgServer) BeginRedelegate(goCtx context.Context, msg *types.MsgBeginRedelegate) (*types.MsgBeginRedelegateResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
valSrcAddr, err := sdk.ValAddressFromBech32(msg.ValidatorSrcAddress)
if err != nil {
return nil, err
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid source validator address: %s", err)
}
valDstAddr, err := sdk.ValAddressFromBech32(msg.ValidatorDstAddress)
if err != nil {
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid destination validator address: %s", err)
}
delegatorAddress, err := k.authKeeper.StringToBytes(msg.DelegatorAddress)
if err != nil {
return nil, err
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid delegator address: %s", err)
}
if !msg.Amount.IsValid() || !msg.Amount.Amount.IsPositive() {
return nil, errorsmod.Wrap(
sdkerrors.ErrInvalidRequest,
"invalid shares amount",
)
}
ctx := sdk.UnwrapSDKContext(goCtx)
shares, err := k.ValidateUnbondAmount(
ctx, delegatorAddress, valSrcAddr, msg.Amount.Amount,
)
@ -271,11 +318,6 @@ func (k msgServer) BeginRedelegate(goCtx context.Context, msg *types.MsgBeginRed
)
}
valDstAddr, err := sdk.ValAddressFromBech32(msg.ValidatorDstAddress)
if err != nil {
return nil, err
}
completionTime, err := k.BeginRedelegation(
ctx, delegatorAddress, valSrcAddr, valDstAddr, shares,
)
@ -311,16 +353,25 @@ func (k msgServer) BeginRedelegate(goCtx context.Context, msg *types.MsgBeginRed
// Undelegate defines a method for performing an undelegation from a delegate and a validator
func (k msgServer) Undelegate(goCtx context.Context, msg *types.MsgUndelegate) (*types.MsgUndelegateResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
addr, err := sdk.ValAddressFromBech32(msg.ValidatorAddress)
if err != nil {
return nil, err
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid validator address: %s", err)
}
delegatorAddress, err := k.authKeeper.StringToBytes(msg.DelegatorAddress)
if err != nil {
return nil, err
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid delegator address: %s", err)
}
if !msg.Amount.IsValid() || !msg.Amount.Amount.IsPositive() {
return nil, errorsmod.Wrap(
sdkerrors.ErrInvalidRequest,
"invalid shares amount",
)
}
ctx := sdk.UnwrapSDKContext(goCtx)
shares, err := k.ValidateUnbondAmount(
ctx, delegatorAddress, addr, msg.Amount.Amount,
)
@ -371,18 +422,32 @@ func (k msgServer) Undelegate(goCtx context.Context, msg *types.MsgUndelegate) (
// CancelUnbondingDelegation defines a method for canceling the unbonding delegation
// and delegate back to the validator.
func (k msgServer) CancelUnbondingDelegation(goCtx context.Context, msg *types.MsgCancelUnbondingDelegation) (*types.MsgCancelUnbondingDelegationResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
valAddr, err := sdk.ValAddressFromBech32(msg.ValidatorAddress)
if err != nil {
return nil, err
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid validator address: %s", err)
}
delegatorAddress, err := k.authKeeper.StringToBytes(msg.DelegatorAddress)
if err != nil {
return nil, err
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid delegator address: %s", err)
}
if !msg.Amount.IsValid() || !msg.Amount.Amount.IsPositive() {
return nil, errorsmod.Wrap(
sdkerrors.ErrInvalidRequest,
"invalid amount",
)
}
if msg.CreationHeight <= 0 {
return nil, errorsmod.Wrap(
sdkerrors.ErrInvalidRequest,
"invalid height",
)
}
ctx := sdk.UnwrapSDKContext(goCtx)
bondDenom := k.BondDenom(ctx)
if msg.Amount.Denom != bondDenom {
return nil, errorsmod.Wrapf(
@ -476,12 +541,16 @@ func (k msgServer) CancelUnbondingDelegation(goCtx context.Context, msg *types.M
}
func (k msgServer) UpdateParams(goCtx context.Context, msg *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
if k.authority != msg.Authority {
return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", k.authority, msg.Authority)
}
if err := msg.Params.Validate(); err != nil {
return nil, err
}
ctx := sdk.UnwrapSDKContext(goCtx)
// store params
if err := k.SetParams(ctx, msg.Params); err != nil {
return nil, err

File diff suppressed because it is too large Load Diff

View File

@ -50,11 +50,8 @@ func (k Keeper) MinCommissionRate(ctx sdk.Context) math.LegacyDec {
}
// SetParams sets the x/staking module parameters.
// CONTRACT: This method performs no validation of the parameters.
func (k Keeper) SetParams(ctx sdk.Context, params types.Params) error {
if err := params.Validate(); err != nil {
return err
}
store := ctx.KVStore(k.storeKey)
bz, err := k.cdc.Marshal(&params)
if err != nil {

View File

@ -61,7 +61,7 @@ func (sh *Helper) CreateValidatorWithMsg(ctx context.Context, msg *stakingtypes.
}
func (sh *Helper) createValidator(addr sdk.ValAddress, pk cryptotypes.PubKey, coin sdk.Coin, ok bool) {
msg, err := stakingtypes.NewMsgCreateValidator(addr, pk, coin, stakingtypes.Description{}, sh.Commission, math.OneInt())
msg, err := stakingtypes.NewMsgCreateValidator(addr, pk, coin, stakingtypes.Description{Moniker: "TestValidator"}, sh.Commission, math.OneInt())
require.NoError(sh.t, err)
res, err := sh.msgSrvr.CreateValidator(sh.Ctx, msg)
if ok {

View File

@ -5,7 +5,6 @@ import (
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)
@ -17,9 +16,6 @@ var (
valAddr1 = sdk.ValAddress(pk1.Address())
valAddr2 = sdk.ValAddress(pk2.Address())
valAddr3 = sdk.ValAddress(pk3.Address())
emptyAddr sdk.ValAddress
emptyPubkey cryptotypes.PubKey
)
func init() {

View File

@ -71,8 +71,8 @@ func (msg MsgCreateValidator) GetSignBytes() []byte {
return sdk.MustSortJSON(bz)
}
// ValidateBasic implements the sdk.Msg interface.
func (msg MsgCreateValidator) ValidateBasic() error {
// Validate validates the MsgCreateValidator sdk msg.
func (msg MsgCreateValidator) Validate() error {
// note that unmarshaling from bech32 ensures both non-empty and valid
_, err := sdk.ValAddressFromBech32(msg.ValidatorAddress)
if err != nil {
@ -141,32 +141,6 @@ func (msg MsgEditValidator) GetSignBytes() []byte {
return sdk.MustSortJSON(bz)
}
// ValidateBasic implements the sdk.Msg interface.
func (msg MsgEditValidator) ValidateBasic() error {
if _, err := sdk.ValAddressFromBech32(msg.ValidatorAddress); err != nil {
return sdkerrors.ErrInvalidAddress.Wrapf("invalid validator address: %s", err)
}
if msg.Description == (Description{}) {
return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "empty description")
}
if msg.MinSelfDelegation != nil && !msg.MinSelfDelegation.IsPositive() {
return errorsmod.Wrap(
sdkerrors.ErrInvalidRequest,
"minimum self delegation must be a positive integer",
)
}
if msg.CommissionRate != nil {
if msg.CommissionRate.GT(math.LegacyOneDec()) || msg.CommissionRate.IsNegative() {
return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "commission rate must be between 0 and 1 (inclusive)")
}
}
return nil
}
// NewMsgDelegate creates a new MsgDelegate instance.
func NewMsgDelegate(delAddr sdk.AccAddress, valAddr sdk.ValAddress, amount sdk.Coin) *MsgDelegate {
return &MsgDelegate{
@ -188,25 +162,6 @@ func (msg MsgDelegate) GetSignBytes() []byte {
return sdk.MustSortJSON(bz)
}
// ValidateBasic implements the sdk.Msg interface.
func (msg MsgDelegate) ValidateBasic() error {
if _, err := sdk.AccAddressFromBech32(msg.DelegatorAddress); err != nil {
return sdkerrors.ErrInvalidAddress.Wrapf("invalid delegator address: %s", err)
}
if _, err := sdk.ValAddressFromBech32(msg.ValidatorAddress); err != nil {
return sdkerrors.ErrInvalidAddress.Wrapf("invalid validator address: %s", err)
}
if !msg.Amount.IsValid() || !msg.Amount.Amount.IsPositive() {
return errorsmod.Wrap(
sdkerrors.ErrInvalidRequest,
"invalid delegation amount",
)
}
return nil
}
// NewMsgBeginRedelegate creates a new MsgBeginRedelegate instance.
func NewMsgBeginRedelegate(
delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress, amount sdk.Coin,
@ -231,28 +186,6 @@ func (msg MsgBeginRedelegate) GetSignBytes() []byte {
return sdk.MustSortJSON(bz)
}
// ValidateBasic implements the sdk.Msg interface.
func (msg MsgBeginRedelegate) ValidateBasic() error {
if _, err := sdk.AccAddressFromBech32(msg.DelegatorAddress); err != nil {
return sdkerrors.ErrInvalidAddress.Wrapf("invalid delegator address: %s", err)
}
if _, err := sdk.ValAddressFromBech32(msg.ValidatorSrcAddress); err != nil {
return sdkerrors.ErrInvalidAddress.Wrapf("invalid source validator address: %s", err)
}
if _, err := sdk.ValAddressFromBech32(msg.ValidatorDstAddress); err != nil {
return sdkerrors.ErrInvalidAddress.Wrapf("invalid destination validator address: %s", err)
}
if !msg.Amount.IsValid() || !msg.Amount.Amount.IsPositive() {
return errorsmod.Wrap(
sdkerrors.ErrInvalidRequest,
"invalid shares amount",
)
}
return nil
}
// NewMsgUndelegate creates a new MsgUndelegate instance.
func NewMsgUndelegate(delAddr sdk.AccAddress, valAddr sdk.ValAddress, amount sdk.Coin) *MsgUndelegate {
return &MsgUndelegate{
@ -274,25 +207,6 @@ func (msg MsgUndelegate) GetSignBytes() []byte {
return sdk.MustSortJSON(bz)
}
// ValidateBasic implements the sdk.Msg interface.
func (msg MsgUndelegate) ValidateBasic() error {
if _, err := sdk.AccAddressFromBech32(msg.DelegatorAddress); err != nil {
return sdkerrors.ErrInvalidAddress.Wrapf("invalid delegator address: %s", err)
}
if _, err := sdk.ValAddressFromBech32(msg.ValidatorAddress); err != nil {
return sdkerrors.ErrInvalidAddress.Wrapf("invalid validator address: %s", err)
}
if !msg.Amount.IsValid() || !msg.Amount.Amount.IsPositive() {
return errorsmod.Wrap(
sdkerrors.ErrInvalidRequest,
"invalid shares amount",
)
}
return nil
}
// NewMsgCancelUnbondingDelegation creates a new MsgCancelUnbondingDelegation instance.
func NewMsgCancelUnbondingDelegation(delAddr sdk.AccAddress, valAddr sdk.ValAddress, creationHeight int64, amount sdk.Coin) *MsgCancelUnbondingDelegation {
return &MsgCancelUnbondingDelegation{
@ -314,32 +228,6 @@ func (msg MsgCancelUnbondingDelegation) GetSignBytes() []byte {
return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg))
}
// ValidateBasic implements the sdk.Msg interface.
func (msg MsgCancelUnbondingDelegation) ValidateBasic() error {
if _, err := sdk.AccAddressFromBech32(msg.DelegatorAddress); err != nil {
return sdkerrors.ErrInvalidAddress.Wrapf("invalid delegator address: %s", err)
}
if _, err := sdk.ValAddressFromBech32(msg.ValidatorAddress); err != nil {
return sdkerrors.ErrInvalidAddress.Wrapf("invalid validator address: %s", err)
}
if !msg.Amount.IsValid() || !msg.Amount.Amount.IsPositive() {
return errorsmod.Wrap(
sdkerrors.ErrInvalidRequest,
"invalid amount",
)
}
if msg.CreationHeight <= 0 {
return errorsmod.Wrap(
sdkerrors.ErrInvalidRequest,
"invalid height",
)
}
return nil
}
// GetSignBytes returns the raw bytes for a MsgUpdateParams message that
// the expected signer needs to sign.
func (m MsgUpdateParams) GetSignBytes() []byte {
@ -347,14 +235,6 @@ func (m MsgUpdateParams) GetSignBytes() []byte {
return sdk.MustSortJSON(bz)
}
// ValidateBasic executes sanity validation on the provided data
func (m MsgUpdateParams) ValidateBasic() error {
if _, err := sdk.AccAddressFromBech32(m.Authority); err != nil {
return errorsmod.Wrap(err, "invalid authority address")
}
return m.Params.Validate()
}
// GetSigners returns the expected signers for a MsgUpdateParams message
func (m MsgUpdateParams) GetSigners() []sdk.AccAddress {
addr, _ := sdk.AccAddressFromBech32(m.Authority)

View File

@ -2,11 +2,8 @@ package types_test
import (
"testing"
"time"
"cosmossdk.io/math"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/stretchr/testify/require"
@ -19,10 +16,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/staking/types"
)
var (
coinPos = sdk.NewInt64Coin(sdk.DefaultBondDenom, 1000)
coinZero = sdk.NewInt64Coin(sdk.DefaultBondDenom, 0)
)
var coinPos = sdk.NewInt64Coin(sdk.DefaultBondDenom, 1000)
func TestMsgDecode(t *testing.T) {
registry := codectypes.NewInterfaceRegistry()
@ -55,300 +49,3 @@ func TestMsgDecode(t *testing.T) {
require.True(t, msg.Value.IsEqual(msg2.Value))
require.True(t, msg.Pubkey.Equal(msg2.Pubkey))
}
// test ValidateBasic for MsgCreateValidator
func TestMsgCreateValidator(t *testing.T) {
commission1 := types.NewCommissionRates(math.LegacyZeroDec(), math.LegacyZeroDec(), math.LegacyZeroDec())
commission2 := types.NewCommissionRates(math.LegacyNewDec(5), math.LegacyNewDec(5), math.LegacyNewDec(5))
tests := []struct {
name, moniker, identity, website, securityContact, details string
CommissionRates types.CommissionRates
minSelfDelegation math.Int
validatorAddr sdk.ValAddress
pubkey cryptotypes.PubKey
bond sdk.Coin
expectPass bool
}{
{"basic good", "a", "b", "c", "d", "e", commission1, math.OneInt(), valAddr1, pk1, coinPos, true},
{"partial description", "", "", "c", "", "", commission1, math.OneInt(), valAddr1, pk1, coinPos, true},
{"empty description", "", "", "", "", "", commission2, math.OneInt(), valAddr1, pk1, coinPos, false},
{"empty address", "a", "b", "c", "d", "e", commission2, math.OneInt(), emptyAddr, pk1, coinPos, false},
{"empty pubkey", "a", "b", "c", "d", "e", commission1, math.OneInt(), valAddr1, emptyPubkey, coinPos, false},
{"empty bond", "a", "b", "c", "d", "e", commission2, math.OneInt(), valAddr1, pk1, coinZero, false},
{"nil bond", "a", "b", "c", "d", "e", commission2, math.OneInt(), valAddr1, pk1, sdk.Coin{}, false},
{"zero min self delegation", "a", "b", "c", "d", "e", commission1, math.ZeroInt(), valAddr1, pk1, coinPos, false},
{"negative min self delegation", "a", "b", "c", "d", "e", commission1, sdk.NewInt(-1), valAddr1, pk1, coinPos, false},
{"delegation less than min self delegation", "a", "b", "c", "d", "e", commission1, coinPos.Amount.Add(math.OneInt()), valAddr1, pk1, coinPos, false},
}
for _, tc := range tests {
description := types.NewDescription(tc.moniker, tc.identity, tc.website, tc.securityContact, tc.details)
msg, err := types.NewMsgCreateValidator(tc.validatorAddr, tc.pubkey, tc.bond, description, tc.CommissionRates, tc.minSelfDelegation)
require.NoError(t, err)
if tc.expectPass {
require.Nil(t, msg.ValidateBasic(), "test: %v", tc.name)
} else {
require.NotNil(t, msg.ValidateBasic(), "test: %v", tc.name)
}
}
}
// test ValidateBasic for MsgEditValidator
func TestMsgEditValidator(t *testing.T) {
tests := []struct {
name, moniker, identity, website, securityContact, details string
validatorAddr sdk.ValAddress
expectPass bool
minSelfDelegation math.Int
}{
{"basic good", "a", "b", "c", "d", "e", valAddr1, true, math.OneInt()},
{"partial description", "", "", "c", "", "", valAddr1, true, math.OneInt()},
{"empty description", "", "", "", "", "", valAddr1, false, math.OneInt()},
{"empty address", "a", "b", "c", "d", "e", emptyAddr, false, math.OneInt()},
{"nil int", "a", "b", "c", "d", "e", emptyAddr, false, math.Int{}},
}
for _, tc := range tests {
description := types.NewDescription(tc.moniker, tc.identity, tc.website, tc.securityContact, tc.details)
newRate := math.LegacyZeroDec()
msg := types.NewMsgEditValidator(tc.validatorAddr, description, &newRate, &tc.minSelfDelegation)
if tc.expectPass {
require.Nil(t, msg.ValidateBasic(), "test: %v", tc.name)
} else {
require.NotNil(t, msg.ValidateBasic(), "test: %v", tc.name)
}
}
}
// test ValidateBasic for MsgDelegate
func TestMsgDelegate(t *testing.T) {
tests := []struct {
name string
delegatorAddr sdk.AccAddress
validatorAddr sdk.ValAddress
bond sdk.Coin
expectPass bool
}{
{"basic good", sdk.AccAddress(valAddr1), valAddr2, coinPos, true},
{"self bond", sdk.AccAddress(valAddr1), valAddr1, coinPos, true},
{"empty delegator", sdk.AccAddress(emptyAddr), valAddr1, coinPos, false},
{"empty validator", sdk.AccAddress(valAddr1), emptyAddr, coinPos, false},
{"empty bond", sdk.AccAddress(valAddr1), valAddr2, coinZero, false},
{"nil bold", sdk.AccAddress(valAddr1), valAddr2, sdk.Coin{}, false},
}
for _, tc := range tests {
msg := types.NewMsgDelegate(tc.delegatorAddr, tc.validatorAddr, tc.bond)
if tc.expectPass {
require.Nil(t, msg.ValidateBasic(), "test: %v", tc.name)
} else {
require.NotNil(t, msg.ValidateBasic(), "test: %v", tc.name)
}
}
}
// test ValidateBasic for MsgUnbond
func TestMsgBeginRedelegate(t *testing.T) {
tests := []struct {
name string
delegatorAddr sdk.AccAddress
validatorSrcAddr sdk.ValAddress
validatorDstAddr sdk.ValAddress
amount sdk.Coin
expectPass bool
}{
{"regular", sdk.AccAddress(valAddr1), valAddr2, valAddr3, sdk.NewInt64Coin(sdk.DefaultBondDenom, 1), true},
{"zero amount", sdk.AccAddress(valAddr1), valAddr2, valAddr3, sdk.NewInt64Coin(sdk.DefaultBondDenom, 0), false},
{"nil amount", sdk.AccAddress(valAddr1), valAddr2, valAddr3, sdk.Coin{}, false},
{"empty delegator", sdk.AccAddress(emptyAddr), valAddr1, valAddr3, sdk.NewInt64Coin(sdk.DefaultBondDenom, 1), false},
{"empty source validator", sdk.AccAddress(valAddr1), emptyAddr, valAddr3, sdk.NewInt64Coin(sdk.DefaultBondDenom, 1), false},
{"empty destination validator", sdk.AccAddress(valAddr1), valAddr2, emptyAddr, sdk.NewInt64Coin(sdk.DefaultBondDenom, 1), false},
}
for _, tc := range tests {
msg := types.NewMsgBeginRedelegate(tc.delegatorAddr, tc.validatorSrcAddr, tc.validatorDstAddr, tc.amount)
if tc.expectPass {
require.Nil(t, msg.ValidateBasic(), "test: %v", tc.name)
} else {
require.NotNil(t, msg.ValidateBasic(), "test: %v", tc.name)
}
}
}
// test ValidateBasic for MsgUnbond
func TestMsgUndelegate(t *testing.T) {
tests := []struct {
name string
delegatorAddr sdk.AccAddress
validatorAddr sdk.ValAddress
amount sdk.Coin
expectPass bool
}{
{"regular", sdk.AccAddress(valAddr1), valAddr2, sdk.NewInt64Coin(sdk.DefaultBondDenom, 1), true},
{"zero amount", sdk.AccAddress(valAddr1), valAddr2, sdk.NewInt64Coin(sdk.DefaultBondDenom, 0), false},
{"nil amount", sdk.AccAddress(valAddr1), valAddr2, sdk.Coin{}, false},
{"empty delegator", sdk.AccAddress(emptyAddr), valAddr1, sdk.NewInt64Coin(sdk.DefaultBondDenom, 1), false},
{"empty validator", sdk.AccAddress(valAddr1), emptyAddr, sdk.NewInt64Coin(sdk.DefaultBondDenom, 1), false},
}
for _, tc := range tests {
msg := types.NewMsgUndelegate(tc.delegatorAddr, tc.validatorAddr, tc.amount)
if tc.expectPass {
require.Nil(t, msg.ValidateBasic(), "test: %v", tc.name)
} else {
require.NotNil(t, msg.ValidateBasic(), "test: %v", tc.name)
}
}
}
func TestMsgUpdateParams(t *testing.T) {
msg := types.MsgUpdateParams{
Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(),
Params: types.DefaultParams(),
}
require.Equal(t, []sdk.AccAddress{authtypes.NewModuleAddress(govtypes.ModuleName)}, msg.GetSigners())
}
func TestMsgUpdateParamsValidateBasic(t *testing.T) {
tests := []struct {
name string
msgUpdateParams types.MsgUpdateParams
expFail bool
expError string
}{
{
"valid msg",
types.MsgUpdateParams{
Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(),
Params: types.DefaultParams(),
},
false,
"",
},
{
"negative unbounding time",
types.MsgUpdateParams{
Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(),
Params: types.Params{
UnbondingTime: time.Hour * 24 * 7 * 3 * -1,
MaxEntries: types.DefaultMaxEntries,
MaxValidators: types.DefaultMaxValidators,
HistoricalEntries: types.DefaultHistoricalEntries,
MinCommissionRate: types.DefaultMinCommissionRate,
BondDenom: "denom",
},
},
true,
"unbonding time must be positive:",
},
{
"cero value max validator",
types.MsgUpdateParams{
Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(),
Params: types.Params{
UnbondingTime: time.Hour * 24 * 7 * 3,
MaxEntries: types.DefaultMaxEntries,
MaxValidators: 0,
HistoricalEntries: types.DefaultHistoricalEntries,
MinCommissionRate: types.DefaultMinCommissionRate,
BondDenom: "denom",
},
},
true,
"max validators must be positive:",
},
{
"cero value max validator",
types.MsgUpdateParams{
Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(),
Params: types.Params{
UnbondingTime: time.Hour * 24 * 7 * 3,
MaxEntries: 0,
MaxValidators: types.DefaultMaxValidators,
HistoricalEntries: types.DefaultHistoricalEntries,
MinCommissionRate: types.DefaultMinCommissionRate,
BondDenom: "denom",
},
},
true,
"max entries must be positive:",
},
{
"negative commission rate",
types.MsgUpdateParams{
Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(),
Params: types.Params{
UnbondingTime: time.Hour * 24 * 7 * 3,
MaxEntries: types.DefaultMaxEntries,
MaxValidators: types.DefaultMaxValidators,
HistoricalEntries: types.DefaultHistoricalEntries,
MinCommissionRate: math.LegacyNewDec(-1),
BondDenom: "denom",
},
},
true,
"minimum commission rate cannot be negative:",
},
{
"negative commission rate",
types.MsgUpdateParams{
Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(),
Params: types.Params{
UnbondingTime: time.Hour * 24 * 7 * 3,
MaxEntries: types.DefaultMaxEntries,
MaxValidators: types.DefaultMaxValidators,
HistoricalEntries: types.DefaultHistoricalEntries,
MinCommissionRate: math.LegacyNewDec(2),
BondDenom: "denom",
},
},
true,
"minimum commission rate cannot be greater than 100",
},
{
"blank bonddenom",
types.MsgUpdateParams{
Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(),
Params: types.Params{
UnbondingTime: time.Hour * 24 * 7 * 3,
MaxEntries: types.DefaultMaxEntries,
MaxValidators: types.DefaultMaxValidators,
HistoricalEntries: types.DefaultHistoricalEntries,
MinCommissionRate: types.DefaultMinCommissionRate,
BondDenom: "",
},
},
true,
"bond denom cannot be blank",
},
{
"Invalid authority",
types.MsgUpdateParams{
Authority: "invalid",
Params: types.Params{
UnbondingTime: time.Hour * 24 * 7 * 3,
MaxEntries: types.DefaultMaxEntries,
MaxValidators: types.DefaultMaxValidators,
HistoricalEntries: types.DefaultHistoricalEntries,
MinCommissionRate: types.DefaultMinCommissionRate,
BondDenom: "denom",
},
},
true,
"invalid authority address",
},
}
for _, tc := range tests {
err := tc.msgUpdateParams.ValidateBasic()
if tc.expFail {
require.Error(t, err)
require.Contains(t, err.Error(), tc.expError)
} else {
require.NoError(t, err)
}
}
}