From 00c7756610d76c5e933a437fe02ebe49a3e606f2 Mon Sep 17 00:00:00 2001 From: Akhil Kumar P <36399231+akhilkumarpilli@users.noreply.github.com> Date: Thu, 5 Dec 2024 18:57:26 +0530 Subject: [PATCH] test(integration): port x/slashing tests to server v2 (#22754) --- tests/integration/slashing/app_config.go | 32 -- tests/integration/slashing/slashing_test.go | 119 -------- .../{ => v2}/slashing/abci_test.go | 76 ++--- .../keeper => v2/slashing}/keeper_test.go | 242 ++++----------- .../slashing}/slash_redelegation_test.go | 277 +++++++----------- .../integration/v2/slashing/slashing_test.go | 175 +++++++++++ testutil/sims/address_helpers.go | 9 +- 7 files changed, 361 insertions(+), 569 deletions(-) delete mode 100644 tests/integration/slashing/app_config.go delete mode 100644 tests/integration/slashing/slashing_test.go rename tests/integration/{ => v2}/slashing/abci_test.go (50%) rename tests/integration/{slashing/keeper => v2/slashing}/keeper_test.go (59%) rename tests/integration/{slashing/keeper => v2/slashing}/slash_redelegation_test.go (61%) create mode 100644 tests/integration/v2/slashing/slashing_test.go diff --git a/tests/integration/slashing/app_config.go b/tests/integration/slashing/app_config.go deleted file mode 100644 index 415bea47145d..000000000000 --- a/tests/integration/slashing/app_config.go +++ /dev/null @@ -1,32 +0,0 @@ -package slashing - -import ( - _ "cosmossdk.io/x/accounts" // import as blank for app wiring - _ "cosmossdk.io/x/bank" // import as blank for app wiring - _ "cosmossdk.io/x/consensus" // import as blank for app wiring - _ "cosmossdk.io/x/distribution" // import as blank for app wiring - _ "cosmossdk.io/x/mint" // import as blank for app wiring - _ "cosmossdk.io/x/protocolpool" // import as blank for app wiring - _ "cosmossdk.io/x/slashing" // import as blank for app wiring - _ "cosmossdk.io/x/staking" // import as blank for app wiring - - "github.com/cosmos/cosmos-sdk/testutil/configurator" - _ "github.com/cosmos/cosmos-sdk/x/auth" // import as blank for app wiring - _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" // import as blank for app wiring - _ "github.com/cosmos/cosmos-sdk/x/genutil" // import as blank for app wiring -) - -var AppConfig = configurator.NewAppConfig( - configurator.AccountsModule(), - configurator.AuthModule(), - configurator.BankModule(), - configurator.StakingModule(), - configurator.SlashingModule(), - configurator.TxModule(), - configurator.ValidateModule(), - configurator.ConsensusModule(), - configurator.GenutilModule(), - configurator.MintModule(), - configurator.DistributionModule(), - configurator.ProtocolPoolModule(), -) diff --git a/tests/integration/slashing/slashing_test.go b/tests/integration/slashing/slashing_test.go deleted file mode 100644 index be116892c240..000000000000 --- a/tests/integration/slashing/slashing_test.go +++ /dev/null @@ -1,119 +0,0 @@ -package slashing_test - -import ( - "errors" - "testing" - - "github.com/stretchr/testify/require" - - "cosmossdk.io/core/header" - "cosmossdk.io/depinject" - "cosmossdk.io/log" - "cosmossdk.io/math" - bankkeeper "cosmossdk.io/x/bank/keeper" - "cosmossdk.io/x/slashing/keeper" - "cosmossdk.io/x/slashing/types" - stakingkeeper "cosmossdk.io/x/staking/keeper" - stakingtypes "cosmossdk.io/x/staking/types" - - "github.com/cosmos/cosmos-sdk/client" - codecaddress "github.com/cosmos/cosmos-sdk/codec/address" - "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - "github.com/cosmos/cosmos-sdk/testutil/configurator" - "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" -) - -var ( - priv1 = secp256k1.GenPrivKey() - addr1 = sdk.AccAddress(priv1.PubKey().Address()) - addrCodec = codecaddress.NewBech32Codec("cosmos") - valaddrCodec = codecaddress.NewBech32Codec("cosmosvaloper") - - valKey = ed25519.GenPrivKey() - valAddr = sdk.AccAddress(valKey.PubKey().Address()) -) - -func TestSlashingMsgs(t *testing.T) { - genTokens := sdk.TokensFromConsensusPower(42, sdk.DefaultPowerReduction) - bondTokens := sdk.TokensFromConsensusPower(10, sdk.DefaultPowerReduction) - genCoin := sdk.NewCoin(sdk.DefaultBondDenom, genTokens) - bondCoin := sdk.NewCoin(sdk.DefaultBondDenom, bondTokens) - - addrStr, err := addrCodec.BytesToString(addr1) - require.NoError(t, err) - acc1 := &authtypes.BaseAccount{ - Address: addrStr, - } - accs := []sims.GenesisAccount{{GenesisAccount: acc1, Coins: sdk.Coins{genCoin}}} - - startupCfg := sims.DefaultStartUpConfig() - startupCfg.GenesisAccounts = accs - - var ( - stakingKeeper *stakingkeeper.Keeper - bankKeeper bankkeeper.Keeper - slashingKeeper keeper.Keeper - txConfig client.TxConfig - ) - - app, err := sims.SetupWithConfiguration( - depinject.Configs( - configurator.NewAppConfig( - configurator.AccountsModule(), - configurator.AuthModule(), - configurator.StakingModule(), - configurator.SlashingModule(), - configurator.TxModule(), - configurator.ValidateModule(), - configurator.ConsensusModule(), - configurator.BankModule(), - ), - depinject.Supply(log.NewNopLogger()), - ), - startupCfg, &stakingKeeper, &bankKeeper, &slashingKeeper, &txConfig) - require.NoError(t, err) - - baseApp := app.BaseApp - - ctxCheck := baseApp.NewContext(true) - require.True(t, sdk.Coins{genCoin}.Equal(bankKeeper.GetAllBalances(ctxCheck, addr1))) - - require.NoError(t, err) - - description := stakingtypes.NewDescription("foo_moniker", "", "", "", "", &stakingtypes.Metadata{}) - commission := stakingtypes.NewCommissionRates(math.LegacyZeroDec(), math.LegacyZeroDec(), math.LegacyZeroDec()) - - addrStrVal, err := valaddrCodec.BytesToString(addr1) - require.NoError(t, err) - createValidatorMsg, err := stakingtypes.NewMsgCreateValidator( - addrStrVal, valKey.PubKey(), bondCoin, description, commission, math.OneInt(), - ) - require.NoError(t, err) - - headerInfo := header.Info{Height: app.LastBlockHeight() + 1} - _, _, err = sims.SignCheckDeliver(t, txConfig, app.BaseApp, headerInfo, []sdk.Msg{createValidatorMsg}, "", []uint64{0}, []uint64{0}, true, true, priv1) - require.NoError(t, err) - require.True(t, sdk.Coins{genCoin.Sub(bondCoin)}.Equal(bankKeeper.GetAllBalances(ctxCheck, addr1))) - - ctxCheck = baseApp.NewContext(true) - validator, err := stakingKeeper.GetValidator(ctxCheck, sdk.ValAddress(addr1)) - require.NoError(t, err) - - require.Equal(t, addrStrVal, validator.OperatorAddress) - require.Equal(t, stakingtypes.Bonded, validator.Status) - require.True(math.IntEq(t, bondTokens, validator.BondedTokens())) - unjailMsg := &types.MsgUnjail{ValidatorAddr: addrStrVal} - - ctxCheck = app.BaseApp.NewContext(true) - _, err = slashingKeeper.ValidatorSigningInfo.Get(ctxCheck, sdk.ConsAddress(valAddr)) - require.NoError(t, err) - - // unjail should fail with unknown validator - headerInfo = header.Info{Height: app.LastBlockHeight() + 1} - _, _, err = sims.SignCheckDeliver(t, txConfig, app.BaseApp, headerInfo, []sdk.Msg{unjailMsg}, "", []uint64{0}, []uint64{1}, false, false, priv1) - require.Error(t, err) - require.True(t, errors.Is(err, types.ErrValidatorNotJailed)) -} diff --git a/tests/integration/slashing/abci_test.go b/tests/integration/v2/slashing/abci_test.go similarity index 50% rename from tests/integration/slashing/abci_test.go rename to tests/integration/v2/slashing/abci_test.go index 96e869743e5d..f771941cf096 100644 --- a/tests/integration/slashing/abci_test.go +++ b/tests/integration/v2/slashing/abci_test.go @@ -8,68 +8,43 @@ import ( "cosmossdk.io/core/comet" coreheader "cosmossdk.io/core/header" - "cosmossdk.io/depinject" - "cosmossdk.io/log" - bankkeeper "cosmossdk.io/x/bank/keeper" + "cosmossdk.io/runtime/v2/services" "cosmossdk.io/x/slashing" - slashingkeeper "cosmossdk.io/x/slashing/keeper" "cosmossdk.io/x/slashing/testutil" - stakingkeeper "cosmossdk.io/x/staking/keeper" stakingtestutil "cosmossdk.io/x/staking/testutil" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/tests/integration/v2" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" ) // TestBeginBlocker is a unit test function that tests the behavior of the BeginBlocker function. // It sets up the necessary dependencies and context, creates a validator, and performs various operations // to test the slashing logic. It checks if the validator is correctly jailed after a certain number of blocks. func TestBeginBlocker(t *testing.T) { - var ( - interfaceRegistry codectypes.InterfaceRegistry - accountKeeper authkeeper.AccountKeeper - bankKeeper bankkeeper.Keeper - stakingKeeper *stakingkeeper.Keeper - slashingKeeper slashingkeeper.Keeper - ) - - app, err := simtestutil.Setup( - depinject.Configs( - AppConfig, - depinject.Supply(log.NewNopLogger()), - ), - &interfaceRegistry, - &accountKeeper, - &bankKeeper, - &stakingKeeper, - &slashingKeeper, - ) - require.NoError(t, err) + f := initFixture(t) - ctx := app.BaseApp.NewContext(false) + ctx := f.ctx pks := simtestutil.CreateTestPubKeys(1) - simtestutil.AddTestAddrsFromPubKeys(bankKeeper, stakingKeeper, ctx, pks, stakingKeeper.TokensFromConsensusPower(ctx, 200)) + simtestutil.AddTestAddrsFromPubKeys(f.bankKeeper, f.stakingKeeper, ctx, pks, f.stakingKeeper.TokensFromConsensusPower(ctx, 200)) addr, pk := sdk.ValAddress(pks[0].Address()), pks[0] - tstaking := stakingtestutil.NewHelper(t, ctx, stakingKeeper) + tstaking := stakingtestutil.NewHelper(t, ctx, f.stakingKeeper) // bond the validator power := int64(100) - acc := accountKeeper.NewAccountWithAddress(ctx, sdk.AccAddress(addr)) - accountKeeper.SetAccount(ctx, acc) + acc := f.accountKeeper.NewAccountWithAddress(ctx, sdk.AccAddress(addr)) + f.accountKeeper.SetAccount(ctx, acc) amt := tstaking.CreateValidatorWithValPower(addr, pk, power, true) - _, err = stakingKeeper.EndBlocker(ctx) + _, err := f.stakingKeeper.EndBlocker(ctx) require.NoError(t, err) - bondDenom, err := stakingKeeper.BondDenom(ctx) + bondDenom, err := f.stakingKeeper.BondDenom(ctx) require.NoError(t, err) require.Equal( - t, bankKeeper.GetAllBalances(ctx, sdk.AccAddress(addr)), + t, f.bankKeeper.GetAllBalances(ctx, sdk.AccAddress(addr)), sdk.NewCoins(sdk.NewCoin(bondDenom, testutil.InitTokens.Sub(amt))), ) - val, err := stakingKeeper.Validator(ctx, addr) + val, err := f.stakingKeeper.Validator(ctx, addr) require.NoError(t, err) require.Equal(t, amt, val.GetBondedTokens()) @@ -78,57 +53,58 @@ func TestBeginBlocker(t *testing.T) { Power: power, } - ctx = ctx.WithCometInfo(comet.Info{ + ctx = integration.SetCometInfo(ctx, comet.Info{ LastCommit: comet.CommitInfo{Votes: []comet.VoteInfo{{ Validator: abciVal, BlockIDFlag: comet.BlockIDFlagCommit, }}}, }) - cometInfoService := runtime.NewContextAwareCometInfoService() + cometInfoService := &services.ContextAwareCometInfoService{} - err = slashing.BeginBlocker(ctx, slashingKeeper, cometInfoService) + err = slashing.BeginBlocker(ctx, f.slashingKeeper, cometInfoService) require.NoError(t, err) - info, err := slashingKeeper.ValidatorSigningInfo.Get(ctx, sdk.ConsAddress(pk.Address())) + info, err := f.slashingKeeper.ValidatorSigningInfo.Get(ctx, sdk.ConsAddress(pk.Address())) require.NoError(t, err) - require.Equal(t, ctx.HeaderInfo().Height, info.StartHeight) + require.Equal(t, integration.HeaderInfoFromContext(ctx).Height, info.StartHeight) require.Equal(t, int64(0), info.IndexOffset) require.Equal(t, time.Unix(0, 0).UTC(), info.JailedUntil) require.Equal(t, int64(0), info.MissedBlocksCounter) height := int64(0) - signedBlocksWindow, err := slashingKeeper.SignedBlocksWindow(ctx) + signedBlocksWindow, err := f.slashingKeeper.SignedBlocksWindow(ctx) require.NoError(t, err) // for 100 blocks, mark the validator as having signed for ; height < signedBlocksWindow; height++ { - ctx = ctx.WithHeaderInfo(coreheader.Info{Height: height}) + ctx = integration.SetHeaderInfo(ctx, coreheader.Info{Height: height}) - err = slashing.BeginBlocker(ctx, slashingKeeper, cometInfoService) + err = slashing.BeginBlocker(ctx, f.slashingKeeper, cometInfoService) require.NoError(t, err) } - minSignedPerWindow, err := slashingKeeper.MinSignedPerWindow(ctx) + minSignedPerWindow, err := f.slashingKeeper.MinSignedPerWindow(ctx) require.NoError(t, err) // for 50 blocks, mark the validator as having not signed for ; height < ((signedBlocksWindow * 2) - minSignedPerWindow + 1); height++ { - ctx = ctx.WithHeaderInfo(coreheader.Info{Height: height}).WithCometInfo(comet.Info{ + ctx = integration.SetHeaderInfo(ctx, coreheader.Info{Height: height}) + ctx = integration.SetCometInfo(ctx, comet.Info{ LastCommit: comet.CommitInfo{Votes: []comet.VoteInfo{{ Validator: abciVal, BlockIDFlag: comet.BlockIDFlagAbsent, }}}, }) - err = slashing.BeginBlocker(ctx, slashingKeeper, cometInfoService) + err = slashing.BeginBlocker(ctx, f.slashingKeeper, cometInfoService) require.NoError(t, err) } // end block - _, err = stakingKeeper.EndBlocker(ctx) + _, err = f.stakingKeeper.EndBlocker(ctx) require.NoError(t, err) // validator should be jailed - validator, err := stakingKeeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(pk)) + validator, err := f.stakingKeeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(pk)) require.NoError(t, err) require.Equal(t, sdk.Unbonding, validator.GetStatus()) } diff --git a/tests/integration/slashing/keeper/keeper_test.go b/tests/integration/v2/slashing/keeper_test.go similarity index 59% rename from tests/integration/slashing/keeper/keeper_test.go rename to tests/integration/v2/slashing/keeper_test.go index 74ccf5da61f8..94a84de3cf12 100644 --- a/tests/integration/slashing/keeper/keeper_test.go +++ b/tests/integration/v2/slashing/keeper_test.go @@ -1,4 +1,4 @@ -package keeper_test +package slashing import ( "context" @@ -6,173 +6,21 @@ import ( "time" "github.com/stretchr/testify/require" - "go.uber.org/mock/gomock" "gotest.tools/v3/assert" - "cosmossdk.io/core/appmodule" "cosmossdk.io/core/comet" coreheader "cosmossdk.io/core/header" - "cosmossdk.io/log" - storetypes "cosmossdk.io/store/types" - "cosmossdk.io/x/bank" - bankkeeper "cosmossdk.io/x/bank/keeper" - banktypes "cosmossdk.io/x/bank/types" - "cosmossdk.io/x/consensus" - consensusparamkeeper "cosmossdk.io/x/consensus/keeper" - consensustypes "cosmossdk.io/x/consensus/types" - minttypes "cosmossdk.io/x/mint/types" - "cosmossdk.io/x/slashing" - slashingkeeper "cosmossdk.io/x/slashing/keeper" + "cosmossdk.io/core/transaction" "cosmossdk.io/x/slashing/testutil" slashingtypes "cosmossdk.io/x/slashing/types" - "cosmossdk.io/x/staking" - stakingkeeper "cosmossdk.io/x/staking/keeper" stakingtestutil "cosmossdk.io/x/staking/testutil" stakingtypes "cosmossdk.io/x/staking/types" - "github.com/cosmos/cosmos-sdk/baseapp" - "github.com/cosmos/cosmos-sdk/codec" - addresscodec "github.com/cosmos/cosmos-sdk/codec/address" - codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil" - "github.com/cosmos/cosmos-sdk/runtime" - "github.com/cosmos/cosmos-sdk/testutil/integration" + "github.com/cosmos/cosmos-sdk/tests/integration/v2" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" - moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" - "github.com/cosmos/cosmos-sdk/x/auth" - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" - authtestutil "github.com/cosmos/cosmos-sdk/x/auth/testutil" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) -type fixture struct { - app *integration.App - - ctx sdk.Context - - accountKeeper authkeeper.AccountKeeper - bankKeeper bankkeeper.Keeper - slashingKeeper slashingkeeper.Keeper - stakingKeeper *stakingkeeper.Keeper - - addrDels []sdk.AccAddress - valAddrs []sdk.ValAddress -} - -func initFixture(tb testing.TB) *fixture { - tb.Helper() - keys := storetypes.NewKVStoreKeys( - authtypes.StoreKey, banktypes.StoreKey, slashingtypes.StoreKey, stakingtypes.StoreKey, consensustypes.StoreKey, - ) - encodingCfg := moduletestutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}, auth.AppModule{}) - cdc := encodingCfg.Codec - - authority := authtypes.NewModuleAddress("gov") - - maccPerms := map[string][]string{ - minttypes.ModuleName: {authtypes.Minter}, - stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, - stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, - } - - msgRouter := baseapp.NewMsgServiceRouter() - queryRouter := baseapp.NewGRPCQueryRouter() - - // gomock initializations - ctrl := gomock.NewController(tb) - acctsModKeeper := authtestutil.NewMockAccountsModKeeper(ctrl) - accNum := uint64(0) - acctsModKeeper.EXPECT().NextAccountNumber(gomock.Any()).AnyTimes().DoAndReturn(func(ctx context.Context) (uint64, error) { - currentNum := accNum - accNum++ - return currentNum, nil - }) - - accountKeeper := authkeeper.NewAccountKeeper( - runtime.NewEnvironment(runtime.NewKVStoreService(keys[authtypes.StoreKey]), log.NewNopLogger(), runtime.EnvWithQueryRouterService(queryRouter), runtime.EnvWithMsgRouterService(msgRouter)), - cdc, - authtypes.ProtoBaseAccount, - acctsModKeeper, - maccPerms, - addresscodec.NewBech32Codec(sdk.Bech32MainPrefix), - sdk.Bech32MainPrefix, - authority.String(), - ) - - blockedAddresses := map[string]bool{ - accountKeeper.GetAuthority(): false, - } - bankKeeper := bankkeeper.NewBaseKeeper( - runtime.NewEnvironment(runtime.NewKVStoreService(keys[banktypes.StoreKey]), log.NewNopLogger(), runtime.EnvWithQueryRouterService(queryRouter), runtime.EnvWithMsgRouterService(msgRouter)), - cdc, - accountKeeper, - blockedAddresses, - authority.String(), - ) - - cometInfoService := runtime.NewContextAwareCometInfoService() - - consensusParamsKeeper := consensusparamkeeper.NewKeeper(cdc, runtime.NewEnvironment(runtime.NewKVStoreService(keys[consensustypes.StoreKey]), log.NewNopLogger(), runtime.EnvWithQueryRouterService(queryRouter), runtime.EnvWithMsgRouterService(msgRouter)), authtypes.NewModuleAddress("gov").String()) - - stakingKeeper := stakingkeeper.NewKeeper(cdc, runtime.NewEnvironment(runtime.NewKVStoreService(keys[stakingtypes.StoreKey]), log.NewNopLogger(), runtime.EnvWithQueryRouterService(queryRouter), runtime.EnvWithMsgRouterService(msgRouter)), accountKeeper, bankKeeper, consensusParamsKeeper, authority.String(), addresscodec.NewBech32Codec(sdk.Bech32PrefixValAddr), addresscodec.NewBech32Codec(sdk.Bech32PrefixConsAddr), cometInfoService) - - slashingKeeper := slashingkeeper.NewKeeper(runtime.NewEnvironment(runtime.NewKVStoreService(keys[slashingtypes.StoreKey]), log.NewNopLogger(), runtime.EnvWithQueryRouterService(queryRouter), runtime.EnvWithMsgRouterService(msgRouter)), cdc, &codec.LegacyAmino{}, stakingKeeper, authority.String()) - - bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper) - stakingModule := staking.NewAppModule(cdc, stakingKeeper) - slashingModule := slashing.NewAppModule(cdc, slashingKeeper, accountKeeper, bankKeeper, stakingKeeper, cdc.InterfaceRegistry(), cometInfoService) - consensusModule := consensus.NewAppModule(cdc, consensusParamsKeeper) - - integrationApp := integration.NewIntegrationApp(log.NewNopLogger(), keys, cdc, - encodingCfg.InterfaceRegistry.SigningContext().AddressCodec(), - encodingCfg.InterfaceRegistry.SigningContext().ValidatorAddressCodec(), - map[string]appmodule.AppModule{ - banktypes.ModuleName: bankModule, - stakingtypes.ModuleName: stakingModule, - slashingtypes.ModuleName: slashingModule, - consensustypes.ModuleName: consensusModule, - }, - msgRouter, - queryRouter, - ) - - sdkCtx := sdk.UnwrapSDKContext(integrationApp.Context()) - - // Register MsgServer and QueryServer - slashingtypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), slashingkeeper.NewMsgServerImpl(slashingKeeper)) - slashingtypes.RegisterQueryServer(integrationApp.QueryHelper(), slashingkeeper.NewQuerier(slashingKeeper)) - - // set default staking params - // TestParams set the SignedBlocksWindow to 1000 and MaxMissedBlocksPerWindow to 500 - err := slashingKeeper.Params.Set(sdkCtx, testutil.TestParams()) - assert.NilError(tb, err) - addrDels := simtestutil.AddTestAddrsIncremental(bankKeeper, stakingKeeper, sdkCtx, 6, stakingKeeper.TokensFromConsensusPower(sdkCtx, 200)) - valAddrs := simtestutil.ConvertAddrsToValAddrs(addrDels) - - consaddr0, err := stakingKeeper.ConsensusAddressCodec().BytesToString(addrDels[0]) - assert.NilError(tb, err) - consaddr1, err := stakingKeeper.ConsensusAddressCodec().BytesToString(addrDels[1]) - assert.NilError(tb, err) - - info1 := slashingtypes.NewValidatorSigningInfo(consaddr0, int64(4), time.Unix(2, 0), false, int64(10)) - info2 := slashingtypes.NewValidatorSigningInfo(consaddr1, int64(5), time.Unix(2, 0), false, int64(10)) - - err = slashingKeeper.ValidatorSigningInfo.Set(sdkCtx, sdk.ConsAddress(addrDels[0]), info1) - assert.NilError(tb, err) - err = slashingKeeper.ValidatorSigningInfo.Set(sdkCtx, sdk.ConsAddress(addrDels[1]), info2) - assert.NilError(tb, err) - return &fixture{ - app: integrationApp, - ctx: sdkCtx, - accountKeeper: accountKeeper, - bankKeeper: bankKeeper, - slashingKeeper: slashingKeeper, - stakingKeeper: stakingKeeper, - addrDels: addrDels, - valAddrs: valAddrs, - } -} - func TestUnJailNotBonded(t *testing.T) { t.Parallel() f := initFixture(t) @@ -194,8 +42,8 @@ func TestUnJailNotBonded(t *testing.T) { _, err = f.stakingKeeper.EndBlocker(f.ctx) assert.NilError(t, err) - newHeight := f.ctx.BlockHeight() + 1 - f.ctx = f.ctx.WithBlockHeight(newHeight).WithHeaderInfo(coreheader.Info{Height: newHeight}) + newHeight := int64(f.app.LastBlockHeight()) + 1 + 1 + f.ctx = integration.SetHeaderInfo(f.ctx, coreheader.Info{Height: newHeight}) // create a 6th validator with less power than the cliff validator (won't be bonded) addr, val := f.valAddrs[5], pks[5] @@ -211,8 +59,8 @@ func TestUnJailNotBonded(t *testing.T) { _, err = f.stakingKeeper.EndBlocker(f.ctx) assert.NilError(t, err) - newHeight = f.ctx.BlockHeight() + 1 - f.ctx = f.ctx.WithBlockHeight(newHeight).WithHeaderInfo(coreheader.Info{Height: newHeight}) + newHeight = integration.HeaderInfoFromContext(f.ctx).Height + 1 + f.ctx = integration.SetHeaderInfo(f.ctx, coreheader.Info{Height: newHeight}) tstaking.CheckValidator(addr, stakingtypes.Unbonded, false) @@ -226,8 +74,8 @@ func TestUnJailNotBonded(t *testing.T) { _, err = f.stakingKeeper.EndBlocker(f.ctx) assert.NilError(t, err) - newHeight = f.ctx.BlockHeight() + 1 - f.ctx = f.ctx.WithBlockHeight(newHeight).WithHeaderInfo(coreheader.Info{Height: newHeight}) + newHeight = integration.HeaderInfoFromContext(f.ctx).Height + 1 + f.ctx = integration.SetHeaderInfo(f.ctx, coreheader.Info{Height: newHeight}) // verify that validator is jailed tstaking.CheckValidator(addr, -1, true) @@ -237,16 +85,20 @@ func TestUnJailNotBonded(t *testing.T) { ValidatorAddr: addr.String(), } _, err = f.app.RunMsg( - &msgUnjail, - integration.WithAutomaticFinalizeBlock(), + t, + f.ctx, + func(ctx context.Context) (transaction.Msg, error) { + res, err := f.slashingMsgServer.Unjail(ctx, &msgUnjail) + return res, err + }, integration.WithAutomaticCommit(), ) assert.ErrorContains(t, err, "cannot be unjailed") _, err = f.stakingKeeper.EndBlocker(f.ctx) assert.NilError(t, err) - newHeight = f.ctx.BlockHeight() + 1 - f.ctx = f.ctx.WithBlockHeight(newHeight).WithHeaderInfo(coreheader.Info{Height: newHeight}) + newHeight = integration.HeaderInfoFromContext(f.ctx).Height + 1 + f.ctx = integration.SetHeaderInfo(f.ctx, coreheader.Info{Height: newHeight}) // bond to meet minimum self-delegationa accAddr, err = f.accountKeeper.AddressCodec().BytesToString(addr) assert.NilError(t, err) @@ -256,13 +108,17 @@ func TestUnJailNotBonded(t *testing.T) { _, err = f.stakingKeeper.EndBlocker(f.ctx) assert.NilError(t, err) - newHeight = f.ctx.BlockHeight() + 1 - f.ctx = f.ctx.WithBlockHeight(newHeight).WithHeaderInfo(coreheader.Info{Height: newHeight}) + newHeight = integration.HeaderInfoFromContext(f.ctx).Height + 1 + f.ctx = integration.SetHeaderInfo(f.ctx, coreheader.Info{Height: newHeight}) // verify we can immediately unjail _, err = f.app.RunMsg( - &msgUnjail, - integration.WithAutomaticFinalizeBlock(), + t, + f.ctx, + func(ctx context.Context) (transaction.Msg, error) { + res, err := f.slashingMsgServer.Unjail(ctx, &msgUnjail) + return res, err + }, integration.WithAutomaticCommit(), ) assert.NilError(t, err) @@ -277,18 +133,25 @@ func TestHandleNewValidator(t *testing.T) { t.Parallel() f := initFixture(t) + bondDenom, err := f.stakingKeeper.BondDenom(f.ctx) + require.NoError(t, err) + + bondPool := f.stakingKeeper.GetBondedPool(f.ctx) + + initialBondPoolBal := f.bankKeeper.GetBalance(f.ctx, bondPool.GetAddress(), bondDenom).Amount + pks := simtestutil.CreateTestPubKeys(1) addr, valpubkey := f.valAddrs[0], pks[0] tstaking := stakingtestutil.NewHelper(t, f.ctx, f.stakingKeeper) signedBlocksWindow, err := f.slashingKeeper.SignedBlocksWindow(f.ctx) assert.NilError(t, err) - f.ctx = f.ctx.WithBlockHeight(signedBlocksWindow + 1).WithHeaderInfo(coreheader.Info{Height: signedBlocksWindow + 1}) + f.ctx = integration.SetHeaderInfo(f.ctx, coreheader.Info{Height: signedBlocksWindow + 1}) assert.NilError(t, f.slashingKeeper.AddrPubkeyRelation.Set(f.ctx, pks[0].Address(), pks[0])) consaddr, err := f.stakingKeeper.ConsensusAddressCodec().BytesToString(valpubkey.Address()) assert.NilError(t, err) - info := slashingtypes.NewValidatorSigningInfo(consaddr, f.ctx.BlockHeight(), time.Unix(0, 0), false, int64(0)) + info := slashingtypes.NewValidatorSigningInfo(consaddr, integration.HeaderInfoFromContext(f.ctx).Height, time.Unix(0, 0), false, int64(0)) assert.NilError(t, f.slashingKeeper.ValidatorSigningInfo.Set(f.ctx, sdk.ConsAddress(valpubkey.Address()), info)) assert.Equal(t, signedBlocksWindow+1, info.StartHeight) @@ -300,9 +163,6 @@ func TestHandleNewValidator(t *testing.T) { _, err = f.stakingKeeper.EndBlocker(f.ctx) require.NoError(t, err) - bondDenom, err := f.stakingKeeper.BondDenom(f.ctx) - require.NoError(t, err) - assert.DeepEqual( t, f.bankKeeper.GetAllBalances(f.ctx, sdk.AccAddress(addr)), sdk.NewCoins(sdk.NewCoin(bondDenom, testutil.InitTokens.Sub(amt))), @@ -314,7 +174,7 @@ func TestHandleNewValidator(t *testing.T) { // Now a validator, for two blocks assert.NilError(t, f.slashingKeeper.HandleValidatorSignature(f.ctx, valpubkey.Address(), 100, comet.BlockIDFlagCommit)) - f.ctx = f.ctx.WithBlockHeight(signedBlocksWindow + 2).WithHeaderInfo(coreheader.Info{Height: signedBlocksWindow + 2}) + f.ctx = integration.SetHeaderInfo(f.ctx, coreheader.Info{Height: signedBlocksWindow + 2}) assert.NilError(t, f.slashingKeeper.HandleValidatorSignature(f.ctx, valpubkey.Address(), 100, comet.BlockIDFlagAbsent)) info, found := f.slashingKeeper.ValidatorSigningInfo.Get(f.ctx, sdk.ConsAddress(valpubkey.Address())) @@ -326,8 +186,7 @@ func TestHandleNewValidator(t *testing.T) { // validator should be bonded still, should not have been jailed or slashed validator, _ := f.stakingKeeper.GetValidatorByConsAddr(f.ctx, sdk.GetConsAddress(valpubkey)) assert.Equal(t, sdk.Bonded, validator.GetStatus()) - bondPool := f.stakingKeeper.GetBondedPool(f.ctx) - expTokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 100) + expTokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 100).Add(initialBondPoolBal) assert.Assert(t, expTokens.Equal(f.bankKeeper.GetBalance(f.ctx, bondPool.GetAddress(), bondDenom).Amount)) } @@ -348,7 +207,7 @@ func TestHandleAlreadyJailed(t *testing.T) { consaddr, err := f.stakingKeeper.ConsensusAddressCodec().BytesToString(val.Address()) assert.NilError(t, err) - info := slashingtypes.NewValidatorSigningInfo(consaddr, f.ctx.HeaderInfo().Height, time.Unix(0, 0), false, int64(0)) + info := slashingtypes.NewValidatorSigningInfo(consaddr, integration.HeaderInfoFromContext(f.ctx).Height, time.Unix(0, 0), false, int64(0)) assert.NilError(t, f.slashingKeeper.ValidatorSigningInfo.Set(f.ctx, sdk.ConsAddress(val.Address()), info)) acc := f.accountKeeper.NewAccountWithAddress(f.ctx, sdk.AccAddress(addr)) @@ -365,7 +224,7 @@ func TestHandleAlreadyJailed(t *testing.T) { // 1000 first blocks OK height := int64(0) for ; height < signedBlocksWindow; height++ { - f.ctx = f.ctx.WithHeaderInfo(coreheader.Info{Height: height}) + f.ctx = integration.SetHeaderInfo(f.ctx, coreheader.Info{Height: height}) err = f.slashingKeeper.HandleValidatorSignature(f.ctx, val.Address(), power, comet.BlockIDFlagCommit) assert.NilError(t, err) } @@ -375,7 +234,7 @@ func TestHandleAlreadyJailed(t *testing.T) { // 501 blocks missed for ; height < signedBlocksWindow+(signedBlocksWindow-minSignedPerWindow)+1; height++ { - f.ctx = f.ctx.WithHeaderInfo(coreheader.Info{Height: height}) + f.ctx = integration.SetHeaderInfo(f.ctx, coreheader.Info{Height: height}) err = f.slashingKeeper.HandleValidatorSignature(f.ctx, val.Address(), power, comet.BlockIDFlagAbsent) assert.NilError(t, err) } @@ -393,7 +252,7 @@ func TestHandleAlreadyJailed(t *testing.T) { assert.DeepEqual(t, resultingTokens, validator.GetTokens()) // another block missed - f.ctx = f.ctx.WithHeaderInfo(coreheader.Info{Height: height}) + f.ctx = integration.SetHeaderInfo(f.ctx, coreheader.Info{Height: height}) assert.NilError(t, f.slashingKeeper.HandleValidatorSignature(f.ctx, val.Address(), power, comet.BlockIDFlagAbsent)) // validator should not have been slashed twice @@ -432,19 +291,20 @@ func TestValidatorDippingInAndOut(t *testing.T) { consaddrStr, err := f.stakingKeeper.ConsensusAddressCodec().BytesToString(addr) assert.NilError(t, err) - info := slashingtypes.NewValidatorSigningInfo(consaddrStr, f.ctx.BlockHeight(), time.Unix(0, 0), false, int64(0)) + info := slashingtypes.NewValidatorSigningInfo(consaddrStr, integration.HeaderInfoFromContext(f.ctx).Height, time.Unix(0, 0), false, int64(0)) assert.NilError(t, f.slashingKeeper.ValidatorSigningInfo.Set(f.ctx, consAddr, info)) tstaking.CreateValidatorWithValPower(valAddr, val, power, true) validatorUpdates, err := f.stakingKeeper.EndBlocker(f.ctx) require.NoError(t, err) - assert.Equal(t, 1, len(validatorUpdates)) + // validator updates length should be equal to 2 as we already have one default validator + assert.Equal(t, 2, len(validatorUpdates)) tstaking.CheckValidator(valAddr, stakingtypes.Bonded, false) // 100 first blocks OK height := int64(0) for ; height < int64(100); height++ { - f.ctx = f.ctx.WithBlockHeight(height).WithHeaderInfo(coreheader.Info{Height: height}) + f.ctx = integration.SetHeaderInfo(f.ctx, coreheader.Info{Height: height}) assert.NilError(t, f.slashingKeeper.HandleValidatorSignature(f.ctx, val.Address(), power, comet.BlockIDFlagCommit)) } @@ -458,8 +318,10 @@ func TestValidatorDippingInAndOut(t *testing.T) { // 600 more blocks happened height += 600 - f.ctx = f.ctx.WithBlockHeight(height).WithHeaderInfo(coreheader.Info{Height: height}) + f.ctx = integration.SetHeaderInfo(f.ctx, coreheader.Info{Height: height}) + // store this height as we don't have block height value in context + startHeight := height // validator added back in accAddr, err := f.accountKeeper.AddressCodec().BytesToString(sdk.AccAddress(pks[2].Address())) assert.NilError(t, err) @@ -488,7 +350,7 @@ func TestValidatorDippingInAndOut(t *testing.T) { // misses 500 blocks + within the signing windows i.e. 700-1700 // validators misses all 1000 blocks of a SignedBlockWindows for ; height < latest+1; height++ { - err = f.slashingKeeper.HandleValidatorSignature(f.ctx.WithHeaderInfo(coreheader.Info{Height: height}), val.Address(), newPower, comet.BlockIDFlagAbsent) + err = f.slashingKeeper.HandleValidatorSignature(integration.SetHeaderInfo(f.ctx, coreheader.Info{Height: height}), val.Address(), newPower, comet.BlockIDFlagAbsent) assert.NilError(t, err) } @@ -497,7 +359,7 @@ func TestValidatorDippingInAndOut(t *testing.T) { assert.NilError(t, err) tstaking.CheckValidator(valAddr, stakingtypes.Unbonding, true) - info = slashingtypes.NewValidatorSigningInfo(consaddrStr, f.ctx.BlockHeight(), time.Unix(0, 0), false, int64(0)) + info = slashingtypes.NewValidatorSigningInfo(consaddrStr, startHeight, time.Unix(0, 0), false, int64(0)) err = f.slashingKeeper.ValidatorSigningInfo.Set(f.ctx, consAddr, info) assert.NilError(t, err) @@ -510,9 +372,9 @@ func TestValidatorDippingInAndOut(t *testing.T) { // some blocks pass height = int64(5000) - f.ctx = f.ctx.WithBlockHeight(height).WithHeaderInfo(coreheader.Info{Height: height}) + f.ctx = integration.SetHeaderInfo(f.ctx, coreheader.Info{Height: height}) - info = slashingtypes.NewValidatorSigningInfo(consaddrStr, f.ctx.BlockHeight(), time.Unix(0, 0), false, int64(0)) + info = slashingtypes.NewValidatorSigningInfo(consaddrStr, integration.HeaderInfoFromContext(f.ctx).Height, time.Unix(0, 0), false, int64(0)) err = f.slashingKeeper.ValidatorSigningInfo.Set(f.ctx, consAddr, info) assert.NilError(t, err) @@ -538,7 +400,7 @@ func TestValidatorDippingInAndOut(t *testing.T) { // validator misses 501 blocks after SignedBlockWindow period (1000 blocks) latest = signedBlocksWindow + height for ; height < latest+minSignedPerWindow; height++ { - f.ctx = f.ctx.WithBlockHeight(height).WithHeaderInfo(coreheader.Info{Height: height}) + f.ctx = integration.SetHeaderInfo(f.ctx, coreheader.Info{Height: height}) err = f.slashingKeeper.HandleValidatorSignature(f.ctx, val.Address(), newPower, comet.BlockIDFlagAbsent) assert.NilError(t, err) } diff --git a/tests/integration/slashing/keeper/slash_redelegation_test.go b/tests/integration/v2/slashing/slash_redelegation_test.go similarity index 61% rename from tests/integration/slashing/keeper/slash_redelegation_test.go rename to tests/integration/v2/slashing/slash_redelegation_test.go index b1a8ce858925..4d4b56ff2d33 100644 --- a/tests/integration/slashing/keeper/slash_redelegation_test.go +++ b/tests/integration/v2/slashing/slash_redelegation_test.go @@ -1,4 +1,4 @@ -package keeper_test +package slashing import ( "context" @@ -8,50 +8,24 @@ import ( "github.com/stretchr/testify/require" "cosmossdk.io/core/header" - "cosmossdk.io/depinject" - "cosmossdk.io/log" "cosmossdk.io/math" bankkeeper "cosmossdk.io/x/bank/keeper" banktestutil "cosmossdk.io/x/bank/testutil" - distributionkeeper "cosmossdk.io/x/distribution/keeper" - slashingkeeper "cosmossdk.io/x/slashing/keeper" stakingkeeper "cosmossdk.io/x/staking/keeper" stakingtypes "cosmossdk.io/x/staking/types" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - "github.com/cosmos/cosmos-sdk/tests/integration/slashing" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" + "github.com/cosmos/cosmos-sdk/tests/integration/v2" sdk "github.com/cosmos/cosmos-sdk/types" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" ) func TestSlashRedelegation(t *testing.T) { - // setting up - var ( - authKeeper authkeeper.AccountKeeper - stakingKeeper *stakingkeeper.Keeper - bankKeeper bankkeeper.Keeper - slashKeeper slashingkeeper.Keeper - distrKeeper distributionkeeper.Keeper - ) - - app, err := simtestutil.Setup( - depinject.Configs( - depinject.Supply(log.NewNopLogger()), - slashing.AppConfig, - ), - &stakingKeeper, - &bankKeeper, - &slashKeeper, - &distrKeeper, - &authKeeper, - ) - require.NoError(t, err) - - // get sdk context, staking msg server and bond denom - ctx := app.BaseApp.NewContext(false) - stakingMsgServer := stakingkeeper.NewMsgServerImpl(stakingKeeper) - bondDenom, err := stakingKeeper.BondDenom(ctx) + f := initFixture(t) + ctx := f.ctx + + stakingMsgServer := stakingkeeper.NewMsgServerImpl(f.stakingKeeper) + bondDenom, err := f.stakingKeeper.BondDenom(ctx) require.NoError(t, err) // evilVal will be slashed, goodVal won't be slashed @@ -65,12 +39,12 @@ func TestSlashRedelegation(t *testing.T) { testAcc2 := sdk.AccAddress([]byte("addr2_______________")) // fund acc 1 and acc 2 - testCoin := sdk.NewCoin(bondDenom, stakingKeeper.TokensFromConsensusPower(ctx, 10)) - fundAccount(t, ctx, bankKeeper, authKeeper, testAcc1, testCoin) - fundAccount(t, ctx, bankKeeper, authKeeper, testAcc2, testCoin) + testCoin := sdk.NewCoin(bondDenom, f.stakingKeeper.TokensFromConsensusPower(ctx, 10)) + fundAccount(t, ctx, f.bankKeeper, f.accountKeeper, testAcc1, testCoin) + fundAccount(t, ctx, f.bankKeeper, f.accountKeeper, testAcc2, testCoin) - balance1Before := bankKeeper.GetBalance(ctx, testAcc1, bondDenom) - balance2Before := bankKeeper.GetBalance(ctx, testAcc2, bondDenom) + balance1Before := f.bankKeeper.GetBalance(ctx, testAcc1, bondDenom) + balance2Before := f.bankKeeper.GetBalance(ctx, testAcc2, bondDenom) // assert acc 1 and acc 2 balance require.Equal(t, balance1Before.Amount.String(), testCoin.Amount.String()) @@ -78,7 +52,7 @@ func TestSlashRedelegation(t *testing.T) { // creating evil val evilValAddr := sdk.ValAddress(evilValPubKey.Address()) - fundAccount(t, ctx, bankKeeper, authKeeper, sdk.AccAddress(evilValAddr), testCoin) + fundAccount(t, ctx, f.bankKeeper, f.accountKeeper, sdk.AccAddress(evilValAddr), testCoin) createValMsg1, _ := stakingtypes.NewMsgCreateValidator( evilValAddr.String(), evilValPubKey, testCoin, stakingtypes.Description{Details: "test"}, stakingtypes.NewCommissionRates(math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDec(0)), math.OneInt()) _, err = stakingMsgServer.CreateValidator(ctx, createValMsg1) @@ -86,16 +60,17 @@ func TestSlashRedelegation(t *testing.T) { // creating good val goodValAddr := sdk.ValAddress(goodValPubKey.Address()) - fundAccount(t, ctx, bankKeeper, authKeeper, sdk.AccAddress(goodValAddr), testCoin) + fundAccount(t, ctx, f.bankKeeper, f.accountKeeper, sdk.AccAddress(goodValAddr), testCoin) createValMsg2, _ := stakingtypes.NewMsgCreateValidator( goodValAddr.String(), goodValPubKey, testCoin, stakingtypes.Description{Details: "test"}, stakingtypes.NewCommissionRates(math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDec(0)), math.OneInt()) _, err = stakingMsgServer.CreateValidator(ctx, createValMsg2) require.NoError(t, err) - ctx = ctx.WithBlockHeight(1).WithHeaderInfo(header.Info{Height: 1}) + ctx = integration.SetHeaderInfo(ctx, header.Info{Height: 1}) // next block, commit height 1, move to height 2 // acc 1 and acc 2 delegate to evil val - ctx, err = simtestutil.NextBlock(app, ctx, time.Duration(1)) + _, state := f.app.Deliver(t, ctx, nil) + _, err = f.app.Commit(state) require.NoError(t, err) // Acc 2 delegate @@ -111,13 +86,14 @@ func TestSlashRedelegation(t *testing.T) { // next block, commit height 2, move to height 3 // with the new delegations, evil val increases in voting power and commit byzantine behavior at height 3 consensus // at the same time, acc 1 and acc 2 withdraw delegation from evil val - ctx, err = simtestutil.NextBlock(app, ctx, time.Duration(1)) + _, state = f.app.Deliver(t, ctx, nil) + _, err = f.app.Commit(state) require.NoError(t, err) - evilVal, err := stakingKeeper.GetValidator(ctx, evilValAddr) + evilVal, err := f.stakingKeeper.GetValidator(ctx, evilValAddr) require.NoError(t, err) - evilPower := stakingKeeper.TokensToConsensusPower(ctx, evilVal.Tokens) + evilPower := f.stakingKeeper.TokensToConsensusPower(ctx, evilVal.Tokens) // Acc 1 redelegate from evil val to good val redelMsg := stakingtypes.NewMsgBeginRedelegate(testAcc1.String(), evilValAddr.String(), goodValAddr.String(), testCoin) @@ -135,81 +111,60 @@ func TestSlashRedelegation(t *testing.T) { require.NoError(t, err) // next block, commit height 3, move to height 4 - // Slash evil val for byzantine behavior at height 3 consensus, + // Slash evil val for byzantine behavior at height 2 consensus, // at which acc 1 and acc 2 still contributed to evil val voting power // even tho they undelegate at block 3, the valset update is applied after committed block 3 when height 3 consensus already passes - ctx, err = simtestutil.NextBlock(app, ctx, time.Duration(1)) + _, state = f.app.Deliver(t, ctx, nil) + _, err = f.app.Commit(state) require.NoError(t, err) // slash evil val with slash factor = 0.9, leaving only 10% of stake after slashing - evilVal, _ = stakingKeeper.GetValidator(ctx, evilValAddr) + evilVal, _ = f.stakingKeeper.GetValidator(ctx, evilValAddr) evilValConsAddr, err := evilVal.GetConsAddr() require.NoError(t, err) - err = slashKeeper.Slash(ctx, evilValConsAddr, math.LegacyMustNewDecFromStr("0.9"), evilPower, 3) + err = f.slashingKeeper.Slash(ctx, evilValConsAddr, math.LegacyMustNewDecFromStr("0.9"), evilPower, 2) require.NoError(t, err) - // assert invariant to make sure we conduct slashing correctly - _, stop := stakingkeeper.AllInvariants(stakingKeeper)(ctx) - require.False(t, stop) - - _, stop = bankkeeper.AllInvariants(bankKeeper)(ctx) - require.False(t, stop) - - _, stop = distributionkeeper.AllInvariants(distrKeeper)(ctx) - require.False(t, stop) - // one eternity later - ctx, err = simtestutil.NextBlock(app, ctx, time.Duration(1000000000000000000)) - require.NoError(t, err) - ctx, err = simtestutil.NextBlock(app, ctx, time.Duration(1)) + ctxHeader := integration.HeaderInfoFromContext(ctx) + ctxHeader.Time = ctxHeader.Time.Add(time.Duration(1000000000000000000)) + ctx = integration.SetHeaderInfo(ctx, ctxHeader) + _, state = f.app.Deliver(t, ctx, nil) + _, err = f.app.Commit(state) require.NoError(t, err) // confirm that account 1 and account 2 has been slashed, and the slash amount is correct - balance1AfterSlashing := bankKeeper.GetBalance(ctx, testAcc1, bondDenom) - balance2AfterSlashing := bankKeeper.GetBalance(ctx, testAcc2, bondDenom) + balance1AfterSlashing := f.bankKeeper.GetBalance(ctx, testAcc1, bondDenom) + balance2AfterSlashing := f.bankKeeper.GetBalance(ctx, testAcc2, bondDenom) require.Equal(t, balance1AfterSlashing.Amount.Mul(math.NewIntFromUint64(10)).String(), balance1Before.Amount.String()) require.Equal(t, balance2AfterSlashing.Amount.Mul(math.NewIntFromUint64(10)).String(), balance2Before.Amount.String()) } -func fundAccount(t *testing.T, ctx context.Context, bankKeeper bankkeeper.Keeper, authKeeper authkeeper.AccountKeeper, addr sdk.AccAddress, amount ...sdk.Coin) { +func fundAccount(t *testing.T, ctx context.Context, bankKeeper bankkeeper.Keeper, accountKeeper authkeeper.AccountKeeper, addr sdk.AccAddress, amount ...sdk.Coin) { t.Helper() - if authKeeper.GetAccount(ctx, addr) == nil { - addrAcc := authKeeper.NewAccountWithAddress(ctx, addr) - authKeeper.SetAccount(ctx, addrAcc) + if accountKeeper.GetAccount(ctx, addr) == nil { + addrAcc := accountKeeper.NewAccountWithAddress(ctx, addr) + accountKeeper.SetAccount(ctx, addrAcc) } require.NoError(t, banktestutil.FundAccount(ctx, bankKeeper, addr, amount)) } func TestOverSlashing(t *testing.T) { + f := initFixture(t) + ctx := f.ctx + // slash penalty percentage slashFraction := "0.45" // percentage of (undelegation/(undelegation + redelegation)) undelegationPercentageStr := "0.30" - // setting up - var ( - stakingKeeper *stakingkeeper.Keeper - bankKeeper bankkeeper.Keeper - slashKeeper slashingkeeper.Keeper - distrKeeper distributionkeeper.Keeper - authKeeper authkeeper.AccountKeeper - ) - - app, err := simtestutil.Setup(depinject.Configs( - depinject.Supply(log.NewNopLogger()), - slashing.AppConfig, - ), &stakingKeeper, &bankKeeper, &slashKeeper, &distrKeeper, &authKeeper) - require.NoError(t, err) - - // get sdk context, staking msg server and bond denom - ctx := app.BaseApp.NewContext(false) - stakingMsgServer := stakingkeeper.NewMsgServerImpl(stakingKeeper) - bondDenom, err := stakingKeeper.BondDenom(ctx) + stakingMsgServer := stakingkeeper.NewMsgServerImpl(f.stakingKeeper) + bondDenom, err := f.stakingKeeper.BondDenom(ctx) require.NoError(t, err) // evilVal will be slashed, goodVal won't be slashed @@ -231,13 +186,13 @@ func TestOverSlashing(t *testing.T) { // fund all accounts testCoin := sdk.NewCoin(bondDenom, math.NewInt(1_000_000)) - fundAccount(t, ctx, bankKeeper, authKeeper, testAcc1, testCoin) - fundAccount(t, ctx, bankKeeper, authKeeper, testAcc2, testCoin) - fundAccount(t, ctx, bankKeeper, authKeeper, testAcc3, testCoin) + fundAccount(t, ctx, f.bankKeeper, f.accountKeeper, testAcc1, testCoin) + fundAccount(t, ctx, f.bankKeeper, f.accountKeeper, testAcc2, testCoin) + fundAccount(t, ctx, f.bankKeeper, f.accountKeeper, testAcc3, testCoin) - balance1Before := bankKeeper.GetBalance(ctx, testAcc1, bondDenom) - balance2Before := bankKeeper.GetBalance(ctx, testAcc2, bondDenom) - balance3Before := bankKeeper.GetBalance(ctx, testAcc3, bondDenom) + balance1Before := f.bankKeeper.GetBalance(ctx, testAcc1, bondDenom) + balance2Before := f.bankKeeper.GetBalance(ctx, testAcc2, bondDenom) + balance3Before := f.bankKeeper.GetBalance(ctx, testAcc3, bondDenom) // assert acc 1, 2 and 3 balance require.Equal(t, testCoin.Amount.String(), balance1Before.Amount.String()) @@ -246,7 +201,7 @@ func TestOverSlashing(t *testing.T) { // create evil val evilValAddr := sdk.ValAddress(evilValPubKey.Address()) - fundAccount(t, ctx, bankKeeper, authKeeper, sdk.AccAddress(evilValAddr), testCoin) + fundAccount(t, ctx, f.bankKeeper, f.accountKeeper, sdk.AccAddress(evilValAddr), testCoin) createValMsg1, _ := stakingtypes.NewMsgCreateValidator( evilValAddr.String(), evilValPubKey, testCoin, stakingtypes.Description{Details: "test"}, stakingtypes.NewCommissionRates(math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDec(0)), math.OneInt()) _, err = stakingMsgServer.CreateValidator(ctx, createValMsg1) @@ -254,15 +209,16 @@ func TestOverSlashing(t *testing.T) { // create good val 1 goodValAddr := sdk.ValAddress(goodValPubKey.Address()) - fundAccount(t, ctx, bankKeeper, authKeeper, sdk.AccAddress(goodValAddr), testCoin) + fundAccount(t, ctx, f.bankKeeper, f.accountKeeper, sdk.AccAddress(goodValAddr), testCoin) createValMsg2, _ := stakingtypes.NewMsgCreateValidator( goodValAddr.String(), goodValPubKey, testCoin, stakingtypes.Description{Details: "test"}, stakingtypes.NewCommissionRates(math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDec(0)), math.OneInt()) _, err = stakingMsgServer.CreateValidator(ctx, createValMsg2) require.NoError(t, err) // next block - ctx = ctx.WithBlockHeight(app.LastBlockHeight() + 1).WithHeaderInfo(header.Info{Height: app.LastBlockHeight() + 1}) - ctx, err = simtestutil.NextBlock(app, ctx, time.Duration(1)) + ctx = integration.SetHeaderInfo(ctx, header.Info{Height: int64(f.app.LastBlockHeight()) + 1}) + _, state := f.app.Deliver(t, ctx, nil) + _, err = f.app.Commit(state) require.NoError(t, err) // delegate all accs to evil val @@ -279,21 +235,23 @@ func TestOverSlashing(t *testing.T) { require.NoError(t, err) // next block - ctx, err = simtestutil.NextBlock(app, ctx, time.Duration(1)) + _, state = f.app.Deliver(t, ctx, nil) + _, err = f.app.Commit(state) require.NoError(t, err) // evilValAddr done something bad - misbehaveHeight := ctx.BlockHeader().Height - evilVal, err := stakingKeeper.GetValidator(ctx, evilValAddr) + misbehaveHeight := integration.HeaderInfoFromContext(ctx).Height + evilVal, err := f.stakingKeeper.GetValidator(ctx, evilValAddr) require.NoError(t, err) evilValConsAddr, err := evilVal.GetConsAddr() require.NoError(t, err) - evilPower := stakingKeeper.TokensToConsensusPower(ctx, evilVal.Tokens) + evilPower := f.stakingKeeper.TokensToConsensusPower(ctx, evilVal.Tokens) // next block - ctx, err = simtestutil.NextBlock(app, ctx, time.Duration(1)) + _, state = f.app.Deliver(t, ctx, nil) + _, err = f.app.Commit(state) require.NoError(t, err) // acc 1: redelegate to goodval1 and undelegate FULL amount @@ -319,7 +277,8 @@ func TestOverSlashing(t *testing.T) { amountToUndelegate := undelegationAmountDec.TruncateInt() // next block - ctx, err = simtestutil.NextBlock(app, ctx, time.Duration(1)) + _, state = f.app.Deliver(t, ctx, nil) + _, err = f.app.Commit(state) require.NoError(t, err) portionofTestCoins := sdk.NewCoin(bondDenom, amountToUndelegate) @@ -328,38 +287,35 @@ func TestOverSlashing(t *testing.T) { require.NoError(t, err) // next block - ctx, err = simtestutil.NextBlock(app, ctx, time.Duration(1)) + _, state = f.app.Deliver(t, ctx, nil) + _, err = f.app.Commit(state) require.NoError(t, err) // slash the evil val - err = slashKeeper.Slash(ctx, evilValConsAddr, math.LegacyMustNewDecFromStr(slashFraction), evilPower, misbehaveHeight) + err = f.slashingKeeper.Slash(ctx, evilValConsAddr, math.LegacyMustNewDecFromStr(slashFraction), evilPower, misbehaveHeight) require.NoError(t, err) - // assert invariants - _, stop := stakingkeeper.AllInvariants(stakingKeeper)(ctx) - require.False(t, stop) - _, stop = bankkeeper.AllInvariants(bankKeeper)(ctx) - require.False(t, stop) - _, stop = distributionkeeper.AllInvariants(distrKeeper)(ctx) - require.False(t, stop) - // fastforward 2 blocks to complete redelegations and unbondings for i := 0; i < 2; i++ { - ctx, err = simtestutil.NextBlock(app, ctx, time.Duration(1000000000000000000)) + ctxHeader := integration.HeaderInfoFromContext(ctx) + ctxHeader.Time = ctxHeader.Time.Add(time.Duration(1000000000000000000)) + ctx = integration.SetHeaderInfo(ctx, ctxHeader) + _, state = f.app.Deliver(t, ctx, nil) + _, err = f.app.Commit(state) require.NoError(t, err) } // we check all accounts should be slashed with the equal amount, and they should end up with same balance including staked amount - stakedAcc1, err := stakingKeeper.GetDelegatorBonded(ctx, testAcc1) + stakedAcc1, err := f.stakingKeeper.GetDelegatorBonded(ctx, testAcc1) require.NoError(t, err) - stakedAcc2, err := stakingKeeper.GetDelegatorBonded(ctx, testAcc2) + stakedAcc2, err := f.stakingKeeper.GetDelegatorBonded(ctx, testAcc2) require.NoError(t, err) - stakedAcc3, err := stakingKeeper.GetDelegatorBonded(ctx, testAcc3) + stakedAcc3, err := f.stakingKeeper.GetDelegatorBonded(ctx, testAcc3) require.NoError(t, err) - balance1AfterSlashing := bankKeeper.GetBalance(ctx, testAcc1, bondDenom).Add(sdk.NewCoin(bondDenom, stakedAcc1)) - balance2AfterSlashing := bankKeeper.GetBalance(ctx, testAcc2, bondDenom).Add(sdk.NewCoin(bondDenom, stakedAcc2)) - balance3AfterSlashing := bankKeeper.GetBalance(ctx, testAcc3, bondDenom).Add(sdk.NewCoin(bondDenom, stakedAcc3)) + balance1AfterSlashing := f.bankKeeper.GetBalance(ctx, testAcc1, bondDenom).Add(sdk.NewCoin(bondDenom, stakedAcc1)) + balance2AfterSlashing := f.bankKeeper.GetBalance(ctx, testAcc2, bondDenom).Add(sdk.NewCoin(bondDenom, stakedAcc2)) + balance3AfterSlashing := f.bankKeeper.GetBalance(ctx, testAcc3, bondDenom).Add(sdk.NewCoin(bondDenom, stakedAcc3)) require.Equal(t, "550000stake", balance1AfterSlashing.String()) require.Equal(t, "550000stake", balance2AfterSlashing.String()) @@ -367,32 +323,11 @@ func TestOverSlashing(t *testing.T) { } func TestSlashRedelegation_ValidatorLeftWithNoTokens(t *testing.T) { - // setting up - var ( - authKeeper authkeeper.AccountKeeper - stakingKeeper *stakingkeeper.Keeper - bankKeeper bankkeeper.Keeper - slashKeeper slashingkeeper.Keeper - distrKeeper distributionkeeper.Keeper - ) - - app, err := simtestutil.Setup( - depinject.Configs( - depinject.Supply(log.NewNopLogger()), - slashing.AppConfig, - ), - &stakingKeeper, - &bankKeeper, - &slashKeeper, - &distrKeeper, - &authKeeper, - ) - require.NoError(t, err) - - // get sdk context, staking msg server and bond denom - ctx := app.BaseApp.NewContext(false).WithBlockHeight(1).WithHeaderInfo(header.Info{Height: 1}) - stakingMsgServer := stakingkeeper.NewMsgServerImpl(stakingKeeper) - bondDenom, err := stakingKeeper.BondDenom(ctx) + f := initFixture(t) + ctx := f.ctx + + stakingMsgServer := stakingkeeper.NewMsgServerImpl(f.stakingKeeper) + bondDenom, err := f.stakingKeeper.BondDenom(ctx) require.NoError(t, err) // create validators DST and SRC @@ -402,9 +337,9 @@ func TestSlashRedelegation_ValidatorLeftWithNoTokens(t *testing.T) { dstAddr := sdk.ValAddress(dstPubKey.Address()) srcAddr := sdk.ValAddress(srcPubKey.Address()) - testCoin := sdk.NewCoin(bondDenom, stakingKeeper.TokensFromConsensusPower(ctx, 1000)) - fundAccount(t, ctx, bankKeeper, authKeeper, sdk.AccAddress(dstAddr), testCoin) - fundAccount(t, ctx, bankKeeper, authKeeper, sdk.AccAddress(srcAddr), testCoin) + testCoin := sdk.NewCoin(bondDenom, f.stakingKeeper.TokensFromConsensusPower(ctx, 1000)) + fundAccount(t, ctx, f.bankKeeper, f.accountKeeper, sdk.AccAddress(dstAddr), testCoin) + fundAccount(t, ctx, f.bankKeeper, f.accountKeeper, sdk.AccAddress(srcAddr), testCoin) createValMsgDST, _ := stakingtypes.NewMsgCreateValidator( dstAddr.String(), dstPubKey, testCoin, stakingtypes.Description{Details: "Validator DST"}, stakingtypes.NewCommissionRates(math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDec(0)), math.OneInt()) @@ -418,10 +353,10 @@ func TestSlashRedelegation_ValidatorLeftWithNoTokens(t *testing.T) { // create a user accounts and delegate to SRC and DST userAcc := sdk.AccAddress([]byte("user1_______________")) - fundAccount(t, ctx, bankKeeper, authKeeper, userAcc, testCoin) + fundAccount(t, ctx, f.bankKeeper, f.accountKeeper, userAcc, testCoin) userAcc2 := sdk.AccAddress([]byte("user2_______________")) - fundAccount(t, ctx, bankKeeper, authKeeper, userAcc2, testCoin) + fundAccount(t, ctx, f.bankKeeper, f.accountKeeper, userAcc2, testCoin) delMsg := stakingtypes.NewMsgDelegate(userAcc.String(), srcAddr.String(), testCoin) _, err = stakingMsgServer.Delegate(ctx, delMsg) @@ -431,18 +366,20 @@ func TestSlashRedelegation_ValidatorLeftWithNoTokens(t *testing.T) { _, err = stakingMsgServer.Delegate(ctx, delMsg) require.NoError(t, err) - ctx, err = simtestutil.NextBlock(app, ctx, time.Duration(1)) + _, state := f.app.Deliver(t, ctx, nil) + _, err = f.app.Commit(state) require.NoError(t, err) // commit an infraction with DST and store the power at this height - dstVal, err := stakingKeeper.GetValidator(ctx, dstAddr) + dstVal, err := f.stakingKeeper.GetValidator(ctx, dstAddr) require.NoError(t, err) - dstPower := stakingKeeper.TokensToConsensusPower(ctx, dstVal.Tokens) + dstPower := f.stakingKeeper.TokensToConsensusPower(ctx, dstVal.Tokens) dstConsAddr, err := dstVal.GetConsAddr() require.NoError(t, err) - dstInfractionHeight := ctx.BlockHeight() + dstInfractionHeight := f.app.LastBlockHeight() + 1 - ctx, err = simtestutil.NextBlock(app, ctx, time.Duration(1)) + _, state = f.app.Deliver(t, ctx, nil) + _, err = f.app.Commit(state) require.NoError(t, err) // undelegate all the user tokens from DST @@ -451,14 +388,15 @@ func TestSlashRedelegation_ValidatorLeftWithNoTokens(t *testing.T) { require.NoError(t, err) // commit an infraction with SRC and store the power at this height - srcVal, err := stakingKeeper.GetValidator(ctx, srcAddr) + srcVal, err := f.stakingKeeper.GetValidator(ctx, srcAddr) require.NoError(t, err) - srcPower := stakingKeeper.TokensToConsensusPower(ctx, srcVal.Tokens) + srcPower := f.stakingKeeper.TokensToConsensusPower(ctx, srcVal.Tokens) srcConsAddr, err := srcVal.GetConsAddr() require.NoError(t, err) - srcInfractionHeight := ctx.BlockHeight() + srcInfractionHeight := f.app.LastBlockHeight() + 1 - ctx, err = simtestutil.NextBlock(app, ctx, time.Duration(1)) + _, state = f.app.Deliver(t, ctx, nil) + _, err = f.app.Commit(state) require.NoError(t, err) // redelegate all the user tokens from SRC to DST @@ -471,7 +409,8 @@ func TestSlashRedelegation_ValidatorLeftWithNoTokens(t *testing.T) { _, err = stakingMsgServer.Undelegate(ctx, undelMsg) require.NoError(t, err) - ctx, err = simtestutil.NextBlock(app, ctx, time.Duration(1)) + _, state = f.app.Deliver(t, ctx, nil) + _, err = f.app.Commit(state) require.NoError(t, err) undelMsg = stakingtypes.NewMsgUndelegate(userAcc.String(), dstAddr.String(), testCoin) @@ -479,24 +418,14 @@ func TestSlashRedelegation_ValidatorLeftWithNoTokens(t *testing.T) { require.NoError(t, err) // check that dst now has zero tokens - valDst, err := stakingKeeper.GetValidator(ctx, dstAddr) + valDst, err := f.stakingKeeper.GetValidator(ctx, dstAddr) require.NoError(t, err) require.Equal(t, math.ZeroInt().String(), valDst.Tokens.String()) // slash the infractions - err = slashKeeper.Slash(ctx, dstConsAddr, math.LegacyMustNewDecFromStr("0.8"), dstPower, dstInfractionHeight) + err = f.slashingKeeper.Slash(ctx, dstConsAddr, math.LegacyMustNewDecFromStr("0.8"), dstPower, int64(dstInfractionHeight)) require.NoError(t, err) - err = slashKeeper.Slash(ctx, srcConsAddr, math.LegacyMustNewDecFromStr("0.5"), srcPower, srcInfractionHeight) + err = f.slashingKeeper.Slash(ctx, srcConsAddr, math.LegacyMustNewDecFromStr("0.5"), srcPower, int64(srcInfractionHeight)) require.NoError(t, err) - - // assert invariants to ensure correctness - _, stop := stakingkeeper.AllInvariants(stakingKeeper)(ctx) - require.False(t, stop) - - _, stop = bankkeeper.AllInvariants(bankKeeper)(ctx) - require.False(t, stop) - - _, stop = distributionkeeper.AllInvariants(distrKeeper)(ctx) - require.False(t, stop) } diff --git a/tests/integration/v2/slashing/slashing_test.go b/tests/integration/v2/slashing/slashing_test.go new file mode 100644 index 000000000000..bc835e84a39a --- /dev/null +++ b/tests/integration/v2/slashing/slashing_test.go @@ -0,0 +1,175 @@ +package slashing + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/require" + "gotest.tools/v3/assert" + + "cosmossdk.io/depinject" + "cosmossdk.io/log" + "cosmossdk.io/math" + _ "cosmossdk.io/x/accounts" // import as blank for app wiring + _ "cosmossdk.io/x/bank" // import as blank for app wiring + bankkeeper "cosmossdk.io/x/bank/keeper" + banktestutil "cosmossdk.io/x/bank/testutil" + _ "cosmossdk.io/x/consensus" // import as blank for app wiring + _ "cosmossdk.io/x/distribution" // import as blank for app wiring + distrkeeper "cosmossdk.io/x/distribution/keeper" + _ "cosmossdk.io/x/mint" // import as blank for app wiring + _ "cosmossdk.io/x/protocolpool" // import as blank for app wiring + _ "cosmossdk.io/x/slashing" // import as blank for app wiring + slashingkeeper "cosmossdk.io/x/slashing/keeper" + "cosmossdk.io/x/slashing/testutil" + slashingtypes "cosmossdk.io/x/slashing/types" + _ "cosmossdk.io/x/staking" // import as blank for app wiring + stakingkeeper "cosmossdk.io/x/staking/keeper" + stakingtypes "cosmossdk.io/x/staking/types" + + "github.com/cosmos/cosmos-sdk/client" + codecaddress "github.com/cosmos/cosmos-sdk/codec/address" + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/tests/integration/v2" + "github.com/cosmos/cosmos-sdk/testutil/configurator" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" + sdk "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/cosmos-sdk/x/auth" // import as blank for app wiring + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" // import as blank for app wiring + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + _ "github.com/cosmos/cosmos-sdk/x/genutil" // import as blank for app wiring +) + +var ( + priv1 = secp256k1.GenPrivKey() + addr1 = sdk.AccAddress(priv1.PubKey().Address()) + valaddrCodec = codecaddress.NewBech32Codec("cosmosvaloper") + + valKey = ed25519.GenPrivKey() + valAddr = sdk.AccAddress(valKey.PubKey().Address()) +) + +type fixture struct { + app *integration.App + + ctx context.Context + + accountKeeper authkeeper.AccountKeeper + bankKeeper bankkeeper.Keeper + slashingKeeper slashingkeeper.Keeper + stakingKeeper *stakingkeeper.Keeper + distrKeeper distrkeeper.Keeper + + slashingMsgServer slashingtypes.MsgServer + txConfig client.TxConfig + + valAddrs []sdk.ValAddress +} + +func initFixture(t *testing.T) *fixture { + t.Helper() + + res := fixture{} + + moduleConfigs := []configurator.ModuleOption{ + configurator.AccountsModule(), + configurator.AuthModule(), + configurator.BankModule(), + configurator.StakingModule(), + configurator.SlashingModule(), + configurator.TxModule(), + configurator.ValidateModule(), + configurator.ConsensusModule(), + configurator.GenutilModule(), + configurator.MintModule(), + configurator.DistributionModule(), + configurator.ProtocolPoolModule(), + } + + acc := &authtypes.BaseAccount{ + Address: addr1.String(), + } + + var err error + startupCfg := integration.DefaultStartUpConfig(t) + startupCfg.GenesisAccounts = []integration.GenesisAccount{{GenesisAccount: acc}} + + startupCfg.BranchService = &integration.BranchService{} + startupCfg.HeaderService = &integration.HeaderService{} + + res.app, err = integration.NewApp( + depinject.Configs(configurator.NewAppV2Config(moduleConfigs...), depinject.Supply(log.NewNopLogger())), + startupCfg, + &res.bankKeeper, &res.accountKeeper, &res.stakingKeeper, &res.slashingKeeper, &res.distrKeeper, &res.txConfig) + require.NoError(t, err) + + res.ctx = res.app.StateLatestContext(t) + + // set default staking params + // TestParams set the SignedBlocksWindow to 1000 and MaxMissedBlocksPerWindow to 500 + err = res.slashingKeeper.Params.Set(res.ctx, testutil.TestParams()) + assert.NilError(t, err) + + addrDels := simtestutil.AddTestAddrsIncremental(res.bankKeeper, res.stakingKeeper, res.ctx, 6, res.stakingKeeper.TokensFromConsensusPower(res.ctx, 200)) + valAddrs := simtestutil.ConvertAddrsToValAddrs(addrDels) + + consaddr0, err := res.stakingKeeper.ConsensusAddressCodec().BytesToString(addrDels[0]) + require.NoError(t, err) + consaddr1, err := res.stakingKeeper.ConsensusAddressCodec().BytesToString(addrDels[1]) + require.NoError(t, err) + + info1 := slashingtypes.NewValidatorSigningInfo(consaddr0, int64(4), time.Unix(2, 0), false, int64(10)) + info2 := slashingtypes.NewValidatorSigningInfo(consaddr1, int64(5), time.Unix(2, 0), false, int64(10)) + + err = res.slashingKeeper.ValidatorSigningInfo.Set(res.ctx, sdk.ConsAddress(addrDels[0]), info1) + require.NoError(t, err) + err = res.slashingKeeper.ValidatorSigningInfo.Set(res.ctx, sdk.ConsAddress(addrDels[1]), info2) + require.NoError(t, err) + + res.valAddrs = valAddrs + res.slashingMsgServer = slashingkeeper.NewMsgServerImpl(res.slashingKeeper) + + return &res +} + +func TestSlashingMsgs(t *testing.T) { + f := initFixture(t) + + genTokens := sdk.TokensFromConsensusPower(42, sdk.DefaultPowerReduction) + bondTokens := sdk.TokensFromConsensusPower(10, sdk.DefaultPowerReduction) + genCoin := sdk.NewCoin(sdk.DefaultBondDenom, genTokens) + bondCoin := sdk.NewCoin(sdk.DefaultBondDenom, bondTokens) + + require.NoError(t, banktestutil.FundAccount(f.ctx, f.bankKeeper, addr1, sdk.NewCoins(genCoin))) + + description := stakingtypes.NewDescription("foo_moniker", "", "", "", "", &stakingtypes.Metadata{}) + commission := stakingtypes.NewCommissionRates(math.LegacyZeroDec(), math.LegacyZeroDec(), math.LegacyZeroDec()) + + addrStrVal, err := valaddrCodec.BytesToString(addr1) + require.NoError(t, err) + createValidatorMsg, err := stakingtypes.NewMsgCreateValidator( + addrStrVal, valKey.PubKey(), bondCoin, description, commission, math.OneInt(), + ) + require.NoError(t, err) + + _ = f.app.SignCheckDeliver(t, f.ctx, []sdk.Msg{createValidatorMsg}, "", []uint64{0}, []uint64{0}, []cryptotypes.PrivKey{priv1}, "") + require.True(t, sdk.Coins{genCoin.Sub(bondCoin)}.Equal(f.bankKeeper.GetAllBalances(f.ctx, addr1))) + + validator, err := f.stakingKeeper.GetValidator(f.ctx, sdk.ValAddress(addr1)) + require.NoError(t, err) + + require.Equal(t, addrStrVal, validator.OperatorAddress) + require.Equal(t, stakingtypes.Bonded, validator.Status) + require.True(math.IntEq(t, bondTokens, validator.BondedTokens())) + unjailMsg := &slashingtypes.MsgUnjail{ValidatorAddr: addrStrVal} + + _, err = f.slashingKeeper.ValidatorSigningInfo.Get(f.ctx, sdk.ConsAddress(valAddr)) + require.NoError(t, err) + + // unjail should fail with validator not jailed error + _ = f.app.SignCheckDeliver(t, f.ctx, []sdk.Msg{unjailMsg}, "", []uint64{0}, []uint64{1}, []cryptotypes.PrivKey{priv1}, slashingtypes.ErrValidatorNotJailed.Error()) +} diff --git a/testutil/sims/address_helpers.go b/testutil/sims/address_helpers.go index d0b8bb8ce7fc..f90225502b80 100644 --- a/testutil/sims/address_helpers.go +++ b/testutil/sims/address_helpers.go @@ -2,6 +2,7 @@ package sims import ( "bytes" + "context" "encoding/hex" "errors" "strconv" @@ -20,7 +21,7 @@ const mintModuleName = "mint" type GenerateAccountStrategy func(int) []sdk.AccAddress // AddTestAddrsFromPubKeys adds the addresses into the SimApp providing only the public keys. -func AddTestAddrsFromPubKeys(bankKeeper BankKeeper, stakingKeeper StakingKeeper, ctx sdk.Context, pubKeys []cryptotypes.PubKey, accAmt math.Int) { +func AddTestAddrsFromPubKeys(bankKeeper BankKeeper, stakingKeeper StakingKeeper, ctx context.Context, pubKeys []cryptotypes.PubKey, accAmt math.Int) { bondDenom, err := stakingKeeper.BondDenom(ctx) if err != nil { panic(err) @@ -39,11 +40,11 @@ func AddTestAddrs(bankKeeper BankKeeper, stakingKeeper StakingKeeper, ctx sdk.Co } // AddTestAddrsIncremental constructs and returns accNum amount of accounts with an initial balance of accAmt in random order -func AddTestAddrsIncremental(bankKeeper BankKeeper, stakingKeeper StakingKeeper, ctx sdk.Context, accNum int, accAmt math.Int) []sdk.AccAddress { +func AddTestAddrsIncremental(bankKeeper BankKeeper, stakingKeeper StakingKeeper, ctx context.Context, accNum int, accAmt math.Int) []sdk.AccAddress { return addTestAddrs(bankKeeper, stakingKeeper, ctx, accNum, accAmt, CreateIncrementalAccounts) } -func addTestAddrs(bankKeeper BankKeeper, stakingKeeper StakingKeeper, ctx sdk.Context, accNum int, accAmt math.Int, strategy GenerateAccountStrategy) []sdk.AccAddress { +func addTestAddrs(bankKeeper BankKeeper, stakingKeeper StakingKeeper, ctx context.Context, accNum int, accAmt math.Int, strategy GenerateAccountStrategy) []sdk.AccAddress { testAddrs := strategy(accNum) bondDenom, err := stakingKeeper.BondDenom(ctx) if err != nil { @@ -58,7 +59,7 @@ func addTestAddrs(bankKeeper BankKeeper, stakingKeeper StakingKeeper, ctx sdk.Co return testAddrs } -func initAccountWithCoins(bankKeeper BankKeeper, ctx sdk.Context, addr sdk.AccAddress, coins sdk.Coins) { +func initAccountWithCoins(bankKeeper BankKeeper, ctx context.Context, addr sdk.AccAddress, coins sdk.Coins) { if err := bankKeeper.MintCoins(ctx, mintModuleName, coins); err != nil { panic(err) }