1287 lines
52 KiB
Go
1287 lines
52 KiB
Go
package staking
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
abci "github.com/tendermint/tendermint/abci/types"
|
|
"github.com/tendermint/tendermint/crypto/secp256k1"
|
|
tmtypes "github.com/tendermint/tendermint/types"
|
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
keep "github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
|
"github.com/cosmos/cosmos-sdk/x/staking/types"
|
|
)
|
|
|
|
//______________________________________________________________________
|
|
|
|
// retrieve params which are instant
|
|
func setInstantUnbondPeriod(keeper keep.Keeper, ctx sdk.Context) types.Params {
|
|
params := keeper.GetParams(ctx)
|
|
params.UnbondingTime = 0
|
|
keeper.SetParams(ctx, params)
|
|
return params
|
|
}
|
|
|
|
//______________________________________________________________________
|
|
|
|
func TestValidatorByPowerIndex(t *testing.T) {
|
|
validatorAddr, validatorAddr3 := sdk.ValAddress(keep.Addrs[0]), sdk.ValAddress(keep.Addrs[1])
|
|
|
|
initPower := int64(1000000)
|
|
initBond := sdk.TokensFromTendermintPower(initPower)
|
|
ctx, _, keeper := keep.CreateTestInput(t, false, initPower)
|
|
_ = setInstantUnbondPeriod(keeper, ctx)
|
|
|
|
// create validator
|
|
msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], initBond)
|
|
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got)
|
|
|
|
// must end-block
|
|
updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
|
require.Equal(t, 1, len(updates))
|
|
|
|
// verify the self-delegation exists
|
|
bond, found := keeper.GetDelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr)
|
|
require.True(t, found)
|
|
gotBond := bond.Shares.RoundInt()
|
|
require.Equal(t, initBond, gotBond)
|
|
|
|
// verify that the by power index exists
|
|
validator, found := keeper.GetValidator(ctx, validatorAddr)
|
|
require.True(t, found)
|
|
power := keep.GetValidatorsByPowerIndexKey(validator)
|
|
require.True(t, keep.ValidatorByPowerIndexExists(ctx, keeper, power))
|
|
|
|
// create a second validator keep it bonded
|
|
msgCreateValidator = NewTestMsgCreateValidator(validatorAddr3, keep.PKs[2], initBond)
|
|
got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got)
|
|
|
|
// must end-block
|
|
updates = keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
|
require.Equal(t, 1, len(updates))
|
|
|
|
// slash and jail the first validator
|
|
consAddr0 := sdk.ConsAddress(keep.PKs[0].Address())
|
|
keeper.Slash(ctx, consAddr0, 0, initPower, sdk.NewDecWithPrec(5, 1))
|
|
keeper.Jail(ctx, consAddr0)
|
|
keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
|
validator, found = keeper.GetValidator(ctx, validatorAddr)
|
|
require.True(t, found)
|
|
require.Equal(t, sdk.Unbonding, validator.Status) // ensure is unbonding
|
|
require.Equal(t, initBond.DivRaw(2), validator.Tokens) // ensure tokens slashed
|
|
keeper.Unjail(ctx, consAddr0)
|
|
|
|
// the old power record should have been deleted as the power changed
|
|
require.False(t, keep.ValidatorByPowerIndexExists(ctx, keeper, power))
|
|
|
|
// but the new power record should have been created
|
|
validator, found = keeper.GetValidator(ctx, validatorAddr)
|
|
require.True(t, found)
|
|
power2 := GetValidatorsByPowerIndexKey(validator)
|
|
require.True(t, keep.ValidatorByPowerIndexExists(ctx, keeper, power2))
|
|
|
|
// now the new record power index should be the same as the original record
|
|
power3 := GetValidatorsByPowerIndexKey(validator)
|
|
require.Equal(t, power2, power3)
|
|
|
|
// unbond self-delegation
|
|
msgUndelegate := NewMsgUndelegate(sdk.AccAddress(validatorAddr), validatorAddr, sdk.NewDecFromInt(initBond))
|
|
got = handleMsgUndelegate(ctx, msgUndelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
|
|
var finishTime time.Time
|
|
types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime)
|
|
ctx = ctx.WithBlockTime(finishTime)
|
|
EndBlocker(ctx, keeper)
|
|
|
|
EndBlocker(ctx, keeper)
|
|
|
|
// verify that by power key nolonger exists
|
|
_, found = keeper.GetValidator(ctx, validatorAddr)
|
|
require.False(t, found)
|
|
require.False(t, keep.ValidatorByPowerIndexExists(ctx, keeper, power3))
|
|
}
|
|
|
|
func TestDuplicatesMsgCreateValidator(t *testing.T) {
|
|
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
|
|
|
addr1, addr2 := sdk.ValAddress(keep.Addrs[0]), sdk.ValAddress(keep.Addrs[1])
|
|
pk1, pk2 := keep.PKs[0], keep.PKs[1]
|
|
|
|
valTokens := sdk.TokensFromTendermintPower(10)
|
|
msgCreateValidator1 := NewTestMsgCreateValidator(addr1, pk1, valTokens)
|
|
got := handleMsgCreateValidator(ctx, msgCreateValidator1, keeper)
|
|
require.True(t, got.IsOK(), "%v", got)
|
|
|
|
keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
|
|
|
validator, found := keeper.GetValidator(ctx, addr1)
|
|
require.True(t, found)
|
|
assert.Equal(t, sdk.Bonded, validator.Status)
|
|
assert.Equal(t, addr1, validator.OperatorAddr)
|
|
assert.Equal(t, pk1, validator.ConsPubKey)
|
|
assert.Equal(t, valTokens, validator.BondedTokens())
|
|
assert.Equal(t, sdk.NewDecFromInt(valTokens), validator.DelegatorShares)
|
|
assert.Equal(t, Description{}, validator.Description)
|
|
|
|
// two validators can't have the same operator address
|
|
msgCreateValidator2 := NewTestMsgCreateValidator(addr1, pk2, valTokens)
|
|
got = handleMsgCreateValidator(ctx, msgCreateValidator2, keeper)
|
|
require.False(t, got.IsOK(), "%v", got)
|
|
|
|
// two validators can't have the same pubkey
|
|
msgCreateValidator3 := NewTestMsgCreateValidator(addr2, pk1, valTokens)
|
|
got = handleMsgCreateValidator(ctx, msgCreateValidator3, keeper)
|
|
require.False(t, got.IsOK(), "%v", got)
|
|
|
|
// must have different pubkey and operator
|
|
msgCreateValidator4 := NewTestMsgCreateValidator(addr2, pk2, valTokens)
|
|
got = handleMsgCreateValidator(ctx, msgCreateValidator4, keeper)
|
|
require.True(t, got.IsOK(), "%v", got)
|
|
|
|
// must end-block
|
|
updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
|
require.Equal(t, 1, len(updates))
|
|
|
|
validator, found = keeper.GetValidator(ctx, addr2)
|
|
|
|
require.True(t, found)
|
|
assert.Equal(t, sdk.Bonded, validator.Status)
|
|
assert.Equal(t, addr2, validator.OperatorAddr)
|
|
assert.Equal(t, pk2, validator.ConsPubKey)
|
|
assert.True(sdk.IntEq(t, valTokens, validator.Tokens))
|
|
assert.True(sdk.DecEq(t, sdk.NewDecFromInt(valTokens), validator.DelegatorShares))
|
|
assert.Equal(t, Description{}, validator.Description)
|
|
}
|
|
|
|
func TestInvalidPubKeyTypeMsgCreateValidator(t *testing.T) {
|
|
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
|
|
|
addr := sdk.ValAddress(keep.Addrs[0])
|
|
invalidPk := secp256k1.GenPrivKey().PubKey()
|
|
|
|
// invalid pukKey type should not be allowed
|
|
msgCreateValidator := NewTestMsgCreateValidator(addr, invalidPk, sdk.NewInt(10))
|
|
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.False(t, got.IsOK(), "%v", got)
|
|
|
|
ctx = ctx.WithConsensusParams(&abci.ConsensusParams{
|
|
Validator: &abci.ValidatorParams{PubKeyTypes: []string{tmtypes.ABCIPubKeyTypeSecp256k1}},
|
|
})
|
|
|
|
got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "%v", got)
|
|
}
|
|
|
|
func TestDuplicatesMsgCreateValidatorOnBehalfOf(t *testing.T) {
|
|
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
|
|
|
validatorAddr := sdk.ValAddress(keep.Addrs[0])
|
|
delegatorAddr := keep.Addrs[1]
|
|
pk := keep.PKs[0]
|
|
valTokens := sdk.TokensFromTendermintPower(10)
|
|
msgCreateValidatorOnBehalfOf := NewTestMsgCreateValidatorOnBehalfOf(delegatorAddr, validatorAddr, pk, valTokens)
|
|
got := handleMsgCreateValidator(ctx, msgCreateValidatorOnBehalfOf, keeper)
|
|
require.True(t, got.IsOK(), "%v", got)
|
|
|
|
// must end-block
|
|
updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
|
require.Equal(t, 1, len(updates))
|
|
|
|
validator, found := keeper.GetValidator(ctx, validatorAddr)
|
|
|
|
require.True(t, found)
|
|
assert.Equal(t, sdk.Bonded, validator.Status)
|
|
assert.Equal(t, validatorAddr, validator.OperatorAddr)
|
|
assert.Equal(t, pk, validator.ConsPubKey)
|
|
assert.True(sdk.IntEq(t, valTokens, validator.Tokens))
|
|
assert.True(sdk.DecEq(t, sdk.NewDecFromInt(valTokens), validator.DelegatorShares))
|
|
assert.Equal(t, Description{}, validator.Description)
|
|
|
|
// one validator cannot be created twice even from different delegator
|
|
msgCreateValidatorOnBehalfOf.DelegatorAddr = keep.Addrs[2]
|
|
msgCreateValidatorOnBehalfOf.PubKey = keep.PKs[1]
|
|
got = handleMsgCreateValidator(ctx, msgCreateValidatorOnBehalfOf, keeper)
|
|
require.False(t, got.IsOK(), "%v", got)
|
|
}
|
|
|
|
func TestLegacyValidatorDelegations(t *testing.T) {
|
|
ctx, _, keeper := keep.CreateTestInput(t, false, int64(1000))
|
|
setInstantUnbondPeriod(keeper, ctx)
|
|
|
|
bondAmount := sdk.TokensFromTendermintPower(10)
|
|
valAddr := sdk.ValAddress(keep.Addrs[0])
|
|
valConsPubKey, valConsAddr := keep.PKs[0], sdk.ConsAddress(keep.PKs[0].Address())
|
|
delAddr := keep.Addrs[1]
|
|
|
|
// create validator
|
|
msgCreateVal := NewTestMsgCreateValidator(valAddr, valConsPubKey, bondAmount)
|
|
got := handleMsgCreateValidator(ctx, msgCreateVal, keeper)
|
|
require.True(t, got.IsOK(), "expected create validator msg to be ok, got %v", got)
|
|
|
|
// must end-block
|
|
updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
|
require.Equal(t, 1, len(updates))
|
|
|
|
// verify the validator exists and has the correct attributes
|
|
validator, found := keeper.GetValidator(ctx, valAddr)
|
|
require.True(t, found)
|
|
require.Equal(t, sdk.Bonded, validator.Status)
|
|
require.Equal(t, bondAmount, validator.DelegatorShares.RoundInt())
|
|
require.Equal(t, bondAmount, validator.BondedTokens())
|
|
|
|
// delegate tokens to the validator
|
|
msgDelegate := NewTestMsgDelegate(delAddr, valAddr, bondAmount)
|
|
got = handleMsgDelegate(ctx, msgDelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected delegation to be ok, got %v", got)
|
|
|
|
// verify validator bonded shares
|
|
validator, found = keeper.GetValidator(ctx, valAddr)
|
|
require.True(t, found)
|
|
require.Equal(t, bondAmount.MulRaw(2), validator.DelegatorShares.RoundInt())
|
|
require.Equal(t, bondAmount.MulRaw(2), validator.BondedTokens())
|
|
|
|
// unbond validator total self-delegations (which should jail the validator)
|
|
unbondShares := sdk.TokensFromTendermintPower(10)
|
|
msgUndelegate := NewMsgUndelegate(sdk.AccAddress(valAddr), valAddr, sdk.NewDecFromInt(unbondShares))
|
|
|
|
got = handleMsgUndelegate(ctx, msgUndelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected begin unbonding validator msg to be ok, got %v", got)
|
|
|
|
var finishTime time.Time
|
|
types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime)
|
|
ctx = ctx.WithBlockTime(finishTime)
|
|
EndBlocker(ctx, keeper)
|
|
|
|
// verify the validator record still exists, is jailed, and has correct tokens
|
|
validator, found = keeper.GetValidator(ctx, valAddr)
|
|
require.True(t, found)
|
|
require.True(t, validator.Jailed)
|
|
require.Equal(t, bondAmount, validator.Tokens)
|
|
|
|
// verify delegation still exists
|
|
bond, found := keeper.GetDelegation(ctx, delAddr, valAddr)
|
|
require.True(t, found)
|
|
require.Equal(t, bondAmount, bond.Shares.RoundInt())
|
|
require.Equal(t, bondAmount, validator.DelegatorShares.RoundInt())
|
|
|
|
// verify the validator can still self-delegate
|
|
msgSelfDelegate := NewTestMsgDelegate(sdk.AccAddress(valAddr), valAddr, bondAmount)
|
|
got = handleMsgDelegate(ctx, msgSelfDelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected delegation to be ok, got %v", got)
|
|
|
|
// verify validator bonded shares
|
|
validator, found = keeper.GetValidator(ctx, valAddr)
|
|
require.True(t, found)
|
|
require.Equal(t, bondAmount.MulRaw(2), validator.DelegatorShares.RoundInt())
|
|
require.Equal(t, bondAmount.MulRaw(2), validator.Tokens)
|
|
|
|
// unjail the validator now that is has non-zero self-delegated shares
|
|
keeper.Unjail(ctx, valConsAddr)
|
|
|
|
// verify the validator can now accept delegations
|
|
msgDelegate = NewTestMsgDelegate(delAddr, valAddr, bondAmount)
|
|
got = handleMsgDelegate(ctx, msgDelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected delegation to be ok, got %v", got)
|
|
|
|
// verify validator bonded shares
|
|
validator, found = keeper.GetValidator(ctx, valAddr)
|
|
require.True(t, found)
|
|
require.Equal(t, bondAmount.MulRaw(3), validator.DelegatorShares.RoundInt())
|
|
require.Equal(t, bondAmount.MulRaw(3), validator.Tokens)
|
|
|
|
// verify new delegation
|
|
bond, found = keeper.GetDelegation(ctx, delAddr, valAddr)
|
|
require.True(t, found)
|
|
require.Equal(t, bondAmount.MulRaw(2), bond.Shares.RoundInt())
|
|
require.Equal(t, bondAmount.MulRaw(3), validator.DelegatorShares.RoundInt())
|
|
}
|
|
|
|
func TestIncrementsMsgDelegate(t *testing.T) {
|
|
initPower := int64(1000)
|
|
initBond := sdk.TokensFromTendermintPower(initPower)
|
|
ctx, accMapper, keeper := keep.CreateTestInput(t, false, initPower)
|
|
params := keeper.GetParams(ctx)
|
|
|
|
bondAmount := sdk.TokensFromTendermintPower(10)
|
|
validatorAddr, delegatorAddr := sdk.ValAddress(keep.Addrs[0]), keep.Addrs[1]
|
|
|
|
// first create validator
|
|
msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], bondAmount)
|
|
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected create validator msg to be ok, got %v", got)
|
|
|
|
// apply TM updates
|
|
keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
|
|
|
validator, found := keeper.GetValidator(ctx, validatorAddr)
|
|
require.True(t, found)
|
|
require.Equal(t, sdk.Bonded, validator.Status)
|
|
require.Equal(t, bondAmount, validator.DelegatorShares.RoundInt())
|
|
require.Equal(t, bondAmount, validator.BondedTokens(), "validator: %v", validator)
|
|
|
|
_, found = keeper.GetDelegation(ctx, delegatorAddr, validatorAddr)
|
|
require.False(t, found)
|
|
|
|
bond, found := keeper.GetDelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr)
|
|
require.True(t, found)
|
|
require.Equal(t, bondAmount, bond.Shares.RoundInt())
|
|
|
|
pool := keeper.GetPool(ctx)
|
|
exRate := validator.DelegatorShareExRate()
|
|
require.True(t, exRate.Equal(sdk.OneDec()), "expected exRate 1 got %v", exRate)
|
|
require.Equal(t, bondAmount, pool.BondedTokens)
|
|
|
|
// just send the same msgbond multiple times
|
|
msgDelegate := NewTestMsgDelegate(delegatorAddr, validatorAddr, bondAmount)
|
|
|
|
for i := int64(0); i < 5; i++ {
|
|
ctx = ctx.WithBlockHeight(int64(i))
|
|
|
|
got := handleMsgDelegate(ctx, msgDelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got)
|
|
|
|
//Check that the accounts and the bond account have the appropriate values
|
|
validator, found := keeper.GetValidator(ctx, validatorAddr)
|
|
require.True(t, found)
|
|
bond, found := keeper.GetDelegation(ctx, delegatorAddr, validatorAddr)
|
|
require.True(t, found)
|
|
|
|
exRate := validator.DelegatorShareExRate()
|
|
require.True(t, exRate.Equal(sdk.OneDec()), "expected exRate 1 got %v, i = %v", exRate, i)
|
|
|
|
expBond := bondAmount.MulRaw(i + 1)
|
|
expDelegatorShares := bondAmount.MulRaw(i + 2) // (1 self delegation)
|
|
expDelegatorAcc := initBond.Sub(expBond)
|
|
|
|
gotBond := bond.Shares.RoundInt()
|
|
gotDelegatorShares := validator.DelegatorShares.RoundInt()
|
|
gotDelegatorAcc := accMapper.GetAccount(ctx, delegatorAddr).GetCoins().AmountOf(params.BondDenom)
|
|
|
|
require.Equal(t, expBond, gotBond,
|
|
"i: %v\nexpBond: %v\ngotBond: %v\nvalidator: %v\nbond: %v\n",
|
|
i, expBond, gotBond, validator, bond)
|
|
require.Equal(t, expDelegatorShares, gotDelegatorShares,
|
|
"i: %v\nexpDelegatorShares: %v\ngotDelegatorShares: %v\nvalidator: %v\nbond: %v\n",
|
|
i, expDelegatorShares, gotDelegatorShares, validator, bond)
|
|
require.Equal(t, expDelegatorAcc, gotDelegatorAcc,
|
|
"i: %v\nexpDelegatorAcc: %v\ngotDelegatorAcc: %v\nvalidator: %v\nbond: %v\n",
|
|
i, expDelegatorAcc, gotDelegatorAcc, validator, bond)
|
|
}
|
|
}
|
|
|
|
func TestEditValidatorDecreaseMinSelfDelegation(t *testing.T) {
|
|
validatorAddr := sdk.ValAddress(keep.Addrs[0])
|
|
|
|
initPower := int64(100)
|
|
initBond := sdk.TokensFromTendermintPower(100)
|
|
ctx, _, keeper := keep.CreateTestInput(t, false, initPower)
|
|
_ = setInstantUnbondPeriod(keeper, ctx)
|
|
|
|
// create validator
|
|
msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], initBond)
|
|
msgCreateValidator.MinSelfDelegation = sdk.NewInt(2)
|
|
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got)
|
|
|
|
// must end-block
|
|
updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
|
require.Equal(t, 1, len(updates))
|
|
|
|
// verify the self-delegation exists
|
|
bond, found := keeper.GetDelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr)
|
|
require.True(t, found)
|
|
gotBond := bond.Shares.RoundInt()
|
|
require.Equal(t, initBond, gotBond,
|
|
"initBond: %v\ngotBond: %v\nbond: %v\n",
|
|
initBond, gotBond, bond)
|
|
|
|
newMinSelfDelegation := sdk.OneInt()
|
|
msgEditValidator := NewMsgEditValidator(validatorAddr, Description{}, nil, &newMinSelfDelegation)
|
|
got = handleMsgEditValidator(ctx, msgEditValidator, keeper)
|
|
require.False(t, got.IsOK(), "should not be able to decrease minSelfDelegation")
|
|
}
|
|
|
|
func TestEditValidatorIncreaseMinSelfDelegationBeyondCurrentBond(t *testing.T) {
|
|
validatorAddr := sdk.ValAddress(keep.Addrs[0])
|
|
|
|
initPower := int64(100)
|
|
initBond := sdk.TokensFromTendermintPower(100)
|
|
ctx, _, keeper := keep.CreateTestInput(t, false, initPower)
|
|
_ = setInstantUnbondPeriod(keeper, ctx)
|
|
|
|
// create validator
|
|
msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], initBond)
|
|
msgCreateValidator.MinSelfDelegation = sdk.NewInt(2)
|
|
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got)
|
|
|
|
// must end-block
|
|
updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
|
require.Equal(t, 1, len(updates))
|
|
|
|
// verify the self-delegation exists
|
|
bond, found := keeper.GetDelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr)
|
|
require.True(t, found)
|
|
gotBond := bond.Shares.RoundInt()
|
|
require.Equal(t, initBond, gotBond,
|
|
"initBond: %v\ngotBond: %v\nbond: %v\n",
|
|
initBond, gotBond, bond)
|
|
|
|
newMinSelfDelegation := initBond.Add(sdk.OneInt())
|
|
msgEditValidator := NewMsgEditValidator(validatorAddr, Description{}, nil, &newMinSelfDelegation)
|
|
got = handleMsgEditValidator(ctx, msgEditValidator, keeper)
|
|
require.False(t, got.IsOK(), "should not be able to increase minSelfDelegation above current self delegation")
|
|
}
|
|
|
|
func TestIncrementsMsgUnbond(t *testing.T) {
|
|
initPower := int64(1000)
|
|
initBond := sdk.TokensFromTendermintPower(initPower)
|
|
ctx, accMapper, keeper := keep.CreateTestInput(t, false, initPower)
|
|
params := setInstantUnbondPeriod(keeper, ctx)
|
|
denom := params.BondDenom
|
|
|
|
// create validator, delegate
|
|
validatorAddr, delegatorAddr := sdk.ValAddress(keep.Addrs[0]), keep.Addrs[1]
|
|
|
|
msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], initBond)
|
|
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got)
|
|
|
|
// initial balance
|
|
amt1 := accMapper.GetAccount(ctx, delegatorAddr).GetCoins().AmountOf(denom)
|
|
|
|
msgDelegate := NewTestMsgDelegate(delegatorAddr, validatorAddr, initBond)
|
|
got = handleMsgDelegate(ctx, msgDelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected delegation to be ok, got %v", got)
|
|
|
|
// balance should have been subtracted after delegation
|
|
amt2 := accMapper.GetAccount(ctx, delegatorAddr).GetCoins().AmountOf(denom)
|
|
require.True(sdk.IntEq(t, amt1.Sub(initBond), amt2))
|
|
|
|
// apply TM updates
|
|
keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
|
|
|
validator, found := keeper.GetValidator(ctx, validatorAddr)
|
|
require.True(t, found)
|
|
require.Equal(t, initBond.MulRaw(2), validator.DelegatorShares.RoundInt())
|
|
require.Equal(t, initBond.MulRaw(2), validator.BondedTokens())
|
|
|
|
// just send the same msgUnbond multiple times
|
|
// TODO use decimals here
|
|
unbondShares := sdk.NewDec(10)
|
|
msgUndelegate := NewMsgUndelegate(delegatorAddr, validatorAddr, unbondShares)
|
|
numUnbonds := int64(5)
|
|
for i := int64(0); i < numUnbonds; i++ {
|
|
|
|
got := handleMsgUndelegate(ctx, msgUndelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got)
|
|
var finishTime time.Time
|
|
types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime)
|
|
ctx = ctx.WithBlockTime(finishTime)
|
|
EndBlocker(ctx, keeper)
|
|
|
|
// check that the accounts and the bond account have the appropriate values
|
|
validator, found = keeper.GetValidator(ctx, validatorAddr)
|
|
require.True(t, found)
|
|
bond, found := keeper.GetDelegation(ctx, delegatorAddr, validatorAddr)
|
|
require.True(t, found)
|
|
|
|
expBond := initBond.Sub(unbondShares.MulInt64(i + 1).RoundInt())
|
|
expDelegatorShares := (initBond.MulRaw(2)).Sub(unbondShares.MulInt64(i + 1).RoundInt())
|
|
expDelegatorAcc := initBond.Sub(expBond)
|
|
|
|
gotBond := bond.Shares.RoundInt()
|
|
gotDelegatorShares := validator.DelegatorShares.RoundInt()
|
|
gotDelegatorAcc := accMapper.GetAccount(ctx, delegatorAddr).GetCoins().AmountOf(params.BondDenom)
|
|
|
|
require.Equal(t, expBond, gotBond,
|
|
"i: %v\nexpBond: %v\ngotBond: %v\nvalidator: %v\nbond: %v\n",
|
|
i, expBond, gotBond, validator, bond)
|
|
require.Equal(t, expDelegatorShares, gotDelegatorShares,
|
|
"i: %v\nexpDelegatorShares: %v\ngotDelegatorShares: %v\nvalidator: %v\nbond: %v\n",
|
|
i, expDelegatorShares, gotDelegatorShares, validator, bond)
|
|
require.Equal(t, expDelegatorAcc, gotDelegatorAcc,
|
|
"i: %v\nexpDelegatorAcc: %v\ngotDelegatorAcc: %v\nvalidator: %v\nbond: %v\n",
|
|
i, expDelegatorAcc, gotDelegatorAcc, validator, bond)
|
|
}
|
|
|
|
// these are more than we have bonded now
|
|
errorCases := []sdk.Int{
|
|
//1<<64 - 1, // more than int64 power
|
|
//1<<63 + 1, // more than int64 power
|
|
sdk.TokensFromTendermintPower(1<<63 - 1),
|
|
sdk.TokensFromTendermintPower(1 << 31),
|
|
initBond,
|
|
}
|
|
for i, c := range errorCases {
|
|
unbondShares := sdk.NewDecFromInt(c)
|
|
msgUndelegate := NewMsgUndelegate(delegatorAddr, validatorAddr, unbondShares)
|
|
got = handleMsgUndelegate(ctx, msgUndelegate, keeper)
|
|
require.False(t, got.IsOK(), "expected unbond msg to fail, index: %v", i)
|
|
}
|
|
|
|
leftBonded := initBond.Sub(unbondShares.MulInt64(numUnbonds).RoundInt())
|
|
|
|
// should be unable to unbond one more than we have
|
|
unbondShares = sdk.NewDecFromInt(leftBonded.AddRaw(1))
|
|
msgUndelegate = NewMsgUndelegate(delegatorAddr, validatorAddr, unbondShares)
|
|
got = handleMsgUndelegate(ctx, msgUndelegate, keeper)
|
|
require.False(t, got.IsOK(),
|
|
"got: %v\nmsgUnbond: %v\nshares: %v\nleftBonded: %v\n", got, msgUndelegate, unbondShares.String(), leftBonded)
|
|
|
|
// should be able to unbond just what we have
|
|
unbondShares = sdk.NewDecFromInt(leftBonded)
|
|
msgUndelegate = NewMsgUndelegate(delegatorAddr, validatorAddr, unbondShares)
|
|
got = handleMsgUndelegate(ctx, msgUndelegate, keeper)
|
|
require.True(t, got.IsOK(),
|
|
"got: %v\nmsgUnbond: %v\nshares: %v\nleftBonded: %v\n", got, msgUndelegate, unbondShares, leftBonded)
|
|
}
|
|
|
|
func TestMultipleMsgCreateValidator(t *testing.T) {
|
|
initPower := int64(1000)
|
|
initTokens := sdk.TokensFromTendermintPower(initPower)
|
|
ctx, accMapper, keeper := keep.CreateTestInput(t, false, initPower)
|
|
params := setInstantUnbondPeriod(keeper, ctx)
|
|
|
|
validatorAddrs := []sdk.ValAddress{
|
|
sdk.ValAddress(keep.Addrs[0]),
|
|
sdk.ValAddress(keep.Addrs[1]),
|
|
sdk.ValAddress(keep.Addrs[2]),
|
|
}
|
|
delegatorAddrs := []sdk.AccAddress{
|
|
keep.Addrs[3],
|
|
keep.Addrs[4],
|
|
keep.Addrs[5],
|
|
}
|
|
|
|
// bond them all
|
|
for i, validatorAddr := range validatorAddrs {
|
|
valTokens := sdk.TokensFromTendermintPower(10)
|
|
msgCreateValidatorOnBehalfOf := NewTestMsgCreateValidatorOnBehalfOf(
|
|
delegatorAddrs[i], validatorAddr, keep.PKs[i], valTokens)
|
|
got := handleMsgCreateValidator(ctx, msgCreateValidatorOnBehalfOf, keeper)
|
|
require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got)
|
|
|
|
//Check that the account is bonded
|
|
validators := keeper.GetValidators(ctx, 100)
|
|
require.Equal(t, (i + 1), len(validators))
|
|
val := validators[i]
|
|
balanceExpd := initTokens.Sub(valTokens)
|
|
balanceGot := accMapper.GetAccount(ctx, delegatorAddrs[i]).GetCoins().AmountOf(params.BondDenom)
|
|
require.Equal(t, i+1, len(validators), "expected %d validators got %d, validators: %v", i+1, len(validators), validators)
|
|
require.Equal(t, valTokens, val.DelegatorShares.RoundInt(), "expected %d shares, got %d", 10, val.DelegatorShares)
|
|
require.Equal(t, balanceExpd, balanceGot, "expected account to have %d, got %d", balanceExpd, balanceGot)
|
|
}
|
|
|
|
// unbond them all by removing delegation
|
|
for i, validatorAddr := range validatorAddrs {
|
|
_, found := keeper.GetValidator(ctx, validatorAddr)
|
|
require.True(t, found)
|
|
unbondingTokens := sdk.TokensFromTendermintPower(10)
|
|
msgUndelegate := NewMsgUndelegate(delegatorAddrs[i], validatorAddr, sdk.NewDecFromInt(unbondingTokens)) // remove delegation
|
|
got := handleMsgUndelegate(ctx, msgUndelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got)
|
|
var finishTime time.Time
|
|
// Jump to finishTime for unbonding period and remove from unbonding queue
|
|
types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime)
|
|
ctx = ctx.WithBlockTime(finishTime)
|
|
EndBlocker(ctx, keeper)
|
|
|
|
// Check that the validator is deleted from state
|
|
validators := keeper.GetValidators(ctx, 100)
|
|
require.Equal(t, len(validatorAddrs)-(i+1), len(validators),
|
|
"expected %d validators got %d", len(validatorAddrs)-(i+1), len(validators))
|
|
|
|
_, found = keeper.GetValidator(ctx, validatorAddr)
|
|
require.False(t, found)
|
|
|
|
gotBalance := accMapper.GetAccount(ctx, delegatorAddrs[i]).GetCoins().AmountOf(params.BondDenom)
|
|
require.Equal(t, initTokens, gotBalance, "expected account to have %d, got %d", initTokens, gotBalance)
|
|
}
|
|
}
|
|
|
|
func TestMultipleMsgDelegate(t *testing.T) {
|
|
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
|
validatorAddr, delegatorAddrs := sdk.ValAddress(keep.Addrs[0]), keep.Addrs[1:]
|
|
_ = setInstantUnbondPeriod(keeper, ctx)
|
|
|
|
//first make a validator
|
|
msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], sdk.NewInt(10))
|
|
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
|
|
|
|
// delegate multiple parties
|
|
for i, delegatorAddr := range delegatorAddrs {
|
|
msgDelegate := NewTestMsgDelegate(delegatorAddr, validatorAddr, sdk.NewInt(10))
|
|
got := handleMsgDelegate(ctx, msgDelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got)
|
|
|
|
//Check that the account is bonded
|
|
bond, found := keeper.GetDelegation(ctx, delegatorAddr, validatorAddr)
|
|
require.True(t, found)
|
|
require.NotNil(t, bond, "expected delegatee bond %d to exist", bond)
|
|
}
|
|
|
|
// unbond them all
|
|
for i, delegatorAddr := range delegatorAddrs {
|
|
msgUndelegate := NewMsgUndelegate(delegatorAddr, validatorAddr, sdk.NewDec(10))
|
|
got := handleMsgUndelegate(ctx, msgUndelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got)
|
|
var finishTime time.Time
|
|
types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime)
|
|
ctx = ctx.WithBlockTime(finishTime)
|
|
EndBlocker(ctx, keeper)
|
|
|
|
//Check that the account is unbonded
|
|
_, found := keeper.GetDelegation(ctx, delegatorAddr, validatorAddr)
|
|
require.False(t, found)
|
|
}
|
|
}
|
|
|
|
func TestJailValidator(t *testing.T) {
|
|
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
|
validatorAddr, delegatorAddr := sdk.ValAddress(keep.Addrs[0]), keep.Addrs[1]
|
|
_ = setInstantUnbondPeriod(keeper, ctx)
|
|
|
|
// create the validator
|
|
msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], sdk.NewInt(10))
|
|
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
|
|
|
// bond a delegator
|
|
msgDelegate := NewTestMsgDelegate(delegatorAddr, validatorAddr, sdk.NewInt(10))
|
|
got = handleMsgDelegate(ctx, msgDelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected ok, got %v", got)
|
|
|
|
// unbond the validators bond portion
|
|
msgUndelegateValidator := NewMsgUndelegate(sdk.AccAddress(validatorAddr), validatorAddr, sdk.NewDec(10))
|
|
got = handleMsgUndelegate(ctx, msgUndelegateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected no error: %v", got)
|
|
var finishTime time.Time
|
|
types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime)
|
|
ctx = ctx.WithBlockTime(finishTime)
|
|
EndBlocker(ctx, keeper)
|
|
|
|
validator, found := keeper.GetValidator(ctx, validatorAddr)
|
|
require.True(t, found)
|
|
require.True(t, validator.Jailed, "%v", validator)
|
|
|
|
// test that the delegator can still withdraw their bonds
|
|
msgUndelegateDelegator := NewMsgUndelegate(delegatorAddr, validatorAddr, sdk.NewDec(10))
|
|
got = handleMsgUndelegate(ctx, msgUndelegateDelegator, keeper)
|
|
require.True(t, got.IsOK(), "expected no error")
|
|
types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime)
|
|
ctx = ctx.WithBlockTime(finishTime)
|
|
EndBlocker(ctx, keeper)
|
|
|
|
// verify that the pubkey can now be reused
|
|
got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected ok, got %v", got)
|
|
}
|
|
|
|
func TestValidatorQueue(t *testing.T) {
|
|
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
|
validatorAddr, delegatorAddr := sdk.ValAddress(keep.Addrs[0]), keep.Addrs[1]
|
|
|
|
// set the unbonding time
|
|
params := keeper.GetParams(ctx)
|
|
params.UnbondingTime = 7 * time.Second
|
|
keeper.SetParams(ctx, params)
|
|
|
|
// create the validator
|
|
valTokens := sdk.TokensFromTendermintPower(10)
|
|
msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], valTokens)
|
|
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
|
|
|
// bond a delegator
|
|
delTokens := sdk.TokensFromTendermintPower(10)
|
|
msgDelegate := NewTestMsgDelegate(delegatorAddr, validatorAddr, delTokens)
|
|
got = handleMsgDelegate(ctx, msgDelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected ok, got %v", got)
|
|
|
|
EndBlocker(ctx, keeper)
|
|
|
|
// unbond the all self-delegation to put validator in unbonding state
|
|
msgUndelegateValidator := NewMsgUndelegate(sdk.AccAddress(validatorAddr),
|
|
validatorAddr, sdk.NewDecFromInt(delTokens))
|
|
got = handleMsgUndelegate(ctx, msgUndelegateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected no error: %v", got)
|
|
var finishTime time.Time
|
|
types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime)
|
|
ctx = ctx.WithBlockTime(finishTime)
|
|
EndBlocker(ctx, keeper)
|
|
origHeader := ctx.BlockHeader()
|
|
|
|
validator, found := keeper.GetValidator(ctx, validatorAddr)
|
|
require.True(t, found)
|
|
require.True(t, validator.GetStatus() == sdk.Unbonding, "%v", validator)
|
|
|
|
// should still be unbonding at time 6 seconds later
|
|
ctx = ctx.WithBlockTime(origHeader.Time.Add(time.Second * 6))
|
|
EndBlocker(ctx, keeper)
|
|
validator, found = keeper.GetValidator(ctx, validatorAddr)
|
|
require.True(t, found)
|
|
require.True(t, validator.GetStatus() == sdk.Unbonding, "%v", validator)
|
|
|
|
// should be in unbonded state at time 7 seconds later
|
|
ctx = ctx.WithBlockTime(origHeader.Time.Add(time.Second * 7))
|
|
EndBlocker(ctx, keeper)
|
|
validator, found = keeper.GetValidator(ctx, validatorAddr)
|
|
require.True(t, found)
|
|
require.True(t, validator.GetStatus() == sdk.Unbonded, "%v", validator)
|
|
}
|
|
|
|
func TestUnbondingPeriod(t *testing.T) {
|
|
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
|
validatorAddr := sdk.ValAddress(keep.Addrs[0])
|
|
|
|
// set the unbonding time
|
|
params := keeper.GetParams(ctx)
|
|
params.UnbondingTime = 7 * time.Second
|
|
keeper.SetParams(ctx, params)
|
|
|
|
// create the validator
|
|
valTokens := sdk.TokensFromTendermintPower(10)
|
|
msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], valTokens)
|
|
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
|
|
|
EndBlocker(ctx, keeper)
|
|
|
|
// begin unbonding
|
|
unbondingTokens := sdk.TokensFromTendermintPower(10)
|
|
msgUndelegate := NewMsgUndelegate(sdk.AccAddress(validatorAddr),
|
|
validatorAddr, sdk.NewDecFromInt(unbondingTokens))
|
|
got = handleMsgUndelegate(ctx, msgUndelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected no error")
|
|
origHeader := ctx.BlockHeader()
|
|
|
|
_, found := keeper.GetUnbondingDelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr)
|
|
require.True(t, found, "should not have unbonded")
|
|
|
|
// cannot complete unbonding at same time
|
|
EndBlocker(ctx, keeper)
|
|
_, found = keeper.GetUnbondingDelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr)
|
|
require.True(t, found, "should not have unbonded")
|
|
|
|
// cannot complete unbonding at time 6 seconds later
|
|
ctx = ctx.WithBlockTime(origHeader.Time.Add(time.Second * 6))
|
|
EndBlocker(ctx, keeper)
|
|
_, found = keeper.GetUnbondingDelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr)
|
|
require.True(t, found, "should not have unbonded")
|
|
|
|
// can complete unbonding at time 7 seconds later
|
|
ctx = ctx.WithBlockTime(origHeader.Time.Add(time.Second * 7))
|
|
EndBlocker(ctx, keeper)
|
|
_, found = keeper.GetUnbondingDelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr)
|
|
require.False(t, found, "should have unbonded")
|
|
}
|
|
|
|
func TestUnbondingFromUnbondingValidator(t *testing.T) {
|
|
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
|
validatorAddr, delegatorAddr := sdk.ValAddress(keep.Addrs[0]), keep.Addrs[1]
|
|
|
|
// create the validator
|
|
msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], sdk.NewInt(10))
|
|
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
|
|
|
// bond a delegator
|
|
msgDelegate := NewTestMsgDelegate(delegatorAddr, validatorAddr, sdk.NewInt(10))
|
|
got = handleMsgDelegate(ctx, msgDelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected ok, got %v", got)
|
|
|
|
// unbond the validators bond portion
|
|
msgUndelegateValidator := NewMsgUndelegate(sdk.AccAddress(validatorAddr), validatorAddr, sdk.NewDec(10))
|
|
got = handleMsgUndelegate(ctx, msgUndelegateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected no error")
|
|
|
|
// change the ctx to Block Time one second before the validator would have unbonded
|
|
var finishTime time.Time
|
|
types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime)
|
|
ctx = ctx.WithBlockTime(finishTime.Add(time.Second * -1))
|
|
|
|
// unbond the delegator from the validator
|
|
msgUndelegateDelegator := NewMsgUndelegate(delegatorAddr, validatorAddr, sdk.NewDec(10))
|
|
got = handleMsgUndelegate(ctx, msgUndelegateDelegator, keeper)
|
|
require.True(t, got.IsOK(), "expected no error")
|
|
|
|
// move the Block time forward by one second
|
|
ctx = ctx.WithBlockTime(ctx.BlockHeader().Time.Add(time.Second * 1))
|
|
|
|
// Run the EndBlocker
|
|
EndBlocker(ctx, keeper)
|
|
|
|
// Check to make sure that the unbonding delegation is no longer in state
|
|
// (meaning it was deleted in the above EndBlocker)
|
|
_, found := keeper.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr)
|
|
require.False(t, found, "should be removed from state")
|
|
}
|
|
|
|
func TestRedelegationPeriod(t *testing.T) {
|
|
ctx, AccMapper, keeper := keep.CreateTestInput(t, false, 1000)
|
|
validatorAddr, validatorAddr2 := sdk.ValAddress(keep.Addrs[0]), sdk.ValAddress(keep.Addrs[1])
|
|
denom := keeper.GetParams(ctx).BondDenom
|
|
|
|
// set the unbonding time
|
|
params := keeper.GetParams(ctx)
|
|
params.UnbondingTime = 7 * time.Second
|
|
keeper.SetParams(ctx, params)
|
|
|
|
// create the validators
|
|
msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], sdk.NewInt(10))
|
|
|
|
// initial balance
|
|
amt1 := AccMapper.GetAccount(ctx, sdk.AccAddress(validatorAddr)).GetCoins().AmountOf(denom)
|
|
|
|
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
|
|
|
// balance should have been subtracted after creation
|
|
amt2 := AccMapper.GetAccount(ctx, sdk.AccAddress(validatorAddr)).GetCoins().AmountOf(denom)
|
|
require.Equal(t, amt1.Sub(sdk.NewInt(10)).Int64(), amt2.Int64(), "expected coins to be subtracted")
|
|
|
|
msgCreateValidator = NewTestMsgCreateValidator(validatorAddr2, keep.PKs[1], sdk.NewInt(10))
|
|
got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
|
|
|
bal1 := AccMapper.GetAccount(ctx, sdk.AccAddress(validatorAddr)).GetCoins()
|
|
|
|
// begin redelegate
|
|
msgBeginRedelegate := NewMsgBeginRedelegate(sdk.AccAddress(validatorAddr), validatorAddr, validatorAddr2, sdk.NewDec(10))
|
|
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected no error, %v", got)
|
|
|
|
// origin account should not lose tokens as with a regular delegation
|
|
bal2 := AccMapper.GetAccount(ctx, sdk.AccAddress(validatorAddr)).GetCoins()
|
|
require.Equal(t, bal1, bal2)
|
|
|
|
origHeader := ctx.BlockHeader()
|
|
|
|
// cannot complete redelegation at same time
|
|
EndBlocker(ctx, keeper)
|
|
_, found := keeper.GetRedelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr, validatorAddr2)
|
|
require.True(t, found, "should not have unbonded")
|
|
|
|
// cannot complete redelegation at time 6 seconds later
|
|
ctx = ctx.WithBlockTime(origHeader.Time.Add(time.Second * 6))
|
|
EndBlocker(ctx, keeper)
|
|
_, found = keeper.GetRedelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr, validatorAddr2)
|
|
require.True(t, found, "should not have unbonded")
|
|
|
|
// can complete redelegation at time 7 seconds later
|
|
ctx = ctx.WithBlockTime(origHeader.Time.Add(time.Second * 7))
|
|
EndBlocker(ctx, keeper)
|
|
_, found = keeper.GetRedelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr, validatorAddr2)
|
|
require.False(t, found, "should have unbonded")
|
|
}
|
|
|
|
func TestTransitiveRedelegation(t *testing.T) {
|
|
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
|
validatorAddr := sdk.ValAddress(keep.Addrs[0])
|
|
validatorAddr2 := sdk.ValAddress(keep.Addrs[1])
|
|
validatorAddr3 := sdk.ValAddress(keep.Addrs[2])
|
|
|
|
// set the unbonding time
|
|
params := keeper.GetParams(ctx)
|
|
params.UnbondingTime = 0
|
|
keeper.SetParams(ctx, params)
|
|
|
|
// create the validators
|
|
msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], sdk.NewInt(10))
|
|
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
|
|
|
msgCreateValidator = NewTestMsgCreateValidator(validatorAddr2, keep.PKs[1], sdk.NewInt(10))
|
|
got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
|
|
|
msgCreateValidator = NewTestMsgCreateValidator(validatorAddr3, keep.PKs[2], sdk.NewInt(10))
|
|
got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
|
|
|
// begin redelegate
|
|
msgBeginRedelegate := NewMsgBeginRedelegate(sdk.AccAddress(validatorAddr), validatorAddr, validatorAddr2, sdk.NewDec(10))
|
|
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected no error, %v", got)
|
|
|
|
// cannot redelegation to next validator while first delegation exists
|
|
msgBeginRedelegate = NewMsgBeginRedelegate(sdk.AccAddress(validatorAddr), validatorAddr2, validatorAddr3, sdk.NewDec(10))
|
|
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
|
|
require.True(t, !got.IsOK(), "expected an error, msg: %v", msgBeginRedelegate)
|
|
|
|
// complete first redelegation
|
|
EndBlocker(ctx, keeper)
|
|
|
|
// now should be able to redelegate from the second validator to the third
|
|
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected no error")
|
|
}
|
|
|
|
func TestMultipleRedelegationAtSameTime(t *testing.T) {
|
|
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
|
valAddr := sdk.ValAddress(keep.Addrs[0])
|
|
valAddr2 := sdk.ValAddress(keep.Addrs[1])
|
|
|
|
// set the unbonding time
|
|
params := keeper.GetParams(ctx)
|
|
params.UnbondingTime = 1 * time.Second
|
|
keeper.SetParams(ctx, params)
|
|
|
|
// create the validators
|
|
valTokens := sdk.TokensFromTendermintPower(10)
|
|
msgCreateValidator := NewTestMsgCreateValidator(valAddr, keep.PKs[0], valTokens)
|
|
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
|
|
|
msgCreateValidator = NewTestMsgCreateValidator(valAddr2, keep.PKs[1], valTokens)
|
|
got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
|
|
|
// end block to bond them
|
|
EndBlocker(ctx, keeper)
|
|
|
|
// begin a redelegate
|
|
selfDelAddr := sdk.AccAddress(valAddr) // (the validator is it's own delegator)
|
|
msgBeginRedelegate := NewMsgBeginRedelegate(selfDelAddr,
|
|
valAddr, valAddr2, sdk.NewDecFromInt(valTokens.DivRaw(2)))
|
|
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected no error, %v", got)
|
|
|
|
// there should only be one entry in the redelegation object
|
|
rd, found := keeper.GetRedelegation(ctx, selfDelAddr, valAddr, valAddr2)
|
|
require.True(t, found)
|
|
require.Len(t, rd.Entries, 1)
|
|
|
|
// start a second redelegation at this same time as the first
|
|
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected no error, msg: %v", msgBeginRedelegate)
|
|
|
|
// now there should be two entries
|
|
rd, found = keeper.GetRedelegation(ctx, selfDelAddr, valAddr, valAddr2)
|
|
require.True(t, found)
|
|
require.Len(t, rd.Entries, 2)
|
|
|
|
// move forward in time, should complete both redelegations
|
|
ctx = ctx.WithBlockTime(ctx.BlockHeader().Time.Add(1 * time.Second))
|
|
EndBlocker(ctx, keeper)
|
|
|
|
rd, found = keeper.GetRedelegation(ctx, selfDelAddr, valAddr, valAddr2)
|
|
require.False(t, found)
|
|
}
|
|
|
|
func TestMultipleRedelegationAtUniqueTimes(t *testing.T) {
|
|
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
|
valAddr := sdk.ValAddress(keep.Addrs[0])
|
|
valAddr2 := sdk.ValAddress(keep.Addrs[1])
|
|
|
|
// set the unbonding time
|
|
params := keeper.GetParams(ctx)
|
|
params.UnbondingTime = 10 * time.Second
|
|
keeper.SetParams(ctx, params)
|
|
|
|
// create the validators
|
|
valTokens := sdk.TokensFromTendermintPower(10)
|
|
msgCreateValidator := NewTestMsgCreateValidator(valAddr, keep.PKs[0], valTokens)
|
|
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
|
|
|
msgCreateValidator = NewTestMsgCreateValidator(valAddr2, keep.PKs[1], valTokens)
|
|
got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
|
|
|
// end block to bond them
|
|
EndBlocker(ctx, keeper)
|
|
|
|
// begin a redelegate
|
|
selfDelAddr := sdk.AccAddress(valAddr) // (the validator is it's own delegator)
|
|
msgBeginRedelegate := NewMsgBeginRedelegate(selfDelAddr,
|
|
valAddr, valAddr2, sdk.NewDecFromInt(valTokens.DivRaw(2)))
|
|
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected no error, %v", got)
|
|
|
|
// move forward in time and start a second redelegation
|
|
ctx = ctx.WithBlockTime(ctx.BlockHeader().Time.Add(5 * time.Second))
|
|
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected no error, msg: %v", msgBeginRedelegate)
|
|
|
|
// now there should be two entries
|
|
rd, found := keeper.GetRedelegation(ctx, selfDelAddr, valAddr, valAddr2)
|
|
require.True(t, found)
|
|
require.Len(t, rd.Entries, 2)
|
|
|
|
// move forward in time, should complete the first redelegation, but not the second
|
|
ctx = ctx.WithBlockTime(ctx.BlockHeader().Time.Add(5 * time.Second))
|
|
EndBlocker(ctx, keeper)
|
|
rd, found = keeper.GetRedelegation(ctx, selfDelAddr, valAddr, valAddr2)
|
|
require.True(t, found)
|
|
require.Len(t, rd.Entries, 1)
|
|
|
|
// move forward in time, should complete the second redelegation
|
|
ctx = ctx.WithBlockTime(ctx.BlockHeader().Time.Add(5 * time.Second))
|
|
EndBlocker(ctx, keeper)
|
|
rd, found = keeper.GetRedelegation(ctx, selfDelAddr, valAddr, valAddr2)
|
|
require.False(t, found)
|
|
}
|
|
|
|
func TestMultipleUnbondingDelegationAtSameTime(t *testing.T) {
|
|
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
|
valAddr := sdk.ValAddress(keep.Addrs[0])
|
|
|
|
// set the unbonding time
|
|
params := keeper.GetParams(ctx)
|
|
params.UnbondingTime = 1 * time.Second
|
|
keeper.SetParams(ctx, params)
|
|
|
|
// create the validator
|
|
valTokens := sdk.TokensFromTendermintPower(10)
|
|
msgCreateValidator := NewTestMsgCreateValidator(valAddr, keep.PKs[0], valTokens)
|
|
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
|
|
|
// end block to bond
|
|
EndBlocker(ctx, keeper)
|
|
|
|
// begin an unbonding delegation
|
|
selfDelAddr := sdk.AccAddress(valAddr) // (the validator is it's own delegator)
|
|
msgUndelegate := NewMsgUndelegate(selfDelAddr, valAddr, sdk.NewDecFromInt(valTokens.DivRaw(2)))
|
|
got = handleMsgUndelegate(ctx, msgUndelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected no error, %v", got)
|
|
|
|
// there should only be one entry in the ubd object
|
|
ubd, found := keeper.GetUnbondingDelegation(ctx, selfDelAddr, valAddr)
|
|
require.True(t, found)
|
|
require.Len(t, ubd.Entries, 1)
|
|
|
|
// start a second ubd at this same time as the first
|
|
got = handleMsgUndelegate(ctx, msgUndelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected no error, msg: %v", msgUndelegate)
|
|
|
|
// now there should be two entries
|
|
ubd, found = keeper.GetUnbondingDelegation(ctx, selfDelAddr, valAddr)
|
|
require.True(t, found)
|
|
require.Len(t, ubd.Entries, 2)
|
|
|
|
// move forwaubd in time, should complete both ubds
|
|
ctx = ctx.WithBlockTime(ctx.BlockHeader().Time.Add(1 * time.Second))
|
|
EndBlocker(ctx, keeper)
|
|
|
|
ubd, found = keeper.GetUnbondingDelegation(ctx, selfDelAddr, valAddr)
|
|
require.False(t, found)
|
|
}
|
|
|
|
func TestMultipleUnbondingDelegationAtUniqueTimes(t *testing.T) {
|
|
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
|
valAddr := sdk.ValAddress(keep.Addrs[0])
|
|
|
|
// set the unbonding time
|
|
params := keeper.GetParams(ctx)
|
|
params.UnbondingTime = 10 * time.Second
|
|
keeper.SetParams(ctx, params)
|
|
|
|
// create the validator
|
|
valTokens := sdk.TokensFromTendermintPower(10)
|
|
msgCreateValidator := NewTestMsgCreateValidator(valAddr, keep.PKs[0], valTokens)
|
|
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
|
|
|
// end block to bond
|
|
EndBlocker(ctx, keeper)
|
|
|
|
// begin an unbonding delegation
|
|
selfDelAddr := sdk.AccAddress(valAddr) // (the validator is it's own delegator)
|
|
msgUndelegate := NewMsgUndelegate(selfDelAddr, valAddr, sdk.NewDecFromInt(valTokens.DivRaw(2)))
|
|
got = handleMsgUndelegate(ctx, msgUndelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected no error, %v", got)
|
|
|
|
// there should only be one entry in the ubd object
|
|
ubd, found := keeper.GetUnbondingDelegation(ctx, selfDelAddr, valAddr)
|
|
require.True(t, found)
|
|
require.Len(t, ubd.Entries, 1)
|
|
|
|
// move forwaubd in time and start a second redelegation
|
|
ctx = ctx.WithBlockTime(ctx.BlockHeader().Time.Add(5 * time.Second))
|
|
got = handleMsgUndelegate(ctx, msgUndelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected no error, msg: %v", msgUndelegate)
|
|
|
|
// now there should be two entries
|
|
ubd, found = keeper.GetUnbondingDelegation(ctx, selfDelAddr, valAddr)
|
|
require.True(t, found)
|
|
require.Len(t, ubd.Entries, 2)
|
|
|
|
// move forwaubd in time, should complete the first redelegation, but not the second
|
|
ctx = ctx.WithBlockTime(ctx.BlockHeader().Time.Add(5 * time.Second))
|
|
EndBlocker(ctx, keeper)
|
|
ubd, found = keeper.GetUnbondingDelegation(ctx, selfDelAddr, valAddr)
|
|
require.True(t, found)
|
|
require.Len(t, ubd.Entries, 1)
|
|
|
|
// move forwaubd in time, should complete the second redelegation
|
|
ctx = ctx.WithBlockTime(ctx.BlockHeader().Time.Add(5 * time.Second))
|
|
EndBlocker(ctx, keeper)
|
|
ubd, found = keeper.GetUnbondingDelegation(ctx, selfDelAddr, valAddr)
|
|
require.False(t, found)
|
|
}
|
|
|
|
func TestUnbondingWhenExcessValidators(t *testing.T) {
|
|
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
|
validatorAddr1 := sdk.ValAddress(keep.Addrs[0])
|
|
validatorAddr2 := sdk.ValAddress(keep.Addrs[1])
|
|
validatorAddr3 := sdk.ValAddress(keep.Addrs[2])
|
|
|
|
// set the unbonding time
|
|
params := keeper.GetParams(ctx)
|
|
params.UnbondingTime = 0
|
|
params.MaxValidators = 2
|
|
keeper.SetParams(ctx, params)
|
|
|
|
// add three validators
|
|
valTokens1 := sdk.TokensFromTendermintPower(50)
|
|
msgCreateValidator := NewTestMsgCreateValidator(validatorAddr1, keep.PKs[0], valTokens1)
|
|
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
|
// apply TM updates
|
|
keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
|
require.Equal(t, 1, len(keeper.GetLastValidators(ctx)))
|
|
|
|
valTokens2 := sdk.TokensFromTendermintPower(30)
|
|
msgCreateValidator = NewTestMsgCreateValidator(validatorAddr2, keep.PKs[1], valTokens2)
|
|
got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
|
// apply TM updates
|
|
keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
|
require.Equal(t, 2, len(keeper.GetLastValidators(ctx)))
|
|
|
|
valTokens3 := sdk.TokensFromTendermintPower(10)
|
|
msgCreateValidator = NewTestMsgCreateValidator(validatorAddr3, keep.PKs[2], valTokens3)
|
|
got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
|
// apply TM updates
|
|
keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
|
require.Equal(t, 2, len(keeper.GetLastValidators(ctx)))
|
|
|
|
// unbond the valdator-2
|
|
msgUndelegate := NewMsgUndelegate(sdk.AccAddress(validatorAddr2), validatorAddr2, sdk.NewDecFromInt(valTokens2))
|
|
got = handleMsgUndelegate(ctx, msgUndelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected no error on runMsgUndelegate")
|
|
|
|
// apply TM updates
|
|
keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
|
|
|
// because there are extra validators waiting to get in, the queued
|
|
// validator (aka. validator-1) should make it into the bonded group, thus
|
|
// the total number of validators should stay the same
|
|
vals := keeper.GetLastValidators(ctx)
|
|
require.Equal(t, 2, len(vals), "vals %v", vals)
|
|
val1, found := keeper.GetValidator(ctx, validatorAddr1)
|
|
require.True(t, found)
|
|
require.Equal(t, sdk.Bonded, val1.Status, "%v", val1)
|
|
}
|
|
|
|
func TestBondUnbondRedelegateSlashTwice(t *testing.T) {
|
|
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
|
valA, valB, del := sdk.ValAddress(keep.Addrs[0]), sdk.ValAddress(keep.Addrs[1]), keep.Addrs[2]
|
|
consAddr0 := sdk.ConsAddress(keep.PKs[0].Address())
|
|
|
|
valTokens := sdk.TokensFromTendermintPower(10)
|
|
msgCreateValidator := NewTestMsgCreateValidator(valA, keep.PKs[0], valTokens)
|
|
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
|
|
|
msgCreateValidator = NewTestMsgCreateValidator(valB, keep.PKs[1], valTokens)
|
|
got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
|
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
|
|
|
// delegate 10 stake
|
|
msgDelegate := NewTestMsgDelegate(del, valA, valTokens)
|
|
got = handleMsgDelegate(ctx, msgDelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected no error on runMsgDelegate")
|
|
|
|
// apply Tendermint updates
|
|
updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
|
require.Equal(t, 2, len(updates))
|
|
|
|
// a block passes
|
|
ctx = ctx.WithBlockHeight(1)
|
|
|
|
// begin unbonding 4 stake
|
|
ubdTokens := sdk.TokensFromTendermintPower(4)
|
|
msgUndelegate := NewMsgUndelegate(del, valA, sdk.NewDecFromInt(ubdTokens))
|
|
got = handleMsgUndelegate(ctx, msgUndelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected no error on runMsgUndelegate")
|
|
|
|
// begin redelegate 6 stake
|
|
rdTokens := sdk.TokensFromTendermintPower(6)
|
|
msgBeginRedelegate := NewMsgBeginRedelegate(del, valA, valB, sdk.NewDecFromInt(rdTokens))
|
|
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
|
|
require.True(t, got.IsOK(), "expected no error on runMsgBeginRedelegate")
|
|
|
|
// destination delegation should have 6 shares
|
|
delegation, found := keeper.GetDelegation(ctx, del, valB)
|
|
require.True(t, found)
|
|
require.Equal(t, sdk.NewDecFromInt(rdTokens), delegation.Shares)
|
|
|
|
// must apply validator updates
|
|
updates = keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
|
require.Equal(t, 2, len(updates))
|
|
|
|
// slash the validator by half
|
|
keeper.Slash(ctx, consAddr0, 0, 20, sdk.NewDecWithPrec(5, 1))
|
|
|
|
// unbonding delegation should have been slashed by half
|
|
ubd, found := keeper.GetUnbondingDelegation(ctx, del, valA)
|
|
require.True(t, found)
|
|
require.Len(t, ubd.Entries, 1)
|
|
require.Equal(t, ubdTokens.DivRaw(2), ubd.Entries[0].Balance)
|
|
|
|
// redelegation should have been slashed by half
|
|
redelegation, found := keeper.GetRedelegation(ctx, del, valA, valB)
|
|
require.True(t, found)
|
|
require.Len(t, redelegation.Entries, 1)
|
|
|
|
// destination delegation should have been slashed by half
|
|
delegation, found = keeper.GetDelegation(ctx, del, valB)
|
|
require.True(t, found)
|
|
require.Equal(t, sdk.NewDecFromInt(rdTokens.DivRaw(2)), delegation.Shares)
|
|
|
|
// validator power should have been reduced by half
|
|
validator, found := keeper.GetValidator(ctx, valA)
|
|
require.True(t, found)
|
|
require.Equal(t, valTokens.DivRaw(2), validator.GetBondedTokens())
|
|
|
|
// slash the validator for an infraction committed after the unbonding and redelegation begin
|
|
ctx = ctx.WithBlockHeight(3)
|
|
keeper.Slash(ctx, consAddr0, 2, 10, sdk.NewDecWithPrec(5, 1))
|
|
|
|
// unbonding delegation should be unchanged
|
|
ubd, found = keeper.GetUnbondingDelegation(ctx, del, valA)
|
|
require.True(t, found)
|
|
require.Len(t, ubd.Entries, 1)
|
|
require.Equal(t, ubdTokens.DivRaw(2), ubd.Entries[0].Balance)
|
|
|
|
// redelegation should be unchanged
|
|
redelegation, found = keeper.GetRedelegation(ctx, del, valA, valB)
|
|
require.True(t, found)
|
|
require.Len(t, redelegation.Entries, 1)
|
|
|
|
// destination delegation should be unchanged
|
|
delegation, found = keeper.GetDelegation(ctx, del, valB)
|
|
require.True(t, found)
|
|
require.Equal(t, sdk.NewDecFromInt(rdTokens.DivRaw(2)), delegation.Shares)
|
|
|
|
// end blocker
|
|
EndBlocker(ctx, keeper)
|
|
|
|
// validator power should have been reduced to zero
|
|
// validator should be in unbonding state
|
|
validator, _ = keeper.GetValidator(ctx, valA)
|
|
require.Equal(t, validator.GetStatus(), sdk.Unbonding)
|
|
}
|