2020-10-19 06:04:55 -07:00
|
|
|
package teststaking
|
|
|
|
|
|
|
|
import (
|
2021-07-19 07:49:42 -07:00
|
|
|
"context"
|
2020-10-19 06:04:55 -07:00
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
2020-11-09 08:01:43 -08:00
|
|
|
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
2020-10-19 06:04:55 -07:00
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
|
|
"github.com/cosmos/cosmos-sdk/x/staking"
|
|
|
|
"github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
|
|
|
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
|
|
|
)
|
|
|
|
|
2021-07-19 07:49:42 -07:00
|
|
|
// Helper is a structure which wraps the staking message server
|
2020-10-19 06:04:55 -07:00
|
|
|
// and provides methods useful in tests
|
|
|
|
type Helper struct {
|
2021-07-19 07:49:42 -07:00
|
|
|
t *testing.T
|
|
|
|
msgSrvr stakingtypes.MsgServer
|
|
|
|
k keeper.Keeper
|
2020-10-19 06:04:55 -07:00
|
|
|
|
|
|
|
Ctx sdk.Context
|
|
|
|
Commission stakingtypes.CommissionRates
|
|
|
|
// Coin Denomination
|
|
|
|
Denom string
|
|
|
|
}
|
|
|
|
|
2021-07-19 07:49:42 -07:00
|
|
|
// NewHelper creates a new instance of Helper.
|
2020-10-19 06:04:55 -07:00
|
|
|
func NewHelper(t *testing.T, ctx sdk.Context, k keeper.Keeper) *Helper {
|
2021-07-19 07:49:42 -07:00
|
|
|
return &Helper{t, keeper.NewMsgServerImpl(k), k, ctx, ZeroCommission(), sdk.DefaultBondDenom}
|
2020-10-19 06:04:55 -07:00
|
|
|
}
|
|
|
|
|
2021-07-19 07:49:42 -07:00
|
|
|
// CreateValidator calls staking module `MsgServer/CreateValidator` to create a new validator
|
2020-11-11 08:52:59 -08:00
|
|
|
func (sh *Helper) CreateValidator(addr sdk.ValAddress, pk cryptotypes.PubKey, stakeAmount sdk.Int, ok bool) {
|
2020-11-10 05:05:15 -08:00
|
|
|
coin := sdk.NewCoin(sh.Denom, stakeAmount)
|
2020-10-19 06:04:55 -07:00
|
|
|
sh.createValidator(addr, pk, coin, ok)
|
|
|
|
}
|
|
|
|
|
2021-07-19 07:49:42 -07:00
|
|
|
// CreateValidatorWithValPower calls staking module `MsgServer/CreateValidator` to create a new validator with zero
|
2020-10-19 06:04:55 -07:00
|
|
|
// commission
|
2020-11-09 08:01:43 -08:00
|
|
|
func (sh *Helper) CreateValidatorWithValPower(addr sdk.ValAddress, pk cryptotypes.PubKey, valPower int64, ok bool) sdk.Int {
|
2021-01-28 05:54:39 -08:00
|
|
|
amount := sh.k.TokensFromConsensusPower(sh.Ctx, valPower)
|
2020-10-19 06:04:55 -07:00
|
|
|
coin := sdk.NewCoin(sh.Denom, amount)
|
|
|
|
sh.createValidator(addr, pk, coin, ok)
|
|
|
|
return amount
|
|
|
|
}
|
|
|
|
|
|
|
|
// CreateValidatorMsg returns a message used to create validator in this service.
|
2020-11-11 08:52:59 -08:00
|
|
|
func (sh *Helper) CreateValidatorMsg(addr sdk.ValAddress, pk cryptotypes.PubKey, stakeAmount sdk.Int) *stakingtypes.MsgCreateValidator {
|
2020-11-10 05:05:15 -08:00
|
|
|
coin := sdk.NewCoin(sh.Denom, stakeAmount)
|
2020-10-19 06:04:55 -07:00
|
|
|
msg, err := stakingtypes.NewMsgCreateValidator(addr, pk, coin, stakingtypes.Description{}, sh.Commission, sdk.OneInt())
|
|
|
|
require.NoError(sh.t, err)
|
|
|
|
return msg
|
|
|
|
}
|
|
|
|
|
2021-07-19 07:49:42 -07:00
|
|
|
// CreateValidatorWithMsg calls staking module `MsgServer/CreateValidator`
|
|
|
|
func (sh *Helper) CreateValidatorWithMsg(ctx context.Context, msg *stakingtypes.MsgCreateValidator) (*stakingtypes.MsgCreateValidatorResponse, error) {
|
|
|
|
return sh.msgSrvr.CreateValidator(ctx, msg)
|
|
|
|
}
|
|
|
|
|
2020-11-09 08:01:43 -08:00
|
|
|
func (sh *Helper) createValidator(addr sdk.ValAddress, pk cryptotypes.PubKey, coin sdk.Coin, ok bool) {
|
2020-10-19 06:04:55 -07:00
|
|
|
msg, err := stakingtypes.NewMsgCreateValidator(addr, pk, coin, stakingtypes.Description{}, sh.Commission, sdk.OneInt())
|
|
|
|
require.NoError(sh.t, err)
|
2021-07-19 07:49:42 -07:00
|
|
|
res, err := sh.msgSrvr.CreateValidator(sdk.WrapSDKContext(sh.Ctx), msg)
|
|
|
|
if ok {
|
|
|
|
require.NoError(sh.t, err)
|
|
|
|
require.NotNil(sh.t, res)
|
|
|
|
} else {
|
|
|
|
require.Error(sh.t, err)
|
|
|
|
require.Nil(sh.t, res)
|
|
|
|
}
|
2020-10-19 06:04:55 -07:00
|
|
|
}
|
|
|
|
|
2021-07-19 07:49:42 -07:00
|
|
|
// Delegate calls staking module staking module `MsgServer/Delegate` to delegate stake for a validator
|
2020-11-10 05:05:15 -08:00
|
|
|
func (sh *Helper) Delegate(delegator sdk.AccAddress, val sdk.ValAddress, amount sdk.Int) {
|
|
|
|
coin := sdk.NewCoin(sh.Denom, amount)
|
2020-10-19 06:04:55 -07:00
|
|
|
msg := stakingtypes.NewMsgDelegate(delegator, val, coin)
|
2021-07-19 07:49:42 -07:00
|
|
|
res, err := sh.msgSrvr.Delegate(sdk.WrapSDKContext(sh.Ctx), msg)
|
|
|
|
require.NoError(sh.t, err)
|
|
|
|
require.NotNil(sh.t, res)
|
2020-10-19 06:04:55 -07:00
|
|
|
}
|
|
|
|
|
2021-07-19 07:49:42 -07:00
|
|
|
// DelegateWithPower calls staking module `MsgServer/Delegate` to delegate stake for a validator
|
2020-10-19 06:04:55 -07:00
|
|
|
func (sh *Helper) DelegateWithPower(delegator sdk.AccAddress, val sdk.ValAddress, power int64) {
|
2021-01-28 05:54:39 -08:00
|
|
|
coin := sdk.NewCoin(sh.Denom, sh.k.TokensFromConsensusPower(sh.Ctx, power))
|
2020-10-19 06:04:55 -07:00
|
|
|
msg := stakingtypes.NewMsgDelegate(delegator, val, coin)
|
2021-07-19 07:49:42 -07:00
|
|
|
res, err := sh.msgSrvr.Delegate(sdk.WrapSDKContext(sh.Ctx), msg)
|
|
|
|
require.NoError(sh.t, err)
|
|
|
|
require.NotNil(sh.t, res)
|
2020-10-19 06:04:55 -07:00
|
|
|
}
|
|
|
|
|
2021-07-19 07:49:42 -07:00
|
|
|
// Undelegate calls staking module `MsgServer/Undelegate` to unbound some stake from a validator.
|
|
|
|
func (sh *Helper) Undelegate(delegator sdk.AccAddress, val sdk.ValAddress, amount sdk.Int, ok bool) {
|
2020-10-19 06:04:55 -07:00
|
|
|
unbondAmt := sdk.NewCoin(sh.Denom, amount)
|
|
|
|
msg := stakingtypes.NewMsgUndelegate(delegator, val, unbondAmt)
|
2021-07-19 07:49:42 -07:00
|
|
|
res, err := sh.msgSrvr.Undelegate(sdk.WrapSDKContext(sh.Ctx), msg)
|
2020-10-19 06:04:55 -07:00
|
|
|
if ok {
|
|
|
|
require.NoError(sh.t, err)
|
|
|
|
require.NotNil(sh.t, res)
|
|
|
|
} else {
|
|
|
|
require.Error(sh.t, err)
|
|
|
|
require.Nil(sh.t, res)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// CheckValidator asserts that a validor exists and has a given status (if status!="")
|
|
|
|
// and if has a right jailed flag.
|
|
|
|
func (sh *Helper) CheckValidator(addr sdk.ValAddress, status stakingtypes.BondStatus, jailed bool) stakingtypes.Validator {
|
|
|
|
v, ok := sh.k.GetValidator(sh.Ctx, addr)
|
|
|
|
require.True(sh.t, ok)
|
|
|
|
require.Equal(sh.t, jailed, v.Jailed, "wrong Jalied status")
|
|
|
|
if status >= 0 {
|
|
|
|
require.Equal(sh.t, status, v.Status)
|
|
|
|
}
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
|
|
|
// CheckDelegator asserts that a delegator exists
|
|
|
|
func (sh *Helper) CheckDelegator(delegator sdk.AccAddress, val sdk.ValAddress, found bool) {
|
|
|
|
_, ok := sh.k.GetDelegation(sh.Ctx, delegator, val)
|
|
|
|
require.Equal(sh.t, ok, found)
|
|
|
|
}
|
|
|
|
|
|
|
|
// TurnBlock calls EndBlocker and updates the block time
|
|
|
|
func (sh *Helper) TurnBlock(newTime time.Time) sdk.Context {
|
|
|
|
sh.Ctx = sh.Ctx.WithBlockTime(newTime)
|
|
|
|
staking.EndBlocker(sh.Ctx, sh.k)
|
|
|
|
return sh.Ctx
|
|
|
|
}
|
|
|
|
|
|
|
|
// TurnBlockTimeDiff calls EndBlocker and updates the block time by adding the
|
|
|
|
// duration to the current block time
|
|
|
|
func (sh *Helper) TurnBlockTimeDiff(diff time.Duration) sdk.Context {
|
|
|
|
sh.Ctx = sh.Ctx.WithBlockTime(sh.Ctx.BlockHeader().Time.Add(diff))
|
|
|
|
staking.EndBlocker(sh.Ctx, sh.k)
|
|
|
|
return sh.Ctx
|
|
|
|
}
|
|
|
|
|
|
|
|
// ZeroCommission constructs a commission rates with all zeros.
|
|
|
|
func ZeroCommission() stakingtypes.CommissionRates {
|
|
|
|
return stakingtypes.NewCommissionRates(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec())
|
|
|
|
}
|