github.com/Finschia/finschia-sdk@v0.49.1/x/staking/handler_test.go (about)

     1  package staking_test
     2  
     3  import (
     4  	"strings"
     5  	"testing"
     6  	"time"
     7  
     8  	octypes "github.com/Finschia/ostracon/types"
     9  	"github.com/golang/protobuf/proto"
    10  	"github.com/stretchr/testify/assert"
    11  	"github.com/stretchr/testify/require"
    12  	abci "github.com/tendermint/tendermint/abci/types"
    13  	tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
    14  
    15  	cryptocodec "github.com/Finschia/finschia-sdk/crypto/codec"
    16  	"github.com/Finschia/finschia-sdk/crypto/keys/ed25519"
    17  	"github.com/Finschia/finschia-sdk/crypto/keys/secp256k1"
    18  	cryptotypes "github.com/Finschia/finschia-sdk/crypto/types"
    19  	"github.com/Finschia/finschia-sdk/simapp"
    20  	"github.com/Finschia/finschia-sdk/testutil/testdata"
    21  	sdk "github.com/Finschia/finschia-sdk/types"
    22  	"github.com/Finschia/finschia-sdk/x/staking"
    23  	"github.com/Finschia/finschia-sdk/x/staking/keeper"
    24  	"github.com/Finschia/finschia-sdk/x/staking/teststaking"
    25  	"github.com/Finschia/finschia-sdk/x/staking/types"
    26  )
    27  
    28  func bootstrapHandlerGenesisTest(t *testing.T, power int64, numAddrs int, accAmount sdk.Int) (*simapp.SimApp, sdk.Context, []sdk.AccAddress, []sdk.ValAddress) {
    29  	t.Helper()
    30  	_, app, ctx := getBaseSimappWithCustomKeeper()
    31  
    32  	addrDels, addrVals := generateAddresses(app, ctx, numAddrs, accAmount)
    33  
    34  	amt := app.StakingKeeper.TokensFromConsensusPower(ctx, power)
    35  	totalSupply := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), amt.MulRaw(int64(len(addrDels)))))
    36  
    37  	notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
    38  
    39  	// set non bonded pool balance
    40  	app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
    41  	require.NoError(t, simapp.FundModuleAccount(app, ctx, notBondedPool.GetName(), totalSupply))
    42  	return app, ctx, addrDels, addrVals
    43  }
    44  
    45  func TestValidatorByPowerIndex(t *testing.T) {
    46  	initPower := int64(1000000)
    47  	app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 10, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction))
    48  	validatorAddr, validatorAddr3 := valAddrs[0], valAddrs[1]
    49  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
    50  
    51  	// create validator
    52  	initBond := tstaking.CreateValidatorWithValPower(validatorAddr, PKs[0], initPower, true)
    53  
    54  	// must end-block
    55  	updates, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
    56  	require.NoError(t, err)
    57  	require.Equal(t, 1, len(updates))
    58  
    59  	// verify the self-delegation exists
    60  	bond, found := app.StakingKeeper.GetDelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr)
    61  	require.True(t, found)
    62  	gotBond := bond.Shares.RoundInt()
    63  	require.Equal(t, initBond, gotBond)
    64  
    65  	// verify that the by power index exists
    66  	validator, found := app.StakingKeeper.GetValidator(ctx, validatorAddr)
    67  	require.True(t, found)
    68  	power := types.GetValidatorsByPowerIndexKey(validator, app.StakingKeeper.PowerReduction(ctx))
    69  	require.True(t, keeper.ValidatorByPowerIndexExists(ctx, app.StakingKeeper, power))
    70  
    71  	// create a second validator keep it bonded
    72  	tstaking.CreateValidatorWithValPower(validatorAddr3, PKs[2], initPower, true)
    73  
    74  	// must end-block
    75  	updates, err = app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
    76  	require.NoError(t, err)
    77  	require.Equal(t, 1, len(updates))
    78  
    79  	// slash and jail the first validator
    80  	consAddr0 := sdk.ConsAddress(PKs[0].Address())
    81  	app.StakingKeeper.Slash(ctx, consAddr0, 0, initPower, sdk.NewDecWithPrec(5, 1))
    82  	app.StakingKeeper.Jail(ctx, consAddr0)
    83  	_, err = app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
    84  	require.NoError(t, err)
    85  
    86  	validator, found = app.StakingKeeper.GetValidator(ctx, validatorAddr)
    87  	require.True(t, found)
    88  	require.Equal(t, types.Unbonding, validator.Status)    // ensure is unbonding
    89  	require.Equal(t, initBond.QuoRaw(2), validator.Tokens) // ensure tokens slashed
    90  	app.StakingKeeper.Unjail(ctx, consAddr0)
    91  
    92  	// the old power record should have been deleted as the power changed
    93  	require.False(t, keeper.ValidatorByPowerIndexExists(ctx, app.StakingKeeper, power))
    94  
    95  	// but the new power record should have been created
    96  	validator, found = app.StakingKeeper.GetValidator(ctx, validatorAddr)
    97  	require.True(t, found)
    98  	power2 := types.GetValidatorsByPowerIndexKey(validator, app.StakingKeeper.PowerReduction(ctx))
    99  	require.True(t, keeper.ValidatorByPowerIndexExists(ctx, app.StakingKeeper, power2))
   100  
   101  	// now the new record power index should be the same as the original record
   102  	power3 := types.GetValidatorsByPowerIndexKey(validator, app.StakingKeeper.PowerReduction(ctx))
   103  	require.Equal(t, power2, power3)
   104  
   105  	// unbond self-delegation
   106  	totalBond := validator.TokensFromShares(bond.GetShares()).TruncateInt()
   107  	res := tstaking.Undelegate(sdk.AccAddress(validatorAddr), validatorAddr, totalBond, true)
   108  
   109  	var resData types.MsgUndelegateResponse
   110  	err = proto.Unmarshal(res.Data, &resData)
   111  	require.NoError(t, err)
   112  
   113  	ctx = ctx.WithBlockTime(resData.CompletionTime)
   114  	staking.EndBlocker(ctx, app.StakingKeeper)
   115  	staking.EndBlocker(ctx, app.StakingKeeper)
   116  
   117  	// verify that by power key nolonger exists
   118  	_, found = app.StakingKeeper.GetValidator(ctx, validatorAddr)
   119  	require.False(t, found)
   120  	require.False(t, keeper.ValidatorByPowerIndexExists(ctx, app.StakingKeeper, power3))
   121  }
   122  
   123  func TestDuplicatesMsgCreateValidator(t *testing.T) {
   124  	initPower := int64(1000000)
   125  	app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 10, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction))
   126  
   127  	addr1, addr2 := valAddrs[0], valAddrs[1]
   128  	pk1, pk2 := PKs[0], PKs[1]
   129  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
   130  
   131  	valTokens := tstaking.CreateValidatorWithValPower(addr1, pk1, 10, true)
   132  	_, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
   133  	require.NoError(t, err)
   134  
   135  	validator := tstaking.CheckValidator(addr1, types.Bonded, false)
   136  	assert.Equal(t, addr1.String(), validator.OperatorAddress)
   137  	consKey, err := validator.OcConsPublicKey()
   138  	require.NoError(t, err)
   139  	tmPk1, err := cryptocodec.ToOcProtoPublicKey(pk1)
   140  	require.NoError(t, err)
   141  	assert.Equal(t, tmPk1, consKey)
   142  	assert.Equal(t, valTokens, validator.BondedTokens())
   143  	assert.Equal(t, valTokens.ToDec(), validator.DelegatorShares)
   144  	assert.Equal(t, types.Description{}, validator.Description)
   145  
   146  	// two validators can't have the same operator address
   147  	tstaking.CreateValidator(addr1, pk2, valTokens, false)
   148  
   149  	// two validators can't have the same pubkey
   150  	tstaking.CreateValidator(addr2, pk1, valTokens, false)
   151  
   152  	// must have different pubkey and operator
   153  	tstaking.CreateValidator(addr2, pk2, valTokens, true)
   154  
   155  	// must end-block
   156  	updates, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
   157  	require.NoError(t, err)
   158  	require.Equal(t, 1, len(updates))
   159  
   160  	validator = tstaking.CheckValidator(addr2, types.Bonded, false)
   161  	assert.Equal(t, addr2.String(), validator.OperatorAddress)
   162  	consPk, err := validator.OcConsPublicKey()
   163  	require.NoError(t, err)
   164  	tmPk2, err := cryptocodec.ToOcProtoPublicKey(pk2)
   165  	require.NoError(t, err)
   166  	assert.Equal(t, tmPk2, consPk)
   167  	assert.True(sdk.IntEq(t, valTokens, validator.Tokens))
   168  	assert.True(sdk.DecEq(t, valTokens.ToDec(), validator.DelegatorShares))
   169  	assert.Equal(t, types.Description{}, validator.Description)
   170  }
   171  
   172  func TestInvalidPubKeyTypeMsgCreateValidator(t *testing.T) {
   173  	initPower := int64(1000)
   174  	app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 1, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction))
   175  	ctx = ctx.WithConsensusParams(&abci.ConsensusParams{
   176  		Validator: &tmproto.ValidatorParams{PubKeyTypes: []string{octypes.ABCIPubKeyTypeEd25519}},
   177  	})
   178  
   179  	addr := valAddrs[0]
   180  	invalidPk := secp256k1.GenPrivKey().PubKey()
   181  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
   182  
   183  	// invalid pukKey type should not be allowed
   184  	tstaking.CreateValidator(addr, invalidPk, sdk.NewInt(10), false)
   185  }
   186  
   187  func TestBothPubKeyTypesMsgCreateValidator(t *testing.T) {
   188  	app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, 1000, 2, sdk.NewInt(1000))
   189  	ctx = ctx.WithConsensusParams(&abci.ConsensusParams{
   190  		Validator: &tmproto.ValidatorParams{PubKeyTypes: []string{octypes.ABCIPubKeyTypeEd25519, octypes.ABCIPubKeyTypeSecp256k1}},
   191  	})
   192  
   193  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
   194  
   195  	testCases := []struct {
   196  		name string
   197  		addr sdk.ValAddress
   198  		pk   cryptotypes.PubKey
   199  	}{
   200  		{
   201  			"can create a validator with ed25519 pubkey",
   202  			valAddrs[0],
   203  			ed25519.GenPrivKey().PubKey(),
   204  		},
   205  		{
   206  			"can create a validator with secp256k1 pubkey",
   207  			valAddrs[1],
   208  			secp256k1.GenPrivKey().PubKey(),
   209  		},
   210  	}
   211  	for _, tc := range testCases {
   212  		t.Run(tc.name, func(*testing.T) {
   213  			tstaking.CreateValidator(tc.addr, tc.pk, sdk.NewInt(10), true)
   214  		})
   215  	}
   216  }
   217  
   218  func TestLegacyValidatorDelegations(t *testing.T) {
   219  	initPower := int64(1000)
   220  	app, ctx, delAddrs, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 2, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction))
   221  
   222  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
   223  	valAddr := valAddrs[0]
   224  	valConsPubKey, valConsAddr := PKs[0], sdk.ConsAddress(PKs[0].Address())
   225  	delAddr := delAddrs[1]
   226  
   227  	// create validator
   228  	bondAmount := tstaking.CreateValidatorWithValPower(valAddr, valConsPubKey, 10, true)
   229  
   230  	// must end-block
   231  	updates, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
   232  	require.NoError(t, err)
   233  	require.Equal(t, 1, len(updates))
   234  
   235  	// verify the validator exists and has the correct attributes
   236  	validator := tstaking.CheckValidator(valAddr, types.Bonded, false)
   237  	require.Equal(t, bondAmount, validator.DelegatorShares.RoundInt())
   238  	require.Equal(t, bondAmount, validator.BondedTokens())
   239  
   240  	// delegate tokens to the validator
   241  	tstaking.Delegate(delAddr, valAddr, bondAmount)
   242  
   243  	// verify validator bonded shares
   244  	validator = tstaking.CheckValidator(valAddr, types.Bonded, false)
   245  	require.Equal(t, bondAmount.MulRaw(2), validator.DelegatorShares.RoundInt())
   246  	require.Equal(t, bondAmount.MulRaw(2), validator.BondedTokens())
   247  
   248  	// unbond validator total self-delegations (which should jail the validator)
   249  	res := tstaking.Undelegate(sdk.AccAddress(valAddr), valAddr, bondAmount, true)
   250  
   251  	var resData types.MsgUndelegateResponse
   252  	err = proto.Unmarshal(res.Data, &resData)
   253  	require.NoError(t, err)
   254  
   255  	ctx = ctx.WithBlockTime(resData.CompletionTime)
   256  	tstaking.Ctx = ctx
   257  	staking.EndBlocker(ctx, app.StakingKeeper)
   258  
   259  	// verify the validator record still exists, is jailed, and has correct tokens
   260  	validator = tstaking.CheckValidator(valAddr, -1, true)
   261  	require.Equal(t, bondAmount, validator.Tokens)
   262  
   263  	// verify delegation still exists
   264  	bond, found := app.StakingKeeper.GetDelegation(ctx, delAddr, valAddr)
   265  	require.True(t, found)
   266  	require.Equal(t, bondAmount, bond.Shares.RoundInt())
   267  	require.Equal(t, bondAmount, validator.DelegatorShares.RoundInt())
   268  
   269  	// verify the validator can still self-delegate
   270  	tstaking.Delegate(sdk.AccAddress(valAddr), valAddr, bondAmount)
   271  
   272  	// verify validator bonded shares
   273  	validator, found = app.StakingKeeper.GetValidator(ctx, valAddr)
   274  	require.True(t, found)
   275  	require.Equal(t, bondAmount.MulRaw(2), validator.DelegatorShares.RoundInt())
   276  	require.Equal(t, bondAmount.MulRaw(2), validator.Tokens)
   277  
   278  	// unjail the validator now that is has non-zero self-delegated shares
   279  	app.StakingKeeper.Unjail(ctx, valConsAddr)
   280  
   281  	// verify the validator can now accept delegations
   282  	tstaking.Delegate(delAddr, valAddr, bondAmount)
   283  
   284  	// verify validator bonded shares
   285  	validator, found = app.StakingKeeper.GetValidator(ctx, valAddr)
   286  	require.True(t, found)
   287  	require.Equal(t, bondAmount.MulRaw(3), validator.DelegatorShares.RoundInt())
   288  	require.Equal(t, bondAmount.MulRaw(3), validator.Tokens)
   289  
   290  	// verify new delegation
   291  	bond, found = app.StakingKeeper.GetDelegation(ctx, delAddr, valAddr)
   292  	require.True(t, found)
   293  	require.Equal(t, bondAmount.MulRaw(2), bond.Shares.RoundInt())
   294  	require.Equal(t, bondAmount.MulRaw(3), validator.DelegatorShares.RoundInt())
   295  }
   296  
   297  func TestIncrementsMsgDelegate(t *testing.T) {
   298  	initPower := int64(1000)
   299  	initBond := sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction)
   300  	app, ctx, delAddrs, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 2, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction))
   301  
   302  	params := app.StakingKeeper.GetParams(ctx)
   303  	validatorAddr, delegatorAddr := valAddrs[0], delAddrs[1]
   304  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
   305  
   306  	// first create validator
   307  	bondAmount := tstaking.CreateValidatorWithValPower(validatorAddr, PKs[0], 10, true)
   308  
   309  	// apply TM updates
   310  	_, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
   311  	require.NoError(t, err)
   312  
   313  	validator := tstaking.CheckValidator(validatorAddr, types.Bonded, false)
   314  	require.Equal(t, bondAmount, validator.DelegatorShares.RoundInt())
   315  	require.Equal(t, bondAmount, validator.BondedTokens(), "validator: %v", validator)
   316  
   317  	tstaking.CheckDelegator(delegatorAddr, validatorAddr, false)
   318  
   319  	bond, found := app.StakingKeeper.GetDelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr)
   320  	require.True(t, found)
   321  	require.Equal(t, bondAmount, bond.Shares.RoundInt())
   322  
   323  	bondedTokens := app.StakingKeeper.TotalBondedTokens(ctx)
   324  	require.Equal(t, bondAmount, bondedTokens)
   325  
   326  	for i := int64(0); i < 5; i++ {
   327  		ctx = ctx.WithBlockHeight(i)
   328  		tstaking.Ctx = ctx
   329  		tstaking.Delegate(delegatorAddr, validatorAddr, bondAmount)
   330  
   331  		// Check that the accounts and the bond account have the appropriate values
   332  		validator, found := app.StakingKeeper.GetValidator(ctx, validatorAddr)
   333  		require.True(t, found)
   334  		bond, found := app.StakingKeeper.GetDelegation(ctx, delegatorAddr, validatorAddr)
   335  		require.True(t, found)
   336  
   337  		expBond := bondAmount.MulRaw(i + 1)
   338  		expDelegatorShares := bondAmount.MulRaw(i + 2) // (1 self delegation)
   339  		expDelegatorAcc := initBond.Sub(expBond)
   340  
   341  		gotBond := bond.Shares.RoundInt()
   342  		gotDelegatorShares := validator.DelegatorShares.RoundInt()
   343  		gotDelegatorAcc := app.BankKeeper.GetBalance(ctx, delegatorAddr, params.BondDenom).Amount
   344  
   345  		require.Equal(t, expBond, gotBond,
   346  			"i: %v\nexpBond: %v\ngotBond: %v\nvalidator: %v\nbond: %v\n",
   347  			i, expBond, gotBond, validator, bond)
   348  		require.Equal(t, expDelegatorShares, gotDelegatorShares,
   349  			"i: %v\nexpDelegatorShares: %v\ngotDelegatorShares: %v\nvalidator: %v\nbond: %v\n",
   350  			i, expDelegatorShares, gotDelegatorShares, validator, bond)
   351  		require.Equal(t, expDelegatorAcc, gotDelegatorAcc,
   352  			"i: %v\nexpDelegatorAcc: %v\ngotDelegatorAcc: %v\nvalidator: %v\nbond: %v\n",
   353  			i, expDelegatorAcc, gotDelegatorAcc, validator, bond)
   354  	}
   355  }
   356  
   357  func TestEditValidatorDecreaseMinSelfDelegation(t *testing.T) {
   358  	initPower := int64(100)
   359  	initBond := sdk.TokensFromConsensusPower(100, sdk.DefaultPowerReduction)
   360  	app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 1, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction))
   361  
   362  	validatorAddr := valAddrs[0]
   363  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
   364  
   365  	// create validator
   366  	msgCreateValidator := tstaking.CreateValidatorMsg(validatorAddr, PKs[0], initBond)
   367  	msgCreateValidator.MinSelfDelegation = sdk.NewInt(2)
   368  	tstaking.Handle(msgCreateValidator, true)
   369  
   370  	// must end-block
   371  	updates, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
   372  	require.NoError(t, err)
   373  	require.Equal(t, 1, len(updates))
   374  
   375  	// verify the self-delegation exists
   376  	bond, found := app.StakingKeeper.GetDelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr)
   377  	require.True(t, found)
   378  	gotBond := bond.Shares.RoundInt()
   379  	require.Equal(t, initBond, gotBond,
   380  		"initBond: %v\ngotBond: %v\nbond: %v\n",
   381  		initBond, gotBond, bond)
   382  
   383  	newMinSelfDelegation := sdk.OneInt()
   384  	msgEditValidator := types.NewMsgEditValidator(validatorAddr, types.Description{}, nil, &newMinSelfDelegation)
   385  	tstaking.Handle(msgEditValidator, false)
   386  }
   387  
   388  func TestEditValidatorIncreaseMinSelfDelegationBeyondCurrentBond(t *testing.T) {
   389  	initPower := int64(100)
   390  	initBond := sdk.TokensFromConsensusPower(100, sdk.DefaultPowerReduction)
   391  
   392  	app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 2, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction))
   393  	validatorAddr := valAddrs[0]
   394  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
   395  
   396  	// create validator
   397  	msgCreateValidator := tstaking.CreateValidatorMsg(validatorAddr, PKs[0], initBond)
   398  	msgCreateValidator.MinSelfDelegation = sdk.NewInt(2)
   399  	tstaking.Handle(msgCreateValidator, true)
   400  
   401  	// must end-block
   402  	updates, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
   403  	require.NoError(t, err)
   404  	require.Equal(t, 1, len(updates))
   405  
   406  	// verify the self-delegation exists
   407  	bond, found := app.StakingKeeper.GetDelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr)
   408  	require.True(t, found)
   409  	gotBond := bond.Shares.RoundInt()
   410  	require.Equal(t, initBond, gotBond,
   411  		"initBond: %v\ngotBond: %v\nbond: %v\n",
   412  		initBond, gotBond, bond)
   413  
   414  	newMinSelfDelegation := initBond.Add(sdk.OneInt())
   415  	msgEditValidator := types.NewMsgEditValidator(validatorAddr, types.Description{}, nil, &newMinSelfDelegation)
   416  	tstaking.Handle(msgEditValidator, false)
   417  }
   418  
   419  func TestIncrementsMsgUnbond(t *testing.T) {
   420  	initPower := int64(1000)
   421  
   422  	app, ctx, delAddrs, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 2, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction))
   423  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
   424  	params := app.StakingKeeper.GetParams(ctx)
   425  	denom := params.BondDenom
   426  
   427  	// create validator, delegate
   428  	validatorAddr, delegatorAddr := valAddrs[0], delAddrs[1]
   429  	initBond := tstaking.CreateValidatorWithValPower(validatorAddr, PKs[0], initPower, true)
   430  
   431  	// initial balance
   432  	amt1 := app.BankKeeper.GetBalance(ctx, delegatorAddr, denom).Amount
   433  
   434  	tstaking.Delegate(delegatorAddr, validatorAddr, initBond)
   435  
   436  	// balance should have been subtracted after delegation
   437  	amt2 := app.BankKeeper.GetBalance(ctx, delegatorAddr, denom).Amount
   438  	require.True(sdk.IntEq(t, amt1.Sub(initBond), amt2))
   439  
   440  	// apply TM updates
   441  	_, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
   442  	require.NoError(t, err)
   443  
   444  	validator, found := app.StakingKeeper.GetValidator(ctx, validatorAddr)
   445  	require.True(t, found)
   446  	require.Equal(t, initBond.MulRaw(2), validator.DelegatorShares.RoundInt())
   447  	require.Equal(t, initBond.MulRaw(2), validator.BondedTokens())
   448  
   449  	// just send the same msgUnbond multiple times
   450  	// TODO use decimals here
   451  	unbondAmt := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10))
   452  	msgUndelegate := types.NewMsgUndelegate(delegatorAddr, validatorAddr, unbondAmt)
   453  	numUnbonds := int64(5)
   454  
   455  	for i := int64(0); i < numUnbonds; i++ {
   456  		res := tstaking.Handle(msgUndelegate, true)
   457  
   458  		var resData types.MsgUndelegateResponse
   459  		err := proto.Unmarshal(res.Data, &resData)
   460  		require.NoError(t, err)
   461  
   462  		ctx = ctx.WithBlockTime(resData.CompletionTime)
   463  		tstaking.Ctx = ctx
   464  		staking.EndBlocker(ctx, app.StakingKeeper)
   465  
   466  		// check that the accounts and the bond account have the appropriate values
   467  		validator, found = app.StakingKeeper.GetValidator(ctx, validatorAddr)
   468  		require.True(t, found)
   469  		bond, found := app.StakingKeeper.GetDelegation(ctx, delegatorAddr, validatorAddr)
   470  		require.True(t, found)
   471  
   472  		expBond := initBond.Sub(unbondAmt.Amount.Mul(sdk.NewInt(i + 1)))
   473  		expDelegatorShares := initBond.MulRaw(2).Sub(unbondAmt.Amount.Mul(sdk.NewInt(i + 1)))
   474  		expDelegatorAcc := initBond.Sub(expBond)
   475  
   476  		gotBond := bond.Shares.RoundInt()
   477  		gotDelegatorShares := validator.DelegatorShares.RoundInt()
   478  		gotDelegatorAcc := app.BankKeeper.GetBalance(ctx, delegatorAddr, params.BondDenom).Amount
   479  
   480  		require.Equal(t, expBond, gotBond,
   481  			"i: %v\nexpBond: %v\ngotBond: %v\nvalidator: %v\nbond: %v\n",
   482  			i, expBond, gotBond, validator, bond)
   483  		require.Equal(t, expDelegatorShares, gotDelegatorShares,
   484  			"i: %v\nexpDelegatorShares: %v\ngotDelegatorShares: %v\nvalidator: %v\nbond: %v\n",
   485  			i, expDelegatorShares, gotDelegatorShares, validator, bond)
   486  		require.Equal(t, expDelegatorAcc, gotDelegatorAcc,
   487  			"i: %v\nexpDelegatorAcc: %v\ngotDelegatorAcc: %v\nvalidator: %v\nbond: %v\n",
   488  			i, expDelegatorAcc, gotDelegatorAcc, validator, bond)
   489  	}
   490  
   491  	// these are more than we have bonded now
   492  	errorCases := []sdk.Int{
   493  		// 1<<64 - 1, // more than int64 power
   494  		// 1<<63 + 1, // more than int64 power
   495  		app.StakingKeeper.TokensFromConsensusPower(ctx, 1<<63-1),
   496  		app.StakingKeeper.TokensFromConsensusPower(ctx, 1<<31),
   497  		initBond,
   498  	}
   499  
   500  	for _, c := range errorCases {
   501  		tstaking.Undelegate(delegatorAddr, validatorAddr, c, false)
   502  	}
   503  
   504  	// should be able to unbond remaining
   505  	leftBonded := initBond.Sub(unbondAmt.Amount.Mul(sdk.NewInt(numUnbonds)))
   506  	tstaking.Undelegate(delegatorAddr, validatorAddr, leftBonded, true)
   507  }
   508  
   509  func TestMultipleMsgCreateValidator(t *testing.T) {
   510  	initPower := int64(1000)
   511  	initTokens := sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction)
   512  	app, ctx, delAddrs, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 3, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction))
   513  
   514  	params := app.StakingKeeper.GetParams(ctx)
   515  	blockTime := time.Now().UTC()
   516  	ctx = ctx.WithBlockTime(blockTime)
   517  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
   518  
   519  	validatorAddrs := []sdk.ValAddress{
   520  		valAddrs[0],
   521  		valAddrs[1],
   522  		valAddrs[2],
   523  	}
   524  	delegatorAddrs := []sdk.AccAddress{
   525  		delAddrs[0],
   526  		delAddrs[1],
   527  		delAddrs[2],
   528  	}
   529  
   530  	// bond them all
   531  	amt := app.StakingKeeper.TokensFromConsensusPower(ctx, 10)
   532  	for i, validatorAddr := range validatorAddrs {
   533  		tstaking.CreateValidator(validatorAddr, PKs[i], amt, true)
   534  		// verify that the account is bonded
   535  		validators := app.StakingKeeper.GetValidators(ctx, 100)
   536  		require.Equal(t, (i + 1), len(validators))
   537  
   538  		val := validators[i]
   539  		balanceExpd := initTokens.Sub(amt)
   540  		balanceGot := app.BankKeeper.GetBalance(ctx, delegatorAddrs[i], params.BondDenom).Amount
   541  
   542  		require.Equal(t, i+1, len(validators), "expected %d validators got %d, validators: %v", i+1, len(validators), validators)
   543  		require.Equal(t, amt, val.DelegatorShares.RoundInt(), "expected %d shares, got %d", amt, val.DelegatorShares)
   544  		require.Equal(t, balanceExpd, balanceGot, "expected account to have %d, got %d", balanceExpd, balanceGot)
   545  	}
   546  
   547  	staking.EndBlocker(ctx, app.StakingKeeper)
   548  
   549  	// unbond them all by removing delegation
   550  	for i, validatorAddr := range validatorAddrs {
   551  		_, found := app.StakingKeeper.GetValidator(ctx, validatorAddr)
   552  		require.True(t, found)
   553  
   554  		res := tstaking.Undelegate(delegatorAddrs[i], validatorAddr, amt, true)
   555  
   556  		var resData types.MsgUndelegateResponse
   557  		err := proto.Unmarshal(res.Data, &resData)
   558  		require.NoError(t, err)
   559  
   560  		// adds validator into unbonding queue
   561  		staking.EndBlocker(ctx, app.StakingKeeper)
   562  
   563  		// removes validator from queue and set
   564  		staking.EndBlocker(ctx.WithBlockTime(blockTime.Add(params.UnbondingTime)), app.StakingKeeper)
   565  
   566  		// Check that the validator is deleted from state
   567  		validators := app.StakingKeeper.GetValidators(ctx, 100)
   568  		require.Equal(t, len(validatorAddrs)-(i+1), len(validators),
   569  			"expected %d validators got %d", len(validatorAddrs)-(i+1), len(validators))
   570  
   571  		_, found = app.StakingKeeper.GetValidator(ctx, validatorAddr)
   572  		require.False(t, found)
   573  
   574  		gotBalance := app.BankKeeper.GetBalance(ctx, delegatorAddrs[i], params.BondDenom).Amount
   575  		require.Equal(t, initTokens, gotBalance, "expected account to have %d, got %d", initTokens, gotBalance)
   576  	}
   577  }
   578  
   579  func TestMultipleMsgDelegate(t *testing.T) {
   580  	initPower := int64(1000)
   581  	app, ctx, delAddrs, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 50, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction))
   582  	validatorAddr, delegatorAddrs := valAddrs[0], delAddrs[1:]
   583  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
   584  	var amount int64 = 10
   585  
   586  	// first make a validator
   587  	tstaking.CreateValidator(validatorAddr, PKs[0], sdk.NewInt(amount), true)
   588  
   589  	// delegate multiple parties
   590  	for _, delegatorAddr := range delegatorAddrs {
   591  		tstaking.Delegate(delegatorAddr, validatorAddr, sdk.NewInt(10))
   592  		tstaking.CheckDelegator(delegatorAddr, validatorAddr, true)
   593  	}
   594  
   595  	// unbond them all
   596  	for _, delegatorAddr := range delegatorAddrs {
   597  		res := tstaking.Undelegate(delegatorAddr, validatorAddr, sdk.NewInt(amount), true)
   598  
   599  		var resData types.MsgUndelegateResponse
   600  		err := proto.Unmarshal(res.Data, &resData)
   601  		require.NoError(t, err)
   602  
   603  		ctx = ctx.WithBlockTime(resData.CompletionTime)
   604  		staking.EndBlocker(ctx, app.StakingKeeper)
   605  		tstaking.Ctx = ctx
   606  
   607  		// check that the account is unbonded
   608  		_, found := app.StakingKeeper.GetDelegation(ctx, delegatorAddr, validatorAddr)
   609  		require.False(t, found)
   610  	}
   611  }
   612  
   613  func TestJailValidator(t *testing.T) {
   614  	initPower := int64(1000)
   615  	app, ctx, delAddrs, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 2, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction))
   616  	validatorAddr, delegatorAddr := valAddrs[0], delAddrs[1]
   617  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
   618  	var amt int64 = 10
   619  
   620  	// create the validator and delegate
   621  	tstaking.CreateValidator(validatorAddr, PKs[0], sdk.NewInt(amt), true)
   622  	tstaking.Delegate(delegatorAddr, validatorAddr, sdk.NewInt(amt))
   623  
   624  	// unbond the validators bond portion
   625  	unamt := sdk.NewInt(amt)
   626  	res := tstaking.Undelegate(sdk.AccAddress(validatorAddr), validatorAddr, unamt, true)
   627  
   628  	var resData types.MsgUndelegateResponse
   629  	err := proto.Unmarshal(res.Data, &resData)
   630  	require.NoError(t, err)
   631  
   632  	ctx = ctx.WithBlockTime(resData.CompletionTime)
   633  	staking.EndBlocker(ctx, app.StakingKeeper)
   634  	tstaking.Ctx = ctx
   635  
   636  	tstaking.CheckValidator(validatorAddr, -1, true)
   637  
   638  	// test that the delegator can still withdraw their bonds
   639  	tstaking.Undelegate(delegatorAddr, validatorAddr, unamt, true)
   640  
   641  	err = proto.Unmarshal(res.Data, &resData)
   642  	require.NoError(t, err)
   643  
   644  	ctx = ctx.WithBlockTime(resData.CompletionTime)
   645  	staking.EndBlocker(ctx, app.StakingKeeper)
   646  	tstaking.Ctx = ctx
   647  
   648  	// verify that the pubkey can now be reused
   649  	tstaking.CreateValidator(validatorAddr, PKs[0], sdk.NewInt(amt), true)
   650  }
   651  
   652  func TestValidatorQueue(t *testing.T) {
   653  	initPower := int64(1000)
   654  	app, ctx, delAddrs, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 2, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction))
   655  	validatorAddr, delegatorAddr := valAddrs[0], delAddrs[1]
   656  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
   657  
   658  	// set the unbonding time
   659  	params := app.StakingKeeper.GetParams(ctx)
   660  	params.UnbondingTime = 7 * time.Second
   661  	app.StakingKeeper.SetParams(ctx, params)
   662  
   663  	// create the validator and make a bond
   664  	amt := tstaking.CreateValidatorWithValPower(validatorAddr, PKs[0], 10, true)
   665  	tstaking.Delegate(delegatorAddr, validatorAddr, amt)
   666  	staking.EndBlocker(ctx, app.StakingKeeper)
   667  
   668  	// unbond the all self-delegation to put validator in unbonding state
   669  	res := tstaking.Undelegate(sdk.AccAddress(validatorAddr), validatorAddr, amt, true)
   670  
   671  	var resData types.MsgUndelegateResponse
   672  	err := proto.Unmarshal(res.Data, &resData)
   673  	require.NoError(t, err)
   674  
   675  	finishTime := resData.CompletionTime
   676  
   677  	ctx = tstaking.TurnBlock(finishTime)
   678  	origHeader := ctx.BlockHeader()
   679  
   680  	validator, found := app.StakingKeeper.GetValidator(ctx, validatorAddr)
   681  	require.True(t, found)
   682  	require.True(t, validator.IsUnbonding(), "%v", validator)
   683  
   684  	// should still be unbonding at time 6 seconds later
   685  	ctx = tstaking.TurnBlock(origHeader.Time.Add(time.Second * 6))
   686  
   687  	validator, found = app.StakingKeeper.GetValidator(ctx, validatorAddr)
   688  	require.True(t, found)
   689  	require.True(t, validator.IsUnbonding(), "%v", validator)
   690  
   691  	// should be in unbonded state at time 7 seconds later
   692  	ctx = tstaking.TurnBlock(origHeader.Time.Add(time.Second * 7))
   693  
   694  	validator, found = app.StakingKeeper.GetValidator(ctx, validatorAddr)
   695  	require.True(t, found)
   696  	require.True(t, validator.IsUnbonded(), "%v", validator)
   697  }
   698  
   699  func TestUnbondingPeriod(t *testing.T) {
   700  	initPower := int64(1000)
   701  	app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 1, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction))
   702  	validatorAddr := valAddrs[0]
   703  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
   704  
   705  	// set the unbonding time
   706  	params := app.StakingKeeper.GetParams(ctx)
   707  	params.UnbondingTime = 7 * time.Second
   708  	app.StakingKeeper.SetParams(ctx, params)
   709  
   710  	// create the validator
   711  	amt := tstaking.CreateValidatorWithValPower(validatorAddr, PKs[0], 10, true)
   712  	staking.EndBlocker(ctx, app.StakingKeeper)
   713  
   714  	// begin unbonding
   715  	tstaking.Undelegate(sdk.AccAddress(validatorAddr), validatorAddr, amt, true)
   716  
   717  	origHeader := ctx.BlockHeader()
   718  
   719  	_, found := app.StakingKeeper.GetUnbondingDelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr)
   720  	require.True(t, found, "should not have unbonded")
   721  
   722  	// cannot complete unbonding at same time
   723  	staking.EndBlocker(ctx, app.StakingKeeper)
   724  	_, found = app.StakingKeeper.GetUnbondingDelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr)
   725  	require.True(t, found, "should not have unbonded")
   726  
   727  	// cannot complete unbonding at time 6 seconds later
   728  	ctx = tstaking.TurnBlock(origHeader.Time.Add(time.Second * 6))
   729  	_, found = app.StakingKeeper.GetUnbondingDelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr)
   730  	require.True(t, found, "should not have unbonded")
   731  
   732  	// can complete unbonding at time 7 seconds later
   733  	ctx = tstaking.TurnBlock(origHeader.Time.Add(time.Second * 7))
   734  	_, found = app.StakingKeeper.GetUnbondingDelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr)
   735  	require.False(t, found, "should have unbonded")
   736  }
   737  
   738  func TestUnbondingFromUnbondingValidator(t *testing.T) {
   739  	initPower := int64(1000)
   740  	app, ctx, delAddrs, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 2, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction))
   741  	validatorAddr, delegatorAddr := valAddrs[0], delAddrs[1]
   742  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
   743  
   744  	// create the validator and delegate
   745  	tstaking.CreateValidator(validatorAddr, PKs[0], sdk.NewInt(10), true)
   746  	tstaking.Delegate(delegatorAddr, validatorAddr, sdk.NewInt(10))
   747  
   748  	// unbond the validators bond portion
   749  	unbondAmt := sdk.NewInt(10)
   750  	res := tstaking.Undelegate(sdk.AccAddress(validatorAddr), validatorAddr, unbondAmt, true)
   751  
   752  	// change the ctx to Block Time one second before the validator would have unbonded
   753  	var resData types.MsgUndelegateResponse
   754  	err := proto.Unmarshal(res.Data, &resData)
   755  	require.NoError(t, err)
   756  
   757  	ctx = ctx.WithBlockTime(resData.CompletionTime.Add(time.Second * -1))
   758  
   759  	// unbond the delegator from the validator
   760  	_ = tstaking.Undelegate(delegatorAddr, validatorAddr, unbondAmt, true)
   761  
   762  	ctx = tstaking.TurnBlockTimeDiff(app.StakingKeeper.UnbondingTime(ctx))
   763  	tstaking.Ctx = ctx
   764  
   765  	// Check to make sure that the unbonding delegation is no longer in state
   766  	// (meaning it was deleted in the above EndBlocker)
   767  	_, found := app.StakingKeeper.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr)
   768  	require.False(t, found, "should be removed from state")
   769  }
   770  
   771  func TestRedelegationPeriod(t *testing.T) {
   772  	initPower := int64(1000)
   773  	app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 2, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction))
   774  	validatorAddr, validatorAddr2 := valAddrs[0], valAddrs[1]
   775  	denom := app.StakingKeeper.GetParams(ctx).BondDenom
   776  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
   777  
   778  	// set the unbonding time
   779  	params := app.StakingKeeper.GetParams(ctx)
   780  	params.UnbondingTime = 7 * time.Second
   781  	app.StakingKeeper.SetParams(ctx, params)
   782  	// initial balance
   783  	amt1 := app.BankKeeper.GetBalance(ctx, sdk.AccAddress(validatorAddr), denom).Amount
   784  
   785  	// create the validators
   786  	tstaking.CreateValidator(validatorAddr, PKs[0], sdk.NewInt(10), true)
   787  
   788  	// balance should have been subtracted after creation
   789  	amt2 := app.BankKeeper.GetBalance(ctx, sdk.AccAddress(validatorAddr), denom).Amount
   790  	require.Equal(t, amt1.Sub(sdk.NewInt(10)), amt2, "expected coins to be subtracted")
   791  
   792  	tstaking.CreateValidator(validatorAddr2, PKs[1], sdk.NewInt(10), true)
   793  	bal1 := app.BankKeeper.GetAllBalances(ctx, sdk.AccAddress(validatorAddr))
   794  
   795  	// begin redelegate
   796  	redAmt := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10))
   797  	msgBeginRedelegate := types.NewMsgBeginRedelegate(sdk.AccAddress(validatorAddr), validatorAddr, validatorAddr2, redAmt)
   798  	tstaking.Handle(msgBeginRedelegate, true)
   799  
   800  	// origin account should not lose tokens as with a regular delegation
   801  	bal2 := app.BankKeeper.GetAllBalances(ctx, sdk.AccAddress(validatorAddr))
   802  	require.Equal(t, bal1, bal2)
   803  
   804  	origHeader := ctx.BlockHeader()
   805  
   806  	// cannot complete redelegation at same time
   807  	staking.EndBlocker(ctx, app.StakingKeeper)
   808  	_, found := app.StakingKeeper.GetRedelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr, validatorAddr2)
   809  	require.True(t, found, "should not have unbonded")
   810  
   811  	// cannot complete redelegation at time 6 seconds later
   812  	ctx = tstaking.TurnBlock(origHeader.Time.Add(time.Second * 6))
   813  	_, found = app.StakingKeeper.GetRedelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr, validatorAddr2)
   814  	require.True(t, found, "should not have unbonded")
   815  
   816  	// can complete redelegation at time 7 seconds later
   817  	ctx = tstaking.TurnBlock(origHeader.Time.Add(time.Second * 7))
   818  	_, found = app.StakingKeeper.GetRedelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr, validatorAddr2)
   819  	require.False(t, found, "should have unbonded")
   820  }
   821  
   822  func TestTransitiveRedelegation(t *testing.T) {
   823  	initPower := int64(1000)
   824  	app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 3, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction))
   825  
   826  	val1, val2, val3 := valAddrs[0], valAddrs[1], valAddrs[2]
   827  	blockTime := time.Now().UTC()
   828  	ctx = ctx.WithBlockTime(blockTime)
   829  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
   830  
   831  	// create the validators
   832  	tstaking.CreateValidator(val1, PKs[0], sdk.NewInt(10), true)
   833  	tstaking.CreateValidator(val2, PKs[1], sdk.NewInt(10), true)
   834  	tstaking.CreateValidator(val3, PKs[2], sdk.NewInt(10), true)
   835  
   836  	// begin redelegate
   837  	redAmt := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10))
   838  	msgBeginRedelegate := types.NewMsgBeginRedelegate(sdk.AccAddress(val1), val1, val2, redAmt)
   839  	tstaking.Handle(msgBeginRedelegate, true)
   840  
   841  	// cannot redelegation to next validator while first delegation exists
   842  	msgBeginRedelegate = types.NewMsgBeginRedelegate(sdk.AccAddress(val1), val2, val3, redAmt)
   843  	tstaking.Handle(msgBeginRedelegate, false)
   844  
   845  	params := app.StakingKeeper.GetParams(ctx)
   846  	ctx = ctx.WithBlockTime(blockTime.Add(params.UnbondingTime))
   847  	tstaking.Ctx = ctx
   848  
   849  	// complete first redelegation
   850  	staking.EndBlocker(ctx, app.StakingKeeper)
   851  
   852  	// now should be able to redelegate from the second validator to the third
   853  	tstaking.Handle(msgBeginRedelegate, true)
   854  }
   855  
   856  func TestMultipleRedelegationAtSameTime(t *testing.T) {
   857  	initPower := int64(1000)
   858  	app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 2, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction))
   859  	valAddr := valAddrs[0]
   860  	valAddr2 := valAddrs[1]
   861  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
   862  
   863  	// set the unbonding time
   864  	params := app.StakingKeeper.GetParams(ctx)
   865  	params.UnbondingTime = 1 * time.Second
   866  	app.StakingKeeper.SetParams(ctx, params)
   867  
   868  	// create the validators
   869  	valTokens := tstaking.CreateValidatorWithValPower(valAddr, PKs[0], 10, true)
   870  	tstaking.CreateValidator(valAddr2, PKs[1], valTokens, true)
   871  
   872  	// end block to bond them
   873  	staking.EndBlocker(ctx, app.StakingKeeper)
   874  
   875  	// begin a redelegate
   876  	selfDelAddr := sdk.AccAddress(valAddr) // (the validator is it's own delegator)
   877  	redAmt := sdk.NewCoin(sdk.DefaultBondDenom, valTokens.QuoRaw(2))
   878  	msgBeginRedelegate := types.NewMsgBeginRedelegate(selfDelAddr, valAddr, valAddr2, redAmt)
   879  	tstaking.Handle(msgBeginRedelegate, true)
   880  
   881  	// there should only be one entry in the redelegation object
   882  	rd, found := app.StakingKeeper.GetRedelegation(ctx, selfDelAddr, valAddr, valAddr2)
   883  	require.True(t, found)
   884  	require.Len(t, rd.Entries, 1)
   885  
   886  	// start a second redelegation at this same time as the first
   887  	tstaking.Handle(msgBeginRedelegate, true)
   888  
   889  	// now there should be two entries
   890  	rd, found = app.StakingKeeper.GetRedelegation(ctx, selfDelAddr, valAddr, valAddr2)
   891  	require.True(t, found)
   892  	require.Len(t, rd.Entries, 2)
   893  
   894  	// move forward in time, should complete both redelegations
   895  	ctx = tstaking.TurnBlockTimeDiff(1 * time.Second)
   896  	_, found = app.StakingKeeper.GetRedelegation(ctx, selfDelAddr, valAddr, valAddr2)
   897  	require.False(t, found)
   898  }
   899  
   900  func TestMultipleRedelegationAtUniqueTimes(t *testing.T) {
   901  	initPower := int64(1000)
   902  	app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 2, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction))
   903  	valAddr := valAddrs[0]
   904  	valAddr2 := valAddrs[1]
   905  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
   906  
   907  	// set the unbonding time
   908  	params := app.StakingKeeper.GetParams(ctx)
   909  	params.UnbondingTime = 10 * time.Second
   910  	app.StakingKeeper.SetParams(ctx, params)
   911  
   912  	// create the validators
   913  	valTokens := tstaking.CreateValidatorWithValPower(valAddr, PKs[0], 10, true)
   914  	tstaking.CreateValidator(valAddr2, PKs[1], valTokens, true)
   915  
   916  	// end block to bond them
   917  	staking.EndBlocker(ctx, app.StakingKeeper)
   918  
   919  	// begin a redelegate
   920  	selfDelAddr := sdk.AccAddress(valAddr) // (the validator is it's own delegator)
   921  	redAmt := sdk.NewCoin(sdk.DefaultBondDenom, valTokens.QuoRaw(2))
   922  	msgBeginRedelegate := types.NewMsgBeginRedelegate(selfDelAddr, valAddr, valAddr2, redAmt)
   923  	tstaking.Handle(msgBeginRedelegate, true)
   924  
   925  	// move forward in time and start a second redelegation
   926  	ctx = ctx.WithBlockTime(ctx.BlockHeader().Time.Add(5 * time.Second))
   927  	tstaking.Ctx = ctx
   928  	tstaking.Handle(msgBeginRedelegate, true)
   929  
   930  	// now there should be two entries
   931  	rd, found := app.StakingKeeper.GetRedelegation(ctx, selfDelAddr, valAddr, valAddr2)
   932  	require.True(t, found)
   933  	require.Len(t, rd.Entries, 2)
   934  
   935  	// move forward in time, should complete the first redelegation, but not the second
   936  	ctx = tstaking.TurnBlockTimeDiff(5 * time.Second)
   937  	rd, found = app.StakingKeeper.GetRedelegation(ctx, selfDelAddr, valAddr, valAddr2)
   938  	require.True(t, found)
   939  	require.Len(t, rd.Entries, 1)
   940  
   941  	// move forward in time, should complete the second redelegation
   942  	ctx = tstaking.TurnBlockTimeDiff(5 * time.Second)
   943  	_, found = app.StakingKeeper.GetRedelegation(ctx, selfDelAddr, valAddr, valAddr2)
   944  	require.False(t, found)
   945  }
   946  
   947  func TestMultipleUnbondingDelegationAtSameTime(t *testing.T) {
   948  	initPower := int64(1000)
   949  	app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 1, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction))
   950  	valAddr := valAddrs[0]
   951  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
   952  
   953  	// set the unbonding time
   954  	params := app.StakingKeeper.GetParams(ctx)
   955  	params.UnbondingTime = 1 * time.Second
   956  	app.StakingKeeper.SetParams(ctx, params)
   957  
   958  	// create the validators
   959  	valTokens := tstaking.CreateValidatorWithValPower(valAddr, PKs[0], 10, true)
   960  
   961  	// end block to bond
   962  	staking.EndBlocker(ctx, app.StakingKeeper)
   963  
   964  	// begin an unbonding delegation
   965  	selfDelAddr := sdk.AccAddress(valAddr) // (the validator is it's own delegator)
   966  	tstaking.Undelegate(selfDelAddr, valAddr, valTokens.QuoRaw(2), true)
   967  
   968  	// there should only be one entry in the ubd object
   969  	ubd, found := app.StakingKeeper.GetUnbondingDelegation(ctx, selfDelAddr, valAddr)
   970  	require.True(t, found)
   971  	require.Len(t, ubd.Entries, 1)
   972  
   973  	// start a second ubd at this same time as the first
   974  	tstaking.Undelegate(selfDelAddr, valAddr, valTokens.QuoRaw(2), true)
   975  
   976  	// now there should be two entries
   977  	ubd, found = app.StakingKeeper.GetUnbondingDelegation(ctx, selfDelAddr, valAddr)
   978  	require.True(t, found)
   979  	require.Len(t, ubd.Entries, 2)
   980  
   981  	// move forwaubd in time, should complete both ubds
   982  	ctx = tstaking.TurnBlockTimeDiff(1 * time.Second)
   983  	_, found = app.StakingKeeper.GetUnbondingDelegation(ctx, selfDelAddr, valAddr)
   984  	require.False(t, found)
   985  }
   986  
   987  func TestMultipleUnbondingDelegationAtUniqueTimes(t *testing.T) {
   988  	initPower := int64(1000)
   989  	app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 1, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction))
   990  	valAddr := valAddrs[0]
   991  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
   992  
   993  	// set the unbonding time
   994  	params := app.StakingKeeper.GetParams(ctx)
   995  	params.UnbondingTime = 10 * time.Second
   996  	app.StakingKeeper.SetParams(ctx, params)
   997  
   998  	// create the validator
   999  	valTokens := tstaking.CreateValidatorWithValPower(valAddr, PKs[0], 10, true)
  1000  
  1001  	// end block to bond
  1002  	staking.EndBlocker(ctx, app.StakingKeeper)
  1003  
  1004  	// begin an unbonding delegation
  1005  	selfDelAddr := sdk.AccAddress(valAddr) // (the validator is it's own delegator)
  1006  	tstaking.Undelegate(selfDelAddr, valAddr, valTokens.QuoRaw(2), true)
  1007  
  1008  	// there should only be one entry in the ubd object
  1009  	ubd, found := app.StakingKeeper.GetUnbondingDelegation(ctx, selfDelAddr, valAddr)
  1010  	require.True(t, found)
  1011  	require.Len(t, ubd.Entries, 1)
  1012  
  1013  	// move forwaubd in time and start a second redelegation
  1014  	ctx = ctx.WithBlockTime(ctx.BlockHeader().Time.Add(5 * time.Second))
  1015  	tstaking.Ctx = ctx
  1016  	tstaking.Undelegate(selfDelAddr, valAddr, valTokens.QuoRaw(2), true)
  1017  
  1018  	// now there should be two entries
  1019  	ubd, found = app.StakingKeeper.GetUnbondingDelegation(ctx, selfDelAddr, valAddr)
  1020  	require.True(t, found)
  1021  	require.Len(t, ubd.Entries, 2)
  1022  
  1023  	// move forwaubd in time, should complete the first redelegation, but not the second
  1024  	ctx = tstaking.TurnBlockTimeDiff(5 * time.Second)
  1025  	ubd, found = app.StakingKeeper.GetUnbondingDelegation(ctx, selfDelAddr, valAddr)
  1026  	require.True(t, found)
  1027  	require.Len(t, ubd.Entries, 1)
  1028  
  1029  	// move forwaubd in time, should complete the second redelegation
  1030  	ctx = tstaking.TurnBlockTimeDiff(5 * time.Second)
  1031  	_, found = app.StakingKeeper.GetUnbondingDelegation(ctx, selfDelAddr, valAddr)
  1032  	require.False(t, found)
  1033  }
  1034  
  1035  func TestUnbondingWhenExcessValidators(t *testing.T) {
  1036  	initPower := int64(1000)
  1037  	app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 3, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction))
  1038  	val1 := valAddrs[0]
  1039  	val2 := valAddrs[1]
  1040  	val3 := valAddrs[2]
  1041  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
  1042  
  1043  	// set the unbonding time
  1044  	params := app.StakingKeeper.GetParams(ctx)
  1045  	params.MaxValidators = 2
  1046  	app.StakingKeeper.SetParams(ctx, params)
  1047  
  1048  	// add three validators
  1049  	tstaking.CreateValidatorWithValPower(val1, PKs[0], 50, true)
  1050  	// apply TM updates
  1051  	_, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
  1052  	require.NoError(t, err)
  1053  	require.Equal(t, 1, len(app.StakingKeeper.GetLastValidators(ctx)))
  1054  
  1055  	valTokens2 := tstaking.CreateValidatorWithValPower(val2, PKs[1], 30, true)
  1056  	_, err = app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
  1057  	require.NoError(t, err)
  1058  	require.Equal(t, 2, len(app.StakingKeeper.GetLastValidators(ctx)))
  1059  
  1060  	tstaking.CreateValidatorWithValPower(val3, PKs[2], 10, true)
  1061  	_, err = app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
  1062  	require.NoError(t, err)
  1063  	require.Equal(t, 2, len(app.StakingKeeper.GetLastValidators(ctx)))
  1064  
  1065  	// unbond the validator-2
  1066  	tstaking.Undelegate(sdk.AccAddress(val2), val2, valTokens2, true)
  1067  	// apply TM updates
  1068  	_, err = app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
  1069  	require.NoError(t, err)
  1070  
  1071  	// because there are extra validators waiting to get in, the queued
  1072  	// validator (aka. validator-1) should make it into the bonded group, thus
  1073  	// the total number of validators should stay the same
  1074  	vals := app.StakingKeeper.GetLastValidators(ctx)
  1075  	require.Equal(t, 2, len(vals), "vals %v", vals)
  1076  	tstaking.CheckValidator(val1, types.Bonded, false)
  1077  }
  1078  
  1079  func TestBondUnbondRedelegateSlashTwice(t *testing.T) {
  1080  	initPower := int64(1000)
  1081  	app, ctx, delAddrs, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 3, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction))
  1082  	valA, valB, del := valAddrs[0], valAddrs[1], delAddrs[2]
  1083  	consAddr0 := sdk.ConsAddress(PKs[0].Address())
  1084  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
  1085  
  1086  	valTokens := tstaking.CreateValidatorWithValPower(valA, PKs[0], 10, true)
  1087  	tstaking.CreateValidator(valB, PKs[1], valTokens, true)
  1088  
  1089  	// delegate 10 stake
  1090  	tstaking.Delegate(del, valA, valTokens)
  1091  
  1092  	// apply Tendermint updates
  1093  	updates, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
  1094  	require.NoError(t, err)
  1095  	require.Equal(t, 2, len(updates))
  1096  
  1097  	// a block passes
  1098  	ctx = ctx.WithBlockHeight(1)
  1099  	tstaking.Ctx = ctx
  1100  
  1101  	// begin unbonding 4 stake
  1102  	unbondAmt := app.StakingKeeper.TokensFromConsensusPower(ctx, 4)
  1103  	tstaking.Undelegate(del, valA, unbondAmt, true)
  1104  
  1105  	// begin redelegate 6 stake
  1106  	redAmt := sdk.NewCoin(sdk.DefaultBondDenom, app.StakingKeeper.TokensFromConsensusPower(ctx, 6))
  1107  	msgBeginRedelegate := types.NewMsgBeginRedelegate(del, valA, valB, redAmt)
  1108  	tstaking.Handle(msgBeginRedelegate, true)
  1109  
  1110  	// destination delegation should have 6 shares
  1111  	delegation, found := app.StakingKeeper.GetDelegation(ctx, del, valB)
  1112  	require.True(t, found)
  1113  	require.Equal(t, sdk.NewDecFromInt(redAmt.Amount), delegation.Shares)
  1114  
  1115  	// must apply validator updates
  1116  	updates, err = app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
  1117  	require.NoError(t, err)
  1118  	require.Equal(t, 2, len(updates))
  1119  
  1120  	// slash the validator by half
  1121  	app.StakingKeeper.Slash(ctx, consAddr0, 0, 20, sdk.NewDecWithPrec(5, 1))
  1122  
  1123  	// unbonding delegation should have been slashed by half
  1124  	ubd, found := app.StakingKeeper.GetUnbondingDelegation(ctx, del, valA)
  1125  	require.True(t, found)
  1126  	require.Len(t, ubd.Entries, 1)
  1127  	require.Equal(t, unbondAmt.QuoRaw(2), ubd.Entries[0].Balance)
  1128  
  1129  	// redelegation should have been slashed by half
  1130  	redelegation, found := app.StakingKeeper.GetRedelegation(ctx, del, valA, valB)
  1131  	require.True(t, found)
  1132  	require.Len(t, redelegation.Entries, 1)
  1133  
  1134  	// destination delegation should have been slashed by half
  1135  	delegation, found = app.StakingKeeper.GetDelegation(ctx, del, valB)
  1136  	require.True(t, found)
  1137  	require.Equal(t, sdk.NewDecFromInt(redAmt.Amount.QuoRaw(2)), delegation.Shares)
  1138  
  1139  	// validator power should have been reduced by half
  1140  	validator, found := app.StakingKeeper.GetValidator(ctx, valA)
  1141  	require.True(t, found)
  1142  	require.Equal(t, valTokens.QuoRaw(2), validator.GetBondedTokens())
  1143  
  1144  	// slash the validator for an infraction committed after the unbonding and redelegation begin
  1145  	ctx = ctx.WithBlockHeight(3)
  1146  	app.StakingKeeper.Slash(ctx, consAddr0, 2, 10, sdk.NewDecWithPrec(5, 1))
  1147  	tstaking.Ctx = ctx
  1148  
  1149  	// unbonding delegation should be unchanged
  1150  	ubd, found = app.StakingKeeper.GetUnbondingDelegation(ctx, del, valA)
  1151  	require.True(t, found)
  1152  	require.Len(t, ubd.Entries, 1)
  1153  	require.Equal(t, unbondAmt.QuoRaw(2), ubd.Entries[0].Balance)
  1154  
  1155  	// redelegation should be unchanged
  1156  	redelegation, found = app.StakingKeeper.GetRedelegation(ctx, del, valA, valB)
  1157  	require.True(t, found)
  1158  	require.Len(t, redelegation.Entries, 1)
  1159  
  1160  	// destination delegation should be unchanged
  1161  	delegation, found = app.StakingKeeper.GetDelegation(ctx, del, valB)
  1162  	require.True(t, found)
  1163  	require.Equal(t, sdk.NewDecFromInt(redAmt.Amount.QuoRaw(2)), delegation.Shares)
  1164  
  1165  	// end blocker
  1166  	staking.EndBlocker(ctx, app.StakingKeeper)
  1167  
  1168  	// validator power should have been reduced to zero
  1169  	// validator should be in unbonding state
  1170  	validator, _ = app.StakingKeeper.GetValidator(ctx, valA)
  1171  	require.Equal(t, validator.GetStatus(), types.Unbonding)
  1172  }
  1173  
  1174  func TestInvalidMsg(t *testing.T) {
  1175  	k := keeper.Keeper{}
  1176  	h := staking.NewHandler(k)
  1177  
  1178  	res, err := h(sdk.NewContext(nil, tmproto.Header{}, false, nil), testdata.NewTestMsg())
  1179  	require.Error(t, err)
  1180  	require.Nil(t, res)
  1181  	require.True(t, strings.Contains(err.Error(), "unrecognized staking message type"))
  1182  }
  1183  
  1184  func TestInvalidCoinDenom(t *testing.T) {
  1185  	initPower := int64(1000)
  1186  	app, ctx, delAddrs, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 3, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction))
  1187  	valA, valB, delAddr := valAddrs[0], valAddrs[1], delAddrs[2]
  1188  	tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)
  1189  
  1190  	valTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 100)
  1191  	invalidCoin := sdk.NewCoin("churros", valTokens)
  1192  	validCoin := sdk.NewCoin(sdk.DefaultBondDenom, valTokens)
  1193  	oneCoin := sdk.NewCoin(sdk.DefaultBondDenom, sdk.OneInt())
  1194  
  1195  	commission := types.NewCommissionRates(sdk.OneDec(), sdk.OneDec(), sdk.ZeroDec())
  1196  	msgCreate, err := types.NewMsgCreateValidator(valA, PKs[0], invalidCoin, types.Description{}, commission, sdk.OneInt())
  1197  	require.NoError(t, err)
  1198  	tstaking.Handle(msgCreate, false)
  1199  
  1200  	msgCreate, err = types.NewMsgCreateValidator(valA, PKs[0], validCoin, types.Description{}, commission, sdk.OneInt())
  1201  	require.NoError(t, err)
  1202  	tstaking.Handle(msgCreate, true)
  1203  
  1204  	msgCreate, err = types.NewMsgCreateValidator(valB, PKs[1], validCoin, types.Description{}, commission, sdk.OneInt())
  1205  	require.NoError(t, err)
  1206  	tstaking.Handle(msgCreate, true)
  1207  
  1208  	msgDelegate := types.NewMsgDelegate(delAddr, valA, invalidCoin)
  1209  	tstaking.Handle(msgDelegate, false)
  1210  
  1211  	msgDelegate = types.NewMsgDelegate(delAddr, valA, validCoin)
  1212  	tstaking.Handle(msgDelegate, true)
  1213  
  1214  	msgUndelegate := types.NewMsgUndelegate(delAddr, valA, invalidCoin)
  1215  	tstaking.Handle(msgUndelegate, false)
  1216  
  1217  	msgUndelegate = types.NewMsgUndelegate(delAddr, valA, oneCoin)
  1218  	tstaking.Handle(msgUndelegate, true)
  1219  
  1220  	msgRedelegate := types.NewMsgBeginRedelegate(delAddr, valA, valB, invalidCoin)
  1221  	tstaking.Handle(msgRedelegate, false)
  1222  
  1223  	msgRedelegate = types.NewMsgBeginRedelegate(delAddr, valA, valB, oneCoin)
  1224  	tstaking.Handle(msgRedelegate, true)
  1225  }