test(integration): port x/slashing tests to server v2 (#22754)

This commit is contained in:
Akhil Kumar P 2024-12-05 18:57:26 +05:30 committed by GitHub
parent 66c593f147
commit 00c7756610
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 359 additions and 567 deletions

View File

@ -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(),
)

View File

@ -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))
}

View File

@ -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
)
f := initFixture(t)
app, err := simtestutil.Setup(
depinject.Configs(
AppConfig,
depinject.Supply(log.NewNopLogger()),
),
&interfaceRegistry,
&accountKeeper,
&bankKeeper,
&stakingKeeper,
&slashingKeeper,
)
require.NoError(t, err)
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())
}

View File

@ -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)
}

View File

@ -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
)
f := initFixture(t)
ctx := f.ctx
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
@ -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
)
f := initFixture(t)
ctx := f.ctx
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)
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)
}

View File

@ -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())
}

View File

@ -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)
}