Merge PR #3400: power reduction for Tendermint
* add uncompiled power functionality * fix some compile errors * Power -> TendermintPower * tests rename GetTendermintPower * test fix * working * fix delegation tests * fix slash tests * staking/keeper tests passing * docs reversion * debuggin workin * x/staking test pass * fix gov tests * fix x/slashing tests * working distribution test fixes * fix distribution tests * lint * fix lcd tests * fix gov test * lint * CLI fixes, rm stakingTypes * typos * working cli fixes * cli test fix * cli tests fixed * testnet creation modification * typo * pending * Sanitize Dec.Roundint64 (#3475) * merge fixes * @cwgoes comments * fix tests * change power reduction to 10^-6 * option to turn off minting for LCD tests
This commit is contained in:
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
"github.com/cosmos/cosmos-sdk/x/mock"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking"
|
||||
stakingTypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -26,7 +25,7 @@ func getMockApp(t *testing.T) (*mock.App, staking.Keeper, Keeper) {
|
||||
mapp := mock.NewApp()
|
||||
|
||||
RegisterCodec(mapp.Cdc)
|
||||
stakingTypes.RegisterCodec(mapp.Cdc)
|
||||
staking.RegisterCodec(mapp.Cdc)
|
||||
|
||||
keyStaking := sdk.NewKVStoreKey(staking.StoreKey)
|
||||
tkeyStaking := sdk.NewTransientStoreKey(staking.TStoreKey)
|
||||
@@ -62,7 +61,8 @@ func getInitChainer(mapp *mock.App, keeper staking.Keeper) sdk.InitChainer {
|
||||
return func(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
|
||||
mapp.InitChainer(ctx, req)
|
||||
stakingGenesis := staking.DefaultGenesisState()
|
||||
stakingGenesis.Pool.NotBondedTokens = sdk.NewInt(100000)
|
||||
tokens := staking.TokensFromTendermintPower(100000)
|
||||
stakingGenesis.Pool.NotBondedTokens = tokens
|
||||
validators, err := staking.InitGenesis(ctx, keeper, stakingGenesis)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -93,8 +93,10 @@ func checkValidatorSigningInfo(t *testing.T, mapp *mock.App, keeper Keeper,
|
||||
func TestSlashingMsgs(t *testing.T) {
|
||||
mapp, stakingKeeper, keeper := getMockApp(t)
|
||||
|
||||
genCoin := sdk.NewInt64Coin(stakingTypes.DefaultBondDenom, 42)
|
||||
bondCoin := sdk.NewInt64Coin(stakingTypes.DefaultBondDenom, 10)
|
||||
genTokens := staking.TokensFromTendermintPower(42)
|
||||
bondTokens := staking.TokensFromTendermintPower(10)
|
||||
genCoin := sdk.NewCoin(staking.DefaultBondDenom, genTokens)
|
||||
bondCoin := sdk.NewCoin(staking.DefaultBondDenom, bondTokens)
|
||||
|
||||
acc1 := &auth.BaseAccount{
|
||||
Address: addr1,
|
||||
@@ -116,7 +118,7 @@ func TestSlashingMsgs(t *testing.T) {
|
||||
validator := checkValidator(t, mapp, stakingKeeper, addr1, true)
|
||||
require.Equal(t, sdk.ValAddress(addr1), validator.OperatorAddr)
|
||||
require.Equal(t, sdk.Bonded, validator.Status)
|
||||
require.True(sdk.IntEq(t, sdk.NewInt(10), validator.BondedTokens()))
|
||||
require.True(sdk.IntEq(t, bondTokens, validator.BondedTokens()))
|
||||
unjailMsg := MsgUnjail{ValidatorAddr: sdk.ValAddress(validator.ConsPubKey.Address())}
|
||||
|
||||
// no signing info yet
|
||||
|
||||
@@ -8,24 +8,25 @@ import (
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
func TestCannotUnjailUnlessJailed(t *testing.T) {
|
||||
// initial setup
|
||||
ctx, ck, sk, _, keeper := createTestInput(t, DefaultParams())
|
||||
slh := NewHandler(keeper)
|
||||
amtInt := int64(100)
|
||||
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
|
||||
amt := types.TokensFromTendermintPower(100)
|
||||
addr, val := addrs[0], pks[0]
|
||||
msg := NewTestMsgCreateValidator(addr, val, amt)
|
||||
got := staking.NewHandler(sk)(ctx, msg)
|
||||
require.True(t, got.IsOK())
|
||||
require.True(t, got.IsOK(), "%v", got)
|
||||
staking.EndBlocker(ctx, sk)
|
||||
|
||||
require.Equal(
|
||||
t, ck.GetCoins(ctx, sdk.AccAddress(addr)),
|
||||
sdk.Coins{sdk.NewCoin(sk.GetParams(ctx).BondDenom, initCoins.Sub(amt))},
|
||||
)
|
||||
require.True(sdk.IntEq(t, amt, sk.Validator(ctx, addr).GetPower()))
|
||||
require.Equal(t, amt, sk.Validator(ctx, addr).GetBondedTokens())
|
||||
|
||||
// assert non-jailed validator can't be unjailed
|
||||
got = slh(ctx, NewMsgUnjail(addr))
|
||||
@@ -42,8 +43,8 @@ func TestJailedValidatorDelegations(t *testing.T) {
|
||||
stakingKeeper.SetParams(ctx, stakingParams)
|
||||
|
||||
// create a validator
|
||||
amount := int64(10)
|
||||
valPubKey, bondAmount := pks[0], sdk.NewInt(amount)
|
||||
bondAmount := staking.TokensFromTendermintPower(10)
|
||||
valPubKey := pks[0]
|
||||
valAddr, consAddr := addrs[1], sdk.ConsAddress(addrs[0])
|
||||
|
||||
msgCreateVal := NewTestMsgCreateValidator(valAddr, valPubKey, bondAmount)
|
||||
@@ -54,12 +55,7 @@ func TestJailedValidatorDelegations(t *testing.T) {
|
||||
staking.EndBlocker(ctx, stakingKeeper)
|
||||
|
||||
// set dummy signing info
|
||||
newInfo := ValidatorSigningInfo{
|
||||
StartHeight: int64(0),
|
||||
IndexOffset: int64(0),
|
||||
JailedUntil: time.Unix(0, 0),
|
||||
MissedBlocksCounter: int64(0),
|
||||
}
|
||||
newInfo := NewValidatorSigningInfo(0, 0, time.Unix(0, 0), false, 0)
|
||||
slashingKeeper.SetValidatorSigningInfo(ctx, consAddr, newInfo)
|
||||
|
||||
// delegate tokens to the validator
|
||||
@@ -68,7 +64,7 @@ func TestJailedValidatorDelegations(t *testing.T) {
|
||||
got = staking.NewHandler(stakingKeeper)(ctx, msgDelegate)
|
||||
require.True(t, got.IsOK(), "expected delegation to be ok, got %v", got)
|
||||
|
||||
unbondShares := sdk.NewDec(10)
|
||||
unbondShares := sdk.NewDecFromInt(bondAmount)
|
||||
|
||||
// unbond validator total self-delegations (which should jail the validator)
|
||||
msgUndelegate := staking.NewMsgUndelegate(sdk.AccAddress(valAddr), valAddr, unbondShares)
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
staking "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
staking "github.com/cosmos/cosmos-sdk/x/staking"
|
||||
)
|
||||
|
||||
// Keeper of the slashing store
|
||||
@@ -49,7 +49,8 @@ func (k Keeper) handleDoubleSign(ctx sdk.Context, addr crypto.Address, infractio
|
||||
|
||||
// Reject evidence if the double is too old
|
||||
if age > k.MaxEvidenceAge(ctx) {
|
||||
logger.Info(fmt.Sprintf("Ignored double sign from %s at height %d, age of %d past max age of %d", pubkey.Address(), infractionHeight, age, k.MaxEvidenceAge(ctx)))
|
||||
logger.Info(fmt.Sprintf("Ignored double sign from %s at height %d, age of %d past max age of %d",
|
||||
pubkey.Address(), infractionHeight, age, k.MaxEvidenceAge(ctx)))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
+60
-50
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
// Have to change these parameters for tests
|
||||
@@ -30,8 +31,9 @@ func TestHandleDoubleSign(t *testing.T) {
|
||||
ctx, ck, sk, _, keeper := createTestInput(t, keeperTestParams())
|
||||
// validator added pre-genesis
|
||||
ctx = ctx.WithBlockHeight(-1)
|
||||
amtInt := int64(100)
|
||||
operatorAddr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
|
||||
power := int64(100)
|
||||
amt := staking.TokensFromTendermintPower(power)
|
||||
operatorAddr, val := addrs[0], pks[0]
|
||||
got := staking.NewHandler(sk)(ctx, NewTestMsgCreateValidator(operatorAddr, val, amt))
|
||||
require.True(t, got.IsOK())
|
||||
staking.EndBlocker(ctx, sk)
|
||||
@@ -39,15 +41,15 @@ func TestHandleDoubleSign(t *testing.T) {
|
||||
t, ck.GetCoins(ctx, sdk.AccAddress(operatorAddr)),
|
||||
sdk.Coins{sdk.NewCoin(sk.GetParams(ctx).BondDenom, initCoins.Sub(amt))},
|
||||
)
|
||||
require.True(sdk.IntEq(t, amt, sk.Validator(ctx, operatorAddr).GetPower()))
|
||||
require.Equal(t, amt, sk.Validator(ctx, operatorAddr).GetBondedTokens())
|
||||
|
||||
// handle a signature to set signing info
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, true)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), amt.Int64(), true)
|
||||
|
||||
oldTokens := sk.Validator(ctx, operatorAddr).GetTokens()
|
||||
|
||||
// double sign less than max age
|
||||
keeper.handleDoubleSign(ctx, val.Address(), 0, time.Unix(0, 0), amtInt)
|
||||
keeper.handleDoubleSign(ctx, val.Address(), 0, time.Unix(0, 0), power)
|
||||
|
||||
// should be jailed
|
||||
require.True(t, sk.Validator(ctx, operatorAddr).GetJailed())
|
||||
@@ -57,7 +59,7 @@ func TestHandleDoubleSign(t *testing.T) {
|
||||
require.True(t, newTokens.LT(oldTokens))
|
||||
|
||||
// New evidence
|
||||
keeper.handleDoubleSign(ctx, val.Address(), 0, time.Unix(0, 0), amtInt)
|
||||
keeper.handleDoubleSign(ctx, val.Address(), 0, time.Unix(0, 0), power)
|
||||
|
||||
// tokens should be the same (capped slash)
|
||||
require.True(t, sk.Validator(ctx, operatorAddr).GetTokens().Equal(newTokens))
|
||||
@@ -87,8 +89,9 @@ func TestPastMaxEvidenceAge(t *testing.T) {
|
||||
ctx, ck, sk, _, keeper := createTestInput(t, keeperTestParams())
|
||||
// validator added pre-genesis
|
||||
ctx = ctx.WithBlockHeight(-1)
|
||||
amtInt := int64(100)
|
||||
operatorAddr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
|
||||
power := int64(100)
|
||||
amt := staking.TokensFromTendermintPower(power)
|
||||
operatorAddr, val := addrs[0], pks[0]
|
||||
got := staking.NewHandler(sk)(ctx, NewTestMsgCreateValidator(operatorAddr, val, amt))
|
||||
require.True(t, got.IsOK())
|
||||
staking.EndBlocker(ctx, sk)
|
||||
@@ -96,23 +99,23 @@ func TestPastMaxEvidenceAge(t *testing.T) {
|
||||
t, ck.GetCoins(ctx, sdk.AccAddress(operatorAddr)),
|
||||
sdk.Coins{sdk.NewCoin(sk.GetParams(ctx).BondDenom, initCoins.Sub(amt))},
|
||||
)
|
||||
require.True(sdk.IntEq(t, amt, sk.Validator(ctx, operatorAddr).GetPower()))
|
||||
require.Equal(t, amt, sk.Validator(ctx, operatorAddr).GetBondedTokens())
|
||||
|
||||
// handle a signature to set signing info
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, true)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), power, true)
|
||||
|
||||
ctx = ctx.WithBlockHeader(abci.Header{Time: time.Unix(1, 0).Add(keeper.MaxEvidenceAge(ctx))})
|
||||
|
||||
oldPower := sk.Validator(ctx, operatorAddr).GetPower()
|
||||
oldPower := sk.Validator(ctx, operatorAddr).GetTendermintPower()
|
||||
|
||||
// double sign past max age
|
||||
keeper.handleDoubleSign(ctx, val.Address(), 0, time.Unix(0, 0), amtInt)
|
||||
keeper.handleDoubleSign(ctx, val.Address(), 0, time.Unix(0, 0), power)
|
||||
|
||||
// should still be bonded
|
||||
require.True(t, sk.Validator(ctx, operatorAddr).GetStatus() == sdk.Bonded)
|
||||
|
||||
// should still have same power
|
||||
require.True(t, sk.Validator(ctx, operatorAddr).GetPower().Equal(oldPower))
|
||||
require.Equal(t, oldPower, sk.Validator(ctx, operatorAddr).GetTendermintPower())
|
||||
}
|
||||
|
||||
// Test a validator through uptime, downtime, revocation,
|
||||
@@ -121,8 +124,9 @@ func TestHandleAbsentValidator(t *testing.T) {
|
||||
|
||||
// initial setup
|
||||
ctx, ck, sk, _, keeper := createTestInput(t, keeperTestParams())
|
||||
amtInt64 := int64(100)
|
||||
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt64)
|
||||
power := int64(100)
|
||||
amt := staking.TokensFromTendermintPower(power)
|
||||
addr, val := addrs[0], pks[0]
|
||||
sh := staking.NewHandler(sk)
|
||||
slh := NewHandler(keeper)
|
||||
got := sh(ctx, NewTestMsgCreateValidator(addr, val, amt))
|
||||
@@ -133,7 +137,7 @@ func TestHandleAbsentValidator(t *testing.T) {
|
||||
t, ck.GetCoins(ctx, sdk.AccAddress(addr)),
|
||||
sdk.Coins{sdk.NewCoin(sk.GetParams(ctx).BondDenom, initCoins.Sub(amt))},
|
||||
)
|
||||
require.True(sdk.IntEq(t, amt, sk.Validator(ctx, addr).GetPower()))
|
||||
require.Equal(t, amt, sk.Validator(ctx, addr).GetBondedTokens())
|
||||
|
||||
// will exist since the validator has been bonded
|
||||
info, found := keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address()))
|
||||
@@ -147,7 +151,7 @@ func TestHandleAbsentValidator(t *testing.T) {
|
||||
// 1000 first blocks OK
|
||||
for ; height < keeper.SignedBlocksWindow(ctx); height++ {
|
||||
ctx = ctx.WithBlockHeight(height)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), amtInt64, true)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), power, true)
|
||||
}
|
||||
info, found = keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address()))
|
||||
require.True(t, found)
|
||||
@@ -157,7 +161,7 @@ func TestHandleAbsentValidator(t *testing.T) {
|
||||
// 500 blocks missed
|
||||
for ; height < keeper.SignedBlocksWindow(ctx)+(keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx)); height++ {
|
||||
ctx = ctx.WithBlockHeight(height)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), amtInt64, false)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), power, false)
|
||||
}
|
||||
info, found = keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address()))
|
||||
require.True(t, found)
|
||||
@@ -172,7 +176,7 @@ func TestHandleAbsentValidator(t *testing.T) {
|
||||
|
||||
// 501st block missed
|
||||
ctx = ctx.WithBlockHeight(height)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), amtInt64, false)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), power, false)
|
||||
info, found = keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address()))
|
||||
require.True(t, found)
|
||||
require.Equal(t, int64(0), info.StartHeight)
|
||||
@@ -186,15 +190,15 @@ func TestHandleAbsentValidator(t *testing.T) {
|
||||
validator, _ = sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val))
|
||||
require.Equal(t, sdk.Unbonding, validator.GetStatus())
|
||||
|
||||
slashAmt := sdk.NewDec(amtInt64).Mul(keeper.SlashFractionDowntime(ctx)).RoundInt64()
|
||||
slashAmt := sdk.NewDecFromInt(amt).Mul(keeper.SlashFractionDowntime(ctx)).RoundInt64()
|
||||
|
||||
// validator should have been slashed
|
||||
require.Equal(t, amtInt64-slashAmt, validator.GetTokens().Int64())
|
||||
require.Equal(t, amt.Int64()-slashAmt, validator.GetTokens().Int64())
|
||||
|
||||
// 502nd block *also* missed (since the LastCommit would have still included the just-unbonded validator)
|
||||
height++
|
||||
ctx = ctx.WithBlockHeight(height)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), amtInt64, false)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), power, false)
|
||||
info, found = keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address()))
|
||||
require.True(t, found)
|
||||
require.Equal(t, int64(0), info.StartHeight)
|
||||
@@ -205,7 +209,7 @@ func TestHandleAbsentValidator(t *testing.T) {
|
||||
|
||||
// validator should not have been slashed any more, since it was already jailed
|
||||
validator, _ = sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val))
|
||||
require.Equal(t, amtInt64-slashAmt, validator.GetTokens().Int64())
|
||||
require.Equal(t, amt.Int64()-slashAmt, validator.GetTokens().Int64())
|
||||
|
||||
// unrevocation should fail prior to jail expiration
|
||||
got = slh(ctx, NewMsgUnjail(addr))
|
||||
@@ -225,7 +229,7 @@ func TestHandleAbsentValidator(t *testing.T) {
|
||||
|
||||
// validator should have been slashed
|
||||
pool = sk.GetPool(ctx)
|
||||
require.Equal(t, amtInt64-slashAmt, pool.BondedTokens.Int64())
|
||||
require.Equal(t, amt.Int64()-slashAmt, pool.BondedTokens.Int64())
|
||||
|
||||
// Validator start height should not have been changed
|
||||
info, found = keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address()))
|
||||
@@ -237,7 +241,7 @@ func TestHandleAbsentValidator(t *testing.T) {
|
||||
// validator should not be immediately jailed again
|
||||
height++
|
||||
ctx = ctx.WithBlockHeight(height)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), amtInt64, false)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), power, false)
|
||||
validator, _ = sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val))
|
||||
require.Equal(t, sdk.Bonded, validator.GetStatus())
|
||||
|
||||
@@ -245,7 +249,7 @@ func TestHandleAbsentValidator(t *testing.T) {
|
||||
nextHeight := height + keeper.MinSignedPerWindow(ctx) + 1
|
||||
for ; height < nextHeight; height++ {
|
||||
ctx = ctx.WithBlockHeight(height)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), amtInt64, false)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), power, false)
|
||||
}
|
||||
|
||||
// end block
|
||||
@@ -255,7 +259,7 @@ func TestHandleAbsentValidator(t *testing.T) {
|
||||
nextHeight = height + keeper.MinSignedPerWindow(ctx) + 1
|
||||
for ; height <= nextHeight; height++ {
|
||||
ctx = ctx.WithBlockHeight(height)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), amtInt64, false)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), power, false)
|
||||
}
|
||||
|
||||
// end block
|
||||
@@ -271,22 +275,23 @@ func TestHandleAbsentValidator(t *testing.T) {
|
||||
func TestHandleNewValidator(t *testing.T) {
|
||||
// initial setup
|
||||
ctx, ck, sk, _, keeper := createTestInput(t, keeperTestParams())
|
||||
addr, val, amt := addrs[0], pks[0], int64(100)
|
||||
addr, val := addrs[0], pks[0]
|
||||
amt := staking.TokensFromTendermintPower(100)
|
||||
sh := staking.NewHandler(sk)
|
||||
|
||||
// 1000 first blocks not a validator
|
||||
ctx = ctx.WithBlockHeight(keeper.SignedBlocksWindow(ctx) + 1)
|
||||
|
||||
// Validator created
|
||||
got := sh(ctx, NewTestMsgCreateValidator(addr, val, sdk.NewInt(amt)))
|
||||
got := sh(ctx, NewTestMsgCreateValidator(addr, val, amt))
|
||||
require.True(t, got.IsOK())
|
||||
staking.EndBlocker(ctx, sk)
|
||||
|
||||
require.Equal(
|
||||
t, ck.GetCoins(ctx, sdk.AccAddress(addr)),
|
||||
sdk.Coins{sdk.NewCoin(sk.GetParams(ctx).BondDenom, initCoins.SubRaw(amt))},
|
||||
sdk.Coins{sdk.NewCoin(sk.GetParams(ctx).BondDenom, initCoins.Sub(amt))},
|
||||
)
|
||||
require.Equal(t, amt, sk.Validator(ctx, addr).GetPower().Int64())
|
||||
require.Equal(t, amt, sk.Validator(ctx, addr).GetBondedTokens())
|
||||
|
||||
// Now a validator, for two blocks
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), 100, true)
|
||||
@@ -304,7 +309,8 @@ func TestHandleNewValidator(t *testing.T) {
|
||||
validator, _ := sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val))
|
||||
require.Equal(t, sdk.Bonded, validator.GetStatus())
|
||||
pool := sk.GetPool(ctx)
|
||||
require.Equal(t, int64(100), pool.BondedTokens.Int64())
|
||||
expTokens := staking.TokensFromTendermintPower(100)
|
||||
require.Equal(t, expTokens, pool.BondedTokens)
|
||||
}
|
||||
|
||||
// Test a jailed validator being "down" twice
|
||||
@@ -313,8 +319,9 @@ func TestHandleAlreadyJailed(t *testing.T) {
|
||||
|
||||
// initial setup
|
||||
ctx, _, sk, _, keeper := createTestInput(t, DefaultParams())
|
||||
amtInt := int64(100)
|
||||
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
|
||||
power := int64(100)
|
||||
amt := staking.TokensFromTendermintPower(power)
|
||||
addr, val := addrs[0], pks[0]
|
||||
sh := staking.NewHandler(sk)
|
||||
got := sh(ctx, NewTestMsgCreateValidator(addr, val, amt))
|
||||
require.True(t, got.IsOK())
|
||||
@@ -324,13 +331,13 @@ func TestHandleAlreadyJailed(t *testing.T) {
|
||||
height := int64(0)
|
||||
for ; height < keeper.SignedBlocksWindow(ctx); height++ {
|
||||
ctx = ctx.WithBlockHeight(height)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, true)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), power, true)
|
||||
}
|
||||
|
||||
// 501 blocks missed
|
||||
for ; height < keeper.SignedBlocksWindow(ctx)+(keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx))+1; height++ {
|
||||
ctx = ctx.WithBlockHeight(height)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), power, false)
|
||||
}
|
||||
|
||||
// end block
|
||||
@@ -341,15 +348,16 @@ func TestHandleAlreadyJailed(t *testing.T) {
|
||||
require.Equal(t, sdk.Unbonding, validator.GetStatus())
|
||||
|
||||
// validator should have been slashed
|
||||
require.Equal(t, amtInt-1, validator.GetTokens().Int64())
|
||||
resultingTokens := amt.Sub(staking.TokensFromTendermintPower(1))
|
||||
require.Equal(t, resultingTokens, validator.GetTokens())
|
||||
|
||||
// another block missed
|
||||
ctx = ctx.WithBlockHeight(height)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), power, false)
|
||||
|
||||
// validator should not have been slashed twice
|
||||
validator, _ = sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val))
|
||||
require.Equal(t, amtInt-1, validator.GetTokens().Int64())
|
||||
require.Equal(t, resultingTokens, validator.GetTokens())
|
||||
|
||||
}
|
||||
|
||||
@@ -364,8 +372,9 @@ func TestValidatorDippingInAndOut(t *testing.T) {
|
||||
params := sk.GetParams(ctx)
|
||||
params.MaxValidators = 1
|
||||
sk.SetParams(ctx, params)
|
||||
amtInt := int64(100)
|
||||
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
|
||||
power := int64(100)
|
||||
amt := staking.TokensFromTendermintPower(power)
|
||||
addr, val := addrs[0], pks[0]
|
||||
consAddr := sdk.ConsAddress(addr)
|
||||
sh := staking.NewHandler(sk)
|
||||
got := sh(ctx, NewTestMsgCreateValidator(addr, val, amt))
|
||||
@@ -376,12 +385,12 @@ func TestValidatorDippingInAndOut(t *testing.T) {
|
||||
height := int64(0)
|
||||
for ; height < int64(100); height++ {
|
||||
ctx = ctx.WithBlockHeight(height)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, true)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), power, true)
|
||||
}
|
||||
|
||||
// validator kicked out of validator set
|
||||
newAmt := int64(101)
|
||||
got = sh(ctx, NewTestMsgCreateValidator(addrs[1], pks[1], sdk.NewInt(newAmt)))
|
||||
newAmt := staking.TokensFromTendermintPower(101)
|
||||
got = sh(ctx, NewTestMsgCreateValidator(addrs[1], pks[1], newAmt))
|
||||
require.True(t, got.IsOK())
|
||||
validatorUpdates, _ := staking.EndBlocker(ctx, sk)
|
||||
require.Equal(t, 2, len(validatorUpdates))
|
||||
@@ -393,16 +402,17 @@ func TestValidatorDippingInAndOut(t *testing.T) {
|
||||
ctx = ctx.WithBlockHeight(height)
|
||||
|
||||
// validator added back in
|
||||
got = sh(ctx, newTestMsgDelegate(sdk.AccAddress(addrs[2]), addrs[0], sdk.NewInt(3)))
|
||||
delTokens := types.TokensFromTendermintPower(3)
|
||||
got = sh(ctx, newTestMsgDelegate(sdk.AccAddress(addrs[2]), addrs[0], delTokens))
|
||||
require.True(t, got.IsOK())
|
||||
validatorUpdates, _ = staking.EndBlocker(ctx, sk)
|
||||
require.Equal(t, 2, len(validatorUpdates))
|
||||
validator, _ = sk.GetValidator(ctx, addr)
|
||||
require.Equal(t, sdk.Bonded, validator.Status)
|
||||
newAmt = int64(103)
|
||||
newPower := int64(103)
|
||||
|
||||
// validator misses a block
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), newAmt, false)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), newPower, false)
|
||||
height++
|
||||
|
||||
// shouldn't be jailed/kicked yet
|
||||
@@ -413,7 +423,7 @@ func TestValidatorDippingInAndOut(t *testing.T) {
|
||||
latest := height
|
||||
for ; height < latest+500; height++ {
|
||||
ctx = ctx.WithBlockHeight(height)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), newAmt, false)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), newPower, false)
|
||||
}
|
||||
|
||||
// should now be jailed & kicked
|
||||
@@ -438,7 +448,7 @@ func TestValidatorDippingInAndOut(t *testing.T) {
|
||||
|
||||
// validator rejoins and starts signing again
|
||||
sk.Unjail(ctx, consAddr)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), newAmt, true)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), newPower, true)
|
||||
height++
|
||||
|
||||
// validator should not be kicked since we reset counter/array when it was jailed
|
||||
@@ -450,7 +460,7 @@ func TestValidatorDippingInAndOut(t *testing.T) {
|
||||
latest = height
|
||||
for ; height < latest+501; height++ {
|
||||
ctx = ctx.WithBlockHeight(height)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), newAmt, false)
|
||||
keeper.handleValidatorSignature(ctx, val.Address(), newPower, false)
|
||||
}
|
||||
|
||||
// validator should now be jailed & kicked
|
||||
|
||||
@@ -81,11 +81,13 @@ func DefaultParams() Params {
|
||||
// TODO Temporarily set to 10 minutes for testnets
|
||||
DowntimeJailDuration: 60 * 10 * time.Second,
|
||||
|
||||
// CONTRACT must be less than 1
|
||||
// TODO enforce this contract https://github.com/cosmos/cosmos-sdk/issues/3474
|
||||
MinSignedPerWindow: sdk.NewDecWithPrec(5, 1),
|
||||
|
||||
SlashFractionDoubleSign: sdk.NewDec(1).Quo(sdk.NewDec(20)),
|
||||
SlashFractionDoubleSign: sdk.NewDec(1).QuoInt64(20),
|
||||
|
||||
SlashFractionDowntime: sdk.NewDec(1).Quo(sdk.NewDec(100)),
|
||||
SlashFractionDowntime: sdk.NewDec(1).QuoInt64(100),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +109,10 @@ func (k Keeper) MinSignedPerWindow(ctx sdk.Context) int64 {
|
||||
var minSignedPerWindow sdk.Dec
|
||||
k.paramspace.Get(ctx, KeyMinSignedPerWindow, &minSignedPerWindow)
|
||||
signedBlocksWindow := k.SignedBlocksWindow(ctx)
|
||||
return sdk.NewDec(signedBlocksWindow).Mul(minSignedPerWindow).RoundInt64()
|
||||
|
||||
// NOTE: RoundInt64 will never panic as minSignedPerWindow is
|
||||
// less than 1.
|
||||
return minSignedPerWindow.MulInt64(signedBlocksWindow).RoundInt64()
|
||||
}
|
||||
|
||||
// Downtime unbond duration
|
||||
|
||||
+13
-11
@@ -90,17 +90,6 @@ func (k Keeper) clearValidatorMissedBlockBitArray(ctx sdk.Context, address sdk.C
|
||||
}
|
||||
}
|
||||
|
||||
// Construct a new `ValidatorSigningInfo` struct
|
||||
func NewValidatorSigningInfo(startHeight int64, indexOffset int64, jailedUntil time.Time, tombstoned bool, missedBlocksCounter int64) ValidatorSigningInfo {
|
||||
return ValidatorSigningInfo{
|
||||
StartHeight: startHeight,
|
||||
IndexOffset: indexOffset,
|
||||
JailedUntil: jailedUntil,
|
||||
Tombstoned: tombstoned,
|
||||
MissedBlocksCounter: missedBlocksCounter,
|
||||
}
|
||||
}
|
||||
|
||||
// Signing info for a validator
|
||||
type ValidatorSigningInfo struct {
|
||||
StartHeight int64 `json:"start_height"` // height at which validator was first a candidate OR was unjailed
|
||||
@@ -110,6 +99,19 @@ type ValidatorSigningInfo struct {
|
||||
MissedBlocksCounter int64 `json:"missed_blocks_counter"` // missed blocks counter (to avoid scanning the array every time)
|
||||
}
|
||||
|
||||
// Construct a new `ValidatorSigningInfo` struct
|
||||
func NewValidatorSigningInfo(startHeight, indexOffset int64, jailedUntil time.Time,
|
||||
tombstoned bool, missedBlocksCounter int64) ValidatorSigningInfo {
|
||||
|
||||
return ValidatorSigningInfo{
|
||||
StartHeight: startHeight,
|
||||
IndexOffset: indexOffset,
|
||||
JailedUntil: jailedUntil,
|
||||
Tombstoned: tombstoned,
|
||||
MissedBlocksCounter: missedBlocksCounter,
|
||||
}
|
||||
}
|
||||
|
||||
// Return human readable signing info
|
||||
func (i ValidatorSigningInfo) String() string {
|
||||
return fmt.Sprintf(`Start Height: %d
|
||||
|
||||
@@ -21,7 +21,6 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking"
|
||||
stakingTypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
// TODO remove dependencies on staking (should only refer to validator set type from sdk)
|
||||
@@ -37,7 +36,7 @@ var (
|
||||
sdk.ValAddress(pks[1].Address()),
|
||||
sdk.ValAddress(pks[2].Address()),
|
||||
}
|
||||
initCoins = sdk.NewInt(200)
|
||||
initCoins = staking.TokensFromTendermintPower(200)
|
||||
)
|
||||
|
||||
func createTestCodec() *codec.Codec {
|
||||
@@ -76,7 +75,7 @@ func createTestInput(t *testing.T, defaults Params) (sdk.Context, bank.Keeper, s
|
||||
sk := staking.NewKeeper(cdc, keyStaking, tkeyStaking, ck, paramsKeeper.Subspace(staking.DefaultParamspace), staking.DefaultCodespace)
|
||||
genesis := staking.DefaultGenesisState()
|
||||
|
||||
genesis.Pool.NotBondedTokens = sdk.NewInt(initCoins.MulRaw(int64(len(addrs))).Int64())
|
||||
genesis.Pool.NotBondedTokens = initCoins.MulRaw(int64(len(addrs)))
|
||||
|
||||
_, err = staking.InitGenesis(ctx, sk, genesis)
|
||||
require.Nil(t, err)
|
||||
@@ -116,7 +115,7 @@ func testAddr(addr string) sdk.AccAddress {
|
||||
func NewTestMsgCreateValidator(address sdk.ValAddress, pubKey crypto.PubKey, amt sdk.Int) staking.MsgCreateValidator {
|
||||
commission := staking.NewCommissionMsg(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec())
|
||||
return staking.NewMsgCreateValidator(
|
||||
address, pubKey, sdk.NewCoin(stakingTypes.DefaultBondDenom, amt),
|
||||
address, pubKey, sdk.NewCoin(staking.DefaultBondDenom, amt),
|
||||
staking.Description{}, commission,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -10,11 +10,14 @@ import (
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
func TestBeginBlocker(t *testing.T) {
|
||||
ctx, ck, sk, _, keeper := createTestInput(t, DefaultParams())
|
||||
addr, pk, amt := addrs[2], pks[2], sdk.NewInt(100)
|
||||
power := int64(100)
|
||||
amt := types.TokensFromTendermintPower(power)
|
||||
addr, pk := addrs[2], pks[2]
|
||||
|
||||
// bond the validator
|
||||
got := staking.NewHandler(sk)(ctx, NewTestMsgCreateValidator(addr, pk, amt))
|
||||
@@ -24,7 +27,7 @@ func TestBeginBlocker(t *testing.T) {
|
||||
t, ck.GetCoins(ctx, sdk.AccAddress(addr)),
|
||||
sdk.Coins{sdk.NewCoin(sk.GetParams(ctx).BondDenom, initCoins.Sub(amt))},
|
||||
)
|
||||
require.True(sdk.IntEq(t, amt, sk.Validator(ctx, addr).GetPower()))
|
||||
require.Equal(t, amt, sk.Validator(ctx, addr).GetBondedTokens())
|
||||
|
||||
val := abci.Validator{
|
||||
Address: pk.Address(),
|
||||
|
||||
Reference in New Issue
Block a user