diff --git a/simapp/test_helpers.go b/simapp/test_helpers.go index a557e7f5d..300235fe1 100644 --- a/simapp/test_helpers.go +++ b/simapp/test_helpers.go @@ -116,6 +116,25 @@ func createIncrementalAccounts(accNum int) []sdk.AccAddress { return addresses } +// AddTestAddrsFromPubKeys adds the addresses into the SimApp providing only the public keys. +func AddTestAddrsFromPubKeys(app *SimApp, ctx sdk.Context, pubKeys []crypto.PubKey, accAmt sdk.Int) { + initCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), accAmt)) + + setTotalSupply(app, ctx, accAmt, len(pubKeys)) + + // fill all the addresses with some coins, set the loose pool tokens simultaneously + for _, pubKey := range pubKeys { + saveAccount(app, ctx, sdk.AccAddress(pubKey.Address()), initCoins) + } +} + +// setTotalSupply provides the total supply based on accAmt * totalAccounts. +func setTotalSupply(app *SimApp, ctx sdk.Context, accAmt sdk.Int, totalAccounts int) { + totalSupply := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), accAmt.MulRaw(int64(totalAccounts)))) + prevSupply := app.SupplyKeeper.GetSupply(ctx) + app.SupplyKeeper.SetSupply(ctx, supply.NewSupply(prevSupply.GetTotal().Add(totalSupply...))) +} + // AddTestAddrs constructs and returns accNum amount of accounts with an // initial balance of accAmt in random order func AddTestAddrs(app *SimApp, ctx sdk.Context, accNum int, accAmt sdk.Int) []sdk.AccAddress { @@ -132,23 +151,26 @@ func addTestAddrs(app *SimApp, ctx sdk.Context, accNum int, accAmt sdk.Int, stra testAddrs := strategy(accNum) initCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), accAmt)) - totalSupply := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), accAmt.MulRaw(int64(len(testAddrs))))) - prevSupply := app.SupplyKeeper.GetSupply(ctx) - app.SupplyKeeper.SetSupply(ctx, supply.NewSupply(prevSupply.GetTotal().Add(totalSupply...))) + setTotalSupply(app, ctx, accAmt, accNum) // fill all the addresses with some coins, set the loose pool tokens simultaneously for _, addr := range testAddrs { - acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr) - app.AccountKeeper.SetAccount(ctx, acc) - - _, err := app.BankKeeper.AddCoins(ctx, addr, initCoins) - if err != nil { - panic(err) - } + saveAccount(app, ctx, addr, initCoins) } + return testAddrs } +// saveAccount saves the provided account into the simapp with balance based on initCoins. +func saveAccount(app *SimApp, ctx sdk.Context, addr sdk.AccAddress, initCoins sdk.Coins) { + acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr) + app.AccountKeeper.SetAccount(ctx, acc) + _, err := app.BankKeeper.AddCoins(ctx, addr, initCoins) + if err != nil { + panic(err) + } +} + // ConvertAddrsToValAddrs converts the provided addresses to ValAddress. func ConvertAddrsToValAddrs(addrs []sdk.AccAddress) []sdk.ValAddress { valAddrs := make([]sdk.ValAddress, len(addrs)) diff --git a/x/slashing/abci_test.go b/x/slashing/abci_test.go index c1b0f62ff..cd9efc553 100644 --- a/x/slashing/abci_test.go +++ b/x/slashing/abci_test.go @@ -4,32 +4,37 @@ import ( "testing" "time" - "github.com/stretchr/testify/require" - abci "github.com/tendermint/tendermint/abci/types" - + "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/slashing" slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" "github.com/cosmos/cosmos-sdk/x/staking" + "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" ) func TestBeginBlocker(t *testing.T) { - ctx, bk, sk, _, keeper := slashingkeeper.CreateTestInput(t, slashing.DefaultParams()) + app := simapp.Setup(false) + ctx := app.BaseApp.NewContext(false, abci.Header{}) + + pks := simapp.CreateTestPubKeys(1) + simapp.AddTestAddrsFromPubKeys(app, ctx, pks, sdk.TokensFromConsensusPower(200)) + power := int64(100) amt := sdk.TokensFromConsensusPower(power) - addr, pk := slashingkeeper.Addrs[2], slashingkeeper.Pks[2] + addr, pk := sdk.ValAddress(pks[0].Address()), pks[0] // bond the validator - res, err := staking.NewHandler(sk)(ctx, slashingkeeper.NewTestMsgCreateValidator(addr, pk, amt)) + res, err := staking.NewHandler(app.StakingKeeper)(ctx, slashingkeeper.NewTestMsgCreateValidator(addr, pk, amt)) require.NoError(t, err) require.NotNil(t, res) - staking.EndBlocker(ctx, sk) + staking.EndBlocker(ctx, app.StakingKeeper) require.Equal( - t, bk.GetAllBalances(ctx, sdk.AccAddress(addr)), - sdk.NewCoins(sdk.NewCoin(sk.GetParams(ctx).BondDenom, slashingkeeper.InitTokens.Sub(amt))), + t, app.BankKeeper.GetAllBalances(ctx, sdk.AccAddress(addr)), + sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.GetParams(ctx).BondDenom, slashingkeeper.InitTokens.Sub(amt))), ) - require.Equal(t, amt, sk.Validator(ctx, addr).GetBondedTokens()) + require.Equal(t, amt, app.StakingKeeper.Validator(ctx, addr).GetBondedTokens()) val := abci.Validator{ Address: pk.Address(), @@ -46,9 +51,9 @@ func TestBeginBlocker(t *testing.T) { }, } - slashing.BeginBlocker(ctx, req, keeper) + slashing.BeginBlocker(ctx, req, app.SlashingKeeper) - info, found := keeper.GetValidatorSigningInfo(ctx, sdk.ConsAddress(pk.Address())) + info, found := app.SlashingKeeper.GetValidatorSigningInfo(ctx, sdk.ConsAddress(pk.Address())) require.True(t, found) require.Equal(t, ctx.BlockHeight(), info.StartHeight) require.Equal(t, int64(1), info.IndexOffset) @@ -58,7 +63,7 @@ func TestBeginBlocker(t *testing.T) { height := int64(0) // for 1000 blocks, mark the validator as having signed - for ; height < keeper.SignedBlocksWindow(ctx); height++ { + for ; height < app.SlashingKeeper.SignedBlocksWindow(ctx); height++ { ctx = ctx.WithBlockHeight(height) req = abci.RequestBeginBlock{ LastCommitInfo: abci.LastCommitInfo{ @@ -69,11 +74,11 @@ func TestBeginBlocker(t *testing.T) { }, } - slashing.BeginBlocker(ctx, req, keeper) + slashing.BeginBlocker(ctx, req, app.SlashingKeeper) } // for 500 blocks, mark the validator as having not signed - for ; height < ((keeper.SignedBlocksWindow(ctx) * 2) - keeper.MinSignedPerWindow(ctx) + 1); height++ { + for ; height < ((app.SlashingKeeper.SignedBlocksWindow(ctx) * 2) - app.SlashingKeeper.MinSignedPerWindow(ctx) + 1); height++ { ctx = ctx.WithBlockHeight(height) req = abci.RequestBeginBlock{ LastCommitInfo: abci.LastCommitInfo{ @@ -84,14 +89,14 @@ func TestBeginBlocker(t *testing.T) { }, } - slashing.BeginBlocker(ctx, req, keeper) + slashing.BeginBlocker(ctx, req, app.SlashingKeeper) } // end block - staking.EndBlocker(ctx, sk) + staking.EndBlocker(ctx, app.StakingKeeper) // validator should be jailed - validator, found := sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(pk)) + validator, found := app.StakingKeeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(pk)) require.True(t, found) require.Equal(t, sdk.Unbonding, validator.GetStatus()) } diff --git a/x/slashing/handler_test.go b/x/slashing/handler_test.go index abd5e5255..955eeadb8 100644 --- a/x/slashing/handler_test.go +++ b/x/slashing/handler_test.go @@ -6,35 +6,42 @@ import ( "testing" "time" - "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/x/slashing/types" + + "github.com/cosmos/cosmos-sdk/simapp" abci "github.com/tendermint/tendermint/abci/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/slashing" slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" - "github.com/cosmos/cosmos-sdk/x/slashing/types" "github.com/cosmos/cosmos-sdk/x/staking" + "github.com/stretchr/testify/require" ) func TestCannotUnjailUnlessJailed(t *testing.T) { // initial setup - ctx, bk, sk, _, keeper := slashingkeeper.CreateTestInput(t, slashing.DefaultParams()) - slh := slashing.NewHandler(keeper) + app := simapp.Setup(false) + ctx := app.BaseApp.NewContext(false, abci.Header{}) + + pks := simapp.CreateTestPubKeys(1) + simapp.AddTestAddrsFromPubKeys(app, ctx, pks, sdk.TokensFromConsensusPower(200)) + + slh := slashing.NewHandler(app.SlashingKeeper) amt := sdk.TokensFromConsensusPower(100) - addr, val := slashingkeeper.Addrs[0], slashingkeeper.Pks[0] + addr, val := sdk.ValAddress(pks[0].Address()), pks[0] msg := slashingkeeper.NewTestMsgCreateValidator(addr, val, amt) - res, err := staking.NewHandler(sk)(ctx, msg) + res, err := staking.NewHandler(app.StakingKeeper)(ctx, msg) require.NoError(t, err) require.NotNil(t, res) - staking.EndBlocker(ctx, sk) + staking.EndBlocker(ctx, app.StakingKeeper) require.Equal( - t, bk.GetAllBalances(ctx, sdk.AccAddress(addr)), - sdk.Coins{sdk.NewCoin(sk.GetParams(ctx).BondDenom, slashingkeeper.InitTokens.Sub(amt))}, + t, app.BankKeeper.GetAllBalances(ctx, sdk.AccAddress(addr)), + sdk.Coins{sdk.NewCoin(app.StakingKeeper.GetParams(ctx).BondDenom, slashingkeeper.InitTokens.Sub(amt))}, ) - require.Equal(t, amt, sk.Validator(ctx, addr).GetBondedTokens()) + require.Equal(t, amt, app.StakingKeeper.Validator(ctx, addr).GetBondedTokens()) // assert non-jailed validator can't be unjailed res, err = slh(ctx, slashing.NewMsgUnjail(addr)) @@ -45,31 +52,35 @@ func TestCannotUnjailUnlessJailed(t *testing.T) { func TestCannotUnjailUnlessMeetMinSelfDelegation(t *testing.T) { // initial setup - ctx, bk, sk, _, keeper := slashingkeeper.CreateTestInput(t, slashing.DefaultParams()) - slh := slashing.NewHandler(keeper) + app := simapp.Setup(false) + ctx := app.BaseApp.NewContext(false, abci.Header{}) + pks := simapp.CreateTestPubKeys(1) + simapp.AddTestAddrsFromPubKeys(app, ctx, pks, sdk.TokensFromConsensusPower(200)) + + slh := slashing.NewHandler(app.SlashingKeeper) amtInt := int64(100) - addr, val, amt := slashingkeeper.Addrs[0], slashingkeeper.Pks[0], sdk.TokensFromConsensusPower(amtInt) + addr, val, amt := sdk.ValAddress(pks[0].Address()), pks[0], sdk.TokensFromConsensusPower(amtInt) msg := slashingkeeper.NewTestMsgCreateValidator(addr, val, amt) msg.MinSelfDelegation = amt - res, err := staking.NewHandler(sk)(ctx, msg) + res, err := staking.NewHandler(app.StakingKeeper)(ctx, msg) require.NoError(t, err) require.NotNil(t, res) - staking.EndBlocker(ctx, sk) + staking.EndBlocker(ctx, app.StakingKeeper) require.Equal( - t, bk.GetAllBalances(ctx, sdk.AccAddress(addr)), - sdk.Coins{sdk.NewCoin(sk.GetParams(ctx).BondDenom, slashingkeeper.InitTokens.Sub(amt))}, + t, app.BankKeeper.GetAllBalances(ctx, sdk.AccAddress(addr)), + sdk.Coins{sdk.NewCoin(app.StakingKeeper.GetParams(ctx).BondDenom, slashingkeeper.InitTokens.Sub(amt))}, ) - unbondAmt := sdk.NewCoin(sk.GetParams(ctx).BondDenom, sdk.OneInt()) + unbondAmt := sdk.NewCoin(app.StakingKeeper.GetParams(ctx).BondDenom, sdk.OneInt()) undelegateMsg := staking.NewMsgUndelegate(sdk.AccAddress(addr), addr, unbondAmt) - res, err = staking.NewHandler(sk)(ctx, undelegateMsg) + res, err = staking.NewHandler(app.StakingKeeper)(ctx, undelegateMsg) require.NoError(t, err) require.NotNil(t, res) - require.True(t, sk.Validator(ctx, addr).IsJailed()) + require.True(t, app.StakingKeeper.Validator(ctx, addr).IsJailed()) // assert non-jailed validator can't be unjailed res, err = slh(ctx, slashing.NewMsgUnjail(addr)) @@ -79,64 +90,70 @@ func TestCannotUnjailUnlessMeetMinSelfDelegation(t *testing.T) { } func TestJailedValidatorDelegations(t *testing.T) { - ctx, _, stakingKeeper, _, slashingKeeper := slashingkeeper.CreateTestInput(t, slashing.DefaultParams()) + // initial setup + app := simapp.Setup(false) + ctx := app.BaseApp.NewContext(false, abci.Header{Time: time.Unix(0, 0)}) - stakingParams := stakingKeeper.GetParams(ctx) - stakingKeeper.SetParams(ctx, stakingParams) + pks := simapp.CreateTestPubKeys(3) + simapp.AddTestAddrsFromPubKeys(app, ctx, pks, sdk.TokensFromConsensusPower(20)) + app.SlashingKeeper.SetParams(ctx, slashingkeeper.TestParams()) + + stakingParams := app.StakingKeeper.GetParams(ctx) + app.StakingKeeper.SetParams(ctx, stakingParams) // create a validator bondAmount := sdk.TokensFromConsensusPower(10) - valPubKey := slashingkeeper.Pks[0] - valAddr, consAddr := slashingkeeper.Addrs[1], sdk.ConsAddress(slashingkeeper.Addrs[0]) + valPubKey := pks[1] + valAddr, consAddr := sdk.ValAddress(pks[1].Address()), sdk.ConsAddress(pks[0].Address()) msgCreateVal := slashingkeeper.NewTestMsgCreateValidator(valAddr, valPubKey, bondAmount) - res, err := staking.NewHandler(stakingKeeper)(ctx, msgCreateVal) + res, err := staking.NewHandler(app.StakingKeeper)(ctx, msgCreateVal) require.NoError(t, err) require.NotNil(t, res) // end block - staking.EndBlocker(ctx, stakingKeeper) + staking.EndBlocker(ctx, app.StakingKeeper) // set dummy signing info newInfo := slashing.NewValidatorSigningInfo(consAddr, 0, 0, time.Unix(0, 0), false, 0) - slashingKeeper.SetValidatorSigningInfo(ctx, consAddr, newInfo) + app.SlashingKeeper.SetValidatorSigningInfo(ctx, consAddr, newInfo) // delegate tokens to the validator - delAddr := sdk.AccAddress(slashingkeeper.Addrs[2]) + delAddr := sdk.AccAddress(pks[2].Address()) msgDelegate := slashingkeeper.NewTestMsgDelegate(delAddr, valAddr, bondAmount) - res, err = staking.NewHandler(stakingKeeper)(ctx, msgDelegate) + res, err = staking.NewHandler(app.StakingKeeper)(ctx, msgDelegate) require.NoError(t, err) require.NotNil(t, res) - unbondAmt := sdk.NewCoin(stakingKeeper.GetParams(ctx).BondDenom, bondAmount) + unbondAmt := sdk.NewCoin(app.StakingKeeper.GetParams(ctx).BondDenom, bondAmount) // unbond validator total self-delegations (which should jail the validator) msgUndelegate := staking.NewMsgUndelegate(sdk.AccAddress(valAddr), valAddr, unbondAmt) - res, err = staking.NewHandler(stakingKeeper)(ctx, msgUndelegate) + res, err = staking.NewHandler(app.StakingKeeper)(ctx, msgUndelegate) require.NoError(t, err) require.NotNil(t, res) - err = stakingKeeper.CompleteUnbonding(ctx, sdk.AccAddress(valAddr), valAddr) + err = app.StakingKeeper.CompleteUnbonding(ctx, sdk.AccAddress(valAddr), valAddr) require.Nil(t, err, "expected complete unbonding validator to be ok, got: %v", err) // verify validator still exists and is jailed - validator, found := stakingKeeper.GetValidator(ctx, valAddr) + validator, found := app.StakingKeeper.GetValidator(ctx, valAddr) require.True(t, found) require.True(t, validator.IsJailed()) // verify the validator cannot unjail itself - res, err = slashing.NewHandler(slashingKeeper)(ctx, slashing.NewMsgUnjail(valAddr)) + res, err = slashing.NewHandler(app.SlashingKeeper)(ctx, slashing.NewMsgUnjail(valAddr)) require.Error(t, err) require.Nil(t, res) // self-delegate to validator msgSelfDelegate := slashingkeeper.NewTestMsgDelegate(sdk.AccAddress(valAddr), valAddr, bondAmount) - res, err = staking.NewHandler(stakingKeeper)(ctx, msgSelfDelegate) + res, err = staking.NewHandler(app.StakingKeeper)(ctx, msgSelfDelegate) require.NoError(t, err) require.NotNil(t, res) // verify the validator can now unjail itself - res, err = slashing.NewHandler(slashingKeeper)(ctx, slashing.NewMsgUnjail(valAddr)) + res, err = slashing.NewHandler(app.SlashingKeeper)(ctx, slashing.NewMsgUnjail(valAddr)) require.NoError(t, err) require.NotNil(t, res) } @@ -155,27 +172,33 @@ func TestInvalidMsg(t *testing.T) { // unrevocation, starting height reset, and revocation again func TestHandleAbsentValidator(t *testing.T) { // initial setup - ctx, bk, sk, _, keeper := slashingkeeper.CreateTestInput(t, slashingkeeper.TestParams()) + app := simapp.Setup(false) + ctx := app.BaseApp.NewContext(false, abci.Header{Time: time.Unix(0, 0)}) + + pks := simapp.CreateTestPubKeys(1) + simapp.AddTestAddrsFromPubKeys(app, ctx, pks, sdk.TokensFromConsensusPower(200)) + app.SlashingKeeper.SetParams(ctx, slashingkeeper.TestParams()) + power := int64(100) amt := sdk.TokensFromConsensusPower(power) - addr, val := slashingkeeper.Addrs[0], slashingkeeper.Pks[0] - sh := staking.NewHandler(sk) - slh := slashing.NewHandler(keeper) + addr, val := sdk.ValAddress(pks[0].Address()), pks[0] + sh := staking.NewHandler(app.StakingKeeper) + slh := slashing.NewHandler(app.SlashingKeeper) res, err := sh(ctx, slashingkeeper.NewTestMsgCreateValidator(addr, val, amt)) require.NoError(t, err) require.NotNil(t, res) - staking.EndBlocker(ctx, sk) + staking.EndBlocker(ctx, app.StakingKeeper) require.Equal( - t, bk.GetAllBalances(ctx, sdk.AccAddress(addr)), - sdk.NewCoins(sdk.NewCoin(sk.GetParams(ctx).BondDenom, slashingkeeper.InitTokens.Sub(amt))), + t, app.BankKeeper.GetAllBalances(ctx, sdk.AccAddress(addr)), + sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.GetParams(ctx).BondDenom, slashingkeeper.InitTokens.Sub(amt))), ) - require.Equal(t, amt, sk.Validator(ctx, addr).GetBondedTokens()) + require.Equal(t, amt, app.StakingKeeper.Validator(ctx, addr).GetBondedTokens()) // will exist since the validator has been bonded - info, found := keeper.GetValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) + info, found := app.SlashingKeeper.GetValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) require.True(t, found) require.Equal(t, int64(0), info.StartHeight) require.Equal(t, int64(0), info.IndexOffset) @@ -184,49 +207,49 @@ func TestHandleAbsentValidator(t *testing.T) { height := int64(0) // 1000 first blocks OK - for ; height < keeper.SignedBlocksWindow(ctx); height++ { + for ; height < app.SlashingKeeper.SignedBlocksWindow(ctx); height++ { ctx = ctx.WithBlockHeight(height) - keeper.HandleValidatorSignature(ctx, val.Address(), power, true) + app.SlashingKeeper.HandleValidatorSignature(ctx, val.Address(), power, true) } - info, found = keeper.GetValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) + info, found = app.SlashingKeeper.GetValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) require.True(t, found) require.Equal(t, int64(0), info.StartHeight) require.Equal(t, int64(0), info.MissedBlocksCounter) // 500 blocks missed - for ; height < keeper.SignedBlocksWindow(ctx)+(keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx)); height++ { + for ; height < app.SlashingKeeper.SignedBlocksWindow(ctx)+(app.SlashingKeeper.SignedBlocksWindow(ctx)-app.SlashingKeeper.MinSignedPerWindow(ctx)); height++ { ctx = ctx.WithBlockHeight(height) - keeper.HandleValidatorSignature(ctx, val.Address(), power, false) + app.SlashingKeeper.HandleValidatorSignature(ctx, val.Address(), power, false) } - info, found = keeper.GetValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) + info, found = app.SlashingKeeper.GetValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) require.True(t, found) require.Equal(t, int64(0), info.StartHeight) - require.Equal(t, keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx), info.MissedBlocksCounter) + require.Equal(t, app.SlashingKeeper.SignedBlocksWindow(ctx)-app.SlashingKeeper.MinSignedPerWindow(ctx), info.MissedBlocksCounter) // validator should be bonded still - validator, _ := sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) + validator, _ := app.StakingKeeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, sdk.Bonded, validator.GetStatus()) - bondPool := sk.GetBondedPool(ctx) - require.True(sdk.IntEq(t, amt, bk.GetBalance(ctx, bondPool.GetAddress(), sk.BondDenom(ctx)).Amount)) + bondPool := app.StakingKeeper.GetBondedPool(ctx) + require.True(sdk.IntEq(t, amt, app.BankKeeper.GetBalance(ctx, bondPool.GetAddress(), app.StakingKeeper.BondDenom(ctx)).Amount)) // 501st block missed ctx = ctx.WithBlockHeight(height) - keeper.HandleValidatorSignature(ctx, val.Address(), power, false) - info, found = keeper.GetValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) + app.SlashingKeeper.HandleValidatorSignature(ctx, val.Address(), power, false) + info, found = app.SlashingKeeper.GetValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) require.True(t, found) require.Equal(t, int64(0), info.StartHeight) // counter now reset to zero require.Equal(t, int64(0), info.MissedBlocksCounter) // end block - staking.EndBlocker(ctx, sk) + staking.EndBlocker(ctx, app.StakingKeeper) // validator should have been jailed - validator, _ = sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) + validator, _ = app.StakingKeeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, sdk.Unbonding, validator.GetStatus()) - slashAmt := amt.ToDec().Mul(keeper.SlashFractionDowntime(ctx)).RoundInt64() + slashAmt := amt.ToDec().Mul(app.SlashingKeeper.SlashFractionDowntime(ctx)).RoundInt64() // validator should have been slashed require.Equal(t, amt.Int64()-slashAmt, validator.GetTokens().Int64()) @@ -234,17 +257,17 @@ func TestHandleAbsentValidator(t *testing.T) { // 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(), power, false) - info, found = keeper.GetValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) + app.SlashingKeeper.HandleValidatorSignature(ctx, val.Address(), power, false) + info, found = app.SlashingKeeper.GetValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) require.True(t, found) require.Equal(t, int64(0), info.StartHeight) require.Equal(t, int64(1), info.MissedBlocksCounter) // end block - staking.EndBlocker(ctx, sk) + staking.EndBlocker(ctx, app.StakingKeeper) // validator should not have been slashed any more, since it was already jailed - validator, _ = sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) + validator, _ = app.StakingKeeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, amt.Int64()-slashAmt, validator.GetTokens().Int64()) // unrevocation should fail prior to jail expiration @@ -253,23 +276,23 @@ func TestHandleAbsentValidator(t *testing.T) { require.Nil(t, res) // unrevocation should succeed after jail expiration - ctx = ctx.WithBlockHeader(abci.Header{Time: time.Unix(1, 0).Add(keeper.DowntimeJailDuration(ctx))}) + ctx = ctx.WithBlockHeader(abci.Header{Time: time.Unix(1, 0).Add(app.SlashingKeeper.DowntimeJailDuration(ctx))}) res, err = slh(ctx, types.NewMsgUnjail(addr)) require.NoError(t, err) require.NotNil(t, res) // end block - staking.EndBlocker(ctx, sk) + staking.EndBlocker(ctx, app.StakingKeeper) // validator should be rebonded now - validator, _ = sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) + validator, _ = app.StakingKeeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, sdk.Bonded, validator.GetStatus()) // validator should have been slashed - require.Equal(t, amt.Int64()-slashAmt, bk.GetBalance(ctx, bondPool.GetAddress(), sk.BondDenom(ctx)).Amount.Int64()) + require.Equal(t, amt.Int64()-slashAmt, app.BankKeeper.GetBalance(ctx, bondPool.GetAddress(), app.StakingKeeper.BondDenom(ctx)).Amount.Int64()) // Validator start height should not have been changed - info, found = keeper.GetValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) + info, found = app.SlashingKeeper.GetValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) require.True(t, found) require.Equal(t, int64(0), info.StartHeight) // we've missed 2 blocks more than the maximum, so the counter was reset to 0 at 1 block more and is now 1 @@ -278,30 +301,30 @@ func TestHandleAbsentValidator(t *testing.T) { // validator should not be immediately jailed again height++ ctx = ctx.WithBlockHeight(height) - keeper.HandleValidatorSignature(ctx, val.Address(), power, false) - validator, _ = sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) + app.SlashingKeeper.HandleValidatorSignature(ctx, val.Address(), power, false) + validator, _ = app.StakingKeeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, sdk.Bonded, validator.GetStatus()) // 500 signed blocks - nextHeight := height + keeper.MinSignedPerWindow(ctx) + 1 + nextHeight := height + app.SlashingKeeper.MinSignedPerWindow(ctx) + 1 for ; height < nextHeight; height++ { ctx = ctx.WithBlockHeight(height) - keeper.HandleValidatorSignature(ctx, val.Address(), power, false) + app.SlashingKeeper.HandleValidatorSignature(ctx, val.Address(), power, false) } // end block - staking.EndBlocker(ctx, sk) + staking.EndBlocker(ctx, app.StakingKeeper) // validator should be jailed again after 500 unsigned blocks - nextHeight = height + keeper.MinSignedPerWindow(ctx) + 1 + nextHeight = height + app.SlashingKeeper.MinSignedPerWindow(ctx) + 1 for ; height <= nextHeight; height++ { ctx = ctx.WithBlockHeight(height) - keeper.HandleValidatorSignature(ctx, val.Address(), power, false) + app.SlashingKeeper.HandleValidatorSignature(ctx, val.Address(), power, false) } // end block - staking.EndBlocker(ctx, sk) + staking.EndBlocker(ctx, app.StakingKeeper) - validator, _ = sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) + validator, _ = app.StakingKeeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, sdk.Unbonding, validator.GetStatus()) } diff --git a/x/slashing/keeper/common_test.go b/x/slashing/keeper/common_test.go new file mode 100644 index 000000000..940d995ca --- /dev/null +++ b/x/slashing/keeper/common_test.go @@ -0,0 +1,7 @@ +package keeper_test + +import sdk "github.com/cosmos/cosmos-sdk/types" + +var ( + InitTokens = sdk.TokensFromConsensusPower(200) +) diff --git a/x/slashing/keeper/keeper_test.go b/x/slashing/keeper/keeper_test.go index 4f4f555bb..ce28a5607 100644 --- a/x/slashing/keeper/keeper_test.go +++ b/x/slashing/keeper/keeper_test.go @@ -1,13 +1,16 @@ -package keeper +package keeper_test import ( "testing" "time" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/slashing/types" + "github.com/cosmos/cosmos-sdk/x/slashing/keeper" "github.com/cosmos/cosmos-sdk/x/staking" ) @@ -15,82 +18,91 @@ import ( // Ensure that SigningInfo.StartHeight is set correctly // and that they are not immediately jailed func TestHandleNewValidator(t *testing.T) { - // initial setup - ctx, bk, sk, _, keeper := CreateTestInput(t, TestParams()) - addr, val := Addrs[0], Pks[0] - amt := sdk.TokensFromConsensusPower(100) - sh := staking.NewHandler(sk) + app := simapp.Setup(false) + ctx := app.BaseApp.NewContext(false, abci.Header{}) - // 1000 first blocks not a validator - ctx = ctx.WithBlockHeight(keeper.SignedBlocksWindow(ctx) + 1) + addrDels := simapp.AddTestAddrsIncremental(app, ctx, 1, sdk.TokensFromConsensusPower(200)) + valAddrs := simapp.ConvertAddrsToValAddrs(addrDels) + pks := simapp.CreateTestPubKeys(1) + + addr, val := valAddrs[0], pks[0] + amt := sdk.TokensFromConsensusPower(100) + sh := staking.NewHandler(app.StakingKeeper) + + ctx = ctx.WithBlockHeight(app.SlashingKeeper.SignedBlocksWindow(ctx) + 1) // Validator created - res, err := sh(ctx, NewTestMsgCreateValidator(addr, val, amt)) + res, err := sh(ctx, keeper.NewTestMsgCreateValidator(addr, val, amt)) require.NoError(t, err) require.NotNil(t, res) - staking.EndBlocker(ctx, sk) + staking.EndBlocker(ctx, app.StakingKeeper) require.Equal( - t, bk.GetAllBalances(ctx, sdk.AccAddress(addr)), - sdk.NewCoins(sdk.NewCoin(sk.GetParams(ctx).BondDenom, InitTokens.Sub(amt))), + t, app.BankKeeper.GetAllBalances(ctx, sdk.AccAddress(addr)), + sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.GetParams(ctx).BondDenom, InitTokens.Sub(amt))), ) - require.Equal(t, amt, sk.Validator(ctx, addr).GetBondedTokens()) + require.Equal(t, amt, app.StakingKeeper.Validator(ctx, addr).GetBondedTokens()) // Now a validator, for two blocks - keeper.HandleValidatorSignature(ctx, val.Address(), 100, true) - ctx = ctx.WithBlockHeight(keeper.SignedBlocksWindow(ctx) + 2) - keeper.HandleValidatorSignature(ctx, val.Address(), 100, false) + app.SlashingKeeper.HandleValidatorSignature(ctx, val.Address(), 100, true) + ctx = ctx.WithBlockHeight(app.SlashingKeeper.SignedBlocksWindow(ctx) + 2) + app.SlashingKeeper.HandleValidatorSignature(ctx, val.Address(), 100, false) - info, found := keeper.GetValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) + info, found := app.SlashingKeeper.GetValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) require.True(t, found) - require.Equal(t, keeper.SignedBlocksWindow(ctx)+1, info.StartHeight) + require.Equal(t, app.SlashingKeeper.SignedBlocksWindow(ctx)+1, info.StartHeight) require.Equal(t, int64(2), info.IndexOffset) require.Equal(t, int64(1), info.MissedBlocksCounter) require.Equal(t, time.Unix(0, 0).UTC(), info.JailedUntil) // validator should be bonded still, should not have been jailed or slashed - validator, _ := sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) + validator, _ := app.StakingKeeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, sdk.Bonded, validator.GetStatus()) - bondPool := sk.GetBondedPool(ctx) + bondPool := app.StakingKeeper.GetBondedPool(ctx) expTokens := sdk.TokensFromConsensusPower(100) - require.Equal(t, expTokens.Int64(), bk.GetBalance(ctx, bondPool.GetAddress(), sk.BondDenom(ctx)).Amount.Int64()) + require.Equal(t, expTokens.Int64(), app.BankKeeper.GetBalance(ctx, bondPool.GetAddress(), app.StakingKeeper.BondDenom(ctx)).Amount.Int64()) } // Test a jailed validator being "down" twice // Ensure that they're only slashed once func TestHandleAlreadyJailed(t *testing.T) { - // initial setup - ctx, _, sk, _, keeper := CreateTestInput(t, types.DefaultParams()) + app := simapp.Setup(false) + ctx := app.BaseApp.NewContext(false, abci.Header{}) power := int64(100) + amt := sdk.TokensFromConsensusPower(power) - addr, val := Addrs[0], Pks[0] - sh := staking.NewHandler(sk) - res, err := sh(ctx, NewTestMsgCreateValidator(addr, val, amt)) + addrDels := simapp.AddTestAddrsIncremental(app, ctx, 1, sdk.TokensFromConsensusPower(200)) + valAddrs := simapp.ConvertAddrsToValAddrs(addrDels) + pks := simapp.CreateTestPubKeys(1) + + addr, val := valAddrs[0], pks[0] + sh := staking.NewHandler(app.StakingKeeper) + res, err := sh(ctx, keeper.NewTestMsgCreateValidator(addr, val, amt)) require.NoError(t, err) require.NotNil(t, res) - staking.EndBlocker(ctx, sk) + staking.EndBlocker(ctx, app.StakingKeeper) // 1000 first blocks OK height := int64(0) - for ; height < keeper.SignedBlocksWindow(ctx); height++ { + for ; height < app.SlashingKeeper.SignedBlocksWindow(ctx); height++ { ctx = ctx.WithBlockHeight(height) - keeper.HandleValidatorSignature(ctx, val.Address(), power, true) + app.SlashingKeeper.HandleValidatorSignature(ctx, val.Address(), power, true) } // 501 blocks missed - for ; height < keeper.SignedBlocksWindow(ctx)+(keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx))+1; height++ { + for ; height < app.SlashingKeeper.SignedBlocksWindow(ctx)+(app.SlashingKeeper.SignedBlocksWindow(ctx)-app.SlashingKeeper.MinSignedPerWindow(ctx))+1; height++ { ctx = ctx.WithBlockHeight(height) - keeper.HandleValidatorSignature(ctx, val.Address(), power, false) + app.SlashingKeeper.HandleValidatorSignature(ctx, val.Address(), power, false) } // end block - staking.EndBlocker(ctx, sk) + staking.EndBlocker(ctx, app.StakingKeeper) // validator should have been jailed and slashed - validator, _ := sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) + validator, _ := app.StakingKeeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, sdk.Unbonding, validator.GetStatus()) // validator should have been slashed @@ -99,12 +111,11 @@ func TestHandleAlreadyJailed(t *testing.T) { // another block missed ctx = ctx.WithBlockHeight(height) - keeper.HandleValidatorSignature(ctx, val.Address(), power, false) + app.SlashingKeeper.HandleValidatorSignature(ctx, val.Address(), power, false) // validator should not have been slashed twice - validator, _ = sk.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) + validator, _ = app.StakingKeeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(val)) require.Equal(t, resultingTokens, validator.GetTokens()) - } // Test a validator dipping in and out of the validator set @@ -114,37 +125,44 @@ func TestValidatorDippingInAndOut(t *testing.T) { // initial setup // TestParams set the SignedBlocksWindow to 1000 and MaxMissedBlocksPerWindow to 500 - ctx, _, sk, _, keeper := CreateTestInput(t, TestParams()) - params := sk.GetParams(ctx) + app := simapp.Setup(false) + ctx := app.BaseApp.NewContext(false, abci.Header{}) + app.SlashingKeeper.SetParams(ctx, keeper.TestParams()) + + params := app.StakingKeeper.GetParams(ctx) params.MaxValidators = 1 - sk.SetParams(ctx, params) + app.StakingKeeper.SetParams(ctx, params) power := int64(100) + + pks := simapp.CreateTestPubKeys(3) + simapp.AddTestAddrsFromPubKeys(app, ctx, pks, sdk.TokensFromConsensusPower(200)) + amt := sdk.TokensFromConsensusPower(power) - addr, val := Addrs[0], Pks[0] + addr, val := pks[0].Address(), pks[0] consAddr := sdk.ConsAddress(addr) - sh := staking.NewHandler(sk) - res, err := sh(ctx, NewTestMsgCreateValidator(addr, val, amt)) + sh := staking.NewHandler(app.StakingKeeper) + res, err := sh(ctx, keeper.NewTestMsgCreateValidator(sdk.ValAddress(addr), val, amt)) require.NoError(t, err) require.NotNil(t, res) - staking.EndBlocker(ctx, sk) + staking.EndBlocker(ctx, app.StakingKeeper) // 100 first blocks OK height := int64(0) for ; height < int64(100); height++ { ctx = ctx.WithBlockHeight(height) - keeper.HandleValidatorSignature(ctx, val.Address(), power, true) + app.SlashingKeeper.HandleValidatorSignature(ctx, val.Address(), power, true) } // kick first validator out of validator set newAmt := sdk.TokensFromConsensusPower(101) - res, err = sh(ctx, NewTestMsgCreateValidator(Addrs[1], Pks[1], newAmt)) + res, err = sh(ctx, keeper.NewTestMsgCreateValidator(sdk.ValAddress(pks[1].Address()), pks[1], newAmt)) require.NoError(t, err) require.NotNil(t, res) - validatorUpdates := staking.EndBlocker(ctx, sk) + validatorUpdates := staking.EndBlocker(ctx, app.StakingKeeper) require.Equal(t, 2, len(validatorUpdates)) - validator, _ := sk.GetValidator(ctx, addr) + validator, _ := app.StakingKeeper.GetValidator(ctx, sdk.ValAddress(addr)) require.Equal(t, sdk.Unbonding, validator.Status) // 600 more blocks happened @@ -153,44 +171,44 @@ func TestValidatorDippingInAndOut(t *testing.T) { // validator added back in delTokens := sdk.TokensFromConsensusPower(50) - res, err = sh(ctx, NewTestMsgDelegate(sdk.AccAddress(Addrs[2]), Addrs[0], delTokens)) + res, err = sh(ctx, keeper.NewTestMsgDelegate(sdk.AccAddress(pks[2].Address()), sdk.ValAddress(pks[0].Address()), delTokens)) require.NoError(t, err) require.NotNil(t, res) - validatorUpdates = staking.EndBlocker(ctx, sk) + validatorUpdates = staking.EndBlocker(ctx, app.StakingKeeper) require.Equal(t, 2, len(validatorUpdates)) - validator, _ = sk.GetValidator(ctx, addr) + validator, _ = app.StakingKeeper.GetValidator(ctx, sdk.ValAddress(addr)) require.Equal(t, sdk.Bonded, validator.Status) newPower := int64(150) // validator misses a block - keeper.HandleValidatorSignature(ctx, val.Address(), newPower, false) + app.SlashingKeeper.HandleValidatorSignature(ctx, val.Address(), newPower, false) height++ // shouldn't be jailed/kicked yet - validator, _ = sk.GetValidator(ctx, addr) + validator, _ = app.StakingKeeper.GetValidator(ctx, sdk.ValAddress(addr)) require.Equal(t, sdk.Bonded, validator.Status) // validator misses 500 more blocks, 501 total latest := height for ; height < latest+500; height++ { ctx = ctx.WithBlockHeight(height) - keeper.HandleValidatorSignature(ctx, val.Address(), newPower, false) + app.SlashingKeeper.HandleValidatorSignature(ctx, val.Address(), newPower, false) } // should now be jailed & kicked - staking.EndBlocker(ctx, sk) - validator, _ = sk.GetValidator(ctx, addr) + staking.EndBlocker(ctx, app.StakingKeeper) + validator, _ = app.StakingKeeper.GetValidator(ctx, sdk.ValAddress(addr)) require.Equal(t, sdk.Unbonding, validator.Status) // check all the signing information - signInfo, found := keeper.GetValidatorSigningInfo(ctx, consAddr) + signInfo, found := app.SlashingKeeper.GetValidatorSigningInfo(ctx, consAddr) require.True(t, found) require.Equal(t, int64(0), signInfo.MissedBlocksCounter) require.Equal(t, int64(0), signInfo.IndexOffset) // array should be cleared - for offset := int64(0); offset < keeper.SignedBlocksWindow(ctx); offset++ { - missed := keeper.GetValidatorMissedBlockBitArray(ctx, consAddr, offset) + for offset := int64(0); offset < app.SlashingKeeper.SignedBlocksWindow(ctx); offset++ { + missed := app.SlashingKeeper.GetValidatorMissedBlockBitArray(ctx, consAddr, offset) require.False(t, missed) } @@ -199,25 +217,25 @@ func TestValidatorDippingInAndOut(t *testing.T) { ctx = ctx.WithBlockHeight(height) // validator rejoins and starts signing again - sk.Unjail(ctx, consAddr) - keeper.HandleValidatorSignature(ctx, val.Address(), newPower, true) + app.StakingKeeper.Unjail(ctx, consAddr) + app.SlashingKeeper.HandleValidatorSignature(ctx, val.Address(), newPower, true) height++ // validator should not be kicked since we reset counter/array when it was jailed - staking.EndBlocker(ctx, sk) - validator, _ = sk.GetValidator(ctx, addr) + staking.EndBlocker(ctx, app.StakingKeeper) + validator, _ = app.StakingKeeper.GetValidator(ctx, sdk.ValAddress(addr)) require.Equal(t, sdk.Bonded, validator.Status) // validator misses 501 blocks latest = height for ; height < latest+501; height++ { ctx = ctx.WithBlockHeight(height) - keeper.HandleValidatorSignature(ctx, val.Address(), newPower, false) + app.SlashingKeeper.HandleValidatorSignature(ctx, val.Address(), newPower, false) } // validator should now be jailed & kicked - staking.EndBlocker(ctx, sk) - validator, _ = sk.GetValidator(ctx, addr) + staking.EndBlocker(ctx, app.StakingKeeper) + validator, _ = app.StakingKeeper.GetValidator(ctx, sdk.ValAddress(addr)) require.Equal(t, sdk.Unbonding, validator.Status) } diff --git a/x/slashing/keeper/querier_test.go b/x/slashing/keeper/querier_test.go index fd924bc8e..5413ba599 100644 --- a/x/slashing/keeper/querier_test.go +++ b/x/slashing/keeper/querier_test.go @@ -1,38 +1,53 @@ -package keeper +package keeper_test import ( "testing" "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/simapp" + "github.com/cosmos/cosmos-sdk/x/slashing/keeper" "github.com/cosmos/cosmos-sdk/x/slashing/types" ) func TestNewQuerier(t *testing.T) { - ctx, _, _, _, keeper := CreateTestInput(t, TestParams()) - querier := NewQuerier(keeper) + app := simapp.Setup(false) + ctx := app.BaseApp.NewContext(false, abci.Header{}) + app.SlashingKeeper.SetParams(ctx, keeper.TestParams()) + + querier := keeper.NewQuerier(app.SlashingKeeper) query := abci.RequestQuery{ Path: "", Data: []byte{}, } - _, err := querier(ctx, []string{"parameters"}, query) + _, err := querier(ctx, []string{types.QueryParameters}, query) require.NoError(t, err) } func TestQueryParams(t *testing.T) { cdc := codec.New() - ctx, _, _, _, keeper := CreateTestInput(t, TestParams()) + app := simapp.Setup(false) + ctx := app.BaseApp.NewContext(false, abci.Header{}) + app.SlashingKeeper.SetParams(ctx, keeper.TestParams()) + + querier := keeper.NewQuerier(app.SlashingKeeper) + + query := abci.RequestQuery{ + Path: "", + Data: []byte{}, + } var params types.Params - res, errRes := queryParams(ctx, keeper) - require.NoError(t, errRes) - - err := cdc.UnmarshalJSON(res, ¶ms) + res, err := querier(ctx, []string{types.QueryParameters}, query) require.NoError(t, err) - require.Equal(t, keeper.GetParams(ctx), params) + + err = cdc.UnmarshalJSON(res, ¶ms) + require.NoError(t, err) + require.Equal(t, app.SlashingKeeper.GetParams(ctx), params) } diff --git a/x/slashing/keeper/signing_info_test.go b/x/slashing/keeper/signing_info_test.go index ac8c50752..e10df926c 100644 --- a/x/slashing/keeper/signing_info_test.go +++ b/x/slashing/keeper/signing_info_test.go @@ -1,4 +1,4 @@ -package keeper +package keeper_test import ( "testing" @@ -6,24 +6,30 @@ import ( "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" + + "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/slashing/types" ) func TestGetSetValidatorSigningInfo(t *testing.T) { - ctx, _, _, _, keeper := CreateTestInput(t, types.DefaultParams()) - info, found := keeper.GetValidatorSigningInfo(ctx, sdk.ConsAddress(Addrs[0])) + app := simapp.Setup(false) + ctx := app.BaseApp.NewContext(false, abci.Header{}) + addrDels := simapp.AddTestAddrsIncremental(app, ctx, 1, sdk.TokensFromConsensusPower(200)) + + info, found := app.SlashingKeeper.GetValidatorSigningInfo(ctx, sdk.ConsAddress(addrDels[0])) require.False(t, found) newInfo := types.NewValidatorSigningInfo( - sdk.ConsAddress(Addrs[0]), + sdk.ConsAddress(addrDels[0]), int64(4), int64(3), time.Unix(2, 0), false, int64(10), ) - keeper.SetValidatorSigningInfo(ctx, sdk.ConsAddress(Addrs[0]), newInfo) - info, found = keeper.GetValidatorSigningInfo(ctx, sdk.ConsAddress(Addrs[0])) + app.SlashingKeeper.SetValidatorSigningInfo(ctx, sdk.ConsAddress(addrDels[0]), newInfo) + info, found = app.SlashingKeeper.GetValidatorSigningInfo(ctx, sdk.ConsAddress(addrDels[0])) require.True(t, found) require.Equal(t, info.StartHeight, int64(4)) require.Equal(t, info.IndexOffset, int64(3)) @@ -32,51 +38,60 @@ func TestGetSetValidatorSigningInfo(t *testing.T) { } func TestGetSetValidatorMissedBlockBitArray(t *testing.T) { - ctx, _, _, _, keeper := CreateTestInput(t, types.DefaultParams()) - missed := keeper.GetValidatorMissedBlockBitArray(ctx, sdk.ConsAddress(Addrs[0]), 0) + app := simapp.Setup(false) + ctx := app.BaseApp.NewContext(false, abci.Header{}) + addrDels := simapp.AddTestAddrsIncremental(app, ctx, 1, sdk.TokensFromConsensusPower(200)) + + missed := app.SlashingKeeper.GetValidatorMissedBlockBitArray(ctx, sdk.ConsAddress(addrDels[0]), 0) require.False(t, missed) // treat empty key as not missed - keeper.SetValidatorMissedBlockBitArray(ctx, sdk.ConsAddress(Addrs[0]), 0, true) - missed = keeper.GetValidatorMissedBlockBitArray(ctx, sdk.ConsAddress(Addrs[0]), 0) + app.SlashingKeeper.SetValidatorMissedBlockBitArray(ctx, sdk.ConsAddress(addrDels[0]), 0, true) + missed = app.SlashingKeeper.GetValidatorMissedBlockBitArray(ctx, sdk.ConsAddress(addrDels[0]), 0) require.True(t, missed) // now should be missed } func TestTombstoned(t *testing.T) { - ctx, _, _, _, keeper := CreateTestInput(t, types.DefaultParams()) - require.Panics(t, func() { keeper.Tombstone(ctx, sdk.ConsAddress(Addrs[0])) }) - require.False(t, keeper.IsTombstoned(ctx, sdk.ConsAddress(Addrs[0]))) + app := simapp.Setup(false) + ctx := app.BaseApp.NewContext(false, abci.Header{}) + addrDels := simapp.AddTestAddrsIncremental(app, ctx, 1, sdk.TokensFromConsensusPower(200)) + + require.Panics(t, func() { app.SlashingKeeper.Tombstone(ctx, sdk.ConsAddress(addrDels[0])) }) + require.False(t, app.SlashingKeeper.IsTombstoned(ctx, sdk.ConsAddress(addrDels[0]))) newInfo := types.NewValidatorSigningInfo( - sdk.ConsAddress(Addrs[0]), + sdk.ConsAddress(addrDels[0]), int64(4), int64(3), time.Unix(2, 0), false, int64(10), ) - keeper.SetValidatorSigningInfo(ctx, sdk.ConsAddress(Addrs[0]), newInfo) + app.SlashingKeeper.SetValidatorSigningInfo(ctx, sdk.ConsAddress(addrDels[0]), newInfo) - require.False(t, keeper.IsTombstoned(ctx, sdk.ConsAddress(Addrs[0]))) - keeper.Tombstone(ctx, sdk.ConsAddress(Addrs[0])) - require.True(t, keeper.IsTombstoned(ctx, sdk.ConsAddress(Addrs[0]))) - require.Panics(t, func() { keeper.Tombstone(ctx, sdk.ConsAddress(Addrs[0])) }) + require.False(t, app.SlashingKeeper.IsTombstoned(ctx, sdk.ConsAddress(addrDels[0]))) + app.SlashingKeeper.Tombstone(ctx, sdk.ConsAddress(addrDels[0])) + require.True(t, app.SlashingKeeper.IsTombstoned(ctx, sdk.ConsAddress(addrDels[0]))) + require.Panics(t, func() { app.SlashingKeeper.Tombstone(ctx, sdk.ConsAddress(addrDels[0])) }) } func TestJailUntil(t *testing.T) { - ctx, _, _, _, keeper := CreateTestInput(t, types.DefaultParams()) - require.Panics(t, func() { keeper.JailUntil(ctx, sdk.ConsAddress(Addrs[0]), time.Now()) }) + app := simapp.Setup(false) + ctx := app.BaseApp.NewContext(false, abci.Header{}) + addrDels := simapp.AddTestAddrsIncremental(app, ctx, 1, sdk.TokensFromConsensusPower(200)) + + require.Panics(t, func() { app.SlashingKeeper.JailUntil(ctx, sdk.ConsAddress(addrDels[0]), time.Now()) }) newInfo := types.NewValidatorSigningInfo( - sdk.ConsAddress(Addrs[0]), + sdk.ConsAddress(addrDels[0]), int64(4), int64(3), time.Unix(2, 0), false, int64(10), ) - keeper.SetValidatorSigningInfo(ctx, sdk.ConsAddress(Addrs[0]), newInfo) - keeper.JailUntil(ctx, sdk.ConsAddress(Addrs[0]), time.Unix(253402300799, 0).UTC()) + app.SlashingKeeper.SetValidatorSigningInfo(ctx, sdk.ConsAddress(addrDels[0]), newInfo) + app.SlashingKeeper.JailUntil(ctx, sdk.ConsAddress(addrDels[0]), time.Unix(253402300799, 0).UTC()) - info, ok := keeper.GetValidatorSigningInfo(ctx, sdk.ConsAddress(Addrs[0])) + info, ok := app.SlashingKeeper.GetValidatorSigningInfo(ctx, sdk.ConsAddress(addrDels[0])) require.True(t, ok) require.Equal(t, time.Unix(253402300799, 0).UTC(), info.JailedUntil) } diff --git a/x/slashing/keeper/test_common.go b/x/slashing/keeper/test_common.go index d80c68b7e..20eb8eda6 100644 --- a/x/slashing/keeper/test_common.go +++ b/x/slashing/keeper/test_common.go @@ -5,143 +5,18 @@ package keeper // noalias import ( - "encoding/hex" - "testing" - "time" - - "github.com/stretchr/testify/require" - abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/crypto" - "github.com/tendermint/tendermint/crypto/ed25519" - "github.com/tendermint/tendermint/libs/log" - dbm "github.com/tendermint/tm-db" - - "github.com/cosmos/cosmos-sdk/codec" - simappcodec "github.com/cosmos/cosmos-sdk/simapp/codec" - "github.com/cosmos/cosmos-sdk/store" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/auth" - "github.com/cosmos/cosmos-sdk/x/bank" - "github.com/cosmos/cosmos-sdk/x/params/keeper" - paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" "github.com/cosmos/cosmos-sdk/x/slashing/types" "github.com/cosmos/cosmos-sdk/x/staking" - "github.com/cosmos/cosmos-sdk/x/supply" + "github.com/tendermint/tendermint/crypto" ) // TODO remove dependencies on staking (should only refer to validator set type from sdk) var ( - Pks = []crypto.PubKey{ - newPubKey("0B485CFC0EECC619440448436F8FC9DF40566F2369E72400281454CB552AFB50"), - newPubKey("0B485CFC0EECC619440448436F8FC9DF40566F2369E72400281454CB552AFB51"), - newPubKey("0B485CFC0EECC619440448436F8FC9DF40566F2369E72400281454CB552AFB52"), - } - Addrs = []sdk.ValAddress{ - sdk.ValAddress(Pks[0].Address()), - sdk.ValAddress(Pks[1].Address()), - sdk.ValAddress(Pks[2].Address()), - } InitTokens = sdk.TokensFromConsensusPower(200) - initCoins = sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, InitTokens)) ) -func createTestCodec() *codec.Codec { - cdc := codec.New() - sdk.RegisterCodec(cdc) - auth.RegisterCodec(cdc) - supply.RegisterCodec(cdc) - bank.RegisterCodec(cdc) - staking.RegisterCodec(cdc) - codec.RegisterCrypto(cdc) - return cdc -} - -func CreateTestInput(t *testing.T, defaults types.Params) (sdk.Context, bank.Keeper, staking.Keeper, paramtypes.Subspace, Keeper) { - keyAcc := sdk.NewKVStoreKey(auth.StoreKey) - keyBank := sdk.NewKVStoreKey(bank.StoreKey) - keyStaking := sdk.NewKVStoreKey(staking.StoreKey) - keySlashing := sdk.NewKVStoreKey(types.StoreKey) - keySupply := sdk.NewKVStoreKey(supply.StoreKey) - keyParams := sdk.NewKVStoreKey(paramtypes.StoreKey) - tkeyParams := sdk.NewTransientStoreKey(paramtypes.TStoreKey) - - db := dbm.NewMemDB() - - ms := store.NewCommitMultiStore(db) - ms.MountStoreWithDB(keyAcc, sdk.StoreTypeIAVL, db) - ms.MountStoreWithDB(keyBank, sdk.StoreTypeIAVL, db) - ms.MountStoreWithDB(keyStaking, sdk.StoreTypeIAVL, db) - ms.MountStoreWithDB(keySupply, sdk.StoreTypeIAVL, db) - ms.MountStoreWithDB(keySlashing, sdk.StoreTypeIAVL, db) - ms.MountStoreWithDB(keyParams, sdk.StoreTypeIAVL, db) - ms.MountStoreWithDB(tkeyParams, sdk.StoreTypeTransient, db) - - err := ms.LoadLatestVersion() - require.Nil(t, err) - - ctx := sdk.NewContext(ms, abci.Header{Time: time.Unix(0, 0)}, false, log.NewNopLogger()) - cdc := createTestCodec() - appCodec := simappcodec.NewAppCodec(cdc) - - feeCollectorAcc := supply.NewEmptyModuleAccount(auth.FeeCollectorName) - notBondedPool := supply.NewEmptyModuleAccount(staking.NotBondedPoolName, supply.Burner, supply.Staking) - bondPool := supply.NewEmptyModuleAccount(staking.BondedPoolName, supply.Burner, supply.Staking) - - blacklistedAddrs := make(map[string]bool) - blacklistedAddrs[feeCollectorAcc.GetAddress().String()] = true - blacklistedAddrs[notBondedPool.GetAddress().String()] = true - blacklistedAddrs[bondPool.GetAddress().String()] = true - - paramsKeeper := keeper.NewKeeper(appCodec, keyParams, tkeyParams) - accountKeeper := auth.NewAccountKeeper(appCodec, keyAcc, paramsKeeper.Subspace(auth.DefaultParamspace), auth.ProtoBaseAccount) - - bk := bank.NewBaseKeeper(appCodec, keyBank, accountKeeper, paramsKeeper.Subspace(bank.DefaultParamspace), blacklistedAddrs) - maccPerms := map[string][]string{ - auth.FeeCollectorName: nil, - staking.NotBondedPoolName: {supply.Burner, supply.Staking}, - staking.BondedPoolName: {supply.Burner, supply.Staking}, - } - supplyKeeper := supply.NewKeeper(appCodec, keySupply, accountKeeper, bk, maccPerms) - - totalSupply := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, InitTokens.MulRaw(int64(len(Addrs))))) - supplyKeeper.SetSupply(ctx, supply.NewSupply(totalSupply)) - - sk := staking.NewKeeper(staking.ModuleCdc, keyStaking, bk, supplyKeeper, paramsKeeper.Subspace(staking.DefaultParamspace)) - genesis := staking.DefaultGenesisState() - - // set module accounts - supplyKeeper.SetModuleAccount(ctx, feeCollectorAcc) - supplyKeeper.SetModuleAccount(ctx, bondPool) - supplyKeeper.SetModuleAccount(ctx, notBondedPool) - - _ = staking.InitGenesis(ctx, sk, accountKeeper, bk, supplyKeeper, genesis) - - for i, addr := range Addrs { - addr := sdk.AccAddress(addr) - accountKeeper.SetAccount(ctx, auth.NewBaseAccount(addr, Pks[i], uint64(i), 0)) - require.NoError(t, bk.SetBalances(ctx, addr, initCoins)) - } - - paramstore := paramsKeeper.Subspace(types.DefaultParamspace) - keeper := NewKeeper(types.ModuleCdc, keySlashing, &sk, paramstore) - - keeper.SetParams(ctx, defaults) - sk.SetHooks(keeper.Hooks()) - - return ctx, bk, sk, paramstore, keeper -} - -func newPubKey(pk string) (res crypto.PubKey) { - pkBytes, err := hex.DecodeString(pk) - if err != nil { - panic(err) - } - var pkEd ed25519.PubKeyEd25519 - copy(pkEd[:], pkBytes) - return pkEd -} - // Have to change these parameters for tests // lest the tests take forever func TestParams() types.Params {