Merge PR #2238: Ensure Tendermint Validator Update Invariants
This commit is contained in:
parent
55b7c6adf1
commit
854aca2f7d
|
@ -122,6 +122,8 @@ BUG FIXES
|
||||||
* [cli] [\#2265](https://github.com/cosmos/cosmos-sdk/issues/2265) Fix JSON formatting of the `gaiacli send` command.
|
* [cli] [\#2265](https://github.com/cosmos/cosmos-sdk/issues/2265) Fix JSON formatting of the `gaiacli send` command.
|
||||||
|
|
||||||
* Gaia
|
* Gaia
|
||||||
|
* [x/stake] Return correct Tendermint validator update set on `EndBlocker` by not
|
||||||
|
including non previously bonded validators that have zero power. [#2189](https://github.com/cosmos/cosmos-sdk/issues/2189)
|
||||||
|
|
||||||
* SDK
|
* SDK
|
||||||
* [\#1988](https://github.com/cosmos/cosmos-sdk/issues/1988) Make us compile on OpenBSD (disable ledger) [#1988] (https://github.com/cosmos/cosmos-sdk/issues/1988)
|
* [\#1988](https://github.com/cosmos/cosmos-sdk/issues/1988) Make us compile on OpenBSD (disable ledger) [#1988] (https://github.com/cosmos/cosmos-sdk/issues/1988)
|
||||||
|
|
|
@ -12,7 +12,7 @@ the changes cleared
|
||||||
|
|
||||||
```golang
|
```golang
|
||||||
EndBlock() ValidatorSetChanges
|
EndBlock() ValidatorSetChanges
|
||||||
vsc = GetTendermintUpdates()
|
vsc = GetValidTendermintUpdates()
|
||||||
ClearTendermintUpdates()
|
ClearTendermintUpdates()
|
||||||
return vsc
|
return vsc
|
||||||
```
|
```
|
||||||
|
|
|
@ -156,13 +156,16 @@ func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.Operation {
|
||||||
return operationSimulateMsgVote(k, sk, nil, -1)
|
return operationSimulateMsgVote(k, sk, nil, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// nolint: unparam
|
// nolint: unparam
|
||||||
func operationSimulateMsgVote(k gov.Keeper, sk stake.Keeper, key crypto.PrivKey, proposalID int64) simulation.Operation {
|
func operationSimulateMsgVote(k gov.Keeper, sk stake.Keeper, key crypto.PrivKey, proposalID int64) simulation.Operation {
|
||||||
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
|
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
|
||||||
if key == nil {
|
if key == nil {
|
||||||
key = simulation.RandomKey(r, keys)
|
key = simulation.RandomKey(r, keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
var ok bool
|
var ok bool
|
||||||
|
|
||||||
if proposalID < 0 {
|
if proposalID < 0 {
|
||||||
proposalID, ok = randomProposalID(r, k, ctx)
|
proposalID, ok = randomProposalID(r, k, ctx)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -171,15 +174,18 @@ func operationSimulateMsgVote(k gov.Keeper, sk stake.Keeper, key crypto.PrivKey,
|
||||||
}
|
}
|
||||||
addr := sdk.AccAddress(key.PubKey().Address())
|
addr := sdk.AccAddress(key.PubKey().Address())
|
||||||
option := randomVotingOption(r)
|
option := randomVotingOption(r)
|
||||||
|
|
||||||
msg := gov.NewMsgVote(addr, proposalID, option)
|
msg := gov.NewMsgVote(addr, proposalID, option)
|
||||||
if msg.ValidateBasic() != nil {
|
if msg.ValidateBasic() != nil {
|
||||||
return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
|
return "", nil, fmt.Errorf("expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, write := ctx.CacheContext()
|
ctx, write := ctx.CacheContext()
|
||||||
result := gov.NewHandler(k)(ctx, msg)
|
result := gov.NewHandler(k)(ctx, msg)
|
||||||
if result.IsOK() {
|
if result.IsOK() {
|
||||||
write()
|
write()
|
||||||
}
|
}
|
||||||
|
|
||||||
event(fmt.Sprintf("gov/MsgVote/%v", result.IsOK()))
|
event(fmt.Sprintf("gov/MsgVote/%v", result.IsOK()))
|
||||||
action = fmt.Sprintf("TestMsgVote: ok %v, msg %s", result.IsOK(), msg.GetSignBytes())
|
action = fmt.Sprintf("TestMsgVote: ok %v, msg %s", result.IsOK(), msg.GetSignBytes())
|
||||||
return action, nil, nil
|
return action, nil, nil
|
||||||
|
|
|
@ -342,18 +342,14 @@ func RandomRequestBeginBlock(r *rand.Rand, validators map[string]mockValidator,
|
||||||
// updateValidators mimicks Tendermint's update logic
|
// updateValidators mimicks Tendermint's update logic
|
||||||
// nolint: unparam
|
// nolint: unparam
|
||||||
func updateValidators(tb testing.TB, r *rand.Rand, current map[string]mockValidator, updates []abci.Validator, event func(string)) map[string]mockValidator {
|
func updateValidators(tb testing.TB, r *rand.Rand, current map[string]mockValidator, updates []abci.Validator, event func(string)) map[string]mockValidator {
|
||||||
|
|
||||||
for _, update := range updates {
|
for _, update := range updates {
|
||||||
switch {
|
switch {
|
||||||
case update.Power == 0:
|
case update.Power == 0:
|
||||||
// // TEMPORARY DEBUG CODE TO PROVE THAT THE OLD METHOD WAS BROKEN
|
if _, ok := current[string(update.PubKey.Data)]; !ok {
|
||||||
// // (i.e. didn't catch in the event of problem)
|
tb.Fatalf("tried to delete a nonexistent validator")
|
||||||
// if val, ok := tb.(*testing.T); ok {
|
}
|
||||||
// require.NotNil(val, current[string(update.PubKey.Data)])
|
|
||||||
// }
|
|
||||||
// // CORRECT CHECK
|
|
||||||
// if _, ok := current[string(update.PubKey.Data)]; !ok {
|
|
||||||
// tb.Fatalf("tried to delete a nonexistent validator")
|
|
||||||
// }
|
|
||||||
event("endblock/validatorupdates/kicked")
|
event("endblock/validatorupdates/kicked")
|
||||||
delete(current, string(update.PubKey.Data))
|
delete(current, string(update.PubKey.Data))
|
||||||
default:
|
default:
|
||||||
|
@ -368,5 +364,6 @@ func updateValidators(tb testing.TB, r *rand.Rand, current map[string]mockValida
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return current
|
return current
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ func EndBlocker(ctx sdk.Context, k keeper.Keeper) (ValidatorUpdates []abci.Valid
|
||||||
k.SetIntraTxCounter(ctx, 0)
|
k.SetIntraTxCounter(ctx, 0)
|
||||||
|
|
||||||
// calculate validator set changes
|
// calculate validator set changes
|
||||||
ValidatorUpdates = k.GetTendermintUpdates(ctx)
|
ValidatorUpdates = k.GetValidTendermintUpdates(ctx)
|
||||||
k.ClearTendermintUpdates(ctx)
|
k.ClearTendermintUpdates(ctx)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,16 +198,37 @@ func (k Keeper) GetValidatorsByPower(ctx sdk.Context) []types.Validator {
|
||||||
// Accumulated updates to the active/bonded validator set for tendermint
|
// Accumulated updates to the active/bonded validator set for tendermint
|
||||||
|
|
||||||
// get the most recently updated validators
|
// get the most recently updated validators
|
||||||
func (k Keeper) GetTendermintUpdates(ctx sdk.Context) (updates []abci.Validator) {
|
//
|
||||||
|
// CONTRACT: Only validators with non-zero power or zero-power that were bonded
|
||||||
|
// at the previous block height or were removed from the validator set entirely
|
||||||
|
// are returned to Tendermint.
|
||||||
|
func (k Keeper) GetValidTendermintUpdates(ctx sdk.Context) (updates []abci.Validator) {
|
||||||
store := ctx.KVStore(k.storeKey)
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
|
||||||
iterator := sdk.KVStorePrefixIterator(store, TendermintUpdatesKey) //smallest to largest
|
iterator := sdk.KVStorePrefixIterator(store, TendermintUpdatesKey)
|
||||||
for ; iterator.Valid(); iterator.Next() {
|
for ; iterator.Valid(); iterator.Next() {
|
||||||
valBytes := iterator.Value()
|
var abciVal abci.Validator
|
||||||
var val abci.Validator
|
|
||||||
k.cdc.MustUnmarshalBinary(valBytes, &val)
|
abciValBytes := iterator.Value()
|
||||||
updates = append(updates, val)
|
k.cdc.MustUnmarshalBinary(abciValBytes, &abciVal)
|
||||||
|
|
||||||
|
val, found := k.GetValidator(ctx, abciVal.GetAddress())
|
||||||
|
if found {
|
||||||
|
// The validator is new or already exists in the store and must adhere to
|
||||||
|
// Tendermint invariants.
|
||||||
|
prevBonded := val.BondHeight < ctx.BlockHeight() && val.BondHeight > val.UnbondingHeight
|
||||||
|
zeroPower := val.GetPower().Equal(sdk.ZeroDec())
|
||||||
|
|
||||||
|
if !zeroPower || zeroPower && prevBonded {
|
||||||
|
updates = append(updates, abciVal)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Add the ABCI validator in such a case where the validator was removed
|
||||||
|
// from the store as it must have existed before.
|
||||||
|
updates = append(updates, abciVal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
iterator.Close()
|
iterator.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -240,7 +261,7 @@ func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) type
|
||||||
|
|
||||||
validator = k.updateForJailing(ctx, oldFound, oldValidator, validator)
|
validator = k.updateForJailing(ctx, oldFound, oldValidator, validator)
|
||||||
powerIncreasing := k.getPowerIncreasing(ctx, oldFound, oldValidator, validator)
|
powerIncreasing := k.getPowerIncreasing(ctx, oldFound, oldValidator, validator)
|
||||||
validator.BondHeight, validator.BondIntraTxCounter = k.bondIncrement(ctx, oldFound, oldValidator, validator)
|
validator.BondHeight, validator.BondIntraTxCounter = k.bondIncrement(ctx, oldFound, oldValidator)
|
||||||
valPower := k.updateValidatorPower(ctx, oldFound, oldValidator, validator, pool)
|
valPower := k.updateValidatorPower(ctx, oldFound, oldValidator, validator, pool)
|
||||||
cliffPower := k.GetCliffValidatorPower(ctx)
|
cliffPower := k.GetCliffValidatorPower(ctx)
|
||||||
cliffValExists := (cliffPower != nil)
|
cliffValExists := (cliffPower != nil)
|
||||||
|
@ -316,7 +337,7 @@ func (k Keeper) updateCliffValidator(ctx sdk.Context, affectedVal types.Validato
|
||||||
|
|
||||||
oldCliffVal, found := k.GetValidator(ctx, cliffAddr)
|
oldCliffVal, found := k.GetValidator(ctx, cliffAddr)
|
||||||
if !found {
|
if !found {
|
||||||
panic(fmt.Sprintf("cliff validator record not found for address: %v\n", cliffAddr))
|
panic(fmt.Sprintf("cliff validator record not found for address: %X\n", cliffAddr))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a validator iterator ranging from smallest to largest by power
|
// Create a validator iterator ranging from smallest to largest by power
|
||||||
|
@ -331,7 +352,7 @@ func (k Keeper) updateCliffValidator(ctx sdk.Context, affectedVal types.Validato
|
||||||
ensureValidatorFound(found, ownerAddr)
|
ensureValidatorFound(found, ownerAddr)
|
||||||
|
|
||||||
if currVal.Status != sdk.Bonded || currVal.Jailed {
|
if currVal.Status != sdk.Bonded || currVal.Jailed {
|
||||||
panic(fmt.Sprintf("unexpected jailed or unbonded validator for address: %s\n", ownerAddr))
|
panic(fmt.Sprintf("unexpected jailed or unbonded validator for address: %X\n", ownerAddr))
|
||||||
}
|
}
|
||||||
|
|
||||||
newCliffVal = currVal
|
newCliffVal = currVal
|
||||||
|
@ -344,13 +365,10 @@ func (k Keeper) updateCliffValidator(ctx sdk.Context, affectedVal types.Validato
|
||||||
newCliffValRank := GetValidatorsByPowerIndexKey(newCliffVal, pool)
|
newCliffValRank := GetValidatorsByPowerIndexKey(newCliffVal, pool)
|
||||||
|
|
||||||
if bytes.Equal(affectedVal.OperatorAddr, newCliffVal.OperatorAddr) {
|
if bytes.Equal(affectedVal.OperatorAddr, newCliffVal.OperatorAddr) {
|
||||||
|
|
||||||
// The affected validator remains the cliff validator, however, since
|
// The affected validator remains the cliff validator, however, since
|
||||||
// the store does not contain the new power, update the new power rank.
|
// the store does not contain the new power, update the new power rank.
|
||||||
store.Set(ValidatorPowerCliffKey, affectedValRank)
|
store.Set(ValidatorPowerCliffKey, affectedValRank)
|
||||||
|
|
||||||
} else if bytes.Compare(affectedValRank, newCliffValRank) > 0 {
|
} else if bytes.Compare(affectedValRank, newCliffValRank) > 0 {
|
||||||
|
|
||||||
// The affected validator no longer remains the cliff validator as it's
|
// The affected validator no longer remains the cliff validator as it's
|
||||||
// power is greater than the new cliff validator.
|
// power is greater than the new cliff validator.
|
||||||
k.setCliffValidator(ctx, newCliffVal, pool)
|
k.setCliffValidator(ctx, newCliffVal, pool)
|
||||||
|
@ -381,18 +399,20 @@ func (k Keeper) getPowerIncreasing(ctx sdk.Context, oldFound bool, oldValidator,
|
||||||
|
|
||||||
// get the bond height and incremented intra-tx counter
|
// get the bond height and incremented intra-tx counter
|
||||||
// nolint: unparam
|
// nolint: unparam
|
||||||
func (k Keeper) bondIncrement(ctx sdk.Context, oldFound bool, oldValidator,
|
func (k Keeper) bondIncrement(
|
||||||
newValidator types.Validator) (height int64, intraTxCounter int16) {
|
ctx sdk.Context, found bool, oldValidator types.Validator) (height int64, intraTxCounter int16) {
|
||||||
|
|
||||||
// if already a validator, copy the old block height and counter, else set them
|
// if already a validator, copy the old block height and counter
|
||||||
if oldFound && oldValidator.Status == sdk.Bonded {
|
if found && oldValidator.Status == sdk.Bonded {
|
||||||
height = oldValidator.BondHeight
|
height = oldValidator.BondHeight
|
||||||
intraTxCounter = oldValidator.BondIntraTxCounter
|
intraTxCounter = oldValidator.BondIntraTxCounter
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
height = ctx.BlockHeight()
|
height = ctx.BlockHeight()
|
||||||
counter := k.GetIntraTxCounter(ctx)
|
counter := k.GetIntraTxCounter(ctx)
|
||||||
intraTxCounter = counter
|
intraTxCounter = counter
|
||||||
|
|
||||||
k.SetIntraTxCounter(ctx, counter+1)
|
k.SetIntraTxCounter(ctx, counter+1)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -458,22 +478,20 @@ func (k Keeper) UpdateBondedValidators(
|
||||||
|
|
||||||
// if we've reached jailed validators no further bonded validators exist
|
// if we've reached jailed validators no further bonded validators exist
|
||||||
if validator.Jailed {
|
if validator.Jailed {
|
||||||
break
|
if validator.Status == sdk.Bonded {
|
||||||
|
panic(fmt.Sprintf("jailed validator cannot be bonded, address: %X\n", ownerAddr))
|
||||||
}
|
}
|
||||||
|
|
||||||
// increment bondedValidatorsCount / get the validator to bond
|
break
|
||||||
if validator.Status != sdk.Bonded {
|
|
||||||
validatorToBond = validator
|
|
||||||
if newValidatorBonded {
|
|
||||||
panic("already decided to bond a validator, can't bond another!")
|
|
||||||
}
|
|
||||||
newValidatorBonded = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// increment the total number of bonded validators and potentially mark
|
// increment the total number of bonded validators and potentially mark
|
||||||
// the validator to bond
|
// the validator to bond
|
||||||
if validator.Status != sdk.Bonded {
|
if validator.Status != sdk.Bonded {
|
||||||
validatorToBond = validator
|
validatorToBond = validator
|
||||||
|
if newValidatorBonded {
|
||||||
|
panic("already decided to bond a validator, can't bond another!")
|
||||||
|
}
|
||||||
newValidatorBonded = true
|
newValidatorBonded = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -507,7 +525,6 @@ func (k Keeper) UpdateBondedValidators(
|
||||||
// validator was newly bonded and has greater power
|
// validator was newly bonded and has greater power
|
||||||
k.beginUnbondingValidator(ctx, oldCliffVal)
|
k.beginUnbondingValidator(ctx, oldCliffVal)
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// otherwise begin unbonding the affected validator, which must
|
// otherwise begin unbonding the affected validator, which must
|
||||||
// have been kicked out
|
// have been kicked out
|
||||||
affectedValidator = k.beginUnbondingValidator(ctx, affectedValidator)
|
affectedValidator = k.beginUnbondingValidator(ctx, affectedValidator)
|
||||||
|
@ -653,6 +670,8 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types.
|
||||||
panic(fmt.Sprintf("should not already be bonded, validator: %v\n", validator))
|
panic(fmt.Sprintf("should not already be bonded, validator: %v\n", validator))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
validator.BondHeight = ctx.BlockHeight()
|
||||||
|
|
||||||
// set the status
|
// set the status
|
||||||
validator, pool = validator.UpdateStatus(pool, sdk.Bonded)
|
validator, pool = validator.UpdateStatus(pool, sdk.Bonded)
|
||||||
k.SetPool(ctx, pool)
|
k.SetPool(ctx, pool)
|
||||||
|
|
|
@ -16,8 +16,11 @@ func TestSetValidator(t *testing.T) {
|
||||||
ctx, _, keeper := CreateTestInput(t, false, 10)
|
ctx, _, keeper := CreateTestInput(t, false, 10)
|
||||||
pool := keeper.GetPool(ctx)
|
pool := keeper.GetPool(ctx)
|
||||||
|
|
||||||
|
valPubKey := PKs[0]
|
||||||
|
valAddr := sdk.ValAddress(valPubKey.Address().Bytes())
|
||||||
|
|
||||||
// test how the validator is set from a purely unbonbed pool
|
// test how the validator is set from a purely unbonbed pool
|
||||||
validator := types.NewValidator(addrVals[0], PKs[0], types.Description{})
|
validator := types.NewValidator(valAddr, valPubKey, types.Description{})
|
||||||
validator, pool, _ = validator.AddTokensFromDel(pool, sdk.NewInt(10))
|
validator, pool, _ = validator.AddTokensFromDel(pool, sdk.NewInt(10))
|
||||||
require.Equal(t, sdk.Unbonded, validator.Status)
|
require.Equal(t, sdk.Unbonded, validator.Status)
|
||||||
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
|
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
|
||||||
|
@ -26,14 +29,14 @@ func TestSetValidator(t *testing.T) {
|
||||||
keeper.UpdateValidator(ctx, validator)
|
keeper.UpdateValidator(ctx, validator)
|
||||||
|
|
||||||
// after the save the validator should be bonded
|
// after the save the validator should be bonded
|
||||||
validator, found := keeper.GetValidator(ctx, addrVals[0])
|
validator, found := keeper.GetValidator(ctx, valAddr)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
require.Equal(t, sdk.Bonded, validator.Status)
|
require.Equal(t, sdk.Bonded, validator.Status)
|
||||||
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
|
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
|
||||||
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares))
|
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares))
|
||||||
|
|
||||||
// Check each store for being saved
|
// Check each store for being saved
|
||||||
resVal, found := keeper.GetValidator(ctx, addrVals[0])
|
resVal, found := keeper.GetValidator(ctx, valAddr)
|
||||||
assert.True(ValEq(t, validator, resVal))
|
assert.True(ValEq(t, validator, resVal))
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
|
|
||||||
|
@ -45,7 +48,7 @@ func TestSetValidator(t *testing.T) {
|
||||||
require.Equal(t, 1, len(resVals))
|
require.Equal(t, 1, len(resVals))
|
||||||
assert.True(ValEq(t, validator, resVals[0]))
|
assert.True(ValEq(t, validator, resVals[0]))
|
||||||
|
|
||||||
updates := keeper.GetTendermintUpdates(ctx)
|
updates := keeper.GetValidTendermintUpdates(ctx)
|
||||||
require.Equal(t, 1, len(updates))
|
require.Equal(t, 1, len(updates))
|
||||||
require.Equal(t, validator.ABCIValidator(), updates[0])
|
require.Equal(t, validator.ABCIValidator(), updates[0])
|
||||||
}
|
}
|
||||||
|
@ -641,38 +644,47 @@ func TestClearTendermintUpdates(t *testing.T) {
|
||||||
validators := make([]types.Validator, len(amts))
|
validators := make([]types.Validator, len(amts))
|
||||||
for i, amt := range amts {
|
for i, amt := range amts {
|
||||||
pool := keeper.GetPool(ctx)
|
pool := keeper.GetPool(ctx)
|
||||||
validators[i] = types.NewValidator(sdk.ValAddress(Addrs[i]), PKs[i], types.Description{})
|
|
||||||
|
valPubKey := PKs[i]
|
||||||
|
valAddr := sdk.ValAddress(valPubKey.Address().Bytes())
|
||||||
|
|
||||||
|
validators[i] = types.NewValidator(valAddr, valPubKey, types.Description{})
|
||||||
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt))
|
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt))
|
||||||
|
|
||||||
keeper.SetPool(ctx, pool)
|
keeper.SetPool(ctx, pool)
|
||||||
keeper.UpdateValidator(ctx, validators[i])
|
keeper.UpdateValidator(ctx, validators[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
updates := keeper.GetTendermintUpdates(ctx)
|
updates := keeper.GetValidTendermintUpdates(ctx)
|
||||||
require.Equal(t, len(amts), len(updates))
|
require.Equal(t, len(amts), len(updates))
|
||||||
keeper.ClearTendermintUpdates(ctx)
|
keeper.ClearTendermintUpdates(ctx)
|
||||||
updates = keeper.GetTendermintUpdates(ctx)
|
updates = keeper.GetValidTendermintUpdates(ctx)
|
||||||
require.Equal(t, 0, len(updates))
|
require.Equal(t, 0, len(updates))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetTendermintUpdatesAllNone(t *testing.T) {
|
func TestGetValidTendermintUpdatesAllNone(t *testing.T) {
|
||||||
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
||||||
|
|
||||||
amts := []int64{10, 20}
|
amts := []int64{10, 20}
|
||||||
var validators [2]types.Validator
|
var validators [2]types.Validator
|
||||||
for i, amt := range amts {
|
for i, amt := range amts {
|
||||||
pool := keeper.GetPool(ctx)
|
pool := keeper.GetPool(ctx)
|
||||||
validators[i] = types.NewValidator(sdk.ValAddress(Addrs[i]), PKs[i], types.Description{})
|
|
||||||
|
valPubKey := PKs[i+1]
|
||||||
|
valAddr := sdk.ValAddress(valPubKey.Address().Bytes())
|
||||||
|
|
||||||
|
validators[i] = types.NewValidator(valAddr, valPubKey, types.Description{})
|
||||||
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt))
|
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt))
|
||||||
keeper.SetPool(ctx, pool)
|
keeper.SetPool(ctx, pool)
|
||||||
}
|
}
|
||||||
|
|
||||||
// test from nothing to something
|
// test from nothing to something
|
||||||
// tendermintUpdate set: {} -> {c1, c3}
|
// tendermintUpdate set: {} -> {c1, c3}
|
||||||
require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||||
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
||||||
|
|
||||||
updates := keeper.GetTendermintUpdates(ctx)
|
updates := keeper.GetValidTendermintUpdates(ctx)
|
||||||
assert.Equal(t, 2, len(updates))
|
assert.Equal(t, 2, len(updates))
|
||||||
assert.Equal(t, validators[0].ABCIValidator(), updates[0])
|
assert.Equal(t, validators[0].ABCIValidator(), updates[0])
|
||||||
assert.Equal(t, validators[1].ABCIValidator(), updates[1])
|
assert.Equal(t, validators[1].ABCIValidator(), updates[1])
|
||||||
|
@ -680,12 +692,12 @@ func TestGetTendermintUpdatesAllNone(t *testing.T) {
|
||||||
// test from something to nothing
|
// test from something to nothing
|
||||||
// tendermintUpdate set: {} -> {c1, c2, c3, c4}
|
// tendermintUpdate set: {} -> {c1, c2, c3, c4}
|
||||||
keeper.ClearTendermintUpdates(ctx)
|
keeper.ClearTendermintUpdates(ctx)
|
||||||
require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
|
|
||||||
keeper.RemoveValidator(ctx, validators[0].OperatorAddr)
|
keeper.RemoveValidator(ctx, validators[0].OperatorAddr)
|
||||||
keeper.RemoveValidator(ctx, validators[1].OperatorAddr)
|
keeper.RemoveValidator(ctx, validators[1].OperatorAddr)
|
||||||
|
|
||||||
updates = keeper.GetTendermintUpdates(ctx)
|
updates = keeper.GetValidTendermintUpdates(ctx)
|
||||||
assert.Equal(t, 2, len(updates))
|
assert.Equal(t, 2, len(updates))
|
||||||
assert.Equal(t, tmtypes.TM2PB.PubKey(validators[0].ConsPubKey), updates[0].PubKey)
|
assert.Equal(t, tmtypes.TM2PB.PubKey(validators[0].ConsPubKey), updates[0].PubKey)
|
||||||
assert.Equal(t, tmtypes.TM2PB.PubKey(validators[1].ConsPubKey), updates[1].PubKey)
|
assert.Equal(t, tmtypes.TM2PB.PubKey(validators[1].ConsPubKey), updates[1].PubKey)
|
||||||
|
@ -693,7 +705,7 @@ func TestGetTendermintUpdatesAllNone(t *testing.T) {
|
||||||
assert.Equal(t, int64(0), updates[1].Power)
|
assert.Equal(t, int64(0), updates[1].Power)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetTendermintUpdatesIdentical(t *testing.T) {
|
func TestGetValidTendermintUpdatesIdentical(t *testing.T) {
|
||||||
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
||||||
|
|
||||||
amts := []int64{10, 20}
|
amts := []int64{10, 20}
|
||||||
|
@ -707,16 +719,16 @@ func TestGetTendermintUpdatesIdentical(t *testing.T) {
|
||||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||||
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
||||||
keeper.ClearTendermintUpdates(ctx)
|
keeper.ClearTendermintUpdates(ctx)
|
||||||
require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
|
|
||||||
// test identical,
|
// test identical,
|
||||||
// tendermintUpdate set: {} -> {}
|
// tendermintUpdate set: {} -> {}
|
||||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||||
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
||||||
require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetTendermintUpdatesSingleValueChange(t *testing.T) {
|
func TestGetValidTendermintUpdatesSingleValueChange(t *testing.T) {
|
||||||
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
||||||
|
|
||||||
amts := []int64{10, 20}
|
amts := []int64{10, 20}
|
||||||
|
@ -730,7 +742,7 @@ func TestGetTendermintUpdatesSingleValueChange(t *testing.T) {
|
||||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||||
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
||||||
keeper.ClearTendermintUpdates(ctx)
|
keeper.ClearTendermintUpdates(ctx)
|
||||||
require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
|
|
||||||
// test single value change
|
// test single value change
|
||||||
// tendermintUpdate set: {} -> {c1'}
|
// tendermintUpdate set: {} -> {c1'}
|
||||||
|
@ -738,13 +750,13 @@ func TestGetTendermintUpdatesSingleValueChange(t *testing.T) {
|
||||||
validators[0].Tokens = sdk.NewDec(600)
|
validators[0].Tokens = sdk.NewDec(600)
|
||||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||||
|
|
||||||
updates := keeper.GetTendermintUpdates(ctx)
|
updates := keeper.GetValidTendermintUpdates(ctx)
|
||||||
|
|
||||||
require.Equal(t, 1, len(updates))
|
require.Equal(t, 1, len(updates))
|
||||||
require.Equal(t, validators[0].ABCIValidator(), updates[0])
|
require.Equal(t, validators[0].ABCIValidator(), updates[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetTendermintUpdatesMultipleValueChange(t *testing.T) {
|
func TestGetValidTendermintUpdatesMultipleValueChange(t *testing.T) {
|
||||||
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
||||||
|
|
||||||
amts := []int64{10, 20}
|
amts := []int64{10, 20}
|
||||||
|
@ -758,7 +770,7 @@ func TestGetTendermintUpdatesMultipleValueChange(t *testing.T) {
|
||||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||||
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
||||||
keeper.ClearTendermintUpdates(ctx)
|
keeper.ClearTendermintUpdates(ctx)
|
||||||
require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
|
|
||||||
// test multiple value change
|
// test multiple value change
|
||||||
// tendermintUpdate set: {c1, c3} -> {c1', c3'}
|
// tendermintUpdate set: {c1, c3} -> {c1', c3'}
|
||||||
|
@ -769,13 +781,13 @@ func TestGetTendermintUpdatesMultipleValueChange(t *testing.T) {
|
||||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||||
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
||||||
|
|
||||||
updates := keeper.GetTendermintUpdates(ctx)
|
updates := keeper.GetValidTendermintUpdates(ctx)
|
||||||
require.Equal(t, 2, len(updates))
|
require.Equal(t, 2, len(updates))
|
||||||
require.Equal(t, validators[0].ABCIValidator(), updates[0])
|
require.Equal(t, validators[0].ABCIValidator(), updates[0])
|
||||||
require.Equal(t, validators[1].ABCIValidator(), updates[1])
|
require.Equal(t, validators[1].ABCIValidator(), updates[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetTendermintUpdatesInserted(t *testing.T) {
|
func TestGetValidTendermintUpdatesInserted(t *testing.T) {
|
||||||
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
||||||
|
|
||||||
amts := []int64{10, 20, 5, 15, 25}
|
amts := []int64{10, 20, 5, 15, 25}
|
||||||
|
@ -789,12 +801,12 @@ func TestGetTendermintUpdatesInserted(t *testing.T) {
|
||||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||||
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
||||||
keeper.ClearTendermintUpdates(ctx)
|
keeper.ClearTendermintUpdates(ctx)
|
||||||
require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
|
|
||||||
// test validtor added at the beginning
|
// test validtor added at the beginning
|
||||||
// tendermintUpdate set: {} -> {c0}
|
// tendermintUpdate set: {} -> {c0}
|
||||||
validators[2] = keeper.UpdateValidator(ctx, validators[2])
|
validators[2] = keeper.UpdateValidator(ctx, validators[2])
|
||||||
updates := keeper.GetTendermintUpdates(ctx)
|
updates := keeper.GetValidTendermintUpdates(ctx)
|
||||||
require.Equal(t, 1, len(updates))
|
require.Equal(t, 1, len(updates))
|
||||||
require.Equal(t, validators[2].ABCIValidator(), updates[0])
|
require.Equal(t, validators[2].ABCIValidator(), updates[0])
|
||||||
|
|
||||||
|
@ -802,7 +814,7 @@ func TestGetTendermintUpdatesInserted(t *testing.T) {
|
||||||
// tendermintUpdate set: {} -> {c0}
|
// tendermintUpdate set: {} -> {c0}
|
||||||
keeper.ClearTendermintUpdates(ctx)
|
keeper.ClearTendermintUpdates(ctx)
|
||||||
validators[3] = keeper.UpdateValidator(ctx, validators[3])
|
validators[3] = keeper.UpdateValidator(ctx, validators[3])
|
||||||
updates = keeper.GetTendermintUpdates(ctx)
|
updates = keeper.GetValidTendermintUpdates(ctx)
|
||||||
require.Equal(t, 1, len(updates))
|
require.Equal(t, 1, len(updates))
|
||||||
require.Equal(t, validators[3].ABCIValidator(), updates[0])
|
require.Equal(t, validators[3].ABCIValidator(), updates[0])
|
||||||
|
|
||||||
|
@ -810,12 +822,12 @@ func TestGetTendermintUpdatesInserted(t *testing.T) {
|
||||||
// tendermintUpdate set: {} -> {c0}
|
// tendermintUpdate set: {} -> {c0}
|
||||||
keeper.ClearTendermintUpdates(ctx)
|
keeper.ClearTendermintUpdates(ctx)
|
||||||
validators[4] = keeper.UpdateValidator(ctx, validators[4])
|
validators[4] = keeper.UpdateValidator(ctx, validators[4])
|
||||||
updates = keeper.GetTendermintUpdates(ctx)
|
updates = keeper.GetValidTendermintUpdates(ctx)
|
||||||
require.Equal(t, 1, len(updates))
|
require.Equal(t, 1, len(updates))
|
||||||
require.Equal(t, validators[4].ABCIValidator(), updates[0])
|
require.Equal(t, validators[4].ABCIValidator(), updates[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetTendermintUpdatesWithCliffValidator(t *testing.T) {
|
func TestGetValidTendermintUpdatesWithCliffValidator(t *testing.T) {
|
||||||
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
||||||
params := types.DefaultParams()
|
params := types.DefaultParams()
|
||||||
params.MaxValidators = 2
|
params.MaxValidators = 2
|
||||||
|
@ -832,31 +844,31 @@ func TestGetTendermintUpdatesWithCliffValidator(t *testing.T) {
|
||||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||||
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
||||||
keeper.ClearTendermintUpdates(ctx)
|
keeper.ClearTendermintUpdates(ctx)
|
||||||
require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
|
|
||||||
// test validator added at the end but not inserted in the valset
|
// test validator added at the end but not inserted in the valset
|
||||||
// tendermintUpdate set: {} -> {}
|
// tendermintUpdate set: {} -> {}
|
||||||
keeper.UpdateValidator(ctx, validators[2])
|
keeper.UpdateValidator(ctx, validators[2])
|
||||||
updates := keeper.GetTendermintUpdates(ctx)
|
updates := keeper.GetValidTendermintUpdates(ctx)
|
||||||
require.Equal(t, 0, len(updates))
|
require.Equal(t, 0, len(updates))
|
||||||
|
|
||||||
// test validator change its power and become a gotValidator (pushing out an existing)
|
// test validator change its power and become a gotValidator (pushing out an existing)
|
||||||
// tendermintUpdate set: {} -> {c0, c4}
|
// tendermintUpdate set: {} -> {c0, c4}
|
||||||
keeper.ClearTendermintUpdates(ctx)
|
keeper.ClearTendermintUpdates(ctx)
|
||||||
require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
|
|
||||||
pool := keeper.GetPool(ctx)
|
pool := keeper.GetPool(ctx)
|
||||||
validators[2], pool, _ = validators[2].AddTokensFromDel(pool, sdk.NewInt(10))
|
validators[2], pool, _ = validators[2].AddTokensFromDel(pool, sdk.NewInt(10))
|
||||||
keeper.SetPool(ctx, pool)
|
keeper.SetPool(ctx, pool)
|
||||||
validators[2] = keeper.UpdateValidator(ctx, validators[2])
|
validators[2] = keeper.UpdateValidator(ctx, validators[2])
|
||||||
|
|
||||||
updates = keeper.GetTendermintUpdates(ctx)
|
updates = keeper.GetValidTendermintUpdates(ctx)
|
||||||
require.Equal(t, 2, len(updates), "%v", updates)
|
require.Equal(t, 2, len(updates), "%v", updates)
|
||||||
require.Equal(t, validators[0].ABCIValidatorZero(), updates[0])
|
require.Equal(t, validators[0].ABCIValidatorZero(), updates[0])
|
||||||
require.Equal(t, validators[2].ABCIValidator(), updates[1])
|
require.Equal(t, validators[2].ABCIValidator(), updates[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetTendermintUpdatesPowerDecrease(t *testing.T) {
|
func TestGetValidTendermintUpdatesPowerDecrease(t *testing.T) {
|
||||||
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
||||||
|
|
||||||
amts := []int64{100, 100}
|
amts := []int64{100, 100}
|
||||||
|
@ -870,7 +882,7 @@ func TestGetTendermintUpdatesPowerDecrease(t *testing.T) {
|
||||||
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
validators[0] = keeper.UpdateValidator(ctx, validators[0])
|
||||||
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
validators[1] = keeper.UpdateValidator(ctx, validators[1])
|
||||||
keeper.ClearTendermintUpdates(ctx)
|
keeper.ClearTendermintUpdates(ctx)
|
||||||
require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
|
|
||||||
// check initial power
|
// check initial power
|
||||||
require.Equal(t, sdk.NewDec(100).RoundInt64(), validators[0].GetPower().RoundInt64())
|
require.Equal(t, sdk.NewDec(100).RoundInt64(), validators[0].GetPower().RoundInt64())
|
||||||
|
@ -890,8 +902,158 @@ func TestGetTendermintUpdatesPowerDecrease(t *testing.T) {
|
||||||
require.Equal(t, sdk.NewDec(70).RoundInt64(), validators[1].GetPower().RoundInt64())
|
require.Equal(t, sdk.NewDec(70).RoundInt64(), validators[1].GetPower().RoundInt64())
|
||||||
|
|
||||||
// Tendermint updates should reflect power change
|
// Tendermint updates should reflect power change
|
||||||
updates := keeper.GetTendermintUpdates(ctx)
|
updates := keeper.GetValidTendermintUpdates(ctx)
|
||||||
require.Equal(t, 2, len(updates))
|
require.Equal(t, 2, len(updates))
|
||||||
require.Equal(t, validators[0].ABCIValidator(), updates[0])
|
require.Equal(t, validators[0].ABCIValidator(), updates[0])
|
||||||
require.Equal(t, validators[1].ABCIValidator(), updates[1])
|
require.Equal(t, validators[1].ABCIValidator(), updates[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetValidTendermintUpdatesNewValidator(t *testing.T) {
|
||||||
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
||||||
|
params := keeper.GetParams(ctx)
|
||||||
|
params.MaxValidators = uint16(3)
|
||||||
|
|
||||||
|
keeper.SetParams(ctx, params)
|
||||||
|
|
||||||
|
amts := []int64{100, 100}
|
||||||
|
var validators [2]types.Validator
|
||||||
|
|
||||||
|
// initialize some validators into the state
|
||||||
|
for i, amt := range amts {
|
||||||
|
pool := keeper.GetPool(ctx)
|
||||||
|
valPubKey := PKs[i+1]
|
||||||
|
valAddr := sdk.ValAddress(valPubKey.Address().Bytes())
|
||||||
|
|
||||||
|
validators[i] = types.NewValidator(valAddr, valPubKey, types.Description{})
|
||||||
|
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt))
|
||||||
|
|
||||||
|
keeper.SetPool(ctx, pool)
|
||||||
|
validators[i] = keeper.UpdateValidator(ctx, validators[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify initial Tendermint updates are correct
|
||||||
|
updates := keeper.GetValidTendermintUpdates(ctx)
|
||||||
|
require.Equal(t, len(validators), len(updates))
|
||||||
|
require.Equal(t, validators[0].ABCIValidator(), updates[0])
|
||||||
|
require.Equal(t, validators[1].ABCIValidator(), updates[1])
|
||||||
|
|
||||||
|
keeper.ClearTendermintUpdates(ctx)
|
||||||
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
|
|
||||||
|
// update initial validator set
|
||||||
|
for i, amt := range amts {
|
||||||
|
pool := keeper.GetPool(ctx)
|
||||||
|
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt))
|
||||||
|
|
||||||
|
keeper.SetPool(ctx, pool)
|
||||||
|
validators[i] = keeper.UpdateValidator(ctx, validators[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
// add a new validator that goes from zero power, to non-zero power, back to
|
||||||
|
// zero power
|
||||||
|
pool := keeper.GetPool(ctx)
|
||||||
|
valPubKey := PKs[len(validators)+1]
|
||||||
|
valAddr := sdk.ValAddress(valPubKey.Address().Bytes())
|
||||||
|
amt := sdk.NewInt(100)
|
||||||
|
|
||||||
|
validator := types.NewValidator(valAddr, valPubKey, types.Description{})
|
||||||
|
validator, pool, _ = validator.AddTokensFromDel(pool, amt)
|
||||||
|
|
||||||
|
keeper.SetPool(ctx, pool)
|
||||||
|
validator = keeper.UpdateValidator(ctx, validator)
|
||||||
|
|
||||||
|
validator, pool, _ = validator.RemoveDelShares(pool, sdk.NewDecFromInt(amt))
|
||||||
|
validator = keeper.UpdateValidator(ctx, validator)
|
||||||
|
|
||||||
|
// add a new validator that increases in power
|
||||||
|
valPubKey = PKs[len(validators)+2]
|
||||||
|
valAddr = sdk.ValAddress(valPubKey.Address().Bytes())
|
||||||
|
|
||||||
|
validator = types.NewValidator(valAddr, valPubKey, types.Description{})
|
||||||
|
validator, pool, _ = validator.AddTokensFromDel(pool, sdk.NewInt(500))
|
||||||
|
|
||||||
|
keeper.SetPool(ctx, pool)
|
||||||
|
validator = keeper.UpdateValidator(ctx, validator)
|
||||||
|
|
||||||
|
// verify initial Tendermint updates are correct
|
||||||
|
updates = keeper.GetValidTendermintUpdates(ctx)
|
||||||
|
require.Equal(t, len(validators)+1, len(updates))
|
||||||
|
require.Equal(t, validator.ABCIValidator(), updates[0])
|
||||||
|
require.Equal(t, validators[0].ABCIValidator(), updates[1])
|
||||||
|
require.Equal(t, validators[1].ABCIValidator(), updates[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetValidTendermintUpdatesBondTransition(t *testing.T) {
|
||||||
|
ctx, _, keeper := CreateTestInput(t, false, 1000)
|
||||||
|
params := keeper.GetParams(ctx)
|
||||||
|
params.MaxValidators = uint16(2)
|
||||||
|
|
||||||
|
keeper.SetParams(ctx, params)
|
||||||
|
|
||||||
|
amts := []int64{100, 200, 300}
|
||||||
|
var validators [3]types.Validator
|
||||||
|
|
||||||
|
// initialize some validators into the state
|
||||||
|
for i, amt := range amts {
|
||||||
|
pool := keeper.GetPool(ctx)
|
||||||
|
moniker := fmt.Sprintf("%d", i)
|
||||||
|
valPubKey := PKs[i+1]
|
||||||
|
valAddr := sdk.ValAddress(valPubKey.Address().Bytes())
|
||||||
|
|
||||||
|
validators[i] = types.NewValidator(valAddr, valPubKey, types.Description{Moniker: moniker})
|
||||||
|
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt))
|
||||||
|
|
||||||
|
keeper.SetPool(ctx, pool)
|
||||||
|
validators[i] = keeper.UpdateValidator(ctx, validators[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify initial Tendermint updates are correct
|
||||||
|
updates := keeper.GetValidTendermintUpdates(ctx)
|
||||||
|
require.Equal(t, 2, len(updates))
|
||||||
|
require.Equal(t, validators[2].ABCIValidator(), updates[0])
|
||||||
|
require.Equal(t, validators[1].ABCIValidator(), updates[1])
|
||||||
|
|
||||||
|
keeper.ClearTendermintUpdates(ctx)
|
||||||
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
|
|
||||||
|
// delegate to validator with lowest power but not enough to bond
|
||||||
|
ctx = ctx.WithBlockHeight(1)
|
||||||
|
pool := keeper.GetPool(ctx)
|
||||||
|
|
||||||
|
validator, found := keeper.GetValidator(ctx, validators[0].OperatorAddr)
|
||||||
|
require.True(t, found)
|
||||||
|
|
||||||
|
validator, pool, _ = validator.AddTokensFromDel(pool, sdk.NewInt(1))
|
||||||
|
|
||||||
|
keeper.SetPool(ctx, pool)
|
||||||
|
validators[0] = keeper.UpdateValidator(ctx, validator)
|
||||||
|
|
||||||
|
// verify initial Tendermint updates are correct
|
||||||
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
|
|
||||||
|
// create a series of events that will bond and unbond the validator with
|
||||||
|
// lowest power in a single block context (height)
|
||||||
|
ctx = ctx.WithBlockHeight(2)
|
||||||
|
pool = keeper.GetPool(ctx)
|
||||||
|
|
||||||
|
validator, found = keeper.GetValidator(ctx, validators[1].OperatorAddr)
|
||||||
|
require.True(t, found)
|
||||||
|
|
||||||
|
validator, pool, _ = validator.RemoveDelShares(pool, validator.DelegatorShares)
|
||||||
|
|
||||||
|
keeper.SetPool(ctx, pool)
|
||||||
|
validator = keeper.UpdateValidator(ctx, validator)
|
||||||
|
|
||||||
|
validator, pool, _ = validator.AddTokensFromDel(pool, sdk.NewInt(250))
|
||||||
|
|
||||||
|
keeper.SetPool(ctx, pool)
|
||||||
|
validators[1] = keeper.UpdateValidator(ctx, validator)
|
||||||
|
|
||||||
|
// verify initial Tendermint updates are correct
|
||||||
|
updates = keeper.GetValidTendermintUpdates(ctx)
|
||||||
|
require.Equal(t, 1, len(updates))
|
||||||
|
require.Equal(t, validators[1].ABCIValidator(), updates[0])
|
||||||
|
|
||||||
|
keeper.ClearTendermintUpdates(ctx)
|
||||||
|
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue