677 lines
27 KiB
Go
677 lines
27 KiB
Go
package keeper
|
|
|
|
import (
|
|
"testing"
|
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
"github.com/cosmos/cosmos-sdk/x/stake/types"
|
|
tmtypes "github.com/tendermint/tendermint/types"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestSetValidator(t *testing.T) {
|
|
ctx, _, keeper := CreateTestInput(t, false, 10)
|
|
pool := keeper.GetPool(ctx)
|
|
|
|
// test how the validator is set from a purely unbonbed pool
|
|
validator := types.NewValidator(addrVals[0], PKs[0], types.Description{})
|
|
validator, pool, _ = validator.AddTokensFromDel(pool, 10)
|
|
require.Equal(t, sdk.Unbonded, validator.Status())
|
|
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.PoolShares.Unbonded()))
|
|
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.DelegatorShares))
|
|
keeper.SetPool(ctx, pool)
|
|
keeper.UpdateValidator(ctx, validator)
|
|
|
|
// after the save the validator should be bonded
|
|
validator, found := keeper.GetValidator(ctx, addrVals[0])
|
|
require.True(t, found)
|
|
require.Equal(t, sdk.Bonded, validator.Status())
|
|
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.PoolShares.Bonded()))
|
|
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.DelegatorShares))
|
|
|
|
// Check each store for being saved
|
|
resVal, found := keeper.GetValidator(ctx, addrVals[0])
|
|
assert.True(ValEq(t, validator, resVal))
|
|
assert.True(t, found)
|
|
|
|
resVals := keeper.GetValidatorsBonded(ctx)
|
|
require.Equal(t, 1, len(resVals))
|
|
assert.True(ValEq(t, validator, resVals[0]))
|
|
|
|
resVals = keeper.GetValidatorsByPower(ctx)
|
|
require.Equal(t, 1, len(resVals))
|
|
assert.True(ValEq(t, validator, resVals[0]))
|
|
|
|
updates := keeper.GetTendermintUpdates(ctx)
|
|
require.Equal(t, 1, len(updates))
|
|
assert.Equal(t, validator.ABCIValidator(keeper.cdc), updates[0])
|
|
|
|
}
|
|
|
|
func TestUpdateValidatorByPowerIndex(t *testing.T) {
|
|
ctx, _, keeper := CreateTestInput(t, false, 0)
|
|
pool := keeper.GetPool(ctx)
|
|
|
|
// create a random pool
|
|
pool.LooseTokens = 10000
|
|
pool.BondedTokens = 1234
|
|
pool.BondedShares = sdk.NewRat(124)
|
|
pool.UnbondingTokens = 13934
|
|
pool.UnbondingShares = sdk.NewRat(145)
|
|
pool.UnbondedTokens = 154
|
|
pool.UnbondedShares = sdk.NewRat(1333)
|
|
keeper.SetPool(ctx, pool)
|
|
|
|
// add a validator
|
|
validator := types.NewValidator(addrVals[0], PKs[0], types.Description{})
|
|
validator, pool, delSharesCreated := validator.AddTokensFromDel(pool, 100)
|
|
require.Equal(t, sdk.Unbonded, validator.Status())
|
|
assert.Equal(t, int64(100), validator.PoolShares.Tokens(pool).Evaluate())
|
|
keeper.SetPool(ctx, pool)
|
|
keeper.UpdateValidator(ctx, validator)
|
|
validator, found := keeper.GetValidator(ctx, addrVals[0])
|
|
require.True(t, found)
|
|
assert.Equal(t, int64(100), validator.PoolShares.Tokens(pool).Evaluate(), "\nvalidator %v\npool %v", validator, pool)
|
|
|
|
pool = keeper.GetPool(ctx)
|
|
power := GetValidatorsByPowerIndexKey(validator, pool)
|
|
assert.True(t, keeper.validatorByPowerIndexExists(ctx, power))
|
|
|
|
// burn half the delegator shares
|
|
validator, pool, burned := validator.RemoveDelShares(pool, delSharesCreated.Quo(sdk.NewRat(2)))
|
|
assert.Equal(t, int64(50), burned)
|
|
keeper.SetPool(ctx, pool) // update the pool
|
|
keeper.UpdateValidator(ctx, validator) // update the validator, possibly kicking it out
|
|
assert.False(t, keeper.validatorByPowerIndexExists(ctx, power))
|
|
|
|
pool = keeper.GetPool(ctx)
|
|
validator, found = keeper.GetValidator(ctx, addrVals[0])
|
|
assert.True(t, found)
|
|
power = GetValidatorsByPowerIndexKey(validator, pool)
|
|
assert.True(t, keeper.validatorByPowerIndexExists(ctx, power))
|
|
}
|
|
|
|
// This function tests UpdateValidator, GetValidator, GetValidatorsBonded, RemoveValidator
|
|
func TestValidatorBasics(t *testing.T) {
|
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
|
pool := keeper.GetPool(ctx)
|
|
|
|
//construct the validators
|
|
var validators [3]types.Validator
|
|
amts := []int64{9, 8, 7}
|
|
for i, amt := range amts {
|
|
validators[i] = types.NewValidator(addrVals[i], PKs[i], types.Description{})
|
|
validators[i].PoolShares = types.NewUnbondedShares(sdk.ZeroRat())
|
|
validators[i].AddTokensFromDel(pool, amt)
|
|
}
|
|
|
|
// check the empty keeper first
|
|
_, found := keeper.GetValidator(ctx, addrVals[0])
|
|
assert.False(t, found)
|
|
resVals := keeper.GetValidatorsBonded(ctx)
|
|
assert.Zero(t, len(resVals))
|
|
|
|
// set and retrieve a record
|
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
|
resVal, found := keeper.GetValidator(ctx, addrVals[0])
|
|
require.True(t, found)
|
|
assert.True(ValEq(t, validators[0], resVal))
|
|
|
|
resVals = keeper.GetValidatorsBonded(ctx)
|
|
require.Equal(t, 1, len(resVals))
|
|
assert.True(ValEq(t, validators[0], resVals[0]))
|
|
|
|
// modify a records, save, and retrieve
|
|
validators[0].PoolShares = types.NewBondedShares(sdk.NewRat(10))
|
|
validators[0].DelegatorShares = sdk.NewRat(10)
|
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
|
resVal, found = keeper.GetValidator(ctx, addrVals[0])
|
|
require.True(t, found)
|
|
assert.True(ValEq(t, validators[0], resVal))
|
|
|
|
resVals = keeper.GetValidatorsBonded(ctx)
|
|
require.Equal(t, 1, len(resVals))
|
|
assert.True(ValEq(t, validators[0], resVals[0]))
|
|
|
|
// add other validators
|
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
|
validators[2] = keeper.UpdateValidator(ctx, validators[2])
|
|
resVal, found = keeper.GetValidator(ctx, addrVals[1])
|
|
require.True(t, found)
|
|
assert.True(ValEq(t, validators[1], resVal))
|
|
resVal, found = keeper.GetValidator(ctx, addrVals[2])
|
|
require.True(t, found)
|
|
assert.True(ValEq(t, validators[2], resVal))
|
|
|
|
resVals = keeper.GetValidatorsBonded(ctx)
|
|
require.Equal(t, 3, len(resVals))
|
|
assert.True(ValEq(t, validators[0], resVals[0])) // order doesn't matter here
|
|
assert.True(ValEq(t, validators[1], resVals[1]))
|
|
assert.True(ValEq(t, validators[2], resVals[2]))
|
|
|
|
// remove a record
|
|
keeper.RemoveValidator(ctx, validators[1].Owner)
|
|
_, found = keeper.GetValidator(ctx, addrVals[1])
|
|
assert.False(t, found)
|
|
}
|
|
|
|
// test how the validators are sorted, tests GetValidatorsByPower
|
|
func GetValidatorSortingUnmixed(t *testing.T) {
|
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
|
|
|
// initialize some validators into the state
|
|
amts := []int64{0, 100, 1, 400, 200}
|
|
n := len(amts)
|
|
var validators [5]types.Validator
|
|
for i, amt := range amts {
|
|
validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{})
|
|
validators[i].PoolShares = types.NewBondedShares(sdk.NewRat(amt))
|
|
validators[i].DelegatorShares = sdk.NewRat(amt)
|
|
keeper.UpdateValidator(ctx, validators[i])
|
|
}
|
|
|
|
// first make sure everything made it in to the gotValidator group
|
|
resValidators := keeper.GetValidatorsByPower(ctx)
|
|
require.Equal(t, n, len(resValidators))
|
|
assert.Equal(t, sdk.NewRat(400), resValidators[0].PoolShares.Bonded(), "%v", resValidators)
|
|
assert.Equal(t, sdk.NewRat(200), resValidators[1].PoolShares.Bonded(), "%v", resValidators)
|
|
assert.Equal(t, sdk.NewRat(100), resValidators[2].PoolShares.Bonded(), "%v", resValidators)
|
|
assert.Equal(t, sdk.NewRat(1), resValidators[3].PoolShares.Bonded(), "%v", resValidators)
|
|
assert.Equal(t, sdk.NewRat(0), resValidators[4].PoolShares.Bonded(), "%v", resValidators)
|
|
assert.Equal(t, validators[3].Owner, resValidators[0].Owner, "%v", resValidators)
|
|
assert.Equal(t, validators[4].Owner, resValidators[1].Owner, "%v", resValidators)
|
|
assert.Equal(t, validators[1].Owner, resValidators[2].Owner, "%v", resValidators)
|
|
assert.Equal(t, validators[2].Owner, resValidators[3].Owner, "%v", resValidators)
|
|
assert.Equal(t, validators[0].Owner, resValidators[4].Owner, "%v", resValidators)
|
|
|
|
// test a basic increase in voting power
|
|
validators[3].PoolShares = types.NewBondedShares(sdk.NewRat(500))
|
|
keeper.UpdateValidator(ctx, validators[3])
|
|
resValidators = keeper.GetValidatorsByPower(ctx)
|
|
require.Equal(t, len(resValidators), n)
|
|
assert.True(ValEq(t, validators[3], resValidators[0]))
|
|
|
|
// test a decrease in voting power
|
|
validators[3].PoolShares = types.NewBondedShares(sdk.NewRat(300))
|
|
keeper.UpdateValidator(ctx, validators[3])
|
|
resValidators = keeper.GetValidatorsByPower(ctx)
|
|
require.Equal(t, len(resValidators), n)
|
|
assert.True(ValEq(t, validators[3], resValidators[0]))
|
|
assert.True(ValEq(t, validators[4], resValidators[1]))
|
|
|
|
// test equal voting power, different age
|
|
validators[3].PoolShares = types.NewBondedShares(sdk.NewRat(200))
|
|
ctx = ctx.WithBlockHeight(10)
|
|
keeper.UpdateValidator(ctx, validators[3])
|
|
resValidators = keeper.GetValidatorsByPower(ctx)
|
|
require.Equal(t, len(resValidators), n)
|
|
assert.True(ValEq(t, validators[3], resValidators[0]))
|
|
assert.True(ValEq(t, validators[4], resValidators[1]))
|
|
assert.Equal(t, int64(0), resValidators[0].BondHeight, "%v", resValidators)
|
|
assert.Equal(t, int64(0), resValidators[1].BondHeight, "%v", resValidators)
|
|
|
|
// no change in voting power - no change in sort
|
|
ctx = ctx.WithBlockHeight(20)
|
|
keeper.UpdateValidator(ctx, validators[4])
|
|
resValidators = keeper.GetValidatorsByPower(ctx)
|
|
require.Equal(t, len(resValidators), n)
|
|
assert.True(ValEq(t, validators[3], resValidators[0]))
|
|
assert.True(ValEq(t, validators[4], resValidators[1]))
|
|
|
|
// change in voting power of both validators, both still in v-set, no age change
|
|
validators[3].PoolShares = types.NewBondedShares(sdk.NewRat(300))
|
|
validators[4].PoolShares = types.NewBondedShares(sdk.NewRat(300))
|
|
keeper.UpdateValidator(ctx, validators[3])
|
|
resValidators = keeper.GetValidatorsByPower(ctx)
|
|
require.Equal(t, len(resValidators), n)
|
|
ctx = ctx.WithBlockHeight(30)
|
|
keeper.UpdateValidator(ctx, validators[4])
|
|
resValidators = keeper.GetValidatorsByPower(ctx)
|
|
require.Equal(t, len(resValidators), n, "%v", resValidators)
|
|
assert.True(ValEq(t, validators[3], resValidators[0]))
|
|
assert.True(ValEq(t, validators[4], resValidators[1]))
|
|
}
|
|
|
|
func GetValidatorSortingMixed(t *testing.T) {
|
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
|
|
|
// now 2 max resValidators
|
|
params := keeper.GetParams(ctx)
|
|
params.MaxValidators = 2
|
|
keeper.SetParams(ctx, params)
|
|
|
|
// initialize some validators into the state
|
|
amts := []int64{0, 100, 1, 400, 200}
|
|
|
|
n := len(amts)
|
|
var validators [5]types.Validator
|
|
for i, amt := range amts {
|
|
validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{})
|
|
validators[i].DelegatorShares = sdk.NewRat(amt)
|
|
}
|
|
validators[0].PoolShares = types.NewUnbondedShares(sdk.NewRat(amts[0]))
|
|
validators[1].PoolShares = types.NewUnbondedShares(sdk.NewRat(amts[1]))
|
|
validators[2].PoolShares = types.NewUnbondedShares(sdk.NewRat(amts[2]))
|
|
validators[3].PoolShares = types.NewBondedShares(sdk.NewRat(amts[3]))
|
|
validators[4].PoolShares = types.NewBondedShares(sdk.NewRat(amts[4]))
|
|
for i := range amts {
|
|
keeper.UpdateValidator(ctx, validators[i])
|
|
}
|
|
val0, found := keeper.GetValidator(ctx, Addrs[0])
|
|
require.True(t, found)
|
|
val1, found := keeper.GetValidator(ctx, Addrs[1])
|
|
require.True(t, found)
|
|
val2, found := keeper.GetValidator(ctx, Addrs[2])
|
|
require.True(t, found)
|
|
val3, found := keeper.GetValidator(ctx, Addrs[3])
|
|
require.True(t, found)
|
|
val4, found := keeper.GetValidator(ctx, Addrs[4])
|
|
require.True(t, found)
|
|
assert.Equal(t, sdk.Unbonded, val0.Status())
|
|
assert.Equal(t, sdk.Unbonded, val1.Status())
|
|
assert.Equal(t, sdk.Unbonded, val2.Status())
|
|
assert.Equal(t, sdk.Bonded, val3.Status())
|
|
assert.Equal(t, sdk.Bonded, val4.Status())
|
|
|
|
// first make sure everything made it in to the gotValidator group
|
|
resValidators := keeper.GetValidatorsByPower(ctx)
|
|
require.Equal(t, n, len(resValidators))
|
|
assert.Equal(t, sdk.NewRat(400), resValidators[0].PoolShares.Bonded(), "%v", resValidators)
|
|
assert.Equal(t, sdk.NewRat(200), resValidators[1].PoolShares.Bonded(), "%v", resValidators)
|
|
assert.Equal(t, sdk.NewRat(100), resValidators[2].PoolShares.Bonded(), "%v", resValidators)
|
|
assert.Equal(t, sdk.NewRat(1), resValidators[3].PoolShares.Bonded(), "%v", resValidators)
|
|
assert.Equal(t, sdk.NewRat(0), resValidators[4].PoolShares.Bonded(), "%v", resValidators)
|
|
assert.Equal(t, validators[3].Owner, resValidators[0].Owner, "%v", resValidators)
|
|
assert.Equal(t, validators[4].Owner, resValidators[1].Owner, "%v", resValidators)
|
|
assert.Equal(t, validators[1].Owner, resValidators[2].Owner, "%v", resValidators)
|
|
assert.Equal(t, validators[2].Owner, resValidators[3].Owner, "%v", resValidators)
|
|
assert.Equal(t, validators[0].Owner, resValidators[4].Owner, "%v", resValidators)
|
|
}
|
|
|
|
// TODO separate out into multiple tests
|
|
func TestGetValidatorsEdgeCases(t *testing.T) {
|
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
|
var found bool
|
|
|
|
// now 2 max resValidators
|
|
params := keeper.GetParams(ctx)
|
|
nMax := uint16(2)
|
|
params.MaxValidators = nMax
|
|
keeper.SetParams(ctx, params)
|
|
|
|
// initialize some validators into the state
|
|
amts := []int64{0, 100, 400, 400}
|
|
var validators [4]types.Validator
|
|
for i, amt := range amts {
|
|
pool := keeper.GetPool(ctx)
|
|
validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{})
|
|
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt)
|
|
keeper.SetPool(ctx, pool)
|
|
validators[i] = keeper.UpdateValidator(ctx, validators[i])
|
|
}
|
|
for i := range amts {
|
|
validators[i], found = keeper.GetValidator(ctx, validators[i].Owner)
|
|
require.True(t, found)
|
|
}
|
|
resValidators := keeper.GetValidatorsByPower(ctx)
|
|
require.Equal(t, nMax, uint16(len(resValidators)))
|
|
assert.True(ValEq(t, validators[2], resValidators[0]))
|
|
assert.True(ValEq(t, validators[3], resValidators[1]))
|
|
|
|
pool := keeper.GetPool(ctx)
|
|
validators[0], pool, _ = validators[0].AddTokensFromDel(pool, 500)
|
|
keeper.SetPool(ctx, pool)
|
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
|
resValidators = keeper.GetValidatorsByPower(ctx)
|
|
require.Equal(t, nMax, uint16(len(resValidators)))
|
|
assert.True(ValEq(t, validators[0], resValidators[0]))
|
|
assert.True(ValEq(t, validators[2], resValidators[1]))
|
|
|
|
// A validator which leaves the gotValidator set due to a decrease in voting power,
|
|
// then increases to the original voting power, does not get its spot back in the
|
|
// case of a tie.
|
|
|
|
// validator 3 enters bonded validator set
|
|
ctx = ctx.WithBlockHeight(40)
|
|
|
|
validators[3], found = keeper.GetValidator(ctx, validators[3].Owner)
|
|
require.True(t, found)
|
|
validators[3], pool, _ = validators[3].AddTokensFromDel(pool, 1)
|
|
keeper.SetPool(ctx, pool)
|
|
validators[3] = keeper.UpdateValidator(ctx, validators[3])
|
|
resValidators = keeper.GetValidatorsByPower(ctx)
|
|
require.Equal(t, nMax, uint16(len(resValidators)))
|
|
assert.True(ValEq(t, validators[0], resValidators[0]))
|
|
assert.True(ValEq(t, validators[3], resValidators[1]))
|
|
|
|
// validator 3 kicked out temporarily
|
|
validators[3], pool, _ = validators[3].RemoveDelShares(pool, sdk.NewRat(201))
|
|
keeper.SetPool(ctx, pool)
|
|
validators[3] = keeper.UpdateValidator(ctx, validators[3])
|
|
resValidators = keeper.GetValidatorsByPower(ctx)
|
|
require.Equal(t, nMax, uint16(len(resValidators)))
|
|
assert.True(ValEq(t, validators[0], resValidators[0]))
|
|
assert.True(ValEq(t, validators[2], resValidators[1]))
|
|
|
|
// validator 4 does not get spot back
|
|
validators[3], pool, _ = validators[3].AddTokensFromDel(pool, 200)
|
|
keeper.SetPool(ctx, pool)
|
|
validators[3] = keeper.UpdateValidator(ctx, validators[3])
|
|
resValidators = keeper.GetValidatorsByPower(ctx)
|
|
require.Equal(t, nMax, uint16(len(resValidators)))
|
|
assert.True(ValEq(t, validators[0], resValidators[0]))
|
|
assert.True(ValEq(t, validators[2], resValidators[1]))
|
|
validator, exists := keeper.GetValidator(ctx, validators[3].Owner)
|
|
require.Equal(t, exists, true)
|
|
require.Equal(t, int64(40), validator.BondHeight)
|
|
}
|
|
|
|
func TestValidatorBondHeight(t *testing.T) {
|
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
|
|
|
// now 2 max resValidators
|
|
params := keeper.GetParams(ctx)
|
|
params.MaxValidators = 2
|
|
keeper.SetParams(ctx, params)
|
|
|
|
// initialize some validators into the state
|
|
pool := keeper.GetPool(ctx)
|
|
var validators [3]types.Validator
|
|
validators[0] = types.NewValidator(Addrs[0], PKs[0], types.Description{})
|
|
validators[1] = types.NewValidator(Addrs[1], PKs[1], types.Description{})
|
|
validators[2] = types.NewValidator(Addrs[2], PKs[2], types.Description{})
|
|
|
|
validators[0], pool, _ = validators[0].AddTokensFromDel(pool, 200)
|
|
validators[1], pool, _ = validators[1].AddTokensFromDel(pool, 100)
|
|
validators[2], pool, _ = validators[2].AddTokensFromDel(pool, 100)
|
|
|
|
keeper.SetPool(ctx, pool)
|
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
|
////////////////////////////////////////
|
|
// If two validators both increase to the same voting power in the same block,
|
|
// the one with the first transaction should become bonded
|
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
|
validators[2] = keeper.UpdateValidator(ctx, validators[2])
|
|
resValidators := keeper.GetValidatorsByPower(ctx)
|
|
require.Equal(t, uint16(len(resValidators)), params.MaxValidators)
|
|
|
|
assert.True(ValEq(t, validators[0], resValidators[0]))
|
|
assert.True(ValEq(t, validators[1], resValidators[1]))
|
|
validators[1], pool, _ = validators[1].AddTokensFromDel(pool, 50)
|
|
validators[2], pool, _ = validators[2].AddTokensFromDel(pool, 50)
|
|
keeper.SetPool(ctx, pool)
|
|
validators[2] = keeper.UpdateValidator(ctx, validators[2])
|
|
resValidators = keeper.GetValidatorsByPower(ctx)
|
|
require.Equal(t, params.MaxValidators, uint16(len(resValidators)))
|
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
|
assert.True(ValEq(t, validators[0], resValidators[0]))
|
|
assert.True(ValEq(t, validators[2], resValidators[1]))
|
|
}
|
|
|
|
func TestFullValidatorSetPowerChange(t *testing.T) {
|
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
|
params := keeper.GetParams(ctx)
|
|
max := 2
|
|
params.MaxValidators = uint16(2)
|
|
keeper.SetParams(ctx, params)
|
|
|
|
// initialize some validators into the state
|
|
amts := []int64{0, 100, 400, 400, 200}
|
|
var validators [5]types.Validator
|
|
for i, amt := range amts {
|
|
pool := keeper.GetPool(ctx)
|
|
validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{})
|
|
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt)
|
|
keeper.SetPool(ctx, pool)
|
|
keeper.UpdateValidator(ctx, validators[i])
|
|
}
|
|
for i := range amts {
|
|
var found bool
|
|
validators[i], found = keeper.GetValidator(ctx, validators[i].Owner)
|
|
require.True(t, found)
|
|
}
|
|
assert.Equal(t, sdk.Unbonded, validators[0].Status())
|
|
assert.Equal(t, sdk.Unbonded, validators[1].Status())
|
|
assert.Equal(t, sdk.Bonded, validators[2].Status())
|
|
assert.Equal(t, sdk.Bonded, validators[3].Status())
|
|
assert.Equal(t, sdk.Unbonded, validators[4].Status())
|
|
resValidators := keeper.GetValidatorsByPower(ctx)
|
|
require.Equal(t, max, len(resValidators))
|
|
assert.True(ValEq(t, validators[2], resValidators[0])) // in the order of txs
|
|
assert.True(ValEq(t, validators[3], resValidators[1]))
|
|
|
|
// test a swap in voting power
|
|
pool := keeper.GetPool(ctx)
|
|
validators[0], pool, _ = validators[0].AddTokensFromDel(pool, 600)
|
|
keeper.SetPool(ctx, pool)
|
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
|
resValidators = keeper.GetValidatorsByPower(ctx)
|
|
require.Equal(t, max, len(resValidators))
|
|
assert.True(ValEq(t, validators[0], resValidators[0]))
|
|
assert.True(ValEq(t, validators[2], resValidators[1]))
|
|
}
|
|
|
|
// clear the tracked changes to the gotValidator set
|
|
func TestClearTendermintUpdates(t *testing.T) {
|
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
|
|
|
amts := []int64{100, 400, 200}
|
|
validators := make([]types.Validator, len(amts))
|
|
for i, amt := range amts {
|
|
pool := keeper.GetPool(ctx)
|
|
validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{})
|
|
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt)
|
|
keeper.SetPool(ctx, pool)
|
|
keeper.UpdateValidator(ctx, validators[i])
|
|
}
|
|
|
|
updates := keeper.GetTendermintUpdates(ctx)
|
|
assert.Equal(t, len(amts), len(updates))
|
|
keeper.ClearTendermintUpdates(ctx)
|
|
updates = keeper.GetTendermintUpdates(ctx)
|
|
assert.Equal(t, 0, len(updates))
|
|
}
|
|
|
|
func TestGetTendermintUpdatesAllNone(t *testing.T) {
|
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
|
|
|
amts := []int64{10, 20}
|
|
var validators [2]types.Validator
|
|
for i, amt := range amts {
|
|
pool := keeper.GetPool(ctx)
|
|
validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{})
|
|
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt)
|
|
keeper.SetPool(ctx, pool)
|
|
}
|
|
|
|
// test from nothing to something
|
|
// tendermintUpdate set: {} -> {c1, c3}
|
|
assert.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
|
|
|
updates := keeper.GetTendermintUpdates(ctx)
|
|
require.Equal(t, 2, len(updates))
|
|
assert.Equal(t, validators[0].ABCIValidator(keeper.cdc), updates[0])
|
|
assert.Equal(t, validators[1].ABCIValidator(keeper.cdc), updates[1])
|
|
|
|
// test from something to nothing
|
|
// tendermintUpdate set: {} -> {c1, c2, c3, c4}
|
|
keeper.ClearTendermintUpdates(ctx)
|
|
assert.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
|
|
|
keeper.RemoveValidator(ctx, validators[0].Owner)
|
|
keeper.RemoveValidator(ctx, validators[1].Owner)
|
|
|
|
updates = keeper.GetTendermintUpdates(ctx)
|
|
require.Equal(t, 2, len(updates))
|
|
assert.Equal(t, tmtypes.TM2PB.PubKey(validators[0].PubKey), updates[0].PubKey)
|
|
assert.Equal(t, tmtypes.TM2PB.PubKey(validators[1].PubKey), updates[1].PubKey)
|
|
assert.Equal(t, int64(0), updates[0].Power)
|
|
assert.Equal(t, int64(0), updates[1].Power)
|
|
}
|
|
|
|
func TestGetTendermintUpdatesIdentical(t *testing.T) {
|
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
|
|
|
amts := []int64{10, 20}
|
|
var validators [2]types.Validator
|
|
for i, amt := range amts {
|
|
pool := keeper.GetPool(ctx)
|
|
validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{})
|
|
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt)
|
|
keeper.SetPool(ctx, pool)
|
|
}
|
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
|
keeper.ClearTendermintUpdates(ctx)
|
|
assert.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
|
|
|
// test identical,
|
|
// tendermintUpdate set: {} -> {}
|
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
|
assert.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
|
}
|
|
|
|
func TestGetTendermintUpdatesSingleValueChange(t *testing.T) {
|
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
|
|
|
amts := []int64{10, 20}
|
|
var validators [2]types.Validator
|
|
for i, amt := range amts {
|
|
pool := keeper.GetPool(ctx)
|
|
validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{})
|
|
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt)
|
|
keeper.SetPool(ctx, pool)
|
|
}
|
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
|
keeper.ClearTendermintUpdates(ctx)
|
|
assert.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
|
|
|
// test single value change
|
|
// tendermintUpdate set: {} -> {c1'}
|
|
validators[0].PoolShares = types.NewBondedShares(sdk.NewRat(600))
|
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
|
|
|
updates := keeper.GetTendermintUpdates(ctx)
|
|
|
|
require.Equal(t, 1, len(updates))
|
|
assert.Equal(t, validators[0].ABCIValidator(keeper.cdc), updates[0])
|
|
}
|
|
|
|
func TestGetTendermintUpdatesMultipleValueChange(t *testing.T) {
|
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
|
|
|
amts := []int64{10, 20}
|
|
var validators [2]types.Validator
|
|
for i, amt := range amts {
|
|
pool := keeper.GetPool(ctx)
|
|
validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{})
|
|
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt)
|
|
keeper.SetPool(ctx, pool)
|
|
}
|
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
|
keeper.ClearTendermintUpdates(ctx)
|
|
assert.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
|
|
|
// test multiple value change
|
|
// tendermintUpdate set: {c1, c3} -> {c1', c3'}
|
|
pool := keeper.GetPool(ctx)
|
|
validators[0], pool, _ = validators[0].AddTokensFromDel(pool, 190)
|
|
validators[1], pool, _ = validators[1].AddTokensFromDel(pool, 80)
|
|
keeper.SetPool(ctx, pool)
|
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
|
|
|
updates := keeper.GetTendermintUpdates(ctx)
|
|
require.Equal(t, 2, len(updates))
|
|
require.Equal(t, validators[0].ABCIValidator(keeper.cdc), updates[0])
|
|
require.Equal(t, validators[1].ABCIValidator(keeper.cdc), updates[1])
|
|
}
|
|
|
|
func TestGetTendermintUpdatesInserted(t *testing.T) {
|
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
|
|
|
amts := []int64{10, 20, 5, 15, 25}
|
|
var validators [5]types.Validator
|
|
for i, amt := range amts {
|
|
pool := keeper.GetPool(ctx)
|
|
validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{})
|
|
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt)
|
|
keeper.SetPool(ctx, pool)
|
|
}
|
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
|
keeper.ClearTendermintUpdates(ctx)
|
|
assert.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
|
|
|
// test validtor added at the beginning
|
|
// tendermintUpdate set: {} -> {c0}
|
|
validators[2] = keeper.UpdateValidator(ctx, validators[2])
|
|
updates := keeper.GetTendermintUpdates(ctx)
|
|
require.Equal(t, 1, len(updates))
|
|
require.Equal(t, validators[2].ABCIValidator(keeper.cdc), updates[0])
|
|
|
|
// test validtor added at the beginning
|
|
// tendermintUpdate set: {} -> {c0}
|
|
keeper.ClearTendermintUpdates(ctx)
|
|
validators[3] = keeper.UpdateValidator(ctx, validators[3])
|
|
updates = keeper.GetTendermintUpdates(ctx)
|
|
require.Equal(t, 1, len(updates))
|
|
require.Equal(t, validators[3].ABCIValidator(keeper.cdc), updates[0])
|
|
|
|
// test validtor added at the end
|
|
// tendermintUpdate set: {} -> {c0}
|
|
keeper.ClearTendermintUpdates(ctx)
|
|
validators[4] = keeper.UpdateValidator(ctx, validators[4])
|
|
updates = keeper.GetTendermintUpdates(ctx)
|
|
require.Equal(t, 1, len(updates))
|
|
require.Equal(t, validators[4].ABCIValidator(keeper.cdc), updates[0])
|
|
}
|
|
|
|
func TestGetTendermintUpdatesNotValidatorCliff(t *testing.T) {
|
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
|
params := types.DefaultParams()
|
|
params.MaxValidators = 2
|
|
keeper.SetParams(ctx, params)
|
|
|
|
amts := []int64{10, 20, 5}
|
|
var validators [5]types.Validator
|
|
for i, amt := range amts {
|
|
pool := keeper.GetPool(ctx)
|
|
validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{})
|
|
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt)
|
|
keeper.SetPool(ctx, pool)
|
|
}
|
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
|
keeper.ClearTendermintUpdates(ctx)
|
|
assert.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
|
|
|
// test validator added at the end but not inserted in the valset
|
|
// tendermintUpdate set: {} -> {}
|
|
keeper.UpdateValidator(ctx, validators[2])
|
|
updates := keeper.GetTendermintUpdates(ctx)
|
|
require.Equal(t, 0, len(updates))
|
|
|
|
// test validator change its power and become a gotValidator (pushing out an existing)
|
|
// tendermintUpdate set: {} -> {c0, c4}
|
|
keeper.ClearTendermintUpdates(ctx)
|
|
assert.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
|
|
|
pool := keeper.GetPool(ctx)
|
|
validators[2], pool, _ = validators[2].AddTokensFromDel(pool, 10)
|
|
keeper.SetPool(ctx, pool)
|
|
validators[2] = keeper.UpdateValidator(ctx, validators[2])
|
|
|
|
updates = keeper.GetTendermintUpdates(ctx)
|
|
require.Equal(t, 2, len(updates), "%v", updates)
|
|
require.Equal(t, validators[0].ABCIValidatorZero(keeper.cdc), updates[0])
|
|
require.Equal(t, validators[2].ABCIValidator(keeper.cdc), updates[1])
|
|
}
|