From 9eaa5b0e1aa128c245cd3c1f2a921e3290e739e9 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 21 Feb 2020 12:24:41 +0100 Subject: [PATCH] refactor delegation test TestUnbondDelegation to use simapp --- x/staking/keeper/delegation_test.go | 1648 ++++++++++++----------- x/staking/keeper/old_delegation_test.go | 765 +++++++++++ 2 files changed, 1600 insertions(+), 813 deletions(-) create mode 100644 x/staking/keeper/old_delegation_test.go diff --git a/x/staking/keeper/delegation_test.go b/x/staking/keeper/delegation_test.go index eda1a550c..798716b2c 100644 --- a/x/staking/keeper/delegation_test.go +++ b/x/staking/keeper/delegation_test.go @@ -1,19 +1,25 @@ -package keeper +package keeper_test import ( "testing" "time" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/cosmos/cosmos-sdk/x/distribution" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/simapp" + abci "github.com/tendermint/tendermint/abci/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/staking/keeper" + "github.com/cosmos/cosmos-sdk/x/staking/types" ) // tests GetDelegation, GetDelegatorDelegations, SetDelegation, RemoveDelegation, GetDelegatorDelegations func TestDelegation(t *testing.T) { - ctx, _, _, keeper, _ := CreateTestInput(t, false, 10) + app := simapp.Setup(false) + ctx := app.BaseApp.NewContext(false, abci.Header{}) //construct the validators amts := []sdk.Int{sdk.NewInt(9), sdk.NewInt(8), sdk.NewInt(7)} @@ -23,28 +29,28 @@ func TestDelegation(t *testing.T) { validators[i], _ = validators[i].AddTokensFromDel(amt) } - validators[0] = TestingUpdateValidator(keeper, ctx, validators[0], true) - validators[1] = TestingUpdateValidator(keeper, ctx, validators[1], true) - validators[2] = TestingUpdateValidator(keeper, ctx, validators[2], true) + validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], true) + validators[1] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[1], true) + validators[2] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[2], true) // first add a validators[0] to delegate too bond1to1 := types.NewDelegation(addrDels[0], addrVals[0], sdk.NewDec(9)) // check the empty keeper first - _, found := keeper.GetDelegation(ctx, addrDels[0], addrVals[0]) + _, found := app.StakingKeeper.GetDelegation(ctx, addrDels[0], addrVals[0]) require.False(t, found) // set and retrieve a record - keeper.SetDelegation(ctx, bond1to1) - resBond, found := keeper.GetDelegation(ctx, addrDels[0], addrVals[0]) + app.StakingKeeper.SetDelegation(ctx, bond1to1) + resBond, found := app.StakingKeeper.GetDelegation(ctx, addrDels[0], addrVals[0]) require.True(t, found) require.True(t, bond1to1.Equal(resBond)) // modify a records, save, and retrieve bond1to1.Shares = sdk.NewDec(99) - keeper.SetDelegation(ctx, bond1to1) - resBond, found = keeper.GetDelegation(ctx, addrDels[0], addrVals[0]) + app.StakingKeeper.SetDelegation(ctx, bond1to1) + resBond, found = app.StakingKeeper.GetDelegation(ctx, addrDels[0], addrVals[0]) require.True(t, found) require.True(t, bond1to1.Equal(resBond)) @@ -54,28 +60,28 @@ func TestDelegation(t *testing.T) { bond2to1 := types.NewDelegation(addrDels[1], addrVals[0], sdk.NewDec(9)) bond2to2 := types.NewDelegation(addrDels[1], addrVals[1], sdk.NewDec(9)) bond2to3 := types.NewDelegation(addrDels[1], addrVals[2], sdk.NewDec(9)) - keeper.SetDelegation(ctx, bond1to2) - keeper.SetDelegation(ctx, bond1to3) - keeper.SetDelegation(ctx, bond2to1) - keeper.SetDelegation(ctx, bond2to2) - keeper.SetDelegation(ctx, bond2to3) + app.StakingKeeper.SetDelegation(ctx, bond1to2) + app.StakingKeeper.SetDelegation(ctx, bond1to3) + app.StakingKeeper.SetDelegation(ctx, bond2to1) + app.StakingKeeper.SetDelegation(ctx, bond2to2) + app.StakingKeeper.SetDelegation(ctx, bond2to3) // test all bond retrieve capabilities - resBonds := keeper.GetDelegatorDelegations(ctx, addrDels[0], 5) + resBonds := app.StakingKeeper.GetDelegatorDelegations(ctx, addrDels[0], 5) require.Equal(t, 3, len(resBonds)) require.True(t, bond1to1.Equal(resBonds[0])) require.True(t, bond1to2.Equal(resBonds[1])) require.True(t, bond1to3.Equal(resBonds[2])) - resBonds = keeper.GetAllDelegatorDelegations(ctx, addrDels[0]) + resBonds = app.StakingKeeper.GetAllDelegatorDelegations(ctx, addrDels[0]) require.Equal(t, 3, len(resBonds)) - resBonds = keeper.GetDelegatorDelegations(ctx, addrDels[0], 2) + resBonds = app.StakingKeeper.GetDelegatorDelegations(ctx, addrDels[0], 2) require.Equal(t, 2, len(resBonds)) - resBonds = keeper.GetDelegatorDelegations(ctx, addrDels[1], 5) + resBonds = app.StakingKeeper.GetDelegatorDelegations(ctx, addrDels[1], 5) require.Equal(t, 3, len(resBonds)) require.True(t, bond2to1.Equal(resBonds[0])) require.True(t, bond2to2.Equal(resBonds[1])) require.True(t, bond2to3.Equal(resBonds[2])) - allBonds := keeper.GetAllDelegations(ctx) + allBonds := app.StakingKeeper.GetAllDelegations(ctx) require.Equal(t, 6, len(allBonds)) require.True(t, bond1to1.Equal(allBonds[0])) require.True(t, bond1to2.Equal(allBonds[1])) @@ -84,96 +90,108 @@ func TestDelegation(t *testing.T) { require.True(t, bond2to2.Equal(allBonds[4])) require.True(t, bond2to3.Equal(allBonds[5])) - resVals := keeper.GetDelegatorValidators(ctx, addrDels[0], 3) + resVals := app.StakingKeeper.GetDelegatorValidators(ctx, addrDels[0], 3) require.Equal(t, 3, len(resVals)) - resVals = keeper.GetDelegatorValidators(ctx, addrDels[1], 4) + resVals = app.StakingKeeper.GetDelegatorValidators(ctx, addrDels[1], 4) require.Equal(t, 3, len(resVals)) for i := 0; i < 3; i++ { - resVal, err := keeper.GetDelegatorValidator(ctx, addrDels[0], addrVals[i]) + resVal, err := app.StakingKeeper.GetDelegatorValidator(ctx, addrDels[0], addrVals[i]) require.Nil(t, err) require.Equal(t, addrVals[i], resVal.GetOperator()) - resVal, err = keeper.GetDelegatorValidator(ctx, addrDels[1], addrVals[i]) + resVal, err = app.StakingKeeper.GetDelegatorValidator(ctx, addrDels[1], addrVals[i]) require.Nil(t, err) require.Equal(t, addrVals[i], resVal.GetOperator()) - resDels := keeper.GetValidatorDelegations(ctx, addrVals[i]) + resDels := app.StakingKeeper.GetValidatorDelegations(ctx, addrVals[i]) require.Len(t, resDels, 2) } // delete a record - keeper.RemoveDelegation(ctx, bond2to3) - _, found = keeper.GetDelegation(ctx, addrDels[1], addrVals[2]) + app.StakingKeeper.RemoveDelegation(ctx, bond2to3) + _, found = app.StakingKeeper.GetDelegation(ctx, addrDels[1], addrVals[2]) require.False(t, found) - resBonds = keeper.GetDelegatorDelegations(ctx, addrDels[1], 5) + resBonds = app.StakingKeeper.GetDelegatorDelegations(ctx, addrDels[1], 5) require.Equal(t, 2, len(resBonds)) require.True(t, bond2to1.Equal(resBonds[0])) require.True(t, bond2to2.Equal(resBonds[1])) - resBonds = keeper.GetAllDelegatorDelegations(ctx, addrDels[1]) + resBonds = app.StakingKeeper.GetAllDelegatorDelegations(ctx, addrDels[1]) require.Equal(t, 2, len(resBonds)) // delete all the records from delegator 2 - keeper.RemoveDelegation(ctx, bond2to1) - keeper.RemoveDelegation(ctx, bond2to2) - _, found = keeper.GetDelegation(ctx, addrDels[1], addrVals[0]) + app.StakingKeeper.RemoveDelegation(ctx, bond2to1) + app.StakingKeeper.RemoveDelegation(ctx, bond2to2) + _, found = app.StakingKeeper.GetDelegation(ctx, addrDels[1], addrVals[0]) require.False(t, found) - _, found = keeper.GetDelegation(ctx, addrDels[1], addrVals[1]) + _, found = app.StakingKeeper.GetDelegation(ctx, addrDels[1], addrVals[1]) require.False(t, found) - resBonds = keeper.GetDelegatorDelegations(ctx, addrDels[1], 5) + resBonds = app.StakingKeeper.GetDelegatorDelegations(ctx, addrDels[1], 5) require.Equal(t, 0, len(resBonds)) } // tests Get/Set/Remove UnbondingDelegation func TestUnbondingDelegation(t *testing.T) { - ctx, _, _, keeper, _ := CreateTestInput(t, false, 0) + app := simapp.Setup(false) + ctx := app.BaseApp.NewContext(false, abci.Header{}) - ubd := types.NewUnbondingDelegation(addrDels[0], addrVals[0], 0, - time.Unix(0, 0), sdk.NewInt(5)) + ubd := types.NewUnbondingDelegation( + addrDels[0], + addrVals[0], + 0, + time.Unix(0, 0), + sdk.NewInt(5), + ) // set and retrieve a record - keeper.SetUnbondingDelegation(ctx, ubd) - resUnbond, found := keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0]) + app.StakingKeeper.SetUnbondingDelegation(ctx, ubd) + resUnbond, found := app.StakingKeeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0]) require.True(t, found) require.True(t, ubd.Equal(resUnbond)) // modify a records, save, and retrieve ubd.Entries[0].Balance = sdk.NewInt(21) - keeper.SetUnbondingDelegation(ctx, ubd) + app.StakingKeeper.SetUnbondingDelegation(ctx, ubd) - resUnbonds := keeper.GetUnbondingDelegations(ctx, addrDels[0], 5) + resUnbonds := app.StakingKeeper.GetUnbondingDelegations(ctx, addrDels[0], 5) require.Equal(t, 1, len(resUnbonds)) - resUnbonds = keeper.GetAllUnbondingDelegations(ctx, addrDels[0]) + resUnbonds = app.StakingKeeper.GetAllUnbondingDelegations(ctx, addrDels[0]) require.Equal(t, 1, len(resUnbonds)) - resUnbond, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0]) + resUnbond, found = app.StakingKeeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0]) require.True(t, found) require.True(t, ubd.Equal(resUnbond)) // delete a record - keeper.RemoveUnbondingDelegation(ctx, ubd) - _, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0]) + app.StakingKeeper.RemoveUnbondingDelegation(ctx, ubd) + _, found = app.StakingKeeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0]) require.False(t, found) - resUnbonds = keeper.GetUnbondingDelegations(ctx, addrDels[0], 5) + resUnbonds = app.StakingKeeper.GetUnbondingDelegations(ctx, addrDels[0], 5) require.Equal(t, 0, len(resUnbonds)) - resUnbonds = keeper.GetAllUnbondingDelegations(ctx, addrDels[0]) + resUnbonds = app.StakingKeeper.GetAllUnbondingDelegations(ctx, addrDels[0]) require.Equal(t, 0, len(resUnbonds)) - } func TestUnbondDelegation(t *testing.T) { - ctx, _, bk, keeper, _ := CreateTestInput(t, false, 0) + app := simapp.Setup(false) + ctx := app.BaseApp.NewContext(false, abci.Header{}) startTokens := sdk.TokensFromConsensusPower(10) - notBondedPool := keeper.GetNotBondedPool(ctx) + notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) - require.NoError(t, bk.SetBalances(ctx, notBondedPool.GetAddress(), sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), startTokens)))) - keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) + require.NoError(t, + app.BankKeeper.SetBalances( + ctx, + notBondedPool.GetAddress(), + sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), startTokens)), + ), + ) + app.SupplyKeeper.SetModuleAccount(ctx, notBondedPool) // create a validator and a delegator to that validator // note this validator starts not-bonded @@ -182,19 +200,23 @@ func TestUnbondDelegation(t *testing.T) { validator, issuedShares := validator.AddTokensFromDel(startTokens) require.Equal(t, startTokens, issuedShares.RoundInt()) - validator = TestingUpdateValidator(keeper, ctx, validator, true) + validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true) delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares) - keeper.SetDelegation(ctx, delegation) + app.StakingKeeper.SetDelegation(ctx, delegation) + app.DistrKeeper.SetDelegatorStartingInfo(ctx, addrVals[0], addrDels[0], distribution.DelegatorStartingInfo{}) + app.DistrKeeper.SetValidatorHistoricalRewards(ctx, addrVals[0], 18446744073709551615, distribution.ValidatorHistoricalRewards{ReferenceCount: 1}) bondTokens := sdk.TokensFromConsensusPower(6) - amount, err := keeper.unbond(ctx, addrDels[0], addrVals[0], bondTokens.ToDec()) + _, err := app.StakingKeeper.Undelegate(ctx, addrDels[0], addrVals[0], bondTokens.ToDec()) require.NoError(t, err) - require.Equal(t, bondTokens, amount) // shares to be added to an unbonding delegation - delegation, found := keeper.GetDelegation(ctx, addrDels[0], addrVals[0]) + notBondedPoolBalance := app.BankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), app.StakingKeeper.BondDenom(ctx)) + require.Equal(t, bondTokens, notBondedPoolBalance.Amount) // shares to be added to an unbonding delegation + + delegation, found := app.StakingKeeper.GetDelegation(ctx, addrDels[0], addrVals[0]) require.True(t, found) - validator, found = keeper.GetValidator(ctx, addrVals[0]) + validator, found = app.StakingKeeper.GetValidator(ctx, addrVals[0]) require.True(t, found) remainingTokens := startTokens.Sub(bondTokens) @@ -202,755 +224,755 @@ func TestUnbondDelegation(t *testing.T) { require.Equal(t, remainingTokens, validator.BondedTokens()) } -func TestUnbondingDelegationsMaxEntries(t *testing.T) { - ctx, _, bk, keeper, _ := CreateTestInput(t, false, 1) - startTokens := sdk.TokensFromConsensusPower(10) - - bondDenom := keeper.BondDenom(ctx) - notBondedPool := keeper.GetNotBondedPool(ctx) - - err := bk.SetBalances(ctx, notBondedPool.GetAddress(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens))) - require.NoError(t, err) - keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) - - // create a validator and a delegator to that validator - validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) - - validator, issuedShares := validator.AddTokensFromDel(startTokens) - require.Equal(t, startTokens, issuedShares.RoundInt()) - - validator = TestingUpdateValidator(keeper, ctx, validator, true) - require.True(sdk.IntEq(t, startTokens, validator.BondedTokens())) - require.True(t, validator.IsBonded()) - - delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares) - keeper.SetDelegation(ctx, delegation) - - maxEntries := keeper.MaxEntries(ctx) - - oldBonded := bk.GetBalance(ctx, keeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount - oldNotBonded := bk.GetBalance(ctx, keeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount - - // should all pass - var completionTime time.Time - for i := uint32(0); i < maxEntries; i++ { - var err error - completionTime, err = keeper.Undelegate(ctx, addrDels[0], addrVals[0], sdk.NewDec(1)) - require.NoError(t, err) - } - - newBonded := bk.GetBalance(ctx, keeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount - newNotBonded := bk.GetBalance(ctx, keeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount - require.True(sdk.IntEq(t, newBonded, oldBonded.SubRaw(int64(maxEntries)))) - require.True(sdk.IntEq(t, newNotBonded, oldNotBonded.AddRaw(int64(maxEntries)))) - - oldBonded = bk.GetBalance(ctx, keeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount - oldNotBonded = bk.GetBalance(ctx, keeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount - - // an additional unbond should fail due to max entries - _, err = keeper.Undelegate(ctx, addrDels[0], addrVals[0], sdk.NewDec(1)) - require.Error(t, err) - - newBonded = bk.GetBalance(ctx, keeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount - newNotBonded = bk.GetBalance(ctx, keeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount - - require.True(sdk.IntEq(t, newBonded, oldBonded)) - require.True(sdk.IntEq(t, newNotBonded, oldNotBonded)) - - // mature unbonding delegations - ctx = ctx.WithBlockTime(completionTime) - err = keeper.CompleteUnbonding(ctx, addrDels[0], addrVals[0]) - require.NoError(t, err) - - newBonded = bk.GetBalance(ctx, keeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount - newNotBonded = bk.GetBalance(ctx, keeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount - require.True(sdk.IntEq(t, newBonded, oldBonded)) - require.True(sdk.IntEq(t, newNotBonded, oldNotBonded.SubRaw(int64(maxEntries)))) - - oldNotBonded = bk.GetBalance(ctx, keeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount - - // unbonding should work again - _, err = keeper.Undelegate(ctx, addrDels[0], addrVals[0], sdk.NewDec(1)) - require.NoError(t, err) - - newBonded = bk.GetBalance(ctx, keeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount - newNotBonded = bk.GetBalance(ctx, keeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount - require.True(sdk.IntEq(t, newBonded, oldBonded.SubRaw(1))) - require.True(sdk.IntEq(t, newNotBonded, oldNotBonded.AddRaw(1))) -} - -// test undelegating self delegation from a validator pushing it below MinSelfDelegation -// shift it from the bonded to unbonding state and jailed -func TestUndelegateSelfDelegationBelowMinSelfDelegation(t *testing.T) { - ctx, _, bk, keeper, _ := CreateTestInput(t, false, 0) - delTokens := sdk.TokensFromConsensusPower(10) - delCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), delTokens)) - - //create a validator with a self-delegation - validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) - - validator.MinSelfDelegation = delTokens - validator, issuedShares := validator.AddTokensFromDel(delTokens) - require.Equal(t, delTokens, issuedShares.RoundInt()) - - // add bonded tokens to pool for delegations - notBondedPool := keeper.GetNotBondedPool(ctx) - oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) - err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(delCoins...)) - require.NoError(t, err) - keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) - - validator = TestingUpdateValidator(keeper, ctx, validator, true) - require.True(t, validator.IsBonded()) - - selfDelegation := types.NewDelegation(sdk.AccAddress(addrVals[0].Bytes()), addrVals[0], issuedShares) - keeper.SetDelegation(ctx, selfDelegation) - - // add bonded tokens to pool for delegations - bondedPool := keeper.GetBondedPool(ctx) - oldBonded := bk.GetAllBalances(ctx, bondedPool.GetAddress()) - err = bk.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) - require.NoError(t, err) - keeper.supplyKeeper.SetModuleAccount(ctx, bondedPool) - - // create a second delegation to this validator - keeper.DeleteValidatorByPowerIndex(ctx, validator) - validator, issuedShares = validator.AddTokensFromDel(delTokens) - require.True(t, validator.IsBonded()) - require.Equal(t, delTokens, issuedShares.RoundInt()) - - // add bonded tokens to pool for delegations - oldBonded = bk.GetAllBalances(ctx, bondedPool.GetAddress()) - err = bk.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) - require.NoError(t, err) - keeper.supplyKeeper.SetModuleAccount(ctx, bondedPool) - - validator = TestingUpdateValidator(keeper, ctx, validator, true) - delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares) - keeper.SetDelegation(ctx, delegation) - - val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) - _, err = keeper.Undelegate(ctx, val0AccAddr, addrVals[0], sdk.TokensFromConsensusPower(6).ToDec()) - require.NoError(t, err) - - // end block - updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) - require.Equal(t, 1, len(updates)) - - validator, found := keeper.GetValidator(ctx, addrVals[0]) - require.True(t, found) - require.Equal(t, sdk.TokensFromConsensusPower(14), validator.Tokens) - require.Equal(t, sdk.Unbonding, validator.Status) - require.True(t, validator.Jailed) -} - -func TestUndelegateFromUnbondingValidator(t *testing.T) { - ctx, _, bk, keeper, _ := CreateTestInput(t, false, 0) - delTokens := sdk.TokensFromConsensusPower(10) - delCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), delTokens)) - - //create a validator with a self-delegation - validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) - - validator, issuedShares := validator.AddTokensFromDel(delTokens) - require.Equal(t, delTokens, issuedShares.RoundInt()) - - // add bonded tokens to pool for delegations - notBondedPool := keeper.GetNotBondedPool(ctx) - oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) - err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(delCoins...)) - require.NoError(t, err) - keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) - - validator = TestingUpdateValidator(keeper, ctx, validator, true) - require.True(t, validator.IsBonded()) - - selfDelegation := types.NewDelegation(sdk.AccAddress(addrVals[0].Bytes()), addrVals[0], issuedShares) - keeper.SetDelegation(ctx, selfDelegation) - - bondedPool := keeper.GetBondedPool(ctx) - oldBonded := bk.GetAllBalances(ctx, bondedPool.GetAddress()) - err = bk.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) - require.NoError(t, err) - keeper.supplyKeeper.SetModuleAccount(ctx, bondedPool) - - // create a second delegation to this validator - keeper.DeleteValidatorByPowerIndex(ctx, validator) - - validator, issuedShares = validator.AddTokensFromDel(delTokens) - require.Equal(t, delTokens, issuedShares.RoundInt()) - - oldBonded = bk.GetAllBalances(ctx, bondedPool.GetAddress()) - err = bk.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) - require.NoError(t, err) - keeper.supplyKeeper.SetModuleAccount(ctx, bondedPool) - - validator = TestingUpdateValidator(keeper, ctx, validator, true) - delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares) - keeper.SetDelegation(ctx, delegation) - - oldBonded = bk.GetAllBalances(ctx, bondedPool.GetAddress()) - err = bk.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) - require.NoError(t, err) - keeper.supplyKeeper.SetModuleAccount(ctx, bondedPool) - - header := ctx.BlockHeader() - blockHeight := int64(10) - header.Height = blockHeight - blockTime := time.Unix(333, 0) - header.Time = blockTime - ctx = ctx.WithBlockHeader(header) - - // unbond the all self-delegation to put validator in unbonding state - val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) - _, err = keeper.Undelegate(ctx, val0AccAddr, addrVals[0], delTokens.ToDec()) - require.NoError(t, err) - - // end block - updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) - require.Equal(t, 1, len(updates)) - - validator, found := keeper.GetValidator(ctx, addrVals[0]) - require.True(t, found) - require.Equal(t, blockHeight, validator.UnbondingHeight) - params := keeper.GetParams(ctx) - require.True(t, blockTime.Add(params.UnbondingTime).Equal(validator.UnbondingTime)) - - blockHeight2 := int64(20) - blockTime2 := time.Unix(444, 0).UTC() - ctx = ctx.WithBlockHeight(blockHeight2) - ctx = ctx.WithBlockTime(blockTime2) - - // unbond some of the other delegation's shares - _, err = keeper.Undelegate(ctx, addrDels[0], addrVals[0], sdk.NewDec(6)) - require.NoError(t, err) - - // retrieve the unbonding delegation - ubd, found := keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0]) - require.True(t, found) - require.Len(t, ubd.Entries, 1) - require.True(t, ubd.Entries[0].Balance.Equal(sdk.NewInt(6))) - assert.Equal(t, blockHeight2, ubd.Entries[0].CreationHeight) - assert.True(t, blockTime2.Add(params.UnbondingTime).Equal(ubd.Entries[0].CompletionTime)) -} - -func TestUndelegateFromUnbondedValidator(t *testing.T) { - ctx, _, bk, keeper, _ := CreateTestInput(t, false, 1) - delTokens := sdk.TokensFromConsensusPower(10) - delCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), delTokens)) - - // add bonded tokens to pool for delegations - notBondedPool := keeper.GetNotBondedPool(ctx) - oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) - err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(delCoins...)) - require.NoError(t, err) - keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) - - // create a validator with a self-delegation - validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) - - valTokens := sdk.TokensFromConsensusPower(10) - validator, issuedShares := validator.AddTokensFromDel(valTokens) - require.Equal(t, valTokens, issuedShares.RoundInt()) - validator = TestingUpdateValidator(keeper, ctx, validator, true) - require.True(t, validator.IsBonded()) - - val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) - selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares) - keeper.SetDelegation(ctx, selfDelegation) - - bondedPool := keeper.GetBondedPool(ctx) - oldBonded := bk.GetAllBalances(ctx, bondedPool.GetAddress()) - err = bk.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) - require.NoError(t, err) - keeper.supplyKeeper.SetModuleAccount(ctx, bondedPool) - - // create a second delegation to this validator - keeper.DeleteValidatorByPowerIndex(ctx, validator) - validator, issuedShares = validator.AddTokensFromDel(delTokens) - require.Equal(t, delTokens, issuedShares.RoundInt()) - validator = TestingUpdateValidator(keeper, ctx, validator, true) - require.True(t, validator.IsBonded()) - delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares) - keeper.SetDelegation(ctx, delegation) - - ctx = ctx.WithBlockHeight(10) - ctx = ctx.WithBlockTime(time.Unix(333, 0)) - - // unbond the all self-delegation to put validator in unbonding state - _, err = keeper.Undelegate(ctx, val0AccAddr, addrVals[0], valTokens.ToDec()) - require.NoError(t, err) - - // end block - updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) - require.Equal(t, 1, len(updates)) - - validator, found := keeper.GetValidator(ctx, addrVals[0]) - require.True(t, found) - require.Equal(t, ctx.BlockHeight(), validator.UnbondingHeight) - params := keeper.GetParams(ctx) - require.True(t, ctx.BlockHeader().Time.Add(params.UnbondingTime).Equal(validator.UnbondingTime)) - - // unbond the validator - ctx = ctx.WithBlockTime(validator.UnbondingTime) - keeper.UnbondAllMatureValidatorQueue(ctx) - - // Make sure validator is still in state because there is still an outstanding delegation - validator, found = keeper.GetValidator(ctx, addrVals[0]) - require.True(t, found) - require.Equal(t, validator.Status, sdk.Unbonded) - - // unbond some of the other delegation's shares - unbondTokens := sdk.TokensFromConsensusPower(6) - _, err = keeper.Undelegate(ctx, addrDels[0], addrVals[0], unbondTokens.ToDec()) - require.NoError(t, err) - - // unbond rest of the other delegation's shares - remainingTokens := delTokens.Sub(unbondTokens) - _, err = keeper.Undelegate(ctx, addrDels[0], addrVals[0], remainingTokens.ToDec()) - require.NoError(t, err) - - // now validator should now be deleted from state - validator, found = keeper.GetValidator(ctx, addrVals[0]) - require.False(t, found, "%v", validator) -} - -func TestUnbondingAllDelegationFromValidator(t *testing.T) { - ctx, _, bk, keeper, _ := CreateTestInput(t, false, 0) - delTokens := sdk.TokensFromConsensusPower(10) - delCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), delTokens)) - - // add bonded tokens to pool for delegations - notBondedPool := keeper.GetNotBondedPool(ctx) - oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) - err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(delCoins...)) - require.NoError(t, err) - keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) - - //create a validator with a self-delegation - validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) - - valTokens := sdk.TokensFromConsensusPower(10) - validator, issuedShares := validator.AddTokensFromDel(valTokens) - require.Equal(t, valTokens, issuedShares.RoundInt()) - - validator = TestingUpdateValidator(keeper, ctx, validator, true) - require.True(t, validator.IsBonded()) - val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) - - selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares) - keeper.SetDelegation(ctx, selfDelegation) - - // create a second delegation to this validator - keeper.DeleteValidatorByPowerIndex(ctx, validator) - validator, issuedShares = validator.AddTokensFromDel(delTokens) - require.Equal(t, delTokens, issuedShares.RoundInt()) - - bondedPool := keeper.GetBondedPool(ctx) - oldBonded := bk.GetAllBalances(ctx, bondedPool.GetAddress()) - err = bk.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) - require.NoError(t, err) - keeper.supplyKeeper.SetModuleAccount(ctx, bondedPool) - - validator = TestingUpdateValidator(keeper, ctx, validator, true) - require.True(t, validator.IsBonded()) - - delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares) - keeper.SetDelegation(ctx, delegation) - - ctx = ctx.WithBlockHeight(10) - ctx = ctx.WithBlockTime(time.Unix(333, 0)) - - // unbond the all self-delegation to put validator in unbonding state - _, err = keeper.Undelegate(ctx, val0AccAddr, addrVals[0], valTokens.ToDec()) - require.NoError(t, err) - - // end block - updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) - require.Equal(t, 1, len(updates)) - - // unbond all the remaining delegation - _, err = keeper.Undelegate(ctx, addrDels[0], addrVals[0], delTokens.ToDec()) - require.NoError(t, err) - - // validator should still be in state and still be in unbonding state - validator, found := keeper.GetValidator(ctx, addrVals[0]) - require.True(t, found) - require.Equal(t, validator.Status, sdk.Unbonding) - - // unbond the validator - ctx = ctx.WithBlockTime(validator.UnbondingTime) - keeper.UnbondAllMatureValidatorQueue(ctx) - - // validator should now be deleted from state - _, found = keeper.GetValidator(ctx, addrVals[0]) - require.False(t, found) -} - -// Make sure that that the retrieving the delegations doesn't affect the state -func TestGetRedelegationsFromSrcValidator(t *testing.T) { - ctx, _, _, keeper, _ := CreateTestInput(t, false, 0) - - rd := types.NewRedelegation(addrDels[0], addrVals[0], addrVals[1], 0, - time.Unix(0, 0), sdk.NewInt(5), - sdk.NewDec(5)) - - // set and retrieve a record - keeper.SetRedelegation(ctx, rd) - resBond, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) - require.True(t, found) - - // get the redelegations one time - redelegations := keeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0]) - require.Equal(t, 1, len(redelegations)) - require.True(t, redelegations[0].Equal(resBond)) - - // get the redelegations a second time, should be exactly the same - redelegations = keeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0]) - require.Equal(t, 1, len(redelegations)) - require.True(t, redelegations[0].Equal(resBond)) -} - -// tests Get/Set/Remove/Has UnbondingDelegation -func TestRedelegation(t *testing.T) { - ctx, _, _, keeper, _ := CreateTestInput(t, false, 0) - - rd := types.NewRedelegation(addrDels[0], addrVals[0], addrVals[1], 0, - time.Unix(0, 0), sdk.NewInt(5), - sdk.NewDec(5)) - - // test shouldn't have and redelegations - has := keeper.HasReceivingRedelegation(ctx, addrDels[0], addrVals[1]) - require.False(t, has) - - // set and retrieve a record - keeper.SetRedelegation(ctx, rd) - resRed, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) - require.True(t, found) - - redelegations := keeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0]) - require.Equal(t, 1, len(redelegations)) - require.True(t, redelegations[0].Equal(resRed)) - - redelegations = keeper.GetRedelegations(ctx, addrDels[0], 5) - require.Equal(t, 1, len(redelegations)) - require.True(t, redelegations[0].Equal(resRed)) - - redelegations = keeper.GetAllRedelegations(ctx, addrDels[0], nil, nil) - require.Equal(t, 1, len(redelegations)) - require.True(t, redelegations[0].Equal(resRed)) - - // check if has the redelegation - has = keeper.HasReceivingRedelegation(ctx, addrDels[0], addrVals[1]) - require.True(t, has) - - // modify a records, save, and retrieve - rd.Entries[0].SharesDst = sdk.NewDec(21) - keeper.SetRedelegation(ctx, rd) - - resRed, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) - require.True(t, found) - require.True(t, rd.Equal(resRed)) - - redelegations = keeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0]) - require.Equal(t, 1, len(redelegations)) - require.True(t, redelegations[0].Equal(resRed)) - - redelegations = keeper.GetRedelegations(ctx, addrDels[0], 5) - require.Equal(t, 1, len(redelegations)) - require.True(t, redelegations[0].Equal(resRed)) - - // delete a record - keeper.RemoveRedelegation(ctx, rd) - _, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) - require.False(t, found) - - redelegations = keeper.GetRedelegations(ctx, addrDels[0], 5) - require.Equal(t, 0, len(redelegations)) - - redelegations = keeper.GetAllRedelegations(ctx, addrDels[0], nil, nil) - require.Equal(t, 0, len(redelegations)) -} - -func TestRedelegateToSameValidator(t *testing.T) { - ctx, _, bk, keeper, _ := CreateTestInput(t, false, 0) - valTokens := sdk.TokensFromConsensusPower(10) - startCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), valTokens)) - - // add bonded tokens to pool for delegations - notBondedPool := keeper.GetNotBondedPool(ctx) - oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) - err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(startCoins...)) - require.NoError(t, err) - keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) - - // create a validator with a self-delegation - validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) - validator, issuedShares := validator.AddTokensFromDel(valTokens) - require.Equal(t, valTokens, issuedShares.RoundInt()) - validator = TestingUpdateValidator(keeper, ctx, validator, true) - require.True(t, validator.IsBonded()) - - val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) - selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares) - keeper.SetDelegation(ctx, selfDelegation) - - _, err = keeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[0], sdk.NewDec(5)) - require.Error(t, err) -} - -func TestRedelegationMaxEntries(t *testing.T) { - ctx, _, bk, keeper, _ := CreateTestInput(t, false, 0) - startTokens := sdk.TokensFromConsensusPower(20) - startCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), startTokens)) - - // add bonded tokens to pool for delegations - notBondedPool := keeper.GetNotBondedPool(ctx) - oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) - err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(startCoins...)) - require.NoError(t, err) - keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) - - // create a validator with a self-delegation - validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) - valTokens := sdk.TokensFromConsensusPower(10) - validator, issuedShares := validator.AddTokensFromDel(valTokens) - require.Equal(t, valTokens, issuedShares.RoundInt()) - validator = TestingUpdateValidator(keeper, ctx, validator, true) - val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) - selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares) - keeper.SetDelegation(ctx, selfDelegation) - - // create a second validator - validator2 := types.NewValidator(addrVals[1], PKs[1], types.Description{}) - validator2, issuedShares = validator2.AddTokensFromDel(valTokens) - require.Equal(t, valTokens, issuedShares.RoundInt()) - - validator2 = TestingUpdateValidator(keeper, ctx, validator2, true) - require.Equal(t, sdk.Bonded, validator2.Status) - - maxEntries := keeper.MaxEntries(ctx) - - // redelegations should pass - var completionTime time.Time - for i := uint32(0); i < maxEntries; i++ { - var err error - completionTime, err = keeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1], sdk.NewDec(1)) - require.NoError(t, err) - } - - // an additional redelegation should fail due to max entries - _, err = keeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1], sdk.NewDec(1)) - require.Error(t, err) - - // mature redelegations - ctx = ctx.WithBlockTime(completionTime) - err = keeper.CompleteRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1]) - require.NoError(t, err) - - // redelegation should work again - _, err = keeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1], sdk.NewDec(1)) - require.NoError(t, err) -} - -func TestRedelegateSelfDelegation(t *testing.T) { - ctx, _, bk, keeper, _ := CreateTestInput(t, false, 0) - startTokens := sdk.TokensFromConsensusPower(30) - startCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), startTokens)) - - // add bonded tokens to pool for delegations - notBondedPool := keeper.GetNotBondedPool(ctx) - oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) - err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(startCoins...)) - require.NoError(t, err) - keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) - - //create a validator with a self-delegation - validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) - valTokens := sdk.TokensFromConsensusPower(10) - validator, issuedShares := validator.AddTokensFromDel(valTokens) - require.Equal(t, valTokens, issuedShares.RoundInt()) - - validator = TestingUpdateValidator(keeper, ctx, validator, true) - - val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) - selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares) - keeper.SetDelegation(ctx, selfDelegation) - - // create a second validator - validator2 := types.NewValidator(addrVals[1], PKs[1], types.Description{}) - validator2, issuedShares = validator2.AddTokensFromDel(valTokens) - require.Equal(t, valTokens, issuedShares.RoundInt()) - validator2 = TestingUpdateValidator(keeper, ctx, validator2, true) - require.Equal(t, sdk.Bonded, validator2.Status) - - // create a second delegation to validator 1 - delTokens := sdk.TokensFromConsensusPower(10) - validator, issuedShares = validator.AddTokensFromDel(delTokens) - require.Equal(t, delTokens, issuedShares.RoundInt()) - validator = TestingUpdateValidator(keeper, ctx, validator, true) - - delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares) - keeper.SetDelegation(ctx, delegation) - - _, err = keeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1], delTokens.ToDec()) - require.NoError(t, err) - - // end block - updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) - require.Equal(t, 2, len(updates)) - - validator, found := keeper.GetValidator(ctx, addrVals[0]) - require.True(t, found) - require.Equal(t, valTokens, validator.Tokens) - require.Equal(t, sdk.Unbonding, validator.Status) -} - -func TestRedelegateFromUnbondingValidator(t *testing.T) { - ctx, _, bk, keeper, _ := CreateTestInput(t, false, 0) - startTokens := sdk.TokensFromConsensusPower(30) - startCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), startTokens)) - - // add bonded tokens to pool for delegations - notBondedPool := keeper.GetNotBondedPool(ctx) - oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) - err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(startCoins...)) - require.NoError(t, err) - keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) - - //create a validator with a self-delegation - validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) - - valTokens := sdk.TokensFromConsensusPower(10) - validator, issuedShares := validator.AddTokensFromDel(valTokens) - require.Equal(t, valTokens, issuedShares.RoundInt()) - validator = TestingUpdateValidator(keeper, ctx, validator, true) - val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) - selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares) - keeper.SetDelegation(ctx, selfDelegation) - - // create a second delegation to this validator - keeper.DeleteValidatorByPowerIndex(ctx, validator) - delTokens := sdk.TokensFromConsensusPower(10) - validator, issuedShares = validator.AddTokensFromDel(delTokens) - require.Equal(t, delTokens, issuedShares.RoundInt()) - validator = TestingUpdateValidator(keeper, ctx, validator, true) - delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares) - keeper.SetDelegation(ctx, delegation) - - // create a second validator - validator2 := types.NewValidator(addrVals[1], PKs[1], types.Description{}) - validator2, issuedShares = validator2.AddTokensFromDel(valTokens) - require.Equal(t, valTokens, issuedShares.RoundInt()) - validator2 = TestingUpdateValidator(keeper, ctx, validator2, true) - - header := ctx.BlockHeader() - blockHeight := int64(10) - header.Height = blockHeight - blockTime := time.Unix(333, 0) - header.Time = blockTime - ctx = ctx.WithBlockHeader(header) - - // unbond the all self-delegation to put validator in unbonding state - _, err = keeper.Undelegate(ctx, val0AccAddr, addrVals[0], delTokens.ToDec()) - require.NoError(t, err) - - // end block - updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) - require.Equal(t, 1, len(updates)) - - validator, found := keeper.GetValidator(ctx, addrVals[0]) - require.True(t, found) - require.Equal(t, blockHeight, validator.UnbondingHeight) - params := keeper.GetParams(ctx) - require.True(t, blockTime.Add(params.UnbondingTime).Equal(validator.UnbondingTime)) - - //change the context - header = ctx.BlockHeader() - blockHeight2 := int64(20) - header.Height = blockHeight2 - blockTime2 := time.Unix(444, 0) - header.Time = blockTime2 - ctx = ctx.WithBlockHeader(header) - - // unbond some of the other delegation's shares - redelegateTokens := sdk.TokensFromConsensusPower(6) - _, err = keeper.BeginRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1], redelegateTokens.ToDec()) - require.NoError(t, err) - - // retrieve the unbonding delegation - ubd, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) - require.True(t, found) - require.Len(t, ubd.Entries, 1) - assert.Equal(t, blockHeight, ubd.Entries[0].CreationHeight) - assert.True(t, blockTime.Add(params.UnbondingTime).Equal(ubd.Entries[0].CompletionTime)) -} - -func TestRedelegateFromUnbondedValidator(t *testing.T) { - ctx, _, bk, keeper, _ := CreateTestInput(t, false, 0) - startTokens := sdk.TokensFromConsensusPower(30) - startCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), startTokens)) - - // add bonded tokens to pool for delegations - notBondedPool := keeper.GetNotBondedPool(ctx) - oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) - err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(startCoins...)) - require.NoError(t, err) - keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) - - //create a validator with a self-delegation - validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) - - valTokens := sdk.TokensFromConsensusPower(10) - validator, issuedShares := validator.AddTokensFromDel(valTokens) - require.Equal(t, valTokens, issuedShares.RoundInt()) - validator = TestingUpdateValidator(keeper, ctx, validator, true) - val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) - selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares) - keeper.SetDelegation(ctx, selfDelegation) - - // create a second delegation to this validator - keeper.DeleteValidatorByPowerIndex(ctx, validator) - delTokens := sdk.TokensFromConsensusPower(10) - validator, issuedShares = validator.AddTokensFromDel(delTokens) - require.Equal(t, delTokens, issuedShares.RoundInt()) - validator = TestingUpdateValidator(keeper, ctx, validator, true) - delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares) - keeper.SetDelegation(ctx, delegation) - - // create a second validator - validator2 := types.NewValidator(addrVals[1], PKs[1], types.Description{}) - validator2, issuedShares = validator2.AddTokensFromDel(valTokens) - require.Equal(t, valTokens, issuedShares.RoundInt()) - validator2 = TestingUpdateValidator(keeper, ctx, validator2, true) - require.Equal(t, sdk.Bonded, validator2.Status) - - ctx = ctx.WithBlockHeight(10) - ctx = ctx.WithBlockTime(time.Unix(333, 0)) - - // unbond the all self-delegation to put validator in unbonding state - _, err = keeper.Undelegate(ctx, val0AccAddr, addrVals[0], delTokens.ToDec()) - require.NoError(t, err) - - // end block - updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) - require.Equal(t, 1, len(updates)) - - validator, found := keeper.GetValidator(ctx, addrVals[0]) - require.True(t, found) - require.Equal(t, ctx.BlockHeight(), validator.UnbondingHeight) - params := keeper.GetParams(ctx) - require.True(t, ctx.BlockHeader().Time.Add(params.UnbondingTime).Equal(validator.UnbondingTime)) - - // unbond the validator - keeper.unbondingToUnbonded(ctx, validator) - - // redelegate some of the delegation's shares - redelegationTokens := sdk.TokensFromConsensusPower(6) - _, err = keeper.BeginRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1], redelegationTokens.ToDec()) - require.NoError(t, err) - - // no red should have been found - red, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) - require.False(t, found, "%v", red) -} +//func TestUnbondingDelegationsMaxEntries(t *testing.T) { +// ctx, _, bk, keeper, _ := CreateTestInput(t, false, 1) +// startTokens := sdk.TokensFromConsensusPower(10) +// +// bondDenom := keeper.BondDenom(ctx) +// notBondedPool := keeper.GetNotBondedPool(ctx) +// +// err := bk.SetBalances(ctx, notBondedPool.GetAddress(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens))) +// require.NoError(t, err) +// keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) +// +// // create a validator and a delegator to that validator +// validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) +// +// validator, issuedShares := validator.AddTokensFromDel(startTokens) +// require.Equal(t, startTokens, issuedShares.RoundInt()) +// +// validator = TestingUpdateValidator(keeper, ctx, validator, true) +// require.True(sdk.IntEq(t, startTokens, validator.BondedTokens())) +// require.True(t, validator.IsBonded()) +// +// delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares) +// keeper.SetDelegation(ctx, delegation) +// +// maxEntries := keeper.MaxEntries(ctx) +// +// oldBonded := bk.GetBalance(ctx, keeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount +// oldNotBonded := bk.GetBalance(ctx, keeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount +// +// // should all pass +// var completionTime time.Time +// for i := uint32(0); i < maxEntries; i++ { +// var err error +// completionTime, err = keeper.Undelegate(ctx, addrDels[0], addrVals[0], sdk.NewDec(1)) +// require.NoError(t, err) +// } +// +// newBonded := bk.GetBalance(ctx, keeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount +// newNotBonded := bk.GetBalance(ctx, keeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount +// require.True(sdk.IntEq(t, newBonded, oldBonded.SubRaw(int64(maxEntries)))) +// require.True(sdk.IntEq(t, newNotBonded, oldNotBonded.AddRaw(int64(maxEntries)))) +// +// oldBonded = bk.GetBalance(ctx, keeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount +// oldNotBonded = bk.GetBalance(ctx, keeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount +// +// // an additional unbond should fail due to max entries +// _, err = keeper.Undelegate(ctx, addrDels[0], addrVals[0], sdk.NewDec(1)) +// require.Error(t, err) +// +// newBonded = bk.GetBalance(ctx, keeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount +// newNotBonded = bk.GetBalance(ctx, keeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount +// +// require.True(sdk.IntEq(t, newBonded, oldBonded)) +// require.True(sdk.IntEq(t, newNotBonded, oldNotBonded)) +// +// // mature unbonding delegations +// ctx = ctx.WithBlockTime(completionTime) +// err = keeper.CompleteUnbonding(ctx, addrDels[0], addrVals[0]) +// require.NoError(t, err) +// +// newBonded = bk.GetBalance(ctx, keeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount +// newNotBonded = bk.GetBalance(ctx, keeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount +// require.True(sdk.IntEq(t, newBonded, oldBonded)) +// require.True(sdk.IntEq(t, newNotBonded, oldNotBonded.SubRaw(int64(maxEntries)))) +// +// oldNotBonded = bk.GetBalance(ctx, keeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount +// +// // unbonding should work again +// _, err = keeper.Undelegate(ctx, addrDels[0], addrVals[0], sdk.NewDec(1)) +// require.NoError(t, err) +// +// newBonded = bk.GetBalance(ctx, keeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount +// newNotBonded = bk.GetBalance(ctx, keeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount +// require.True(sdk.IntEq(t, newBonded, oldBonded.SubRaw(1))) +// require.True(sdk.IntEq(t, newNotBonded, oldNotBonded.AddRaw(1))) +//} +// +//// test undelegating self delegation from a validator pushing it below MinSelfDelegation +//// shift it from the bonded to unbonding state and jailed +//func TestUndelegateSelfDelegationBelowMinSelfDelegation(t *testing.T) { +// ctx, _, bk, keeper, _ := CreateTestInput(t, false, 0) +// delTokens := sdk.TokensFromConsensusPower(10) +// delCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), delTokens)) +// +// //create a validator with a self-delegation +// validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) +// +// validator.MinSelfDelegation = delTokens +// validator, issuedShares := validator.AddTokensFromDel(delTokens) +// require.Equal(t, delTokens, issuedShares.RoundInt()) +// +// // add bonded tokens to pool for delegations +// notBondedPool := keeper.GetNotBondedPool(ctx) +// oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) +// err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(delCoins...)) +// require.NoError(t, err) +// keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) +// +// validator = TestingUpdateValidator(keeper, ctx, validator, true) +// require.True(t, validator.IsBonded()) +// +// selfDelegation := types.NewDelegation(sdk.AccAddress(addrVals[0].Bytes()), addrVals[0], issuedShares) +// keeper.SetDelegation(ctx, selfDelegation) +// +// // add bonded tokens to pool for delegations +// bondedPool := keeper.GetBondedPool(ctx) +// oldBonded := bk.GetAllBalances(ctx, bondedPool.GetAddress()) +// err = bk.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) +// require.NoError(t, err) +// keeper.supplyKeeper.SetModuleAccount(ctx, bondedPool) +// +// // create a second delegation to this validator +// keeper.DeleteValidatorByPowerIndex(ctx, validator) +// validator, issuedShares = validator.AddTokensFromDel(delTokens) +// require.True(t, validator.IsBonded()) +// require.Equal(t, delTokens, issuedShares.RoundInt()) +// +// // add bonded tokens to pool for delegations +// oldBonded = bk.GetAllBalances(ctx, bondedPool.GetAddress()) +// err = bk.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) +// require.NoError(t, err) +// keeper.supplyKeeper.SetModuleAccount(ctx, bondedPool) +// +// validator = TestingUpdateValidator(keeper, ctx, validator, true) +// delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares) +// keeper.SetDelegation(ctx, delegation) +// +// val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) +// _, err = keeper.Undelegate(ctx, val0AccAddr, addrVals[0], sdk.TokensFromConsensusPower(6).ToDec()) +// require.NoError(t, err) +// +// // end block +// updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) +// require.Equal(t, 1, len(updates)) +// +// validator, found := keeper.GetValidator(ctx, addrVals[0]) +// require.True(t, found) +// require.Equal(t, sdk.TokensFromConsensusPower(14), validator.Tokens) +// require.Equal(t, sdk.Unbonding, validator.Status) +// require.True(t, validator.Jailed) +//} +// +//func TestUndelegateFromUnbondingValidator(t *testing.T) { +// ctx, _, bk, keeper, _ := CreateTestInput(t, false, 0) +// delTokens := sdk.TokensFromConsensusPower(10) +// delCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), delTokens)) +// +// //create a validator with a self-delegation +// validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) +// +// validator, issuedShares := validator.AddTokensFromDel(delTokens) +// require.Equal(t, delTokens, issuedShares.RoundInt()) +// +// // add bonded tokens to pool for delegations +// notBondedPool := keeper.GetNotBondedPool(ctx) +// oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) +// err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(delCoins...)) +// require.NoError(t, err) +// keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) +// +// validator = TestingUpdateValidator(keeper, ctx, validator, true) +// require.True(t, validator.IsBonded()) +// +// selfDelegation := types.NewDelegation(sdk.AccAddress(addrVals[0].Bytes()), addrVals[0], issuedShares) +// keeper.SetDelegation(ctx, selfDelegation) +// +// bondedPool := keeper.GetBondedPool(ctx) +// oldBonded := bk.GetAllBalances(ctx, bondedPool.GetAddress()) +// err = bk.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) +// require.NoError(t, err) +// keeper.supplyKeeper.SetModuleAccount(ctx, bondedPool) +// +// // create a second delegation to this validator +// keeper.DeleteValidatorByPowerIndex(ctx, validator) +// +// validator, issuedShares = validator.AddTokensFromDel(delTokens) +// require.Equal(t, delTokens, issuedShares.RoundInt()) +// +// oldBonded = bk.GetAllBalances(ctx, bondedPool.GetAddress()) +// err = bk.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) +// require.NoError(t, err) +// keeper.supplyKeeper.SetModuleAccount(ctx, bondedPool) +// +// validator = TestingUpdateValidator(keeper, ctx, validator, true) +// delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares) +// keeper.SetDelegation(ctx, delegation) +// +// oldBonded = bk.GetAllBalances(ctx, bondedPool.GetAddress()) +// err = bk.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) +// require.NoError(t, err) +// keeper.supplyKeeper.SetModuleAccount(ctx, bondedPool) +// +// header := ctx.BlockHeader() +// blockHeight := int64(10) +// header.Height = blockHeight +// blockTime := time.Unix(333, 0) +// header.Time = blockTime +// ctx = ctx.WithBlockHeader(header) +// +// // unbond the all self-delegation to put validator in unbonding state +// val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) +// _, err = keeper.Undelegate(ctx, val0AccAddr, addrVals[0], delTokens.ToDec()) +// require.NoError(t, err) +// +// // end block +// updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) +// require.Equal(t, 1, len(updates)) +// +// validator, found := keeper.GetValidator(ctx, addrVals[0]) +// require.True(t, found) +// require.Equal(t, blockHeight, validator.UnbondingHeight) +// params := keeper.GetParams(ctx) +// require.True(t, blockTime.Add(params.UnbondingTime).Equal(validator.UnbondingTime)) +// +// blockHeight2 := int64(20) +// blockTime2 := time.Unix(444, 0).UTC() +// ctx = ctx.WithBlockHeight(blockHeight2) +// ctx = ctx.WithBlockTime(blockTime2) +// +// // unbond some of the other delegation's shares +// _, err = keeper.Undelegate(ctx, addrDels[0], addrVals[0], sdk.NewDec(6)) +// require.NoError(t, err) +// +// // retrieve the unbonding delegation +// ubd, found := keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0]) +// require.True(t, found) +// require.Len(t, ubd.Entries, 1) +// require.True(t, ubd.Entries[0].Balance.Equal(sdk.NewInt(6))) +// assert.Equal(t, blockHeight2, ubd.Entries[0].CreationHeight) +// assert.True(t, blockTime2.Add(params.UnbondingTime).Equal(ubd.Entries[0].CompletionTime)) +//} +// +//func TestUndelegateFromUnbondedValidator(t *testing.T) { +// ctx, _, bk, keeper, _ := CreateTestInput(t, false, 1) +// delTokens := sdk.TokensFromConsensusPower(10) +// delCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), delTokens)) +// +// // add bonded tokens to pool for delegations +// notBondedPool := keeper.GetNotBondedPool(ctx) +// oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) +// err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(delCoins...)) +// require.NoError(t, err) +// keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) +// +// // create a validator with a self-delegation +// validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) +// +// valTokens := sdk.TokensFromConsensusPower(10) +// validator, issuedShares := validator.AddTokensFromDel(valTokens) +// require.Equal(t, valTokens, issuedShares.RoundInt()) +// validator = TestingUpdateValidator(keeper, ctx, validator, true) +// require.True(t, validator.IsBonded()) +// +// val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) +// selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares) +// keeper.SetDelegation(ctx, selfDelegation) +// +// bondedPool := keeper.GetBondedPool(ctx) +// oldBonded := bk.GetAllBalances(ctx, bondedPool.GetAddress()) +// err = bk.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) +// require.NoError(t, err) +// keeper.supplyKeeper.SetModuleAccount(ctx, bondedPool) +// +// // create a second delegation to this validator +// keeper.DeleteValidatorByPowerIndex(ctx, validator) +// validator, issuedShares = validator.AddTokensFromDel(delTokens) +// require.Equal(t, delTokens, issuedShares.RoundInt()) +// validator = TestingUpdateValidator(keeper, ctx, validator, true) +// require.True(t, validator.IsBonded()) +// delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares) +// keeper.SetDelegation(ctx, delegation) +// +// ctx = ctx.WithBlockHeight(10) +// ctx = ctx.WithBlockTime(time.Unix(333, 0)) +// +// // unbond the all self-delegation to put validator in unbonding state +// _, err = keeper.Undelegate(ctx, val0AccAddr, addrVals[0], valTokens.ToDec()) +// require.NoError(t, err) +// +// // end block +// updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) +// require.Equal(t, 1, len(updates)) +// +// validator, found := keeper.GetValidator(ctx, addrVals[0]) +// require.True(t, found) +// require.Equal(t, ctx.BlockHeight(), validator.UnbondingHeight) +// params := keeper.GetParams(ctx) +// require.True(t, ctx.BlockHeader().Time.Add(params.UnbondingTime).Equal(validator.UnbondingTime)) +// +// // unbond the validator +// ctx = ctx.WithBlockTime(validator.UnbondingTime) +// keeper.UnbondAllMatureValidatorQueue(ctx) +// +// // Make sure validator is still in state because there is still an outstanding delegation +// validator, found = keeper.GetValidator(ctx, addrVals[0]) +// require.True(t, found) +// require.Equal(t, validator.Status, sdk.Unbonded) +// +// // unbond some of the other delegation's shares +// unbondTokens := sdk.TokensFromConsensusPower(6) +// _, err = keeper.Undelegate(ctx, addrDels[0], addrVals[0], unbondTokens.ToDec()) +// require.NoError(t, err) +// +// // unbond rest of the other delegation's shares +// remainingTokens := delTokens.Sub(unbondTokens) +// _, err = keeper.Undelegate(ctx, addrDels[0], addrVals[0], remainingTokens.ToDec()) +// require.NoError(t, err) +// +// // now validator should now be deleted from state +// validator, found = keeper.GetValidator(ctx, addrVals[0]) +// require.False(t, found, "%v", validator) +//} +// +//func TestUnbondingAllDelegationFromValidator(t *testing.T) { +// ctx, _, bk, keeper, _ := CreateTestInput(t, false, 0) +// delTokens := sdk.TokensFromConsensusPower(10) +// delCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), delTokens)) +// +// // add bonded tokens to pool for delegations +// notBondedPool := keeper.GetNotBondedPool(ctx) +// oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) +// err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(delCoins...)) +// require.NoError(t, err) +// keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) +// +// //create a validator with a self-delegation +// validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) +// +// valTokens := sdk.TokensFromConsensusPower(10) +// validator, issuedShares := validator.AddTokensFromDel(valTokens) +// require.Equal(t, valTokens, issuedShares.RoundInt()) +// +// validator = TestingUpdateValidator(keeper, ctx, validator, true) +// require.True(t, validator.IsBonded()) +// val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) +// +// selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares) +// keeper.SetDelegation(ctx, selfDelegation) +// +// // create a second delegation to this validator +// keeper.DeleteValidatorByPowerIndex(ctx, validator) +// validator, issuedShares = validator.AddTokensFromDel(delTokens) +// require.Equal(t, delTokens, issuedShares.RoundInt()) +// +// bondedPool := keeper.GetBondedPool(ctx) +// oldBonded := bk.GetAllBalances(ctx, bondedPool.GetAddress()) +// err = bk.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) +// require.NoError(t, err) +// keeper.supplyKeeper.SetModuleAccount(ctx, bondedPool) +// +// validator = TestingUpdateValidator(keeper, ctx, validator, true) +// require.True(t, validator.IsBonded()) +// +// delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares) +// keeper.SetDelegation(ctx, delegation) +// +// ctx = ctx.WithBlockHeight(10) +// ctx = ctx.WithBlockTime(time.Unix(333, 0)) +// +// // unbond the all self-delegation to put validator in unbonding state +// _, err = keeper.Undelegate(ctx, val0AccAddr, addrVals[0], valTokens.ToDec()) +// require.NoError(t, err) +// +// // end block +// updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) +// require.Equal(t, 1, len(updates)) +// +// // unbond all the remaining delegation +// _, err = keeper.Undelegate(ctx, addrDels[0], addrVals[0], delTokens.ToDec()) +// require.NoError(t, err) +// +// // validator should still be in state and still be in unbonding state +// validator, found := keeper.GetValidator(ctx, addrVals[0]) +// require.True(t, found) +// require.Equal(t, validator.Status, sdk.Unbonding) +// +// // unbond the validator +// ctx = ctx.WithBlockTime(validator.UnbondingTime) +// keeper.UnbondAllMatureValidatorQueue(ctx) +// +// // validator should now be deleted from state +// _, found = keeper.GetValidator(ctx, addrVals[0]) +// require.False(t, found) +//} +// +//// Make sure that that the retrieving the delegations doesn't affect the state +//func TestGetRedelegationsFromSrcValidator(t *testing.T) { +// ctx, _, _, keeper, _ := CreateTestInput(t, false, 0) +// +// rd := types.NewRedelegation(addrDels[0], addrVals[0], addrVals[1], 0, +// time.Unix(0, 0), sdk.NewInt(5), +// sdk.NewDec(5)) +// +// // set and retrieve a record +// keeper.SetRedelegation(ctx, rd) +// resBond, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) +// require.True(t, found) +// +// // get the redelegations one time +// redelegations := keeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0]) +// require.Equal(t, 1, len(redelegations)) +// require.True(t, redelegations[0].Equal(resBond)) +// +// // get the redelegations a second time, should be exactly the same +// redelegations = keeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0]) +// require.Equal(t, 1, len(redelegations)) +// require.True(t, redelegations[0].Equal(resBond)) +//} +// +//// tests Get/Set/Remove/Has UnbondingDelegation +//func TestRedelegation(t *testing.T) { +// ctx, _, _, keeper, _ := CreateTestInput(t, false, 0) +// +// rd := types.NewRedelegation(addrDels[0], addrVals[0], addrVals[1], 0, +// time.Unix(0, 0), sdk.NewInt(5), +// sdk.NewDec(5)) +// +// // test shouldn't have and redelegations +// has := keeper.HasReceivingRedelegation(ctx, addrDels[0], addrVals[1]) +// require.False(t, has) +// +// // set and retrieve a record +// keeper.SetRedelegation(ctx, rd) +// resRed, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) +// require.True(t, found) +// +// redelegations := keeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0]) +// require.Equal(t, 1, len(redelegations)) +// require.True(t, redelegations[0].Equal(resRed)) +// +// redelegations = keeper.GetRedelegations(ctx, addrDels[0], 5) +// require.Equal(t, 1, len(redelegations)) +// require.True(t, redelegations[0].Equal(resRed)) +// +// redelegations = keeper.GetAllRedelegations(ctx, addrDels[0], nil, nil) +// require.Equal(t, 1, len(redelegations)) +// require.True(t, redelegations[0].Equal(resRed)) +// +// // check if has the redelegation +// has = keeper.HasReceivingRedelegation(ctx, addrDels[0], addrVals[1]) +// require.True(t, has) +// +// // modify a records, save, and retrieve +// rd.Entries[0].SharesDst = sdk.NewDec(21) +// keeper.SetRedelegation(ctx, rd) +// +// resRed, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) +// require.True(t, found) +// require.True(t, rd.Equal(resRed)) +// +// redelegations = keeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0]) +// require.Equal(t, 1, len(redelegations)) +// require.True(t, redelegations[0].Equal(resRed)) +// +// redelegations = keeper.GetRedelegations(ctx, addrDels[0], 5) +// require.Equal(t, 1, len(redelegations)) +// require.True(t, redelegations[0].Equal(resRed)) +// +// // delete a record +// keeper.RemoveRedelegation(ctx, rd) +// _, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) +// require.False(t, found) +// +// redelegations = keeper.GetRedelegations(ctx, addrDels[0], 5) +// require.Equal(t, 0, len(redelegations)) +// +// redelegations = keeper.GetAllRedelegations(ctx, addrDels[0], nil, nil) +// require.Equal(t, 0, len(redelegations)) +//} +// +//func TestRedelegateToSameValidator(t *testing.T) { +// ctx, _, bk, keeper, _ := CreateTestInput(t, false, 0) +// valTokens := sdk.TokensFromConsensusPower(10) +// startCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), valTokens)) +// +// // add bonded tokens to pool for delegations +// notBondedPool := keeper.GetNotBondedPool(ctx) +// oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) +// err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(startCoins...)) +// require.NoError(t, err) +// keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) +// +// // create a validator with a self-delegation +// validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) +// validator, issuedShares := validator.AddTokensFromDel(valTokens) +// require.Equal(t, valTokens, issuedShares.RoundInt()) +// validator = TestingUpdateValidator(keeper, ctx, validator, true) +// require.True(t, validator.IsBonded()) +// +// val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) +// selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares) +// keeper.SetDelegation(ctx, selfDelegation) +// +// _, err = keeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[0], sdk.NewDec(5)) +// require.Error(t, err) +//} +// +//func TestRedelegationMaxEntries(t *testing.T) { +// ctx, _, bk, keeper, _ := CreateTestInput(t, false, 0) +// startTokens := sdk.TokensFromConsensusPower(20) +// startCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), startTokens)) +// +// // add bonded tokens to pool for delegations +// notBondedPool := keeper.GetNotBondedPool(ctx) +// oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) +// err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(startCoins...)) +// require.NoError(t, err) +// keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) +// +// // create a validator with a self-delegation +// validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) +// valTokens := sdk.TokensFromConsensusPower(10) +// validator, issuedShares := validator.AddTokensFromDel(valTokens) +// require.Equal(t, valTokens, issuedShares.RoundInt()) +// validator = TestingUpdateValidator(keeper, ctx, validator, true) +// val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) +// selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares) +// keeper.SetDelegation(ctx, selfDelegation) +// +// // create a second validator +// validator2 := types.NewValidator(addrVals[1], PKs[1], types.Description{}) +// validator2, issuedShares = validator2.AddTokensFromDel(valTokens) +// require.Equal(t, valTokens, issuedShares.RoundInt()) +// +// validator2 = TestingUpdateValidator(keeper, ctx, validator2, true) +// require.Equal(t, sdk.Bonded, validator2.Status) +// +// maxEntries := keeper.MaxEntries(ctx) +// +// // redelegations should pass +// var completionTime time.Time +// for i := uint32(0); i < maxEntries; i++ { +// var err error +// completionTime, err = keeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1], sdk.NewDec(1)) +// require.NoError(t, err) +// } +// +// // an additional redelegation should fail due to max entries +// _, err = keeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1], sdk.NewDec(1)) +// require.Error(t, err) +// +// // mature redelegations +// ctx = ctx.WithBlockTime(completionTime) +// err = keeper.CompleteRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1]) +// require.NoError(t, err) +// +// // redelegation should work again +// _, err = keeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1], sdk.NewDec(1)) +// require.NoError(t, err) +//} +// +//func TestRedelegateSelfDelegation(t *testing.T) { +// ctx, _, bk, keeper, _ := CreateTestInput(t, false, 0) +// startTokens := sdk.TokensFromConsensusPower(30) +// startCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), startTokens)) +// +// // add bonded tokens to pool for delegations +// notBondedPool := keeper.GetNotBondedPool(ctx) +// oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) +// err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(startCoins...)) +// require.NoError(t, err) +// keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) +// +// //create a validator with a self-delegation +// validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) +// valTokens := sdk.TokensFromConsensusPower(10) +// validator, issuedShares := validator.AddTokensFromDel(valTokens) +// require.Equal(t, valTokens, issuedShares.RoundInt()) +// +// validator = TestingUpdateValidator(keeper, ctx, validator, true) +// +// val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) +// selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares) +// keeper.SetDelegation(ctx, selfDelegation) +// +// // create a second validator +// validator2 := types.NewValidator(addrVals[1], PKs[1], types.Description{}) +// validator2, issuedShares = validator2.AddTokensFromDel(valTokens) +// require.Equal(t, valTokens, issuedShares.RoundInt()) +// validator2 = TestingUpdateValidator(keeper, ctx, validator2, true) +// require.Equal(t, sdk.Bonded, validator2.Status) +// +// // create a second delegation to validator 1 +// delTokens := sdk.TokensFromConsensusPower(10) +// validator, issuedShares = validator.AddTokensFromDel(delTokens) +// require.Equal(t, delTokens, issuedShares.RoundInt()) +// validator = TestingUpdateValidator(keeper, ctx, validator, true) +// +// delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares) +// keeper.SetDelegation(ctx, delegation) +// +// _, err = keeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1], delTokens.ToDec()) +// require.NoError(t, err) +// +// // end block +// updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) +// require.Equal(t, 2, len(updates)) +// +// validator, found := keeper.GetValidator(ctx, addrVals[0]) +// require.True(t, found) +// require.Equal(t, valTokens, validator.Tokens) +// require.Equal(t, sdk.Unbonding, validator.Status) +//} +// +//func TestRedelegateFromUnbondingValidator(t *testing.T) { +// ctx, _, bk, keeper, _ := CreateTestInput(t, false, 0) +// startTokens := sdk.TokensFromConsensusPower(30) +// startCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), startTokens)) +// +// // add bonded tokens to pool for delegations +// notBondedPool := keeper.GetNotBondedPool(ctx) +// oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) +// err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(startCoins...)) +// require.NoError(t, err) +// keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) +// +// //create a validator with a self-delegation +// validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) +// +// valTokens := sdk.TokensFromConsensusPower(10) +// validator, issuedShares := validator.AddTokensFromDel(valTokens) +// require.Equal(t, valTokens, issuedShares.RoundInt()) +// validator = TestingUpdateValidator(keeper, ctx, validator, true) +// val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) +// selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares) +// keeper.SetDelegation(ctx, selfDelegation) +// +// // create a second delegation to this validator +// keeper.DeleteValidatorByPowerIndex(ctx, validator) +// delTokens := sdk.TokensFromConsensusPower(10) +// validator, issuedShares = validator.AddTokensFromDel(delTokens) +// require.Equal(t, delTokens, issuedShares.RoundInt()) +// validator = TestingUpdateValidator(keeper, ctx, validator, true) +// delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares) +// keeper.SetDelegation(ctx, delegation) +// +// // create a second validator +// validator2 := types.NewValidator(addrVals[1], PKs[1], types.Description{}) +// validator2, issuedShares = validator2.AddTokensFromDel(valTokens) +// require.Equal(t, valTokens, issuedShares.RoundInt()) +// validator2 = TestingUpdateValidator(keeper, ctx, validator2, true) +// +// header := ctx.BlockHeader() +// blockHeight := int64(10) +// header.Height = blockHeight +// blockTime := time.Unix(333, 0) +// header.Time = blockTime +// ctx = ctx.WithBlockHeader(header) +// +// // unbond the all self-delegation to put validator in unbonding state +// _, err = keeper.Undelegate(ctx, val0AccAddr, addrVals[0], delTokens.ToDec()) +// require.NoError(t, err) +// +// // end block +// updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) +// require.Equal(t, 1, len(updates)) +// +// validator, found := keeper.GetValidator(ctx, addrVals[0]) +// require.True(t, found) +// require.Equal(t, blockHeight, validator.UnbondingHeight) +// params := keeper.GetParams(ctx) +// require.True(t, blockTime.Add(params.UnbondingTime).Equal(validator.UnbondingTime)) +// +// //change the context +// header = ctx.BlockHeader() +// blockHeight2 := int64(20) +// header.Height = blockHeight2 +// blockTime2 := time.Unix(444, 0) +// header.Time = blockTime2 +// ctx = ctx.WithBlockHeader(header) +// +// // unbond some of the other delegation's shares +// redelegateTokens := sdk.TokensFromConsensusPower(6) +// _, err = keeper.BeginRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1], redelegateTokens.ToDec()) +// require.NoError(t, err) +// +// // retrieve the unbonding delegation +// ubd, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) +// require.True(t, found) +// require.Len(t, ubd.Entries, 1) +// assert.Equal(t, blockHeight, ubd.Entries[0].CreationHeight) +// assert.True(t, blockTime.Add(params.UnbondingTime).Equal(ubd.Entries[0].CompletionTime)) +//} +// +//func TestRedelegateFromUnbondedValidator(t *testing.T) { +// ctx, _, bk, keeper, _ := CreateTestInput(t, false, 0) +// startTokens := sdk.TokensFromConsensusPower(30) +// startCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), startTokens)) +// +// // add bonded tokens to pool for delegations +// notBondedPool := keeper.GetNotBondedPool(ctx) +// oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) +// err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(startCoins...)) +// require.NoError(t, err) +// keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) +// +// //create a validator with a self-delegation +// validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) +// +// valTokens := sdk.TokensFromConsensusPower(10) +// validator, issuedShares := validator.AddTokensFromDel(valTokens) +// require.Equal(t, valTokens, issuedShares.RoundInt()) +// validator = TestingUpdateValidator(keeper, ctx, validator, true) +// val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) +// selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares) +// keeper.SetDelegation(ctx, selfDelegation) +// +// // create a second delegation to this validator +// keeper.DeleteValidatorByPowerIndex(ctx, validator) +// delTokens := sdk.TokensFromConsensusPower(10) +// validator, issuedShares = validator.AddTokensFromDel(delTokens) +// require.Equal(t, delTokens, issuedShares.RoundInt()) +// validator = TestingUpdateValidator(keeper, ctx, validator, true) +// delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares) +// keeper.SetDelegation(ctx, delegation) +// +// // create a second validator +// validator2 := types.NewValidator(addrVals[1], PKs[1], types.Description{}) +// validator2, issuedShares = validator2.AddTokensFromDel(valTokens) +// require.Equal(t, valTokens, issuedShares.RoundInt()) +// validator2 = TestingUpdateValidator(keeper, ctx, validator2, true) +// require.Equal(t, sdk.Bonded, validator2.Status) +// +// ctx = ctx.WithBlockHeight(10) +// ctx = ctx.WithBlockTime(time.Unix(333, 0)) +// +// // unbond the all self-delegation to put validator in unbonding state +// _, err = keeper.Undelegate(ctx, val0AccAddr, addrVals[0], delTokens.ToDec()) +// require.NoError(t, err) +// +// // end block +// updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) +// require.Equal(t, 1, len(updates)) +// +// validator, found := keeper.GetValidator(ctx, addrVals[0]) +// require.True(t, found) +// require.Equal(t, ctx.BlockHeight(), validator.UnbondingHeight) +// params := keeper.GetParams(ctx) +// require.True(t, ctx.BlockHeader().Time.Add(params.UnbondingTime).Equal(validator.UnbondingTime)) +// +// // unbond the validator +// keeper.unbondingToUnbonded(ctx, validator) +// +// // redelegate some of the delegation's shares +// redelegationTokens := sdk.TokensFromConsensusPower(6) +// _, err = keeper.BeginRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1], redelegationTokens.ToDec()) +// require.NoError(t, err) +// +// // no red should have been found +// red, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) +// require.False(t, found, "%v", red) +//} diff --git a/x/staking/keeper/old_delegation_test.go b/x/staking/keeper/old_delegation_test.go new file mode 100644 index 000000000..2c83dd757 --- /dev/null +++ b/x/staking/keeper/old_delegation_test.go @@ -0,0 +1,765 @@ +package keeper + +import ( + "testing" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/staking/types" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestUnbondingDelegationsMaxEntries(t *testing.T) { + ctx, _, bk, keeper, _ := CreateTestInput(t, false, 1) + startTokens := sdk.TokensFromConsensusPower(10) + + bondDenom := keeper.BondDenom(ctx) + notBondedPool := keeper.GetNotBondedPool(ctx) + + err := bk.SetBalances(ctx, notBondedPool.GetAddress(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens))) + require.NoError(t, err) + keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) + + // create a validator and a delegator to that validator + validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) + + validator, issuedShares := validator.AddTokensFromDel(startTokens) + require.Equal(t, startTokens, issuedShares.RoundInt()) + + validator = TestingUpdateValidator(keeper, ctx, validator, true) + require.True(sdk.IntEq(t, startTokens, validator.BondedTokens())) + require.True(t, validator.IsBonded()) + + delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares) + keeper.SetDelegation(ctx, delegation) + + maxEntries := keeper.MaxEntries(ctx) + + oldBonded := bk.GetBalance(ctx, keeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount + oldNotBonded := bk.GetBalance(ctx, keeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount + + // should all pass + var completionTime time.Time + for i := uint32(0); i < maxEntries; i++ { + var err error + completionTime, err = keeper.Undelegate(ctx, addrDels[0], addrVals[0], sdk.NewDec(1)) + require.NoError(t, err) + } + + newBonded := bk.GetBalance(ctx, keeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount + newNotBonded := bk.GetBalance(ctx, keeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount + require.True(sdk.IntEq(t, newBonded, oldBonded.SubRaw(int64(maxEntries)))) + require.True(sdk.IntEq(t, newNotBonded, oldNotBonded.AddRaw(int64(maxEntries)))) + + oldBonded = bk.GetBalance(ctx, keeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount + oldNotBonded = bk.GetBalance(ctx, keeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount + + // an additional unbond should fail due to max entries + _, err = keeper.Undelegate(ctx, addrDels[0], addrVals[0], sdk.NewDec(1)) + require.Error(t, err) + + newBonded = bk.GetBalance(ctx, keeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount + newNotBonded = bk.GetBalance(ctx, keeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount + + require.True(sdk.IntEq(t, newBonded, oldBonded)) + require.True(sdk.IntEq(t, newNotBonded, oldNotBonded)) + + // mature unbonding delegations + ctx = ctx.WithBlockTime(completionTime) + err = keeper.CompleteUnbonding(ctx, addrDels[0], addrVals[0]) + require.NoError(t, err) + + newBonded = bk.GetBalance(ctx, keeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount + newNotBonded = bk.GetBalance(ctx, keeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount + require.True(sdk.IntEq(t, newBonded, oldBonded)) + require.True(sdk.IntEq(t, newNotBonded, oldNotBonded.SubRaw(int64(maxEntries)))) + + oldNotBonded = bk.GetBalance(ctx, keeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount + + // unbonding should work again + _, err = keeper.Undelegate(ctx, addrDels[0], addrVals[0], sdk.NewDec(1)) + require.NoError(t, err) + + newBonded = bk.GetBalance(ctx, keeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount + newNotBonded = bk.GetBalance(ctx, keeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount + require.True(sdk.IntEq(t, newBonded, oldBonded.SubRaw(1))) + require.True(sdk.IntEq(t, newNotBonded, oldNotBonded.AddRaw(1))) +} + +// test undelegating self delegation from a validator pushing it below MinSelfDelegation +// shift it from the bonded to unbonding state and jailed +func TestUndelegateSelfDelegationBelowMinSelfDelegation(t *testing.T) { + ctx, _, bk, keeper, _ := CreateTestInput(t, false, 0) + delTokens := sdk.TokensFromConsensusPower(10) + delCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), delTokens)) + + //create a validator with a self-delegation + validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) + + validator.MinSelfDelegation = delTokens + validator, issuedShares := validator.AddTokensFromDel(delTokens) + require.Equal(t, delTokens, issuedShares.RoundInt()) + + // add bonded tokens to pool for delegations + notBondedPool := keeper.GetNotBondedPool(ctx) + oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) + err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(delCoins...)) + require.NoError(t, err) + keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) + + validator = TestingUpdateValidator(keeper, ctx, validator, true) + require.True(t, validator.IsBonded()) + + selfDelegation := types.NewDelegation(sdk.AccAddress(addrVals[0].Bytes()), addrVals[0], issuedShares) + keeper.SetDelegation(ctx, selfDelegation) + + // add bonded tokens to pool for delegations + bondedPool := keeper.GetBondedPool(ctx) + oldBonded := bk.GetAllBalances(ctx, bondedPool.GetAddress()) + err = bk.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) + require.NoError(t, err) + keeper.supplyKeeper.SetModuleAccount(ctx, bondedPool) + + // create a second delegation to this validator + keeper.DeleteValidatorByPowerIndex(ctx, validator) + validator, issuedShares = validator.AddTokensFromDel(delTokens) + require.True(t, validator.IsBonded()) + require.Equal(t, delTokens, issuedShares.RoundInt()) + + // add bonded tokens to pool for delegations + oldBonded = bk.GetAllBalances(ctx, bondedPool.GetAddress()) + err = bk.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) + require.NoError(t, err) + keeper.supplyKeeper.SetModuleAccount(ctx, bondedPool) + + validator = TestingUpdateValidator(keeper, ctx, validator, true) + delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares) + keeper.SetDelegation(ctx, delegation) + + val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) + _, err = keeper.Undelegate(ctx, val0AccAddr, addrVals[0], sdk.TokensFromConsensusPower(6).ToDec()) + require.NoError(t, err) + + // end block + updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) + require.Equal(t, 1, len(updates)) + + validator, found := keeper.GetValidator(ctx, addrVals[0]) + require.True(t, found) + require.Equal(t, sdk.TokensFromConsensusPower(14), validator.Tokens) + require.Equal(t, sdk.Unbonding, validator.Status) + require.True(t, validator.Jailed) +} + +func TestUndelegateFromUnbondingValidator(t *testing.T) { + ctx, _, bk, keeper, _ := CreateTestInput(t, false, 0) + delTokens := sdk.TokensFromConsensusPower(10) + delCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), delTokens)) + + //create a validator with a self-delegation + validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) + + validator, issuedShares := validator.AddTokensFromDel(delTokens) + require.Equal(t, delTokens, issuedShares.RoundInt()) + + // add bonded tokens to pool for delegations + notBondedPool := keeper.GetNotBondedPool(ctx) + oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) + err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(delCoins...)) + require.NoError(t, err) + keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) + + validator = TestingUpdateValidator(keeper, ctx, validator, true) + require.True(t, validator.IsBonded()) + + selfDelegation := types.NewDelegation(sdk.AccAddress(addrVals[0].Bytes()), addrVals[0], issuedShares) + keeper.SetDelegation(ctx, selfDelegation) + + bondedPool := keeper.GetBondedPool(ctx) + oldBonded := bk.GetAllBalances(ctx, bondedPool.GetAddress()) + err = bk.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) + require.NoError(t, err) + keeper.supplyKeeper.SetModuleAccount(ctx, bondedPool) + + // create a second delegation to this validator + keeper.DeleteValidatorByPowerIndex(ctx, validator) + + validator, issuedShares = validator.AddTokensFromDel(delTokens) + require.Equal(t, delTokens, issuedShares.RoundInt()) + + oldBonded = bk.GetAllBalances(ctx, bondedPool.GetAddress()) + err = bk.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) + require.NoError(t, err) + keeper.supplyKeeper.SetModuleAccount(ctx, bondedPool) + + validator = TestingUpdateValidator(keeper, ctx, validator, true) + delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares) + keeper.SetDelegation(ctx, delegation) + + oldBonded = bk.GetAllBalances(ctx, bondedPool.GetAddress()) + err = bk.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) + require.NoError(t, err) + keeper.supplyKeeper.SetModuleAccount(ctx, bondedPool) + + header := ctx.BlockHeader() + blockHeight := int64(10) + header.Height = blockHeight + blockTime := time.Unix(333, 0) + header.Time = blockTime + ctx = ctx.WithBlockHeader(header) + + // unbond the all self-delegation to put validator in unbonding state + val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) + _, err = keeper.Undelegate(ctx, val0AccAddr, addrVals[0], delTokens.ToDec()) + require.NoError(t, err) + + // end block + updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) + require.Equal(t, 1, len(updates)) + + validator, found := keeper.GetValidator(ctx, addrVals[0]) + require.True(t, found) + require.Equal(t, blockHeight, validator.UnbondingHeight) + params := keeper.GetParams(ctx) + require.True(t, blockTime.Add(params.UnbondingTime).Equal(validator.UnbondingTime)) + + blockHeight2 := int64(20) + blockTime2 := time.Unix(444, 0).UTC() + ctx = ctx.WithBlockHeight(blockHeight2) + ctx = ctx.WithBlockTime(blockTime2) + + // unbond some of the other delegation's shares + _, err = keeper.Undelegate(ctx, addrDels[0], addrVals[0], sdk.NewDec(6)) + require.NoError(t, err) + + // retrieve the unbonding delegation + ubd, found := keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0]) + require.True(t, found) + require.Len(t, ubd.Entries, 1) + require.True(t, ubd.Entries[0].Balance.Equal(sdk.NewInt(6))) + assert.Equal(t, blockHeight2, ubd.Entries[0].CreationHeight) + assert.True(t, blockTime2.Add(params.UnbondingTime).Equal(ubd.Entries[0].CompletionTime)) +} + +func TestUndelegateFromUnbondedValidator(t *testing.T) { + ctx, _, bk, keeper, _ := CreateTestInput(t, false, 1) + delTokens := sdk.TokensFromConsensusPower(10) + delCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), delTokens)) + + // add bonded tokens to pool for delegations + notBondedPool := keeper.GetNotBondedPool(ctx) + oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) + err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(delCoins...)) + require.NoError(t, err) + keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) + + // create a validator with a self-delegation + validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) + + valTokens := sdk.TokensFromConsensusPower(10) + validator, issuedShares := validator.AddTokensFromDel(valTokens) + require.Equal(t, valTokens, issuedShares.RoundInt()) + validator = TestingUpdateValidator(keeper, ctx, validator, true) + require.True(t, validator.IsBonded()) + + val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) + selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares) + keeper.SetDelegation(ctx, selfDelegation) + + bondedPool := keeper.GetBondedPool(ctx) + oldBonded := bk.GetAllBalances(ctx, bondedPool.GetAddress()) + err = bk.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) + require.NoError(t, err) + keeper.supplyKeeper.SetModuleAccount(ctx, bondedPool) + + // create a second delegation to this validator + keeper.DeleteValidatorByPowerIndex(ctx, validator) + validator, issuedShares = validator.AddTokensFromDel(delTokens) + require.Equal(t, delTokens, issuedShares.RoundInt()) + validator = TestingUpdateValidator(keeper, ctx, validator, true) + require.True(t, validator.IsBonded()) + delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares) + keeper.SetDelegation(ctx, delegation) + + ctx = ctx.WithBlockHeight(10) + ctx = ctx.WithBlockTime(time.Unix(333, 0)) + + // unbond the all self-delegation to put validator in unbonding state + _, err = keeper.Undelegate(ctx, val0AccAddr, addrVals[0], valTokens.ToDec()) + require.NoError(t, err) + + // end block + updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) + require.Equal(t, 1, len(updates)) + + validator, found := keeper.GetValidator(ctx, addrVals[0]) + require.True(t, found) + require.Equal(t, ctx.BlockHeight(), validator.UnbondingHeight) + params := keeper.GetParams(ctx) + require.True(t, ctx.BlockHeader().Time.Add(params.UnbondingTime).Equal(validator.UnbondingTime)) + + // unbond the validator + ctx = ctx.WithBlockTime(validator.UnbondingTime) + keeper.UnbondAllMatureValidatorQueue(ctx) + + // Make sure validator is still in state because there is still an outstanding delegation + validator, found = keeper.GetValidator(ctx, addrVals[0]) + require.True(t, found) + require.Equal(t, validator.Status, sdk.Unbonded) + + // unbond some of the other delegation's shares + unbondTokens := sdk.TokensFromConsensusPower(6) + _, err = keeper.Undelegate(ctx, addrDels[0], addrVals[0], unbondTokens.ToDec()) + require.NoError(t, err) + + // unbond rest of the other delegation's shares + remainingTokens := delTokens.Sub(unbondTokens) + _, err = keeper.Undelegate(ctx, addrDels[0], addrVals[0], remainingTokens.ToDec()) + require.NoError(t, err) + + // now validator should now be deleted from state + validator, found = keeper.GetValidator(ctx, addrVals[0]) + require.False(t, found, "%v", validator) +} + +func TestUnbondingAllDelegationFromValidator(t *testing.T) { + ctx, _, bk, keeper, _ := CreateTestInput(t, false, 0) + delTokens := sdk.TokensFromConsensusPower(10) + delCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), delTokens)) + + // add bonded tokens to pool for delegations + notBondedPool := keeper.GetNotBondedPool(ctx) + oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) + err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(delCoins...)) + require.NoError(t, err) + keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) + + //create a validator with a self-delegation + validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) + + valTokens := sdk.TokensFromConsensusPower(10) + validator, issuedShares := validator.AddTokensFromDel(valTokens) + require.Equal(t, valTokens, issuedShares.RoundInt()) + + validator = TestingUpdateValidator(keeper, ctx, validator, true) + require.True(t, validator.IsBonded()) + val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) + + selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares) + keeper.SetDelegation(ctx, selfDelegation) + + // create a second delegation to this validator + keeper.DeleteValidatorByPowerIndex(ctx, validator) + validator, issuedShares = validator.AddTokensFromDel(delTokens) + require.Equal(t, delTokens, issuedShares.RoundInt()) + + bondedPool := keeper.GetBondedPool(ctx) + oldBonded := bk.GetAllBalances(ctx, bondedPool.GetAddress()) + err = bk.SetBalances(ctx, bondedPool.GetAddress(), oldBonded.Add(delCoins...)) + require.NoError(t, err) + keeper.supplyKeeper.SetModuleAccount(ctx, bondedPool) + + validator = TestingUpdateValidator(keeper, ctx, validator, true) + require.True(t, validator.IsBonded()) + + delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares) + keeper.SetDelegation(ctx, delegation) + + ctx = ctx.WithBlockHeight(10) + ctx = ctx.WithBlockTime(time.Unix(333, 0)) + + // unbond the all self-delegation to put validator in unbonding state + _, err = keeper.Undelegate(ctx, val0AccAddr, addrVals[0], valTokens.ToDec()) + require.NoError(t, err) + + // end block + updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) + require.Equal(t, 1, len(updates)) + + // unbond all the remaining delegation + _, err = keeper.Undelegate(ctx, addrDels[0], addrVals[0], delTokens.ToDec()) + require.NoError(t, err) + + // validator should still be in state and still be in unbonding state + validator, found := keeper.GetValidator(ctx, addrVals[0]) + require.True(t, found) + require.Equal(t, validator.Status, sdk.Unbonding) + + // unbond the validator + ctx = ctx.WithBlockTime(validator.UnbondingTime) + keeper.UnbondAllMatureValidatorQueue(ctx) + + // validator should now be deleted from state + _, found = keeper.GetValidator(ctx, addrVals[0]) + require.False(t, found) +} + +// Make sure that that the retrieving the delegations doesn't affect the state +func TestGetRedelegationsFromSrcValidator(t *testing.T) { + ctx, _, _, keeper, _ := CreateTestInput(t, false, 0) + + rd := types.NewRedelegation(addrDels[0], addrVals[0], addrVals[1], 0, + time.Unix(0, 0), sdk.NewInt(5), + sdk.NewDec(5)) + + // set and retrieve a record + keeper.SetRedelegation(ctx, rd) + resBond, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) + require.True(t, found) + + // get the redelegations one time + redelegations := keeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0]) + require.Equal(t, 1, len(redelegations)) + require.True(t, redelegations[0].Equal(resBond)) + + // get the redelegations a second time, should be exactly the same + redelegations = keeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0]) + require.Equal(t, 1, len(redelegations)) + require.True(t, redelegations[0].Equal(resBond)) +} + +// tests Get/Set/Remove/Has UnbondingDelegation +func TestRedelegation(t *testing.T) { + ctx, _, _, keeper, _ := CreateTestInput(t, false, 0) + + rd := types.NewRedelegation(addrDels[0], addrVals[0], addrVals[1], 0, + time.Unix(0, 0), sdk.NewInt(5), + sdk.NewDec(5)) + + // test shouldn't have and redelegations + has := keeper.HasReceivingRedelegation(ctx, addrDels[0], addrVals[1]) + require.False(t, has) + + // set and retrieve a record + keeper.SetRedelegation(ctx, rd) + resRed, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) + require.True(t, found) + + redelegations := keeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0]) + require.Equal(t, 1, len(redelegations)) + require.True(t, redelegations[0].Equal(resRed)) + + redelegations = keeper.GetRedelegations(ctx, addrDels[0], 5) + require.Equal(t, 1, len(redelegations)) + require.True(t, redelegations[0].Equal(resRed)) + + redelegations = keeper.GetAllRedelegations(ctx, addrDels[0], nil, nil) + require.Equal(t, 1, len(redelegations)) + require.True(t, redelegations[0].Equal(resRed)) + + // check if has the redelegation + has = keeper.HasReceivingRedelegation(ctx, addrDels[0], addrVals[1]) + require.True(t, has) + + // modify a records, save, and retrieve + rd.Entries[0].SharesDst = sdk.NewDec(21) + keeper.SetRedelegation(ctx, rd) + + resRed, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) + require.True(t, found) + require.True(t, rd.Equal(resRed)) + + redelegations = keeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0]) + require.Equal(t, 1, len(redelegations)) + require.True(t, redelegations[0].Equal(resRed)) + + redelegations = keeper.GetRedelegations(ctx, addrDels[0], 5) + require.Equal(t, 1, len(redelegations)) + require.True(t, redelegations[0].Equal(resRed)) + + // delete a record + keeper.RemoveRedelegation(ctx, rd) + _, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) + require.False(t, found) + + redelegations = keeper.GetRedelegations(ctx, addrDels[0], 5) + require.Equal(t, 0, len(redelegations)) + + redelegations = keeper.GetAllRedelegations(ctx, addrDels[0], nil, nil) + require.Equal(t, 0, len(redelegations)) +} + +func TestRedelegateToSameValidator(t *testing.T) { + ctx, _, bk, keeper, _ := CreateTestInput(t, false, 0) + valTokens := sdk.TokensFromConsensusPower(10) + startCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), valTokens)) + + // add bonded tokens to pool for delegations + notBondedPool := keeper.GetNotBondedPool(ctx) + oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) + err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(startCoins...)) + require.NoError(t, err) + keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) + + // create a validator with a self-delegation + validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) + validator, issuedShares := validator.AddTokensFromDel(valTokens) + require.Equal(t, valTokens, issuedShares.RoundInt()) + validator = TestingUpdateValidator(keeper, ctx, validator, true) + require.True(t, validator.IsBonded()) + + val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) + selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares) + keeper.SetDelegation(ctx, selfDelegation) + + _, err = keeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[0], sdk.NewDec(5)) + require.Error(t, err) +} + +func TestRedelegationMaxEntries(t *testing.T) { + ctx, _, bk, keeper, _ := CreateTestInput(t, false, 0) + startTokens := sdk.TokensFromConsensusPower(20) + startCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), startTokens)) + + // add bonded tokens to pool for delegations + notBondedPool := keeper.GetNotBondedPool(ctx) + oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) + err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(startCoins...)) + require.NoError(t, err) + keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) + + // create a validator with a self-delegation + validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) + valTokens := sdk.TokensFromConsensusPower(10) + validator, issuedShares := validator.AddTokensFromDel(valTokens) + require.Equal(t, valTokens, issuedShares.RoundInt()) + validator = TestingUpdateValidator(keeper, ctx, validator, true) + val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) + selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares) + keeper.SetDelegation(ctx, selfDelegation) + + // create a second validator + validator2 := types.NewValidator(addrVals[1], PKs[1], types.Description{}) + validator2, issuedShares = validator2.AddTokensFromDel(valTokens) + require.Equal(t, valTokens, issuedShares.RoundInt()) + + validator2 = TestingUpdateValidator(keeper, ctx, validator2, true) + require.Equal(t, sdk.Bonded, validator2.Status) + + maxEntries := keeper.MaxEntries(ctx) + + // redelegations should pass + var completionTime time.Time + for i := uint32(0); i < maxEntries; i++ { + var err error + completionTime, err = keeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1], sdk.NewDec(1)) + require.NoError(t, err) + } + + // an additional redelegation should fail due to max entries + _, err = keeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1], sdk.NewDec(1)) + require.Error(t, err) + + // mature redelegations + ctx = ctx.WithBlockTime(completionTime) + err = keeper.CompleteRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1]) + require.NoError(t, err) + + // redelegation should work again + _, err = keeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1], sdk.NewDec(1)) + require.NoError(t, err) +} + +func TestRedelegateSelfDelegation(t *testing.T) { + ctx, _, bk, keeper, _ := CreateTestInput(t, false, 0) + startTokens := sdk.TokensFromConsensusPower(30) + startCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), startTokens)) + + // add bonded tokens to pool for delegations + notBondedPool := keeper.GetNotBondedPool(ctx) + oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) + err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(startCoins...)) + require.NoError(t, err) + keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) + + //create a validator with a self-delegation + validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) + valTokens := sdk.TokensFromConsensusPower(10) + validator, issuedShares := validator.AddTokensFromDel(valTokens) + require.Equal(t, valTokens, issuedShares.RoundInt()) + + validator = TestingUpdateValidator(keeper, ctx, validator, true) + + val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) + selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares) + keeper.SetDelegation(ctx, selfDelegation) + + // create a second validator + validator2 := types.NewValidator(addrVals[1], PKs[1], types.Description{}) + validator2, issuedShares = validator2.AddTokensFromDel(valTokens) + require.Equal(t, valTokens, issuedShares.RoundInt()) + validator2 = TestingUpdateValidator(keeper, ctx, validator2, true) + require.Equal(t, sdk.Bonded, validator2.Status) + + // create a second delegation to validator 1 + delTokens := sdk.TokensFromConsensusPower(10) + validator, issuedShares = validator.AddTokensFromDel(delTokens) + require.Equal(t, delTokens, issuedShares.RoundInt()) + validator = TestingUpdateValidator(keeper, ctx, validator, true) + + delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares) + keeper.SetDelegation(ctx, delegation) + + _, err = keeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1], delTokens.ToDec()) + require.NoError(t, err) + + // end block + updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) + require.Equal(t, 2, len(updates)) + + validator, found := keeper.GetValidator(ctx, addrVals[0]) + require.True(t, found) + require.Equal(t, valTokens, validator.Tokens) + require.Equal(t, sdk.Unbonding, validator.Status) +} + +func TestRedelegateFromUnbondingValidator(t *testing.T) { + ctx, _, bk, keeper, _ := CreateTestInput(t, false, 0) + startTokens := sdk.TokensFromConsensusPower(30) + startCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), startTokens)) + + // add bonded tokens to pool for delegations + notBondedPool := keeper.GetNotBondedPool(ctx) + oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) + err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(startCoins...)) + require.NoError(t, err) + keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) + + //create a validator with a self-delegation + validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) + + valTokens := sdk.TokensFromConsensusPower(10) + validator, issuedShares := validator.AddTokensFromDel(valTokens) + require.Equal(t, valTokens, issuedShares.RoundInt()) + validator = TestingUpdateValidator(keeper, ctx, validator, true) + val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) + selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares) + keeper.SetDelegation(ctx, selfDelegation) + + // create a second delegation to this validator + keeper.DeleteValidatorByPowerIndex(ctx, validator) + delTokens := sdk.TokensFromConsensusPower(10) + validator, issuedShares = validator.AddTokensFromDel(delTokens) + require.Equal(t, delTokens, issuedShares.RoundInt()) + validator = TestingUpdateValidator(keeper, ctx, validator, true) + delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares) + keeper.SetDelegation(ctx, delegation) + + // create a second validator + validator2 := types.NewValidator(addrVals[1], PKs[1], types.Description{}) + validator2, issuedShares = validator2.AddTokensFromDel(valTokens) + require.Equal(t, valTokens, issuedShares.RoundInt()) + validator2 = TestingUpdateValidator(keeper, ctx, validator2, true) + + header := ctx.BlockHeader() + blockHeight := int64(10) + header.Height = blockHeight + blockTime := time.Unix(333, 0) + header.Time = blockTime + ctx = ctx.WithBlockHeader(header) + + // unbond the all self-delegation to put validator in unbonding state + _, err = keeper.Undelegate(ctx, val0AccAddr, addrVals[0], delTokens.ToDec()) + require.NoError(t, err) + + // end block + updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) + require.Equal(t, 1, len(updates)) + + validator, found := keeper.GetValidator(ctx, addrVals[0]) + require.True(t, found) + require.Equal(t, blockHeight, validator.UnbondingHeight) + params := keeper.GetParams(ctx) + require.True(t, blockTime.Add(params.UnbondingTime).Equal(validator.UnbondingTime)) + + //change the context + header = ctx.BlockHeader() + blockHeight2 := int64(20) + header.Height = blockHeight2 + blockTime2 := time.Unix(444, 0) + header.Time = blockTime2 + ctx = ctx.WithBlockHeader(header) + + // unbond some of the other delegation's shares + redelegateTokens := sdk.TokensFromConsensusPower(6) + _, err = keeper.BeginRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1], redelegateTokens.ToDec()) + require.NoError(t, err) + + // retrieve the unbonding delegation + ubd, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) + require.True(t, found) + require.Len(t, ubd.Entries, 1) + assert.Equal(t, blockHeight, ubd.Entries[0].CreationHeight) + assert.True(t, blockTime.Add(params.UnbondingTime).Equal(ubd.Entries[0].CompletionTime)) +} + +func TestRedelegateFromUnbondedValidator(t *testing.T) { + ctx, _, bk, keeper, _ := CreateTestInput(t, false, 0) + startTokens := sdk.TokensFromConsensusPower(30) + startCoins := sdk.NewCoins(sdk.NewCoin(keeper.BondDenom(ctx), startTokens)) + + // add bonded tokens to pool for delegations + notBondedPool := keeper.GetNotBondedPool(ctx) + oldNotBonded := bk.GetAllBalances(ctx, notBondedPool.GetAddress()) + err := bk.SetBalances(ctx, notBondedPool.GetAddress(), oldNotBonded.Add(startCoins...)) + require.NoError(t, err) + keeper.supplyKeeper.SetModuleAccount(ctx, notBondedPool) + + //create a validator with a self-delegation + validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) + + valTokens := sdk.TokensFromConsensusPower(10) + validator, issuedShares := validator.AddTokensFromDel(valTokens) + require.Equal(t, valTokens, issuedShares.RoundInt()) + validator = TestingUpdateValidator(keeper, ctx, validator, true) + val0AccAddr := sdk.AccAddress(addrVals[0].Bytes()) + selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares) + keeper.SetDelegation(ctx, selfDelegation) + + // create a second delegation to this validator + keeper.DeleteValidatorByPowerIndex(ctx, validator) + delTokens := sdk.TokensFromConsensusPower(10) + validator, issuedShares = validator.AddTokensFromDel(delTokens) + require.Equal(t, delTokens, issuedShares.RoundInt()) + validator = TestingUpdateValidator(keeper, ctx, validator, true) + delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares) + keeper.SetDelegation(ctx, delegation) + + // create a second validator + validator2 := types.NewValidator(addrVals[1], PKs[1], types.Description{}) + validator2, issuedShares = validator2.AddTokensFromDel(valTokens) + require.Equal(t, valTokens, issuedShares.RoundInt()) + validator2 = TestingUpdateValidator(keeper, ctx, validator2, true) + require.Equal(t, sdk.Bonded, validator2.Status) + + ctx = ctx.WithBlockHeight(10) + ctx = ctx.WithBlockTime(time.Unix(333, 0)) + + // unbond the all self-delegation to put validator in unbonding state + _, err = keeper.Undelegate(ctx, val0AccAddr, addrVals[0], delTokens.ToDec()) + require.NoError(t, err) + + // end block + updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx) + require.Equal(t, 1, len(updates)) + + validator, found := keeper.GetValidator(ctx, addrVals[0]) + require.True(t, found) + require.Equal(t, ctx.BlockHeight(), validator.UnbondingHeight) + params := keeper.GetParams(ctx) + require.True(t, ctx.BlockHeader().Time.Add(params.UnbondingTime).Equal(validator.UnbondingTime)) + + // unbond the validator + keeper.unbondingToUnbonded(ctx, validator) + + // redelegate some of the delegation's shares + redelegationTokens := sdk.TokensFromConsensusPower(6) + _, err = keeper.BeginRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1], redelegationTokens.ToDec()) + require.NoError(t, err) + + // no red should have been found + red, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) + require.False(t, found, "%v", red) +}